Skip to content

Repository files navigation

cursorful-video-1786851116656.mp4
COMPOS Sync Without Signal — alur transaksi offline dari catalog sampai PostgreSQL

COMPOS

Kasir tetap jalan. Sinkron saat online.

COMPOS adalah point-of-sale offline-first untuk merchant yang harus tetap berjualan
saat koneksi tidak stabil, lalu sinkron otomatis ketika internet kembali.

React 19 Fastify 5 PostgreSQL 17 Offline-ready PWA

Why COMPOS · Guarantees · Sync flow · Demo · Architecture · Quick start · Deploy · Docs

Important

“Transaksi berhasil saat offline” berarti sale, item snapshot, stock projection, dan local outbox sudah tersimpan atomically di device. Backend settlement baru terjadi ketika koneksi sehat. Transport boleh mengirim ulang, tetapi stable transaction ID dan idempotency membuat business effect tetap exactly-once.

Why COMPOS

Koneksi counter UMKM, bazar, atau pop-up store tidak selalu stabil. POS yang bergantung penuh ke request backend bisa membuat antrean berhenti tepat ketika kasir sedang ramai. COMPOS membalik default tersebut: transaksi diselesaikan secara lokal dulu, lalu cloud mengejar state device ketika koneksi kembali.

Project ini bukan mockup checkout. Repository-nya mencakup durable browser persistence, sync engine, merchant-scoped Admin, separate Owner PWA, immutable transaction ledger, reporting read models, reconciliation, PostgreSQL outbox worker, dan automated failure scenarios.

Core guarantees

Guarantee Implementasi nyata
Atomic local checkout Transaction, item snapshots, outbox, stock projection, dan draft cleanup ditulis dalam satu Dexie transaction.
Durable queue Confirmed sale tetap ada setelah reload, logout, auth expiry, network loss, dan abandoned SYNCING recovery.
Stable identity Setiap sale memakai client-generated UUIDv7 yang tidak berubah saat retry atau berpindah batch.
Idempotent settlement ID + payload sama menjadi ALREADY_PROCESSED; reuse ID dengan payload berbeda ditolak tanpa overwrite history.
Partial batch isolation Maksimal 25 due records dikirim per batch; satu item gagal tidak menggagalkan hasil item lain atau mengubah order.
Immutable history Settled transaction tidak diedit; correction dan audit event bersifat append-only.
Eventual inventory Sale diterima lebih dulu, lalu worker menerapkan stock movement secara idempotent dan membuka discrepancy.
Offline authorization lease Checkout lokal boleh lanjut maksimal 72 jam sejak online authentication terakhir tanpa menghapus queued data.

How sync works

flowchart LR
  Sale["Kasir confirm sale"] --> Local[("IndexedDB transaction + outbox")]
  Local --> Receipt["Receipt lokal"]
  Receipt --> Connection{"Connection sehat?"}
  Connection -- "Belum" --> Retry["Queued + exponential backoff"]
  Retry --> Connection
  Connection -- "Ya" --> Batch["Ordered batch, max 25"]
  Batch --> Idempotency{"Stable transaction ID"}
  Idempotency --> Ledger[("PostgreSQL immutable ledger")]
  Ledger --> BackendOutbox["Backend outbox event"]
  BackendOutbox --> Worker["Inventory worker"]
  Worker --> Projection["Stock projection + discrepancy"]
  Ledger --> ReportEvent["Reporting event"]
  ReportEvent --> ReadModel["Daily sales read model"]
  ReadModel --> Owner["COMPOS Owner PWA"]
Loading

Browser scheduler bereaksi pada startup, browser online event, manual reconnect, health probe, dan interval. Sync service hanya mengambil outbox yang sudah due, single-flight, dan tidak menghapus queue ketika token expired. Detail state transition, lost-response handling, dan retry policy ada di Sync Protocol.

Product demo

COMPOS activation and offline sync flow

cursorful-video-1786851116656.mp4

Demo utama yang perlu dibuktikan:

  1. Login dan aktivasi device ketika online.
  2. Matikan koneksi, lakukan checkout, lalu reload browser.
  3. Receipt dan transaksi tetap ada dengan status queued.
  4. Pulihkan koneksi dan lihat automatic settlement tanpa duplicate.
  5. Login sebagai Admin untuk mencoba operator management, catalog pricing, correction, dan inventory reconciliation.

