engineering docs

Aori — Roadmap Implementasi dan Blueprint Eksekusi

Status: hidup dan wajib diperbarui pada setiap perubahan domain. Peta dokumen: 01.index. Source of truth arsitektur: 03.overview. Uji alur bisnis/invariant: 04.study. Aturan kerja agent/contributor: AGENTS.md pada root repository.

Dokumen ini bukan daftar fitur biasa. Ini adalah urutan implementasi Aori sebagai SaaS multi-tenant dan multi-database. Sebuah item hanya boleh dicentang setelah kontrak API, authorization, entitlement bila relevan, validasi, UI, error state, invalidation, test, dan dokumentasi selesai sesuai boundary-nya.

1. Cara Membaca dan Memperbarui

TandaMakna
[x]Selesai pada boundary yang disebutkan; tetap dapat membutuhkan hardening.
[~]Sebagian tersedia; detail setelah tanda wajib diselesaikan sebelum dianggap production-ready.
[ ]Belum dibuat.
BLOCKEDTidak aman diteruskan tanpa kontrak, policy, atau dependency yang disebutkan.

Setiap perubahan wajib memperbarui item terkait dengan tanggal, ringkasan hasil, validasi yang dijalankan, dan kendala. Jangan mencentang berdasarkan adanya model Prisma saja. Jangan mencentang UI bila API belum tenant-scoped dan terotorisasi.

Snapshot implementasi — 2026-10-22

  • [x] Identity/auth dasar, User profile/personalization, Organization, Member/RBAC, Organization profile, address/link/FAQ, Workspace dasar, Team, Position, dan Employee lifecycle dasar tersedia pada Runner/API/container.
  • [x] Billing schema/client dan katalog Plan publik tersedia; evaluator internal entitlement feature tersedia.
  • [~] Project dapat dibuat dan status diubah; belum lifecycle/detail lengkap.
  • [~] Collaboration API telah memiliki draft + owner party, party invite/accept, approval decision, activation, owner-workspace link, dan external participant. Container baru menyediakan draft/list/party acceptance; UI operasional detail, document lifecycle, quota metering, dan access enforcement lanjutan belum selesai.
  • [ ] HR lanjutan (contract, shift, attendance, compensation, payroll), Catalog, Commerce, Inventory, outbox/inbox, observability/audit/retention production belum selesai.

2. Blueprint Kepemilikan dan Dependency Database

DatabaseOwner/sumber kebenaranTenant keyKonsumenLarangan mutlak
RunnerUser, auth, Organization, Member/RBAC, Workspace, Team, Project, Collaboration, HRrelasi Organizationsemua domainowner product/order/stock atau join lintas DB
BillingBillingAccount, Plan, Subscription, Entitlement, UsageRecord, BillingInvoice/Payment Aoriscalar organizationId tervalidasiRunner/Catalog/Commerce/Inventorymemberi permission actor atau menggantikan Commerce invoice
Catalogproduct/service, price list, promotionscalar organizationIdCommerce, Inventory read modelFK Prisma ke Runner atau mutasi stock/order
Commercecustomer, cart, order, invoice customer, payment, shipmentscalar organizationIdCatalog/Inventory via event/projectionmempercayai harga/actor dari browser atau menjadi Billing
Inventorywarehouse, reservation, stock, immutable movementscalar organizationIdCatalog/Commerce via event/projectionmenerima quantity/price/tenant sebagai fakta client

Semua komunikasi lintas domain mengikuti pola:

command di owner DB
  → local transaction + outbox event ber-idempotency
  → publisher
  → inbox consumer per domain
  → projection/read model atau compensation/reconciliation

Tidak ada transaction Prisma, cascade, foreign key, atau join MongoDB lintas lima database. ID lintas domain adalah reference opaque/scalar yang divalidasi oleh service pemiliknya.

3. Gate Universal Sebelum Fitur Dianggap Selesai

  • Kontrak request/response/error code ditulis dan divalidasi di API secara mandiri tanpa Zod; unknown field, nested object, pagination, enum, format, dan size limit ditolak.
  • Actor dari session/trusted proxy; userId, role, ownership, tenant, price, total, status, serta permission dari client tidak pernah dipercaya.
  • Tenant scope dimulai dari resource owner dan diverifikasi kembali untuk relation.
  • Authorization dan entitlement adalah dua pemeriksaan terpisah; quota dihitung oleh domain pemilik resource secara atomik.
  • Mutation yang dapat retry memiliki idempotency key atau invariant unik yang aman; race condition diuji.
  • Response hanya berisi projection aman; BigInt serialisasi aman sebagai string.
  • Container mem-parse seluruh network payload melalui Zod v4 di schema/.
  • UI memiliki loading, empty, forbidden, error, success, keyboard/focus, i18n, invalidation/refetch yang eksplisit; mutasi sensitif tidak optimistic.
  • Test normal, unauthorized, forbidden, tenant mismatch, duplicate/retry, expiry, stale state, dan retention bila relevan telah dijalankan.

4. Tahap 0 — Engineering Governance dan Platform Baseline

Dependency: tidak ada. Database: seluruhnya. Tujuan: menjadikan perubahan berikutnya aman, terukur, dan dapat ditelusuri.

  • [~] Monorepo, internal packages, container host, API proxy, i18n, form primitive, HTTP status, dan Prisma clients tersedia.
    • Catatan: import ESM packages/auth/src/validation.ts telah dinormalisasi untuk NodeNext; typecheck API perlu dijalankan ulang pada akhir tahap untuk memastikan tidak ada blocker toolchain lain.
    • Catatan: lint container terblokir resolusi lama eslint-config-next/core-web-vitals.
  • [~] Initial-load Container dipisahkan dari data non-kritis: server session/cookie menjadi first paint; daftar multi-session memakai snapshot session aktif dan hanya melakukan refresh authoritative lewat aksi eksplisit. Personalization kini dipisahkan dari context-session; policy sync lintas-device sengaja belum diaktifkan kembali. Sisa: ukur Web Vitals dan audit provider/layout lain untuk waterfall atau refresh loop.
  • [ ] Perbaiki blocker toolchain tanpa mengubah semantics aplikasi; CI menjalankan lint/typecheck/test untuk semua workspace.
  • [ ] Establish API contract tests, integration test database terisolasi, seed aman, fixture multi-tenant, dan test idempotency.
  • [ ] Structured log, request/correlation ID, metrics, trace, health/readiness, error taxonomy, alert policy, dan dashboard operasi.
  • [ ] Security baseline: secret rotation, CSP, rate limit, abuse detection, dependency audit, backup/restore drill, vulnerability response, dan incident runbook.
  • [ ] ADR (architecture decision record) untuk tenancy, eventing, document/media, payment provider, data retention, dan external collaboration.

5. Tahap 1 — Identity, Session, Profile, dan Personal Privacy

Owner: Runner. Actor: User global. Tidak membuat Organization otomatis.

  • [x] Signup/signin/signout, multi-session, credential navigation, password flows, User, Account, Session, Verification, UserProfile, dan personalization dasar.
  • [x] Onboarding awal hanya profile User; user tanpa Organization tetap valid.
  • [~] Personalization sync lintas device dan cookie snapshot diperbaiki.
    • Sisa: test multi-device/focus/reconnect/locale transition secara otomatis.
  • [ ] Passkey lifecycle: enrol, challenge, recovery, revoke, device label, audit.
  • [ ] TwoFactor lifecycle: policy enforcement, backup/recovery code, revoke, audit.
  • [ ] OAuth account linking/unlinking dan collision account policy.
  • [ ] Privacy/export/delete request: legal hold, notification, delayed purge, export, and redaction projection lintas domain.
  • [ ] JWK/key rotation dan token/session compromise response.

Exit gate: user dapat memakai aplikasi tanpa tenant; semua auth mutation aman terhadap open redirect, CSRF/session fixation, retry, enumeration, dan rate-limit abuse.

6. Tahap 2 — Organization, Membership, RBAC, dan Workspace Dasar

Owner: Runner. Tenant root: Organization. Dependency: Tahap 1.

  • [x] Organization/profile creation, owner Member, active organization selection, member invitation/accept/revoke, Permission/PermissionRole, RoleHistory dasar.
  • [x] Workspace CRUD dasar; Workspace tidak dapat ada tanpa Organization.
  • [~] Member ↔ WorkspaceMember assignment tersedia lewat management Member.
    • Sisa: dedicated workspace member lifecycle, suspend/revoke reasons, audit list, pagination/filter/search, dan permission granularity.
  • [ ] Permission catalog lifecycle: migration/versioning, role template, effective permission inspection, break-glass policy, review/certification, audit export.
  • [ ] Organization archive/export/retention policy; child organization semantics bila dipertahankan harus tidak mengaburkan tenant root.
  • [ ] Organization category vocabulary/template system: hanya presentation/module order, tidak pernah memberi role, feature access, entitlement, atau URL palsu.
  • [ ] Workspace operational resource model dan per-request access middleware yang memeriksa owner organization + membership/participant state.

Study verification: 04.study.md STEP 2–6, 9, 14, 15.

7. Tahap 3 — Internal Organization Structure dan HR Foundation

Owner: Runner. Dependency: Member/RBAC. Data sensitivity: tinggi.

  • [x] Team (organizationId wajib, workspaceId opsional), TeamMember tenant-safe, Position hierarchy, Employee conversion from active Member, EmployeePositionHistory, basic lifecycle status, dan UI dasar.
  • [~] Team lifecycle.
    • Archive UI telah memakai endpoint archive (bukan delete), sehingga sejarah tetap attributable. Edit Team UI dan assignment revoke telah terintegrasi di host container dengan validasi Zod v4, server action PATCH/DELETE yang tenant-safe, dan refresh otoritatif.
    • Sisa: Team policy/leadership model, audit/history viewer, dan pagination untuk tim/member besar.
  • [~] Position lifecycle.
    • Update/deactivate UI telah menggunakan validasi Zod dan API hierarchy-cycle check.
    • Sisa: historical assignment impact, role/grade policy, dan detail/audit viewer.
  • [~] Employee lifecycle.
    • Sisa: employee detail boundary, change position UI + history viewer, sensitive field encryption/redaction/audit, rehire, termination reason, document references, bulk import.
  • [ ] EmployeeContract: contract type, effective dates, renewal, expiry, signed document opaque reference, approval, archive/legal retention.
  • [ ] Shift and EmployeeShift: timezone, schedule, recurrence, conflict detection, assignment, effective date, absence/holiday policy.
  • [ ] EmployeeAttendance: clock-in/out, geolocation/device/privacy policy, correction, approval, anti-fraud, immutable audit, shift integration.
  • [ ] EmployeeCompensationComponent: money minor-unit BigInt, effective date, immutable version/snapshot, approval, tax/BPJS policy, no client calculation.
  • [ ] BankAccount: encrypted/redacted fields, verification, access audit, change approval.
  • [ ] Payroll/PayrollItem: period lock, server calculation, attendance/contract snapshot, approval/payment lifecycle, immutable finalized ledger, correction by reversal, export, archive/purge/legal hold.

