Skip to content

26.0.1 — Scope ​

Status: 🟡 scoped, re-based for the consumer delivery · Target: 2026-09-10 · Scope freeze: 2026-09-07 · Type: train_biweekly

RE-BASED 2026-09-04 BY OWNER DECISION — READ THIS BEFORE THE SECTIONS BELOW

The owner's instruction was "rebase 26.0.1 completely for Consumer side delivery and release". 26.0.1 keeps its version number because nothing has ever shipped through this system — the production state page says so, and it names 26.0.1 as the release that will be recorded there first. Opening a 26.0.2 would have created two release records for one production deploy, which is the duplicate-source-of-truth class this repo has already paid for once (QRS-249).

Gates G0-G5 are all reset to pending and approvals is empty. G0 had passed for a different release; G4 binds an approval to a commit SHA and a manifest hash, so inheriting a pass for work this record no longer describes would defeat the mechanism rather than save a step.

The change manifest was NOT emptied, and that is deliberate. Its 121 records declare work that is in the repo and therefore deploys with this release — see The carried baseline below. Deleting them to make the record read as purely consumer would UNDECLARE real production changes, which is what the sixth rule forbids and what deploy-prod.yml refuses to apply.

The previous scope is preserved verbatim from Objectives onward as the superseded record.

What this release delivers ​

The plan of record is consumer/end-to-end-plan.md, approved 2026-09-04: §1 every design artboard with a disposition, §3 features F1-F18, §4 tables/RPCs/EFs by status, §10 the architect review R1-R38, §11 phases P0-P9, §12 the decisions adopted.

  1. Ship the CONSUMER product: a person signs in by WhatsApp OTP, claims their permanent qrsetu.com address, builds a Marriage Biodata, publishes it, releases it to named people, and a family reads it in the app or in a browser — every step against a real backend, no stubs in the path.
  2. Ship the surfaces that make that reachable rather than merely present: the consumer tab bar and centre button (there is none today), the round-40 identity home, Scan and verify, the eight Account views, notifications, the two personal QR makers, and the participant half of Meetings.
  3. Ship the marketplace OFF, and off means ABSENT — no "coming soon" tile ever stands in for a section, so this release needs no marketplace backend at all.
  4. Carry the merchant backend built ahead of this release to production for the first time. It is not this release's deliverable, but it is in the repo and it deploys with it, so every one of its change records stays declared. See 00-scope.md, "The carried baseline".
  5. Be the first release to reach production through the governed path, and prove the path by using it.

Scope items ​

Every row is an existing tracker id; the release gate verifies that on every run — and found a real defect doing so on 2026-09-04, since it had been matching exactly three digits and could not see a four-digit id at all (QRS-1041).

IdWhat this release delivers for it
QRS-1017Screen ledger re-transcribed from design round 40 so the printed count is true
QRS-1024Five unregistered consumer artboards written back to the design registry
QRS-981Android upload keystore — the release build is debug-signed today
QRS-1013Two Meta UTILITY templates submitted (biodata subject notice, meeting update)
QRS-917primary_context reaches the server at sign-up, so a consumer is not provisioned as a merchant
QRS-936auth.users.phone carries its E.164 + prefix
QRS-998The account is created on OTP VERIFY, not on send
QRS-909delete_account becomes a soft delete with a documented, tested cascade
QRS-1016manage-media gains an owner scope — a consumer cannot upload anything today
QRS-1019BOTH media constraints widened together (scope XOR and purpose-matches-scope)
QRS-1018feature_grants gains its exactly-one-scope CHECK, via the architecture-change protocol
QRS-1020Reserved route segments single-sourced and bound to the SQL seed by a test
QRS-921Rate limiting for anonymous reads and access requests
QRS-1033Biodata backend: schema, manage-biodata, biodata-read
QRS-1027Consumer chrome: tab bar, centre button, More sheet, header
QRS-1006ConsumerHome rebuilt on the round-40 identity-hub stack
QRS-990The consumer-home parity contract closed out against round 40
QRS-1028My QR setu, the identity home
QRS-1029Marriage biodata: the editor
QRS-1030Marriage biodata: people and access
QRS-1031Marriage biodata: the in-app reader
QRS-1032Marriage biodata: the public page and the /<slug> greeting (apps/web)
QRS-1034The BrandQr primitive, sharing and deep links
QRS-1035Scan and verify, on the existing scanner shell
QRS-1008The dead /consumer/scan link resolved by the screen that belongs there
QRS-1036Consumer account: the eight views
QRS-1037Consumer notifications: new kinds and per-account read state
QRS-1011Notification read state moves from the device to the account
QRS-1038Personal QR makers: Wi-Fi and Link
QRS-1039Meetings, the participant half
QRS-1015manage-chat — the chat write path that no Edge Function provides today
QRS-992The identity QR encodes the build environment origin instead of a hardcoded one
QRS-924Marathi reviewed by a human across every consumer namespace
QRS-1021Decision: "message the family" routes to WhatsApp at launch (D-v)
QRS-1022Decision: the Link maker ships static, with a design copy correction (D-s)
QRS-1023Decision: only In app and WhatsApp are shown as channels (D-p)