Architecture

apps/
  operator-web/   React 19 + Vite PWA, Dexie, Zustand, shadcn primitives
  owner-web/      React 19 + Vite PWA, online-first reporting dan insight history
  api/            Fastify API, PostgreSQL repositories, multi-lane outbox worker
packages/
  contracts/      Canonical Zod wire schemas dan inferred TypeScript DTOs
docs/             Product, architecture, operations, testing, dan ADR playbook
Layer Technology
Operator application React 19, TypeScript, Vite 7, Tailwind CSS 4, PWA, Dexie, Zustand
API Fastify 5, Zod contracts, JWT dengan server-side session jti
Durable local state IndexedDB melalui Dexie
Canonical persistence PostgreSQL 17, explicit SQL repositories, transactional outbox
Background processing Satu Node.js worker; lane inventory, reporting, dan insight
Quality Vitest, fake IndexedDB, PostgreSQL integration suite, Playwright
Tooling pnpm workspace, Oxlint, Oxfmt, GitHub Actions

Beberapa keputusan penting sengaja konservatif: PWA dipilih sebelum React Native, PostgreSQL outbox dipilih sebelum RabbitMQ, dan raw typed repositories dipertahankan sebelum menambah ORM. Alasan dan trade-off lengkap ada di Architecture Decision Records.

Quick start

Requirements: Node.js 22+, pnpm 10, dan Docker Desktop/Compose.

git clone https://github.com/myudak/compos.git
cd compos

pnpm install --frozen-lockfile
pnpm db:up
pnpm db:reset
pnpm dev

Buka Operator di http://localhost:5173 dan Owner di http://localhost:5174/owner/. pnpm dev menjalankan kedua PWA, API di port 3001, serta worker dengan lane inventory, reporting, dan insight.

Role Merchant Operator PIN
Kasir KEDAI-NUSA RANI 1234
Admin KEDAI-NUSA ADMIN 9999
Owner KEDAI-NUSA OWNER 7777

Device activation code: COMPOS-DEMO.

Warning

pnpm db:reset menghapus schema PostgreSQL lokal. Guard bawaan hanya mengizinkan database bernama operator_pos atau operator_pos_*; jangan pernah menjalankannya ke production database.

One-click demo

Deploy COMPOS to Render

Render Blueprint membuat satu same-origin Fastify + PWA service, satu independent inventory worker, dan satu PostgreSQL database di region Singapore. Migration berjalan concurrency-safe saat API dan worker start; deterministic demo seed hanya berjalan pada first deploy.

Caution

Ini adalah isolated demo sandbox, bukan production template. Inventory worker memakai paid starter instance. Free Render PostgreSQL kedaluwarsa setelah 30 hari dan tidak menyediakan backup. Demo credentials di atas bersifat publik. Review estimasi biaya sebelum approve, lalu hapus seluruh Render project setelah selesai mencoba.

Panduan first deploy, smoke test, troubleshooting, dan teardown ada di Render Demo Deployment.

Quality

Command Bukti yang dijalankan
pnpm format:check Repository mengikuti canonical formatting
pnpm lint Oxlint type-aware dan maintainability limits
pnpm typecheck Strict TypeScript untuk contracts, web, dan API
pnpm test Unit + fake IndexedDB integration
pnpm test:integration Real PostgreSQL, auth/admin, idempotency, lost response, worker replay
pnpm test:load Mixed load 50 merchant: sync, Admin, reporting, insight
pnpm test:load:500 Capacity profile eksplisit 500 merchant selama lima menit
pnpm test:e2e Production-build Playwright scenarios
pnpm docs:check Seluruh local Markdown link dan image reference
pnpm run ci Seluruh repository quality gates dalam satu command
GitHub Actions Full repository quality gate dengan PostgreSQL service

Build hijau bukan klaim production-ready. Secrets management, rate limiting/WAF, accessibility, load testing, monitoring, encrypted backup/PITR, dan restore drill tetap wajib sebelum menangani merchant sungguhan.

Documentation

About

Offline-first POS with reliable transaction sync, idempotent retries, and multi-device reconciliation.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages