Work / Seedha Ghar / Wiki / Concepts
non-functional
Conceptcanonicalverified 2026-07-22
CONCEPT.NON-FUNCTIONALNon-functional — Regulatory, SLOs, observability, cost, open questions
The constraints that shape the architecture even though they're not user-facing. Regulatory context in ../product/regulatory.md.
Regulatory constraints (architectural implications)
PPI compliance (RBI, via Razorpay)
Rule: don't hold customer wallet balance long. Closed-loop PPI without a license is risky if balance sits.
Implication
- Weekly cron sweeps wallets with
balance > 0 AND last_activity < now() - 60d; sends a "use it or we refund" nudge. - Wallets untouched for 90 days are auto-refunded to the original source (Razorpay refund API), balance zeroed, wallet_ledger entry
reason='ppi_auto_refund'. - Ledger row cap per user: soft limit 10 000 rows before archival. Long-lived users don't hit this at ₹5 units.
DPDP Act 2023 (effective May 2027)
Rule: explicit consent per purpose, purpose limitation, data minimisation, breach notification, deletion-on-request, DPO if scaled.
Implication
- Every table with PII carries
consent_purposes text[]andcreated_at— enforced at the Drizzle schema layer. DELETE /meendpoint cascades to soft-anonymise (name, phone hashed; wallet ledger retained with user_id nulled — needed for accounting).- Photo retention: 30 days past
listing.state='removed_by_admin'ORsold_or_rented, then hard-deleted by a cron. Buyer's unlocked contacts survive asunlocksrows (anonymised owner) for audit. - Breach notification: any auth-log anomaly emits a Sentry event tagged
dpdp:breach-suspectand pages the DPO email within 72 hours.
RERA (per state; capture-only at MVP)
Rule: agents and builders need registration; individual owner rentals mostly exempt.
Implication
agent_nocstable withrera_agent_no,noc_url,verified_at. Populated forseller_agentrole only.- Reviewer UI (A03) surfaces RERA number and validates format per state (regex table in
packages/schema/rera.ts). - Commercial listings: reviewer must attach state RERA project ID or explicitly flag "under 8 units, exempt" before approve.
IT Rules 2021 (grievance)
Rule: 72-hour acknowledgement, named Grievance Officer, published contact.
Implication
- POST /complaints auto-sends a template email from
firodiya.ritesh@gmail.comwithin 60 seconds of file. - Public /grievance route on
apps/web— no auth wall. - All grievance-officer email replies are archived in R2 under
/grievance/<complaint_id>/.
GST
Rule: invoice per wallet top-up over ₹0.
Implication
- Every Razorpay-webhook-triggered credit generates a PDF invoice and mails to the user's email (email required before first recharge — CATALOG § Identity/KYC).
- Invoice numbering is monotonic per financial year — enforced by a Postgres sequence with a year prefix.
SLOs
Startup MVP scale. Numbers to defend, not to worship.
| Surface | Target | Measurement |
|---|---|---|
apps/web P50 TTFB |
< 300 ms | Vercel Analytics / Sentry web-vitals |
apps/api P50 latency |
< 50 ms | Cloudflare Workers Analytics + Sentry |
apps/api P99 latency |
< 400 ms | same |
| Wallet debit correctness | 100% (zero drift) | weekly reconciliation cron |
| Verification queue SLA | 48 h (CATALOG) | dashboard on A01, alert if backlog > 20 with oldest > 48 h |
| Complaint ack | < 72 h | dashboard + auto-page |
| Availability | 99.5% monthly (~3.6 h/month) | Better Stack uptime |
Deliberately not chased at MVP: five-nines availability, sub-100ms P99, real-time everything. These are Phase 3+ concerns.
Observability
| Signal | Tool | Free tier ceiling | Alert channel |
|---|---|---|---|
| Errors + traces (all surfaces) | Sentry | 5 K events/mo | Slack + email |
| Product analytics | PostHog Cloud | 1 M events/mo | dashboard only |
| Logs (structured JSON) | Better Stack | 3 GB/mo | Slack |
| Uptime + on-call | Better Stack | 10 monitors | Slack + phone (paid tier) |
| Wallet reconciliation | Custom cron in apps/api; posts to Sentry as wallet:drift if sum(ledger.delta) != wallet.balance for any user |
n/a | pager |
Trace propagation
- Sentry
trace_idis generated atapps/web/apps/mobileand forwarded assentry-traceheader on every API call. apps/apicontinues the trace and attaches DB spans via Drizzle instrumentation.- Queue jobs restart the trace by attaching the parent
trace_idfrom the enqueue site.
Cost ceilings (architectural budget)
If any subsystem approaches its ceiling, we redesign the subsystem, not raise the ceiling.
| Item | MVP ceiling | Reason |
|---|---|---|
| Total infra | ₹5 000 / month | Startup budget while validating |
| Cloudflare Workers | 10 M req/mo → $5 | Should cover 10 K MAU; if not, product-market fit is wrong shape |
| Neon Postgres | 10 GB DB, $19/mo Pro | Beyond this, archive listings older than 12 months to R2 (JSON dump) |
| R2 storage | 1 TB → ~$15 | Photo pipeline resizes and re-encodes to AVIF; each listing < 5 MB total |
| MSG91 OTP | ₹0.15 × 30 000 OTPs = ₹4 500 | 1 OTP per sign-in / phone change. If we exceed 30 K/mo we have real traffic; move the discussion. |
| WhatsApp (AiSensy) | ~$25 starter tier | Beyond this, batch notifications instead of per-event |
Open questions (block or shape step 4)
- Mobile map performance — does MapLibre native (
@maplibre/maplibre-react-native) render 18 polygons + labels smoothly on mid-tier Android? Test before locking. Fallback: WebView + MapLibre GL JS. - Reverse-image-search vendor — TinEye API ($200/mo starter), self-hosted CLIP embeddings (free but adds a worker), or Google Vision (pay-per-call, expensive at volume). Decide in step 6.
- Queue-worker cold start — Cloudflare Queues + Workers have a small warm-up cost. Confirm that photo-resize p99 < 30 s end-to-end (upload → resized variants visible). If not, split into a dedicated Cloud Run worker.
- RERA capture UX per state — each state's format differs. Decision: MVP validates only the four biggest (MH, KA, TN, DL) with regex; other states accept free-text with reviewer eyeball check. Revisit at 5-state scale.
- Session strategy on
apps/web— HttpOnly cookie set by Supabase Auth server helper on server actions vs bearer-token in-memory. Decision leaning toward cookie for web; bearer + SecureStore for mobile. Confirm in step 4. - Which Supabase Auth region — Mumbai (ap-south-1) preferred for latency; verify Supabase supports it on the tier we pick.
- Turnstile or hCaptcha on OTP request? MSG91 gets abused if we don't rate-limit. Cloudflare Turnstile is free and works well; recommend, decide in step 4.
Each item should be closed (decision + one-line rationale) before step 5 begins.