Milestones
Purpose: the high-level milestones for the Appwrite migration — coarser than the roadmap, no issue-level detail. Track granular progress on Project 11. Status: as of 2026-07-30 — the ladder now runs past the migration: M6 (the production-cutover gate) closed 2026-07-24, and the live ladder is M9 (feature completion) → M10 (verified MVP) → M11 (go-live).
Milestone ladder
Section titled “Milestone ladder”| # | Milestone | Means | Depends on | State (2026-07-30) |
|---|---|---|---|---|
| M0 | Backlog restructured | Appwrite backlog drafted, promoted to issues, old POS issues superseded | — | ✅ done — 50 issues live; old #34–65 closed/superseded; blocked_by wired |
| M1 | Foundation live | Every repo talks to Appwrite; schema + types generate; CI can push | M0 | ✅ done (2026-07-01) — api CLI/skeleton #111 + server-SDK module #112 + CI schema/functions deploy #122; web SDK client + SSR #90, type gen #100; mobile Kotlin SDK client #108, type gen #109, playground demos #113 |
| M2 | Data migrated | All POS collections exist as code, typed, permissioned; tests adapted | M1 | ✅ done (2026-07-02) — all POS tables as code (schema/types #113, catalog #115, store/terminal/audit #126, staff #129, inventory #136, sales #138), audit wiring #131, tests adapted #141; web re-points read the real tables (#130/#139) |
| M3 | Auth cutover-ready | All auth flows on Appwrite; API authorizes via Appwrite guard | M1 | ✅ done (2026-07-03) — api guard #114 + teams/roles #118 + invites #127 + user-mgmt #130 + PIN #132; web #101/#123/#124/#125/#126/#128/#131; mobile #115/#119/#120/#124; legacy controllers migrated to the Appwrite guard (#148, closed 2026-07-03); residual BetterAuth module removal #149 in flight (PR #151) |
| M4 | Storage + Functions live | Buckets/file-tokens working; functions pipeline deploys | M1 | ✅ done (2026-07-02) — buckets #116 + file service/file-tokens #117 (api), web upload #91, mobile upload #114; functions scaffolding + CI deploy #128 (2026-07-01) validated by hello-world #133 (2026-07-02) |
| M5 | Clients direct | Web reads/writes via the adapter; Android offline-first reads + idempotent sync | M2, M3 | ✅ done (2026-07-03) — web RQ ↔ Appwrite adapter #121 with resources re-pointed (#130/#131 2026-07-01; products/variants/barcodes/tax-rates #139 2026-07-03); Android offline-first direct reads #125 (2026-07-02) |
| M6 | Production cutover gate | The pre-production regimes end: flags exist and are set deliberately, migrations become the only DDL path, CI comes back on | M5 | ✅ done (2026-07-24) — the ProdCutover family: appwrite push backlog flush + pull verify #179, migrations reintroduced as the only DDL path #180 (2026-07-11), frozen BetterAuth tables dropped #248 (07-12), GitHub Actions re-enabled across the repos #265 (07-24). The flag half resolved the other way from the original plan: rather than a dark ramp, the PO set every flag ON for MVP (2026-07-14); the production kill-switch ramp is what remains (#264, open) |
| M7 | Legacy decommissioned | TypeORM POS entities + BetterAuth removed; app boots on Appwrite auth only | M6 | ✅ done (2026-07-12) — decommission #143 (07-03), legacy controllers onto the Appwrite guard #148/PR #150 (07-03), BetterAuth module + strategies removed #149 (07-04), frozen tables dropped by migration #248 (07-12). TypeORM’s migration machinery is intentionally retained as the DDL path for the legacy Postgres remainder (#180) — that is not residue |
| M8 | Stage environment live | A hosted pre-prod env deploys the API + Appwrite, gated by an enforced test suite | M2–M5 | ✅ done (2026-07-08) — terminales-api on ionos at api-stage.io.inspiracode.com (stage stack #214/#216, grafana-stage #215), enforced hermetic test-gate #175, nightly Appwrite backup + restore runbook #170. Since kept current: PR checks + stage/QA deploys moved to the self-hosted ionos runner (07-17..19), customers module enabled (07-27), wallet flags enabled + verified (07-30). No live users yet |
| M9 | MVP feature-complete on all three clients | Every MVP user story has an implementation on web and (where it has a mobile surface) on Android | M6, M8 | 🟢 substantially done (sprints 33–34) — ~240 issues closed since 2026-07-11: VAS screens, Clientes, merchant wallet, platform admin, refunds, held orders, white-label, denomination close, inventory transfer, the full atomic design system in both clients and the screen-parity build-outs. The one structural hole left is the VAS aggregator transport (Mantarys, 10 open tickets) |
| M10 | Verified MVP | Each user story is green on Built · Mock E2E · Live E2E, and the Figma ↔ app parity galleries are clean | M9 | 🟡 in progress — the boards exist and are being driven down: product/user-stories.md + product/mobile-user-stories.md. Mock suite 2026-07-30: 203 passed · 36 skipped · 6 failed; live sweep 07-29..30 left a short blocker list (report store-select drift, /account save, hardcoded admin dashboard #239, hold-resume no-op). Parity: web round 2 merged 07-28, mobile pipeline landed 07-27 |
| M11 | Go-live | Production released; cutover runbook executed; flag kill-switches proven | M10 | ⚪ not started — prod-pipeline.yml + ci/prod/ are built but no release has ever run. Blockers are documentation and process, not code: cutover runbook #263 + its full-migration amendment #262, the FeatureFlags production ramp #264, the OWASP baseline write-up #266, and the Spanish manuals refresh #255 |
- M0 is complete (2026-06-22): the 43-ticket batch + 7 gap tickets are promoted to GitHub issues, the old TypeORM-era POS backend issues (#34–65) are closed as superseded, and
agent_meta.blocked_byis rewritten to same-repo issue numbers. - Implementation started (2026-06-28): the autonomous per-user loops are running sprint 32 unattended. The frontend design-system + shell foundations are done (web #43/#62/#77/#88, mobile #107), unblocking the screen set; first mobile features merged outside the Appwrite track — Notifications #87, Compose-state playground #17. A one-off remediation rewrote 38 issues’
blocked_byfrom unresolvable draft slugs to repo-scoped numbers (seeded issues had silently-blocking slugs — seeticket-conventions). Work is handed out byagentic plan assign, now automated on the monitor (monitoring.autoAssign). - POS web batch landing (2026-06-29): a sprint-32 wave of
terminales-webPOS screens merged — Stores, Categories & Tax Rates (catalog), Stock levels/movements, Sales Orders & Payment Intents (read-only views), Staff-shift Approvals audit, the Daily Sales reporting dashboard, and Web-Terminal PIN login + line-discount supervisor approval + lock/session. Mostly read-only / scaffolding views gated behindNEXT_PUBLIC_FEATURE_FLAG_*(web-terminal / pos-*), built mock-first (per-component*.mocks.ts; seeweb-data-layer). Coarse only — granular state on Project 11. - Auth + storage + catalog wave (2026-06-30): the first real Appwrite auth implementation landed across all three clients — the NestJS Appwrite token-validation guard (api #114,
src/auth/appwrite-auth.guard.ts, replacing the BetterAuth guard), mobile session/JWT handling (SessionManager,JwtAuthInterceptor,EncryptedSessionStorage, #119) + 2FA/forgot-password (email/SMS factors + recovery, #120), and web login (email/password + magic-link callback, #101). Appwrite Storage (file service + scoped file-tokens) landed on the API (#117). On web, the catalog (products + single-axis variants + barcodes, #95) and the backend cutover (posClientswapping mocks→real fetchers behind a flag, #116) advanced M2. This nudged M2/M3/M4 from not-started to in-progress; functions pipeline and the full data set remain. Seeappwrite+ ../business-rules/auth-and-multitenancy.md. - Migration + payments waves complete (2026-07-03): since 2026-06-30 the remaining ladder landed — api CI schema/functions deploy #122, data completion (store/terminal/audit #126, staff #129, inventory #136, sales #138, audit-wiring #131, tests #141), auth completion (invites #127, user-mgmt #130, PIN custom token #132), functions (scaffolding #128, hello-world #133), observability #144, reporting (daily sales #139, Z-report #142); web re-points to real Appwrite data (#130/#131, then #139) + the Vercel preview mock layer #136; mobile PIN login #124 + offline-first direct reads #125. The AngelPay card-payments wave merged 2026-07-02..03: api terminal pairing #137, routing fields #140, PSP adapter #145, multi-tender settlement #146, card-present checkout #147; mobile native card tender #129, terminal registration #130, remote payment listener #131 (web AngelPay #137/#138 still open). The decommission #143 merged 2026-07-03 with legacy controllers moved to the Appwrite guard (#148 via PR #150); BetterAuth module removal #149 is the last open API ticket.
- M6 was the production boundary, and it has been crossed (2026-07-24). Everything the pre-production regime forbade is now in force in reverse: migrations are the only DDL path for Postgres and versioned
appwrite.config.jsonthe only one for Appwrite (no console edits, nopsql), CI is on, and feature flags are real. Any doc that still reads “no flags / no migrations / Actions disabled except gitleaks” is describing the world before this date — including parts ofarchitecture-decisionsandopen-questions-and-todos, which carry inline corrections. - M6’s flag decision inverted the original plan. The plan was a dark ramp: flags default OFF, turned on gradually in production. On 2026-07-14 the PO directed that every flag be ON for MVP — all 21
NEXT_PUBLIC_FEATURE_FLAG_*interminales-web/.env.localplus the backend flags, including on stage. Flags stay runtime-capable (api #173 evaluator + an Appwritefeature_flagstable) so a post-go-live kill-switch is still possible; that ramp is ticket #264. - M7 is fully closed. #143 removed the entities and the auth stack, #149 (2026-07-04) removed the BetterAuth module/strategies, and #248 (2026-07-12) dropped the frozen tables by migration. The old caveat — “re-verify what remains of legacy TypeORM against #143’s diff” — is resolved: no
@Entityclasses remain;typeormsurvives inpackage.jsonsolely to runsrc/database/migrations/*. - MVP hardening wave (2026-07-06..09,
terminales-api): after the migration/decommission, a broad feature+hardening batch merged toward MVP: durable sales finalize + multi-tender settlement (DBOSfinalize-workflow) with thedaily_sales_rollupswriter; the MVP report suite (sales by employee/product/payment-method #178, voids & discounts, cash-movements) with CSV export + shared pagination; the notifications center API (#176); global search (#174); white-label merchant themes + receipt config (#185); a feature-flags evaluator (bucketing/audience #173 — the Epic-G mechanism only; tickets still shipfeature_flag: ""); and a security baseline — Redis rate-limit + lockout (#182), HTTP hardening (#183), sensitive-ops membership validation (#184), store role-scope authorization (#157). This is the API reaching functional MVP behind the stage env (M8); web/mobile counterparts continue on Project 11. See ../business-rules/reporting.md. - Wave 3 execution (sprints 33–34, 2026-07-11 → 07-30) — the largest wave so far, ~240 issues closed (api 53 · web 124 · mobile 63). Coarse shape: (a) feature completion — VAS screens, Clientes, merchant wallet + deposit channels, platform admin + impersonation, merchant onboarding, refunds, held orders, white-label, denomination close, inter-store transfer, role-scoped reports + CSV; (b) the design-system + parity build-out — a full atomic DS in both clients (web Playground + Playwright harness, mobile Maestro harness), 12 web flow-parity tickets and 7 mobile ones, then admin list/screen parity build-outs and a round-2 polish pass; (c) verification — the mock and live Playwright suites plus the two user-story boards. Granular state on Project 11.
- Design parity became a standing pipeline (2026-07-21 → 07-28). Both clients now regenerate a Figma ↔ app gallery from real screenshots and publish it for the client (
/design/parity/,/design/parity-mobile/). Web adds dated frozen snapshots underhistory/<date>/; mobile addsintentional-deviations.mdfor frames the app deliberately improves on. Seedesign-parity-playbook. - Mantarys (the VAS aggregator) is the last structural gap. Manual received 2026-07-23/26 → a 13-ticket, ~91 h, 4-wave plan. Folio derivation (#415), the request-transaction adapter (#416) and stage secrets/egress (#420) merged; 10 remain, two of them waiting on PO decisions (catalog tenancy, blocking-vs-async sale). Until then
VbAggregatorAdapteris a deliberate fail-closed 503 stub and VAS live specs are gated, not failing. - Sprint calendar (from
solution.yml, tzAmerica/Ciudad_Juarez): Sprint 31 = 2026-06-13→06-27, Sprint 32 = 2026-06-27→07-11, Sprint 33 = 2026-07-11→07-25, Sprint 34 (current) = 2026-07-25→08-08, then two-week sprints through Sprint 37 (ends 2026-09-19). Milestone-to-sprint assignment is set on Project 11, not here.
How to update this file
Section titled “How to update this file”When an epic completes, flip its milestone’s State and add the absolute date. Keep it coarse — do not list individual tickets here.