The carried baseline ​

The merchant backend was built before this re-base and ships in the same deploy. It is no longer this release's deliverable, so it has left scope; it has NOT left the change manifest, because the code is in the repo and will be applied to production. Both statements have to be true at once, and keeping them in two different places is what lets them be.

QRS-304 · QRS-305 · QRS-306 · QRS-307 · QRS-308 · QRS-309 · QRS-310 · QRS-311 · QRS-312 · QRS-313 · QRS-314 · QRS-315 · QRS-316 · QRS-317 · QRS-318 · QRS-319 · QRS-320 · QRS-321 · QRS-322 · QRS-249 · QRS-301 · QRS-303 · QRS-299 · QRS-537 · QRS-538 · QRS-539 · QRS-542 · QRS-543 · QRS-551 · QRS-555 · QRS-554 · QRS-559 · QRS-560 · QRS-561 · QRS-566

⚠ Do not read this list as "already in production". Nothing is. It is work that is finished on Dev, declared in 01-change-log.md, and reaching production for the first time with the consumer launch. G3 owes it the same evidence as anything else in the manifest.

What is deliberately NOT in this release ​

  • The marketplace, and off means ABSENT. The design's own default drops every market: true section, so no "coming soon" tile ever stands in for one and the release needs no marketplace backend at all. Item feed, vendor feed, item view, vendor view and the order code stay in the tree reachable from a scanned code, and nothing in the approved navigation links them.
  • Meetings HOSTING. The participant half ships; minting a room needs a Zoom account model and a Marketplace review with no SLA (QRS-1014). The connect gate renders as not connected rather than as a dead control.
  • The intro card, My progress, the UPI and Photos makers, chat media and voice. Each is designed and each is deferred for a stated reason in the plan's §1 and §12, not for want of a design.
  • Push notifications, SMS and email. There is no token table, no sender and no channel. They are rendered ABSENT on the availability axis rather than as toggles that persist a preference nothing reads.

Superseded — the original vendor-money-loop scope, kept verbatim ​

THIS SECTION IS THE PREVIOUS RECORD, NOT THE CURRENT SCOPE

Everything below described 26.0.1 before the 2026-09-04 re-base. It is kept because a release scope is a log: superseding it with a banner preserves why the earlier decisions were taken, while editing it away would destroy the only record of them. Read What this release delivers above for what is actually in scope.

Objectives ​

  1. Ship the complete vendor money loop. A merchant signs up, builds a Setu Card, lists what they sell, publishes, shares it — and a customer opens the card and pays. Every step against a real backend; no stubs in the path.
  2. Deploy 15 Aug with payments dark; activate by 20 Aug via the kill switch.
  3. Establish a governed, auditable path to production and prove it by using it.
  4. Reconcile the branch model so deploy-prod can run at all.

Scope ​

23 items. Every one references an existing QRS-### — releases never mint their own ids, and check:release verifies each exists in the tracker.