Study verification: 04.study.md STEP 5, 7–12, 14.

8. Tahap 4 — Project, Collaboration, dan External Workspace Access

Owner: Runner + Billing entitlement. Dependency: Tahap 2, Team/Member, Billing entitlement. Security rule: external person never becomes Member of host tenant.

4A. Project

  • [x] Project create/list/status update with tenant permission.
  • [~] Full basic edit (name, code, description, timeline, status) is available through the same server-validated Project contract as creation.
    • Selesai pada tahap ini: tenant-scoped code uniqueness validation, lifecycle transition policy (draft → active/cancelled, active ↔ on_hold, terminal completion/cancellation → archived), serta compare-and-set update untuk mencegah stale status transition menimpa perubahan terbaru.
    • Sisa: deliverable/timeline/budget model, Project–Workspace association, Project audit/read model.

4B. Collaboration aggregate

  • [x] Draft creates accepted owner party atomically.
  • [x] Party invitation with organization/team/representative, scope subset, validity boundary, accepted party flow, approval requirement/decision, activation gate, owner-workspace link, and external WorkspaceParticipant API.
  • [x] collaboration.enabled feature entitlement is checked for owner-side mutations.
  • [~] Container supports draft/list, acceptance by invited tenant, serta owner-side proposal dan reversible suspend/resume dengan authoritative refresh. Owner dapat menambah approval requirement untuk party yang sudah ada serta meminta aktivasi; API tetap memutuskan kelayakannya.
    • Sisa: permission-aware owner console for party invite, approval decision, workspace link, participant assignment/revoke, status/history detail, dan confirmation+reason UX untuk termination/archive.
  • [ ] CollaborationDocument: document/media service contract, opaque document reference, issuer validation, verification metadata, NDA/agreement/minutes/attachment, expiry, access policy, immutable audit, retention/legal hold.
  • [~] Lifecycle transitions owner-side: propose, suspend/resume, terminate, archive, revoke non-owner party (termasuk revoke seluruh external participant terkait), dan revoke external participant sudah tersedia pada API.
    • Sisa: automatic expiry job, party suspension/resume, reason/note/audit event per mutation, notification, UI lifecycle operasional, dan policy archive/retention.
  • [ ] requiredByTeamRole requires an explicit Team role model/policy before it is exposed; do not pretend TeamMember has a role it does not store.
  • [ ] Entitlement quotas: external party max, workspace max, external participant max; owner domain atomically counts usage then emits idempotent UsageRecord to Billing.
  • [ ] Access middleware on every workspace resource checks Collaboration active, party accepted, approval complete, scope subset, participant active, validity windows, and immediate revocation/expiry.
  • [ ] Cross-organization organization discovery/invitation policy. Do not expose a global tenant directory without privacy, anti-enumeration, and consent design.

Study verification: 04.study.md STEP 17–18; especially 17 Agustus multi-party scenario.

9. Tahap 5 — Billing, Subscription, Entitlement, dan Retention

Owner: Billing. Dependency: Runner organization exists. Boundary: Billing grants capability/quota, never actor permission.

  • [x] Billing schema/client, Plan version model, public active-plan catalogue, and internal effective feature entitlement lookup.
  • [~] Container pricing board reads public plan data.
    • Sisa: UI must never hardcode source-of-truth price/features.
  • [ ] BillingAccount creation and tenant ownership verification against Runner.
  • [ ] Subscription checkout command: provider abstraction, idempotency key, secure redirect, provider reference secrecy, webhook signature/replay validation.
  • [ ] Subscription state machine: trial/active/grace/restricted/ended/archived; billing projection to effective Entitlement with deterministic precedence.
  • [ ] Entitlement evaluator including quota values and atomic usage decision contract.
  • [ ] UsageRecord inbox/outbox/metering: producer idempotency key, dedupe, retry, reconciliation, late event policy; no synchronous Billing write in operational request.
  • [ ] BillingInvoice/BillingPayment lifecycle; explicitly distinct from Commerce invoice/payment.
  • [ ] Restricted read-only enforcement, account archive, retention/legal hold, notification, export window, purge job and irreversible deletion safeguards.

Study verification: 04.study.md STEP 16 and retention section.

10. Tahap 6 — Catalog Domain

