title: API (production): phase 1 design (Oct–Dec 2026) component: API level: phase period: sprints S2–S5 (1 Nov – 26 Dec 2026); S1 work carried in status: draft 1 (25 Oct) owner: MMDEP Design (Claude) decisions: TD-049, TD-050, TD-057 overall: api/overall.md queues: docs/prompts/api-lane-p/S2/QUEUE.md (P1–P4)
API (production): phase 1¶
1. Goal¶
By the end of phase 1 the production API is the secured, documented, honest door to MF data: write routes need keys, NAV has no duplicates, every route is in the contract, and MM-Cron writes only through it.
2. Baseline (collector, 25 Oct)¶
| Check | Value |
|---|---|
/api/health |
404 (missing) |
/api/schemes |
200, 10,008 schemes, ~4.0 s |
/api/scheme/nav?scheme_code=120245 |
200, 3,379 rows, 3 duplicate dates, one 10-day gap (Feb 2025), latest 23 Oct |
/api/index/nav?symbol=NIFTY 50 |
200, 2,723 rows, 10 duplicate dates, latest 23 Oct |
/category |
200, 180 categories; flags returned as 1 (to verify against the database, HO-18 #7) |
| Write routes | No key enforced; /save-nav key hard-coded in code (KN) |
| Contract | No OpenAPI, no data dictionary (HO-18 #1–2) |
3. Work streams and milestones¶
| Stream | S2 (1–14 Nov) | S3 (15–28 Nov) | S4 (29 Nov–12 Dec) | S5 (13–26 Dec) |
|---|---|---|---|---|
| A. Write security (P1) | Enforcement LLD (Claude reviews); keys issued per consumer; log-only on staging and production | Enforced on staging (day 1); enforced on production after 7 clean log-only days, Atul approves | Read-route rate limits and caching; non-public reads keyed | Old hard-coded key retired everywhere |
| B. NAV integrity (P2) | Read-only audit: duplicate keys and gaps for every scheme and index; writer root cause (with Lane S S5 inventory) | De-dup and persistence-contract LLD (Claude reviews); rehearsal on staging | Production de-dup and unique key, Atul approves; backup and rollback first | Freshness alert stable; gap report published |
| C. Release 2 (P3) | /api/health, /category stored flags plus effective menu tree, stale-connection fix, /api/index/nav and /api/nfos/active fixes from staging: one RC, MWMC and MCRM UAT, Atul approves |
— | — | — |
| D. Contract | OpenAPI draft from code (S4 Lane S); fund-factsheet contract (P4) for MWMC | Contract tests on stgapi in CI; data dictionary, catalogue tables | Dictionary, MF tables; every route in the contract | Breaking-change check in CI (contract diff) |
| E. Ingest routes (for MM-Cron) | Spec in the OpenAPI file: scheme, fund-details, holdings, AUM, TER, performance, NFO, index, run-log (TD-057) | Built and on staging; MM-Cron staging runs use them | On production with keys; MM-Cron production enabled family by family | Direct-write code paths removed |
| F. Holdings | — | New holdings read route on mm_portfolio / mm_portfolio_items; old route unchanged (TD-058) |
Consumers moved (MWMC fund pages) | Old route marked deprecated |
| G. Operations | Production release sha recorded; structured logs | Error tracking; backups verified, restore drill on staging (roadmap §3) | Incident runbook | — |
| H. APIs only | Direct-reader inventory complete (websites, plugins, webapp) | Missing read routes specified for the top readers | First website reads moved to the API (MWMC) | Plan for the rest (phase 2) |
Release cadence: one production release per sprint (S2 to S5), each a single RC MR from api-phase1-staging-release with evidence and consumer UAT. Security and data fixes ride the release; emergency fixes follow the same gate faster.
4. Ingest routes (TD-057)¶
One pattern for every MM-Cron record type, so MM-Cron's publisher has a single client:
POST /api/ingest/<type> type ∈ nav | scheme | aum | ter | performance | nfo | fund-details | holdings | index | runs
Header: X-MM-Key: <consumer key> (environment-specific; production rejects staging keys)
Body: { "run_id": "...", "source_id": "S6", "raw_sha256": "...", "schema": "mmcron/v1", "records": [ ... ] }
Reply: { "run_id": "...", "accepted": n, "unchanged": n, "corrected": n, "rejected": [ {"index": i, "reason": "..."} ] }
- Idempotent: a repeat of the same body gives
unchanged, never duplicates. - Corrections are recorded, not silently applied (TD-050).
- The reply is the API acknowledgement that closes MM-Cron's traceability chain (KN).
/save-navstays for existing callers. It becomes a thin alias of/api/ingest/navonce the P2 rule is in, so both follow one persistence rule.- Schemas come from the MM-Cron adapter schema (sprint-2 LLD), so they are defined once.
5. Interfaces that change¶
| Interface | Change | Breaking? | Consumers to check |
|---|---|---|---|
| All write routes | Key header required | Yes, for writers | MM-Cron, admin panel, staging loader, website forms (server side) |
/category |
Stored flags instead of 1; new effective menu tree | Possibly (flag values) | MWMC, WPDev, MCRM |
| NAV routes | No duplicate dates after P2; as_of added |
Additive plus a data fix | PE, MWMC, websites |
/api/health |
New | No | Collector |
/api/ingest/* |
New | No | MM-Cron |
| Holdings | New route; old unchanged | No | MWMC, PE |
6. Risks¶
| Risk | Impact | Mitigation |
|---|---|---|
| Key enforcement breaks an unknown writer (a form, a script) | Lost leads or stopped jobs | 7 days log-only: every unkeyed write is logged with its caller; enforcement only when the log shows none left |
| NAV de-dup removes the wrong row | Wrong history for funds | Audit first; rule decided per duplicate type; backup table; staging rehearsal; Atul approves; rollback script tested |
| Unique constraint on ~37M rows locks the table | API slow or down | Built on a copy then swapped, or added online off-hours; timed on staging first |
| Shared host: API, WordPress and stgapi compete | Slow pages | stgapi caps (TD-051); /api/schemes caching (4 s today) |
| Production runtime sha unknown | Unsafe rollback | First release records it, and keeps the previous artifact |
| One agent for Lane P and Lane S until API-2 | Throughput | Queues ordered by risk; low-risk items to the harness |
7. What "done" means for phase 1¶
- [ ] Every write route rejects calls without a valid key on production (log shows zero unkeyed writes for 7 days).
- [ ] Zero duplicate
(scheme_code, nav_date)and(symbol, date)in production; a unique key prevents new ones; the collector's duplicate column is empty. - [ ]
/api/healthreturns the release sha on production and staging. - [ ] Every route is in
docs/openapi.yaml; contract tests pass on stgapi in CI; the dictionary covers catalogue and MF tables. - [ ] MM-Cron writes only through
/api/ingest/*and/save-navwith keys. - [ ]
/categoryreturns stored flags and the effective menu tree, accepted by MCRM and MWMC UAT. - [ ] Every production release in phase 1 had an RC MR, evidence, UAT lines, a recorded sha and a rollback.