QRSItemOwnerAcceptance criteriaDepends on
QRS-299Manifest-hash scope fixmaintainerUpdating targets[] mid-deploy leaves the approval intact; editing scope[] voids it. Both directions tested. Done 2026-08-03, 15 tests.—
QRS-301reserved_slugs Prod↔Dev reconciliationmaintaineris_slug_reserved blocks privacy/mumbai/zomato and allows a real merchant slug, on both projects. Dev done 2026-08-03.—
QRS-249Prod taxonomy promotionmaintainerget_business_domains() returns the full set against Prod, and onboarding's industry step renders on a device pointed at ProdCR-01
QRS-303verify_jwt corrected on Type A EFsmaintainerA request with no Authorization header is rejected at the gateway, proven by a live probe—
QRS-304apps/web workspace + PRODUCTION_PATHSmaintainerapps/web builds and deploys; a change under apps/web/** fails check:release without a Change Record—
QRS-305Request-scoped Supabase clientmaintainerTwo concurrent SSR requests cannot observe each other's session. Three-surface device pass on apps/mobile, which shares the seam—
QRS-306Cloudflare Pages + DNS + SSL + deploy workflowmaintainerqrsetu.com serves the landing page over HTTPS; the deploy workflow has a public_web componentQRS-304
QRS-307Public Setu Card SSR + OG + landing + order listmaintainerPasting a real card URL into WhatsApp renders title, description and image. Not a unit testQRS-304, QRS-305, QRS-308
QRS-308is_published + publish toggle + profileService realmaintaineris_published=false ⇒ 404; toggle on ⇒ 200. pgTAP updated. No backfill—
QRS-309Catalog — extend profile_items + item_media + manage-itemmaintainerA merchant's items render publicly on the card; availability_status gates purchasability—
QRS-310Catalog editor, merchant-sidemaintainerAdd/edit/delete an item with a photo, verified on all three surfacesQRS-309
QRS-311_shared/webhook.ts HMAC kitmaintainerSignature verification proven against a real Razorpay payload; a tampered body is rejected. ADR-0002's false claim corrected—
QRS-312Money data modelmaintainerCHECK (gross = vendor + commission) holds; pgTAP proves anon cannot read order or payout tables—
QRS-313create-payment-link EFmaintainerA tampered amount is rejected; the order row exists before the customer pays; reference_id = order UUIDQRS-309, QRS-312
QRS-314razorpay-webhook EFmaintainerKilling the webhook mid-flow still leaves a complete order row; duplicate events are idempotent; a commission mismatch raises a P1QRS-311, QRS-312
QRS-315Payments kill switchmaintainerDemonstrated flipping on and off without a deploy. Ships before the first rupee—
QRS-316Anonymous order write via the WorkermaintainerThe order EF rejects a request without the Worker's shared secret; Turnstile blocks a scripted POSTQRS-306, QRS-313
QRS-317Reconciler EF + cronmaintainerProven to find a deliberately dropped webhook. Cron works on Dev, i.e. the project-URL hardcoding is fixedQRS-312
QRS-318money_health + non-email alertingmaintainerA zero-webhook hour raises an alert on a channel that is not emailQRS-312
QRS-319Banking/Payouts module + API onboardingmaintainerA vendor self-onboards a payout account end to end; the full account number is never persisted; only activation_status='activated' enables the pay button, checked against the APIQRS-311
QRS-320Open-self-serve obligationsownerPrivacy, terms and a named grievance officer are published and reachable before the first public signup; report-abuse works; the takedown runbook is written—
QRS-321Card analyticsmaintainercard_viewed is recorded for a real card view, counted in the SSR loader — no public write endpointQRS-307
QRS-322Festival Vendor discovery + G-D gatemaintainerGate proven negatively: a domain_scoped item with no doc ⇒ exit 1 naming the vertical; add the doc ⇒ exit 0—

Divergence-seam check (QRS-297) — asked at G0, not at G3 ​

The platform-exception path is retired, so an item that turns out to be unbuildable on one surface blocks the whole release. Every seam this release touches, with its per-surface answer:

SeamAndroidiOSWeb PWA
Image upload (QRS-310)native pickernative picker<input type="file">
Share card (QRS-307)RN ShareRN Sharenavigator.share → clipboard fallback
Copy link (QRS-307)⚠ expo-clipboard is not a dependency — surface its weight before addingsamenavigator.clipboard
Open card / deep link (QRS-307)expo-linkingexpo-linkingwindow.open
QR displaypure-JS encoder through the already-bundled react-native-svg — not a seamsamesame
Camera / QR scannot in scope this release——

Notification permission and geolocation are deliberately NOT in this release — they belong to onboarding completion (QRS-326), which is 26.0.2 scope. Web is an honest no-op for notifications (createPort.ts) and there is no expo-location dependency, so both need a recorded per-surface answer before that work starts rather than during it.

Success criteria ​

Release-level and measurable, checked at G5.

  • [ ] A merchant completes signup → card → catalog → publish → share, and a customer opens qrsetu.com/<slug> and sees it render server-side with a correct WhatsApp preview
  • [ ] A real payment reaches a real vendor's real bank account, split by Route, and the vendor sees the order in the app
  • [ ] Payments activated by 2026-08-20 by flipping the kill switch — no deploy, no gate, no review
  • [ ] The reconciler finds a deliberately dropped webhook; a zero-webhook hour alerts off-email
  • [ ] A KYC-inactive vendor cannot accept payment, asserted against the API status
  • [ ] pgTAP proves anon cannot read any order or payout table
  • [ ] Three-surface parity verified per feature as it is built, not batched at G3
  • [ ] Privacy, terms and a named grievance officer published before the first public signup
  • [ ] Prod and Dev agree on migrations, functions, RLS policies and reference data — re-run the 2026-08-03 drift fingerprint

Milestones ​

DateMilestoneGate
2026-08-03Scope agreed — roadmap reconciled into RMSG0 ✅
2026-08-12Scope freeze — only P0/P1 defects in accepted scope after thisG1
2026-08-14Code complete / RCG2
2026-08-15UAT + readiness review, three-surface parity evidence assembledG3
2026-08-15Go/no-go — recorded in a separate session from the requestG4
2026-08-15Deploy. Store loop public, payments DARK—
2026-08-18Live ₹1 settled into a real bank account—
2026-08-20Payments ACTIVATED via kill switch — no deploy—
2026-09-03Closure after the 48h observation window + follow-up release cutG5

Scope-change log ​

Every request that arrived after G0, accepted or not.

DateRequestTriggers firedDecisionRationale
2026-08-03Banking module as core product surface, API payout onboardingnew migration · new EF contract · per-platform behaviour · store policyacceptOwner decision. Open self-serve makes manual linked-account creation unworkable — there is no bounded cohort to hand-create for. Cost +0.75d and it retired the manual-onboarding fallback, leaving one slip lever.
2026-08-03Fully open self-serve publishing at launchconsole-only class · new EFacceptOwner decision. Cost was ~0.9d rather than the ~3d first estimated, because reserved_slugs, is_slug_reserved, the write-once trigger and 12 pgTAP assertions already existed. The real cost is the owner-track grievance officer.

Out of scope ​

Named explicitly, so "we forgot" and "we decided not to" stay distinguishable.

Deferred to 26.0.2 — this is the release's only slip lever ​

The four stub retirements are the only scope not on the vendor money loop, which is exactly why they are out rather than in. Total 3.5 work-days.

ItemDestination
QRS-323 settingsService real26.0.2 (~3 Sep)
QRS-324 accountService real — ⚠ holds Apple 5.1.1(v) account deletion26.0.2
QRS-325 remindersService real — blocked on QRS-28626.0.2
QRS-326 Onboarding completion26.0.2

Why they are out from the start rather than cut later

Scope is ~32.25 work-days against 18 calendar days — ~1.79× against a stated pace of 1.5×, a gap of ~5.25 days. release.json has no state for shipped-minus-four-scope-items; partially_deployed covers targets, not scope; and dropping accepted scope after G1 re-hashes the manifest and voids the G4 approval (QRS-299).

So declaring them out now is what makes the slip valve expressible at all. If the pace holds they get pulled forward — which is a normal scope-change-log entry. Adding them back under date pressure after G1 is the thing this structure exists to prevent.

⚠ QRS-324 is not freely deferrable if iOS submits — in-app account deletion is an Apple review requirement. Either it comes back into 26.0.1 or iOS does not submit in this release.

Not in this release at all ​

ItemWhy
Admin panel + RBAC26.2.0. ADR-0006 is 0% built and it is the real cost. Until then, takedown is a documented SQL runbook
Desktop DOM merchant layout26.3.0. R1 merchants are phone-first; building it now buys nothing and costs a fortnight
Leads · Chat · Contacts26.4.0-26.5.0
Real dashboardNeeds the ADR-0010 read model. Stays on demo data, honestly labelled via the existing isDemoData → DemoChip mechanism
Email OTPBlocked at the SMTP layer (QRS-285). Google sign-in is the only auth path
Refunds, disputes, reversals in code26.1.0. Deliberately manual in v1 with a written runbook — that is what makes safe payments buildable in this window at all
Advance-hold (on_hold)Not available at payment-link creation; settlement-hold is a post-payment PATCH. A stall vendor taking an advance wants the money now
Digital Menu, billingR2 scope / ADR-0002
The 9 orphan Feedback-Forms Edge FunctionsLive in Prod with no source in the repo (QRS-302). Recovery is tracked; conformance is not R1 work
Feature flags (QRS-296)26.2.0. The payments kill switch covers this release's one need