Owner: Catalog. Dependency: Organization scalar tenant key + Billing entitlement + Runner authorization composition. No Runner FK.

  • [~] Product/category functionality operates against Catalog database through tenant/RBAC composition. Product create/update/archive now appends an idempotent Catalog outbox event in the same local transaction; archive replaces physical delete. Price lists and immutable price versions now have tenant-scoped API contracts; price mutations reject floating-point money and overlapping active target/tier validity windows, then append catalog.price.changed locally.
    • Price entry host sekarang dimulai dari Product → valid PriceList → immutable Price version; list validity diperiksa lagi API sebelum write dan history dibatasi ke Product terkait. Perintah create Price kini membawa UUID idempotency key yang tersimpan bersama hash payload privat. Retry dengan payload sama mengembalikan versi yang telah dibuat; reuse key untuk payload atau PriceList lain ditolak tanpa membuat versi baru.
    • Sisa: outbox publisher lease/retry/dead-letter, Inventory/Commerce inbox consumers dan projections, date/tier price editor lengkap, dan migration of remaining legacy product naming.
  • [ ] Catalog schema finalization: product/service, category, variant, attribute, media opaque references, price list, tax class, promotion eligibility, status/version.
    • ProductVariant API lifecycle is available (tenant resolution through parent Product, manual bounded attributes validation, archive-not-delete, and parent projection event). Host juga telah memiliki action archive tenant-scoped dengan refresh otoritatif. Media, identifiers, categories, service definitions, tax, promotion, and read-model contracts are still not exposed.
  • [ ] Catalog APIs: tenant scope, product permission, entitlement, pagination/filter/search, immutable price versioning and BigInt money.
    • Category legacy handlers now reject unknown/invalid input, resolve parent categories in the same tenant, hide archived rows, and archive instead of physically deleting. Search, pagination, entitlement, media and complete category/product composition remain open.
  • [ ] Event contracts: catalog.product.published, catalog.price.changed, catalog.product.archived; idempotent consumers and projection versioning.
    • Versi awal @repo/events sekarang mendefinisikan envelope JSON-safe berversi dan payload Catalog Product/Price. Outbox Catalog menyimpan envelope tersebut dengan eventId yang sama; correlation/causation masih null sampai request context dan publisher/inbox lintas domain tersedia.
  • [ ] Container/catalog MFE routes with safe Zod schemas, server access gating, list/detail, form, error/empty/loading and cache invalidation.
    • Container sekarang memiliki host route /org/[slug]/catalog untuk Product identity/content: server access gate, Zod v4 response/form validation, create/edit pessimistic refresh, loading transition, empty/error access state, dan shortcut capability kategori yang hanya muncul setelah route benar-benar ada. Variant nested route tersedia untuk identity SKU turunan Product yang tervalidasi dan dapat diarsipkan. PriceList metadata juga dapat dibuat/dibaca/diarsipkan dari host; entry harga per produk memakai idempotency key, sedangkan pagination, granular navigation permission/entitlement, date/tier editor, dan MFE remote boundary masih terbuka.

11. Tahap 7 — Inventory Domain

Owner: Inventory. Dependency: Catalog projection; entitlement; warehouse permission. Rule: stock truth is immutable movement ledger, not client quantity.

  • [ ] Warehouse, location/bin, stock item/balance projection, reservation, lot/batch, serial policy, stock movement/adjustment/transfer/count schemas.
  • [ ] Reservation lifecycle with idempotency and expiry; authoritative availability endpoint.
  • [ ] Inventory commands validate tenant, authorization, product projection, quantity bounds, concurrency/optimistic version or ledger invariant; no price from client.
  • [ ] Event contracts to/from Commerce: reserve/confirm/release/fulfill/return; compensation and reconciliation dashboard.
  • [ ] Warehouse/inventory MFE with ledger-first UI, scan accessibility, offline policy only if reconciliation is designed; no localStorage stock source of truth.

Study verification: 04.study.md STEP 13A–13B.

12. Tahap 8 — Commerce Domain

Owner: Commerce. Dependency: Catalog projection, Inventory reservation, Billing entitlement, Runner actor composition. Commerce invoice ≠ BillingInvoice.

  • [ ] Customer/contact/address snapshot model; customer identity/privacy policy.
  • [ ] Cart/quote/order state machine, server-authoritative price/tax/discount snapshot, idempotent checkout/order command, cancellation/return/refund policy.
  • [ ] Customer Invoice, Commerce payment, shipment/fulfilment lifecycle; provider webhooks validated, replay safe, monetary amounts BigInt minor units.
  • [ ] Outbox/inbox flows with Inventory and Catalog projections; reserve → confirm/release, shipment events, failed compensation and reconciliation.
  • [ ] Commerce MFE routes with permission/entitlement gate, authoritative mutation result, no optimistic stock/payment/order finality.

13. Tahap 9 — Cross-Domain Read Models, Eventing, and Reconciliation

Dependency: each owner domain command is stable first.

  • [ ] Shared event envelope: event ID, aggregate/version, organizationId, occurredAt, correlation/causation ID, schema version, idempotency key, PII classification.
  • [ ] Per-database outbox, publisher lease/retry/dead-letter and inbox dedupe tables.
  • [ ] Consumer ordering/duplicate/out-of-order strategy; poison-event tooling and replay.
  • [ ] Projection/composition service contracts for dashboard/search/report; no hidden cross-DB join from UI request.
  • [ ] Reconciliation jobs for subscription usage, catalog/commerce price mismatch, commerce/inventory reservation, payroll/payment and document references.
  • [ ] Data migration/versioning and backfill protocol with rollback/repair plan.

14. Tahap 10 — Audit, Compliance, Data Lifecycle, and Operations

  • [ ] Immutable audit event model/service for access, RBAC, HR, collaboration, money, document, retention, and privileged support action.
  • [ ] Actor impersonation/support policy with explicit consent, audit, expiry and no secret exposure.
  • [ ] Data classification, PII redaction, encryption-at-rest/field encryption, key access, download watermarking where required.
  • [ ] Retention policy engine: active → archived → legal-hold check → warning/export → scheduled purge; every job idempotent and auditable.
  • [ ] Organization backup/export, restore boundaries, disaster recovery RPO/RTO test.
  • [ ] Operational dashboards for auth abuse, queue lag, event failures, entitlement denial, collaboration expiry, payroll lock, stock reconciliation, and data purge.

