diff --git a/CLAUDE.md b/CLAUDE.md index 436c992..2fb120f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -43,7 +43,7 @@ distilled to what applies to HQ. A change that breaks one does not land. | Append-only audit | Every mutation calls `writeAudit(db, userId, action, entity, id, before, after)` in the **same transaction** as the change. The audit log is append-only — never update or delete rows. Previews and the public share route write nothing. | `audit.ts` | | Client id is the future tenant id | `client.id` is a client-generated UUIDv7 that becomes `tenant_id` when the cloud tier stands up — same rows, promoted once. Never re-key clients. | `repos-clients.ts` | | No silent caps | Every list that can grow paginates or warns; never silently truncate. | reports, directory queries | -| Strict TS, green before landing | Strict TypeScript everywhere; `npm run typecheck` and `npm test` both clean before anything lands. Money math is locked by tests — a rounding change without a test change does not land. | `tsc`, vitest (363 tests) | +| Strict TS, green before landing | Strict TypeScript everywhere; `npm run typecheck` and `npm test` both clean before anything lands. Money math is locked by tests — a rounding change without a test change does not land. | `tsc`, vitest (372 tests) | ## Running it @@ -66,7 +66,7 @@ cd apps/hq-web && npm run dev - Postgres integration tests: `HQ_PG_TEST_URL=postgres://hq:hq_dev@localhost:5432/hq_test npm test` (wipes that database each run — never point it at real data). - Health check: `GET /api/health` → `{ ok: true }`. -- Verified state: `npm install` + typecheck clean, 363 tests pass. Exercise real flows end +- Verified state: `npm install` + typecheck clean, 372 tests pass. Exercise real flows end to end before claiming done. ## Docs (kept in `docs/`) diff --git a/README.md b/README.md index 567e149..887fd25 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ document and conversation we've had with them. ## Build state (start here) -Working codebase, not a plan. `npm install` + typecheck are clean and **346 tests pass**. +Working codebase, not a plan. `npm install` + typecheck are clean and **372 tests pass**. Current state and run-vs-pending detail live in **[STATUS.md](STATUS.md)**; the go-live runbook (server, HTTPS, backups, Gmail/AWS/import wiring, the Postgres switch) is in **[docs/DEPLOY-HQ.md](docs/DEPLOY-HQ.md)**. diff --git a/STATUS.md b/STATUS.md index d8d76e1..0d175a6 100644 --- a/STATUS.md +++ b/STATUS.md @@ -25,7 +25,7 @@ section-per-module quotation PDF — then closed all 8 findings from its review. | --- | --- | | `npm install` | clean | | `npm run typecheck` (root + workspaces) | clean, no errors | -| `npm test` (`vitest run`) | **346 tests pass across 66 files** | +| `npm test` (`vitest run`) | **372 tests pass across 70 files** | The 346 figure is the live `vitest run` count measured 2026-07-17, after the D18 go-live cluster **and its post-delivery review pass** (8 reviewer findings diff --git a/docs/06-DECISIONS.md b/docs/06-DECISIONS.md index 6f2fd1b..940fed4 100644 --- a/docs/06-DECISIONS.md +++ b/docs/06-DECISIONS.md @@ -343,3 +343,26 @@ and NO migration — the founder's flexibility mandate, delivered. Built **addit D20 (login trio keeps its columns; retiring them into field_spec is a later cleanup after the direction is confirmed). Verified on the real re-import: RTGS 13 fields / SMS 6 / MobileApp 1, 53/53 RTGS + 102/105 SMS links carrying structured values. Suite 363 green. + +## D23 — SMS volume-band billing (dated rate card) ✅ DELIVERED (2026-07-17) +SMS packs are the majority of billing, so they get first-class quantity-tiered pricing. +`usage_rate_band` is a dated per-module rate card (generic — any usage-billed module can +have one). `resolveUsageRate(module, count, date)` picks the band with the highest +`min_qty <= count`; a count below the lowest band is under the minimum order. `buildLines` +resolves a line's unit price as: explicit per-line override > tiered rate card > dated price +book — so an SMS line prices by count automatically, a save below the minimum is refused, +and the live preview warns instead of throwing. Founder card seeded (effective 2026-04-01): +≥50k → ₹0.40, ≥100k → ₹0.37, ≥200k → ₹0.34, ≥300k → ₹0.30 per SMS, minimum 50,000 — money +locked to the paisa in tests (50k→₹23,600, 100k→₹43,660, 200k→₹80,240, 300k→₹1,06,200 incl +18% GST). Owner routes GET/POST /modules/:id/rate-card. Rates are integer paise; a new card +is a new dated set of rows, so issued invoices keep the rate they were billed at. + +## Catalogue additions (2026-07-17) — CloudBackup + RecoverX configured as data +Two recently-developed modules set up entirely as configuration (no code), proving the D20/ +D21 flexible model: **CloudBackup & Disaster Management** (8 fields incl. AWS creds as a +secret; subscription ₹36k/yr + setup ₹25k + integration ₹10k) and **RecoverX / Recovery +Module** (7 fields incl. CBS server IP, APEX URL, field-officer count, GPS consent, admin +secret; app ₹35k + implementation ₹10k + integration ₹5k + AMC ₹15k/yr). Quote content +seeded from the real quotations for the section-per-module PDF. + +Suite at 372 tests / 70 files after D21 + D23.