Action Items — from the marketing team’s 16 questions
What we need to do, surfaced by answering the team’s 2026-06-25 questions. Owner: Salil. Derived from
marketing-brief.md; each item links to the question it came from. Status: 🔲 not started · 🟡 partial · ✅ done. Priority: P0 now · P1 next · P2 later.
Product / engineering
| # | Action | Why (from) | Status | Pri |
|---|---|---|---|---|
| P1 | Confirm-before-partial processing. ✅ Built. Submit (and case-upload) now returns 409 with the shortfall and debits/stores nothing unless the user confirms; the app shows a “process partial / cancel” dialog and re-submits with confirm_partial=true. Server + client + tests done; spec updated in ../product/pricing.md. | Q12 + your call | ✅ | P0 |
| P2 | Partial-data warnings ✅ — the report carries a prominent “N of M pages” banner, and the Decision panel now shows a partial-statement warning (income/FOIR may be understated; the decision runs on incomplete data). | Q12 | ✅ | P1 |
| P3 | Low-credit nudges ✅ — the top-bar credit count turns amber under 20 and red at 0, with a Top up / Buy credits link to /credits. | Q11, Q12 | ✅ | P1 |
| P4 | Buy-credits CTA at truncation ✅ — an out-of-credits failure (402) now shows a Buy credits button to /credits (plus the always-visible top-bar nudge). | Q12 | ✅ | P1 |
| P5 | Auto-recharge + larger packs (₹5k/₹10k) — NBFCs/fintechs burn a ₹2k pack fast (a 50-borrower NBFC ≈ ₹15k/mo). Key retention lever. | Q11 | 🔲 | P1 |
| P6 | GST invoicing + org billing profile once past the ₹20L threshold / an enterprise buyer needs it. | Q11, pricing | 🔲 | P2 |
| P7 | Tamper / forgery detection — the #1 gap on our own scorecard (Precisa/Perfios/Ocrolus have it). | Q10 | 🔲 (roadmap #2) | P1 |
| P8 | Case-level decision as the primary unit + decision-packet PDF + borrower intake link. | Q2 | 🟡/🔲 | P1 |
Console UX — uploads, statements, search/filters
Full design + decisions: ../product/uploads-and-statements.md.
| # | Action | Why | Status | Pri |
|---|---|---|---|---|
| U1 | Server search + filters on /v1/statements ✅ — q (holder/bank/id), status, bank, risk_band, upload date range, partial-only; JSON-path filters so holder/bank/risk_band need no migration, and total reflects the filter. Reusable client FilterBar wired into the Statements view. Server tests added (286 pass); app typechecks clean. | No list had search/filters; failed parses sat among real statements | ✅ | P1 |
| U2 | Split into Recent Uploads (all statuses, operational) and Statements (done-only, library) ✅. Recent Uploads shows who-uploaded + outcome (complete/partial/failed+reason) + download original; Statements is the done-only searchable library with per-row report download. Shared useStatementList hook; new /uploads route + sidebar link. | Failed/in-flight pollute the statement library; the two answer different questions | ✅ | P1 |
| U3 | ”Uploaded by” attribution ✅ — Job.uploaded_by_user_id column + migration; Bearer user captured at submit (API-key uploads → “API”); uploaded_by_email exposed + filter. | The only schema change; jobs were org-level | ✅ | P1 |
| U4 | Per-row “Download report” (PDF) on Statements ✅ and download original on both lists. | Direct user ask | ✅ | P1 |
| U5 | Retry a failed upload ✅ from Recent Uploads — re-runs from the retained raw (within TTL; else 409 “re-upload”), no re-charge since those pages were already paid. Server POST /v1/statements/{id}/retry + button; tested. | No retry existed; failed jobs were dead-ends | ✅ | P2 |
| U6 | Search/filters on every list ✅. Statements (+ CSV export honoring filters), Recent Uploads, Cases (borrower/ref + status), Queue (product/job-id search + status), Team (email search + role/status) — all via the shared FilterBar. | Consistency across all lists | ✅ | P2 |
| U7 | needs_review resolve UI ✅. Held reports show each flag with its severity, a “View original” button (opens the uploaded statement to check flags against the source), then accept-and-release. Remaining (larger, separate): an editable-ledger correction path — the release API replaces the whole transaction ledger, so that needs a full table editor, deferred. | Flagged 🔲 in features.md | ✅ | P1 |
| SEO | WebSite JSON-LD added ✅ so Google shows “Obsrv” as the site name above the URL instead of the bare domain. | Search result showed obsrv.in, not a site name | ✅ | P1 |
SEO / web (for the blog + organic)
| # | Action | Why (from) | Status | Pri |
|---|---|---|---|---|
| S1 | /blog section built ✅ — index + [slug] routes on the marketing site, reading the 10 docs/blog/*.md drafts (gray-matter + marked), per-post metadata, on-brand prose, Blog nav link. Verified: builds clean, all 10 posts + index prerender. Remaining: publish/announce on a cadence (~1/week). | Q15 | ✅ | P1 |
| S2 | Dynamic sitemap ✅ + BlogPosting/BreadcrumbList JSON-LD ✅ + OG share images ✅. OG cards are generated as a next/og component template (one branded card, no image files to maintain) for the site default, blog index, and each post. Verified: every page’s og:image renders a PNG. | Q13 | ✅ | P1 |
| S3 | Expand the customer-problems bank to 500+ via the documented modifier/Search-Console method once the blog is live. | Q14 | 🔲 (250 seeds ✅) | P2 |
Marketing / GTM (guardrails + targeting)
| # | Action | Why (from) | Status | Pri |
|---|---|---|---|---|
| M1 | Do NOT claim “tamper/forgery detection” in any copy. Say “every number reconciled and computed deterministically; doctored totals/balances don’t pass; uncertain items flagged for a human.” Re-check the site + decks. | Q10 | 🔲 (guardrail) | P0 |
| M2 | Target ICP subtypes in order: small NBFCs + DSAs first, then CA firms / early fintech. | Q3 | 🔲 | P1 |
| M3 | Enforce the orgs-to-avoid list in lead qual (no predatory loan apps, no “make the credit decision,” no big-bank RFPs, no B2C). | Q4 | 🔲 | P1 |
| M4 | Treat international (UAE) as post-PMF — no campaigns yet; localize domain policy + bounce taxonomy first if we probe. | Q5 | 🔲 | P2 |
| M5 | Use the competitor-people list for competitive watch; confirm departed execs (FinBox/CRIF) before any outreach; note Precisa = Finezza’s product. | Q16 | ✅ (list done) → use | P1 |
Handbook / ops (from this build)
| # | Action | Status | Pri |
|---|---|---|---|
| H1 | handbook.obsrv.in is live ✅ (DNS + Vercel root handbook + Deployment Protection). | ✅ | P1 |
| H2 | docsRepositoryBase set ✅ to the real repo (salilchincholikar/obsrv.in) so “Edit this page” links resolve. | ✅ | P2 |
Open decisions this raises
Auto-partial vs confirm-before-partialDecided + built (2026-06-25): confirm. The submit/case-upload endpoints gate partial processing behind explicit consent (409 → confirm → re-submit); nothing is charged until confirmed. Spec:../product/pricing.md§Partial processing.- “500 problems” framing: quantity is not the goal; prioritize by volume/intent. Treat the 250-seed bank as the working set.