15. Tahap 11 — Product Experience, MFE, and Scale

  • [~] Mobile auth foundation berada pada repository saudara C:\Data\AORI-Projects\aori-mobile: Expo Router protected groups memisahkan route publik dan operasional; credential email/password memperoleh bearer session Better Auth melalui API, token hanya disimpan di Expo SecureStore, dan cold start selalu memvalidasinya kembali lewat get-session.
    • OAuth provider (Google, GitHub, Apple, Microsoft bila dikonfigurasi) kini memakai mobile grant bridge: API membuat attempt berumur 10 menit dengan exchange-secret yang hanya ada di memori aplikasi, Better Auth menyelesaikan provider di browser, dan callback deep-link membawa grant opaque sekali pakai—bukan session/bearer token. API mengenkripsi token cookie sementara menggunakan BETTER_AUTH_SECRET, menukarnya sekali melalui HTTPS, lalu menghapus verification record secara atomik. AORI_MOBILE_AUTH_CALLBACK_URL pada API dan EXPO_PUBLIC_AORI_AUTH_CALLBACK_URL pada mobile harus identik (aori://auth/callback); nilai default hanya untuk local development.
    • Batas saat ini: MFA, passkey, recovery, account linking/unlinking, device/session management, API client domain, Zod response schema mobile, i18n, dan universal-link/app-link hardening belum tersedia. EXPO_PUBLIC_AORI_API_URL harus diarahkan ke HTTPS/reachable API (bukan localhost pada perangkat fisik). Bridge tidak boleh dianggap pengganti universal link pada production.
    • Lokasi implementasi aktif: C:/Data/AORI-Projects/aori-mobile. SDK 58 memerlukan root route konkret di src/app/index.tsx; route tersebut dilindungi bersama (app), sementara Stack.Protected menjadi satu-satunya mekanisme redirect menuju auth agar perubahan sesi tidak menciptakan loop navigasi. Respons user Better Auth diparse menjadi projection aman sebelum dipakai state sesi.
    • [~] Mobile profile edit memakai PATCH /api/users/me dengan bearer session, validasi input lokal minimal, state submitting yang menonaktifkan field, dan update state hanya dari respons API tervalidasi. Avatar/media, verifikasi telepon/email, recovery, dan pengelolaan session/device tetap belum tersedia.
    • [~] Mobile security screen tidak lagi memakai switch dua faktor atau daftar perangkat palsu. Ia hanya menampilkan status two-factor dari projection sesi; password, re-authentication, recovery, dan session/device management menunggu lifecycle native yang lengkap.
    • [~] Mobile notification screen tidak lagi menyimpan toggle lokal semu. Delivery preference menunggu push-token registration, izin perangkat, preference API, dan audit delivery yang konsisten.
    • [~] Mobile password change tersedia melalui POST /api/users/me/password: current password, password baru, dan pilihan revoke sesi lain dikirim melalui bearer session; API tetap memeriksa freshness/policy/password lama dan UI tidak melakukan optimistic update. Device-session inventory dan MFA management tetap belum tersedia.
    • [~] Mobile Organization context dapat membaca profil tenant yang member-safe melalui GET /api/organization/:organizationId, hanya atas aksi eksplisit, dengan parse runtime dan race protection. Endpoint Workspace masih owner-only sehingga tidak dipakai sebagai daftar Workspace universal untuk Member.
    • [~] GET /api/users/me/readiness menyediakan UserProfileReadiness v1 yang identity-only; Dashboard mobile merender progress profil dari respons tervalidasi, lazy pada focus dengan throttle dan stale-response guard. OrganizationReadiness dan MemberWorkReadiness belum dibuat karena membutuhkan checklist permission/entitlement dan lifecycle membership yang tidak boleh disatukan.
  • [~] Mobile Organization context memuat projection aman dari GET /api/users/me/organizations hanya atas aksi eksplisit pengguna, mem-parse respons network sebelum dipakai, dan memilih konteks hanya di memori. Provider di-remount per user.id agar tenant akun sebelumnya tidak pernah tampak setelah sign-out/sign-in. Route/tab yang sebelumnya bernama Workspace telah dimigrasikan menjadi Organization karena layar ini bukan daftar Workspace.
    • Layar Organization mobile kini melakukan initial load saat route mendapat focus, hanya ketika state masih idle; refresh manual tetap tersedia dan selection tetap memory-only. Request tidak dipicu dari render dan tidak mengubah boundary authorization API.
    • [~] Dashboard, aktivitas, Catalog, dan Commerce mobile tidak lagi mengonsumsi data contoh perangkat. Saat kontrak read model tenant-scoped belum ada, layar menampilkan empty/unavailable state yang jelas. Daftar Workspace juga sengaja belum diintegrasikan: endpoint yang ada saat ini owner-only, sehingga tidak aman dipakai sebagai daftar universal bagi Member.
    • [~] Ikon navigasi dan affordance mobile memakai expo-symbols atau image asset yang valid; ikon berbasis karakter string dan data mock legacy src/data/workspace.ts telah dihapus. Penggantian icon native tab dapat tetap memakai asset raster multi-ukuran yang sudah tersedia.
  • [ ] Route map per capability/MFE with host ownership, remote boundary, contract version, fallback/error isolation, and progressive loading.
  • [ ] Mobile Remote Config/SDUI/OTA foundation: policy telah dikunci pada root dan mobile AGENTS.md (presentational-only config, validated native registry/action allowlist, built-in fallback, tenant-safe delivery, dan OTA runtime boundary). Implementasi service/config API, cache, registry, Dashboard pilot, test matrix, dan EAS Update activation belum dimulai.
  • [ ] Navigation derived from permission + entitlement + capability availability; category changes labels/template only.
  • [ ] Responsive/mobile, keyboard, screen-reader, locale/RTL, timezone/currency formatting, large-list virtualisation/pagination, and performance budgets.
  • [ ] Notification center, email/push preference, digest, delivery audit, and external invite notification with privacy-safe content.
  • [ ] Search/read model, reporting/export, analytics consent, usage reporting, and data minimization.
  • [ ] Multi-region/scale plan: tenant routing, cache key tenancy, rate limits, queue partitioning, backpressure, SLOs, capacity/load/chaos tests.

16. Route and Contract Delivery Checklist

Untuk setiap route baru, tambahkan baris status di fase domain terkait dan pastikan:

  1. Owner DB, tenant scalar/relation, actor, permission, entitlement, lifecycle, and data classification dicatat.
  2. API validates parameter/query/body manually; unknown keys rejected; response projection safe; idempotency stated.
  3. Event/outbox/projection impact dicatat bila menyentuh database lain.
  4. Container Zod schema, server gate, mutation invalidation, i18n, accessibility, and states selesai.
  5. Test matrix dan 04.study.md scenario mapping diperbarui.
  6. Checklist dalam roadmap diperbarui bersama catatan positif/kendala/risiko.

17. Change Log Roadmap

TanggalPerubahanKeterangan
2026-10-22Roadmap dibuatBaseline menyatukan status Runner/Collaboration dan semua domain lima database.
2026-10-22Collaboration foundationAPI lifecycle awal tersedia; UI detail, document, quota metering, access enforcement, dan eventing masih terbuka.
2026-10-22Collaboration revocation lifecycleAPI menambahkan propose/suspend/resume/terminate/archive serta revoke party/participant; UI, expiry job, audit event, dan notification belum tersedia.
2026-10-22Collaboration owner UI lifecycleContainer menambahkan proposal dan suspend/resume yang reversible; action terminal ditahan sampai confirmation/reason/audit UX tersedia. Container typecheck lulus.
2026-10-22Project basic editContainer menyatukan edit detail dan status Project pada kontrak API tervalidasi; budget/deliverable/workspace/audit belum dimodelkan.
2026-10-22Collaboration approval/activation UIOwner dapat membuat requirement approval pada party yang sudah ada dan meminta aktivasi; projection party memakai display name aman. Container typecheck lulus.
2026-10-22Catalog outbox foundationProduct create/update/archive menulis event lokal idempoten dalam transaksi Catalog; hard delete diganti archive. Publisher dan consumer Inventory/Commerce belum dibuat.
2026-10-22Catalog pricing foundationPriceList dan Price version memiliki route tenant/RBAC, validasi minor-unit BigInt, validity/tier overlap check, serialisasi HTTP aman, serta outbox catalog.price.changed; belum ada publisher/consumer maupun UI.
2026-10-22Catalog host pricing plugContainer memiliki descriptor proxy, schema Zod v4, dan server service untuk price-list/history; route UI tetap belum diekspos sampai manajemen Catalog dan i18n siap.
2026-10-22Catalog variant lifecycleVariant product dapat dibaca/dibuat/diubah/diarsipkan dalam tenant parent Product, atribut dibatasi, dan perubahan memicu projection event Product; typecheck API hanya masih terblokir import ESM legacy di packages/auth.
2026-10-22Catalog category boundaryHandler kategori legacy diperketat dengan validasi manual, tenant-scoped parent, dan archive lifecycle; belum ada event/projection kategori maupun UI.
2026-10-22Shared Catalog event envelopePackage internal @repo/events ditambahkan; outbox Catalog memakai envelope schema v1 JSON-safe dengan event ID yang konsisten. Publisher, inbox, correlation context, dan transport masih BLOCKED oleh ketiadaan worker/broker.
2026-10-23Catalog Product host surfaceContainer menambahkan route Product tenant-scoped dengan Zod, server gate, form reusable, refresh authoritative, serta i18n; Product belum mencakup price, stock, variant, media, atau pagination.
2026-10-23Catalog Variant host surfaceContainer menambahkan route nested Variant yang mengambil parent Product detail (bukan daftar berpagination), memakai Zod, dan melakukan refresh otoritatif setelah mutation. Stock dan harga tetap tidak dimodelkan pada Variant.
2026-10-23Catalog PriceList host surfaceContainer menambahkan route PriceList tenant-scoped dengan create/list Zod dan refresh otoritatif. Entry harga per Product ditahan sampai pemilih Product yang aman dan terpagination tersedia. Container TypeScript lulus.
2026-10-23Catalog Product price flowHarga kini dibuat dari Product menuju PriceList valid lalu Price version minor-unit; API memfilter history menurut Product dan menolak list yang berada di luar masa berlaku. Publisher/inbox dan idempotency command masih terbuka.
2026-10-23Catalog Product archive host actionProduct archive memakai endpoint tenant/RBAC yang sudah ada dan refresh otoritatif; riwayat referensi tidak dihapus. PriceList dan Variant archive UI masih terbuka.
2026-10-24Catalog price idempotency & Variant archivePrice menyimpan idempotency key dan hash payload privat untuk replay aman/race retry; reuse key lintas payload ditolak. Host dapat mengarsipkan Variant melalui parent Product tenant scope dan refresh otoritatif. Prisma Catalog serta shared DB types telah digenerate; API typecheck masih terblokir empat import ESM legacy packages/auth/src/validation.ts.
2026-10-24Catalog PriceList archivePriceList sekarang diarsipkan (bukan dihapus) melalui permission price.manage, menonaktifkan list/default flag, dan mempertahankan Price immutable untuk audit/history. Host memakai action tenant-scoped dengan refresh otoritatif.
2026-10-24Container bootstrap performanceSession server/cookie dipakai untuk first paint; fetch multi-session dipindahkan ke dialog/halaman khusus. Revalidasi personalization dibuat background, tervalidasi Zod, dedupe/throttle focus, dan tidak lagi melakukan refresh route pada sync normal. Container TypeScript lulus; pengukuran Web Vitals serta audit provider lain masih terbuka.
2026-10-24Session/personalization isolation & auth navigationPersonalization dipindahkan dari context-session ke hook snapshot tanpa effect/fetch bootstrap; sinkronisasi lintas-device ditunda sampai policy baru siap. Dialog/halaman multi-session tidak lagi auto-refresh; user memilih refresh authoritative. Auth browser dipaksa melalui proxy same-origin dan sign-up menerima callback URL agar cookie dan navigasi berada pada boundary yang sama. Container TypeScript lulus; profiling browser autentikasi masih diperlukan.
2026-10-24Mobile credential auth foundationaori-mobile memakai Expo Router protected route serta Expo SecureStore. Better Auth bearer token diambil dari header set-auth-token, disimpan encrypted, dan divalidasi ulang terhadap API saat cold start; token tidak menggunakan AsyncStorage/cookie/URL. TypeScript mobile lulus. OAuth, MFA, dan native recovery tetap terbuka.
2026-10-25Mobile workspace SDK 58 migrationImplementasi aktif kembali berada di aori-mobile. Root starter diganti dengan route pengarah sesi src/app/index.tsx; plugin Expo untuk SecureStore, font, image, status bar, dan web browser dinyatakan kembali di app config.
2026-10-25Mobile protected-route sign-out fixRoot index kini berada di group guard autentikasi yang sama dengan (app) dan hanya mengarah ke operasi saat guard lolos. Stack.Protected dengan redirectTo="/sign-in" menjadi satu-satunya redirect logout; ini menghilangkan redirect bersaing yang memicu maximum update depth.
2026-10-25Mobile auth response boundaryRespons sign-in, sign-up, dan get-session tidak lagi di-cast secara buta. Mobile hanya menerima projection AuthUser dengan scalar yang tervalidasi; ISO date tetap string pada boundary JSON. Respons tidak valid memicu validasi sesi ulang atau penolakan sesi.
2026-10-25Mobile profile editProfile mobile dapat mengubah nama, username, dan nomor telepon melalui PATCH /api/users/me yang sudah ada. Mutation bearer-scoped, input form dibatasi sebelum request, dan state user diganti hanya memakai projection respons yang tervalidasi.
2026-10-26Collaboration party invite contractContainer menambahkan schema Zod v4 dan server service untuk owner-side party invitation pada endpoint API yang sudah tersedia. UI invite, organization discovery, team/representative selectors, audit reason, dan pagination masih terbuka; tidak ada endpoint baru atau mock tenant dibuat.
2026-10-26Collaboration discovery privacy boundaryAPI menambahkan discovery exact-slug yang hanya mengembalikan projection publik terbatas setelah collaboration.manage; free-text/global enumeration ditolak, owner tenant tidak dapat ditemukan melalui endpoint ini. UI selector lengkap masih perlu diselesaikan dengan i18n dan team/representative contracts.
2026-10-25Mobile security truthfulnessToggle two-factor lokal dan detail perangkat mock dihapus. Layar keamanan kini read-only, menggunakan status twoFactorEnabled dari sesi dan menyatakan capability yang belum mempunyai lifecycle native secara eksplisit.
2026-10-25Mobile notification truthfulnessToggle notifikasi lokal dihapus. Layar notifikasi menyatakan dependency push permission/token, preference API, dan delivery audit sebelum preference dapat dimutasi dari mobile.
2026-10-25Mobile credential and Organization expansionMobile membuka perubahan password melalui kontrak User yang telah ada (server tetap memverifikasi session/password/policy) dan menambahkan pembacaan profil Organization yang member-safe atas aksi eksplisit. Daftar sesi, MFA, dan Workspace member-safe masih belum tersedia.
2026-10-25User profile readiness v1API menambahkan projection readiness identity-only pada User; Dashboard mobile menampilkan progress nyata tanpa menyebut Workspace atau mewajibkan Organization. Checklist tenant dan kerja anggota ditahan sebagai projection terpisah agar skenario collaboration lintas Organization tidak bocor atau salah dihitung.
2026-10-25Mobile dynamic-delivery boundaryInstruksi root dan mobile mengunci pemisahan Remote Config, SDUI, dan OTA agar tidak dapat mengubah tenant/authorization/entitlement atau menjalankan capability arbitrer. Ini hanya policy/design guard; endpoint config, registry, cache, dan EAS Update belum diimplementasikan.
2026-10-25Mobile tenant-context hardeningMobile menambahkan Organization context dari endpoint user-scoped, selection memory-only, dan remount per user untuk mencegah sisa tenant lintas sesi. Route seleksi yang semula ambigu bernama Workspace diganti menjadi Organization; Workspace tetap belum ditampilkan karena route API saat ini owner-only.
2026-10-25Mobile mock removal and icon migrationData dashboard/activity/catalog/commerce contoh serta ikon karakter string dihapus. Semua layar tersebut kini tenant-aware dan jujur terhadap kontrak yang belum tersedia; affordance menggunakan expo-symbols/asset ikon valid.
2026-10-26Mobile OAuth one-use grant bridgeAPI menambahkan start/callback/exchange native OAuth yang mengikat attempt pada exchange-secret memori, mengenkripsi token sesi sementara, dan menghapus grant atomik sesudah exchange. Mobile menampilkan provider yang benar-benar dikonfigurasi serta menyimpan bearer hanya setelah respons HTTPS. Masih perlu universal link/app link, automated expiry cleanup, rate-limit spesifik auth, dan test integrasi provider/callback sebelum production.
2026-10-26TypeScript auth boundaryTypecheck mobile lulus setelah projection readiness mempersempit data unknown secara runtime. Import ESM pada @repo/auth/validation dinormalisasi untuk resolver NodeNext; typecheck API dijalankan ulang setelah perubahan.
2026-10-26Mobile Organization initial loadLayar Organization memuat daftar tenant saat pertama kali mendapat focus bila belum pernah dimuat; refresh manual dan projection API tetap dipertahankan, tanpa persistence atau asumsi akses client.
2026-10-26Auth provider platform capabilityGET /api/auth/providers kini mengembalikan capability web, ios, dan android; Google memakai client ID platform masing-masing dengan GOOGLE_CLIENT_SECRET bersama. Web dan mobile memilih projection platformnya sendiri sebelum merender provider.
2026-10-26Mobile OAuth authorization boundaryMobile OAuth menolak authorization URL yang mengarah ke API/web Aori atau host yang tidak sesuai provider; flow tetap memakai Expo native browser auth session dan callback opaque aori://auth/callback, tanpa menaruh bearer token pada deep link.
2026-10-26Mobile native provider sign-inMobile Google memakai react-native-nitro-google-signin dan Apple memakai expo-apple-authentication; API menerima credential ID token melalui endpoint mobile khusus dan meneruskannya ke Better Auth untuk validasi server-side. Native modules memerlukan development/production native rebuild, bukan Expo Go.
2026-10-27Mobile user settings modularizationAccount mobile kini memiliki module src/components/settings/user dengan menu, preferences, dan address. Address memakai endpoint user-scoped nyata dengan runtime parsing, loading/empty/error state, create, dan delete; profile, password, security, notification, provider connection, delete account, dan MFA tetap dibatasi oleh lifecycle kontrak yang tersedia.
2026-10-28Mobile owner-agnostic address formMobile menambahkan components/ui/address-form.tsx yang hanya menangani input address dan menerima onSubmit dari caller. Cascading province/city/district/village serta postal-code lookup mengambil data dari endpoint geography publik dan memvalidasi response runtime; user address memakai adapter callback, sementara organization adapter belum diaktifkan di layar mobile. TypeScript mobile lulus.
2026-10-28Mobile Select bottom-sheet gesture/scroll correctionSelect mobile membatasi tinggi sheet secara eksplisit 65% viewport, memberi ruang bounded pada ScrollView agar opsi banyak dapat discroll, serta memasang root gesture handler di dalam native Modal; gesture tarik tetap dibatasi pada header sehingga tidak merebut scroll options. Runtime verification pada native development build masih diperlukan.
2026-10-28Mobile Select sheet sizing and overlay polishSheet kembali intrinsik mengikuti content dengan batas maksimum 65% viewport; daftar panjang tetap memiliki batas scroll tersendiri. Spring rebound memakai overshoot clamping untuk menghilangkan gap saat kembali ke posisi awal, dan modal confirmation/select memberi tint status bar yang lebih terang agar konsisten dengan overlay.
2026-10-28Mobile modal StatusBar compatibilityStatusBar modal disederhanakan ke barStyle karena tipe Expo/RN proyek tidak menyediakan translucent atau backgroundColor; modal memakai statusBarTranslucent dan backdrop transparan untuk mempertahankan tint overlay tanpa error TypeScript.
2026-10-22HR structure lifecyclePosition update/deactivation dan Team archive UI ditambahkan; Team edit serta assignment lifecycle masih terbuka.
2026-10-23Team edit & member revoke lifecycleContainer menambahkan form edit Team (nama, deskripsi, workspace reassignment) serta aksi revoke penugasan member dengan status aman dan refresh otoritatif.

| 2026-10-28 | Sheets modal performance/accessibility | Core Sheets mengurangi listener Escape saat tertutup, memindahkan multiple-open render scheduling ke provider tunggal, mencegah setiap panel mengunci scrollbar, dan menambahkan focus trap pada modal content. Scrollbar lock kini ref-counted agar beberapa modal tidak saling menghapus style body; browser verification dan a11y test otomatis masih terbuka. |

18. Definition of Done Produk Besar

Aori tidak dianggap selesai hanya karena halaman atau model sudah ada. Target akhir tercapai apabila setiap domain owner dapat bekerja independen dengan kontrak event/versioning yang teruji; tenant tidak dapat bocor; entitlement dan permission tidak saling menggantikan; money/stock/payroll/legal record authoritative serta auditable; recovery/retention/operation teruji; dan pengalaman User, Member, Employee, owner, serta collaborator eksternal jelas tanpa memalsukan relasi Organization–Workspace–Project–Collaboration.