Readiness Framework — Interactive Criteria Scorecard
Framework v3.0 · audits of 31 July 2026 · click any pillar to expand its criteria.
ND = NodeDough · composite 4.2/10 · not cleared for paid launch F8 = FedM8 Scan · composite 5.00/10 · not cleared for paid launch
ND = NodeDough · composite 4.2/10 · not cleared for paid launch F8 = FedM8 Scan · composite 5.00/10 · not cleared for paid launch
How to read this. Each pillar expands to its individual criteria from the v3.0 framework. Every criterion carries the
AI's 1–10 rating per project with the evidence behind it, from the 2026-07-31 audit runs
(NodeDough · FedM8).
Rubric anchors: 1–3 absent · 4–6 partial / manual / untested (no evidence caps at 6) ·
7–8 implemented + tested + evidenced · 9–10 automated, monitored, verified <90 days.
Pillar scores are the audited values; criterion ratings are the AI's decomposition of the same evidence — where the audit
could not see (e.g. FedM8's CI, dependency scanning), the rating reflects absence of evidence, not confirmed absence.
Go-live gate (T1): every pillar ≥ 6 and Security, Billing, Legal ≥ 7. ND fails on Billing 3 · Legal 2 · Obs 4 · Funnel 4 · Retention 3 · Support 3. F8 fails on Billing 4 · Legal 5 · Obs 4 · Funnel 4 · Retention 3 · Pricing 5 · Support 3 (Security passes at 7).
Go-live gate (T1): every pillar ≥ 6 and Security, Billing, Legal ≥ 7. ND fails on Billing 3 · Legal 2 · Obs 4 · Funnel 4 · Retention 3 · Support 3. F8 fails on Billing 4 · Legal 5 · Obs 4 · Funnel 4 · Retention 3 · Pricing 5 · Support 3 (Security passes at 7).
1 Reliability & Infrastructure 15% ND 5F8 6 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| Reproducible deploys via CI/CD; no manual prod changes | T1 | 7 | Railway deploys from GitHub main automatically; both domains attached. | 5 | GitHub Pages deploys on push; CI/branch protection unassessed (no repo access in audit) — capped on absent evidence. |
| Rollback tested, not just documented | T1 | 3 | No rollback drill on record. Railway redeploy-from-source exists but untested as a procedure. | 3 | No rollback drill on record for Pages or the database layer. |
| Automated DB backups + restore actually tested | T1 | 4 | Supabase automated backups exist; a restore has never been drilled. | 4 | Supabase backups exist; 692,699 award rows never proven recoverable — restore drill explicitly recommended. |
| Health checks + auto-restart on the platform | T1 | 2 | No healthcheck path configured on the Railway service. | 6 | Static origin on GitHub Pages/Fastly — platform-managed; no app-level check exists or is needed at this tier. |
| Staging environment matching prod | T2 | 2 | None. main deploys straight to production. | 3 | No staging evidenced; single production surface. |
| Defined RTO/RPO; DR runbook exercised | T2 | 1 | Not defined, never exercised. | 1 | Not defined, never exercised. |
| Multi-AZ/region, or documented acceptance of single-point risk | T3 | 2 | Single region, risk not documented. | 2 | Single origin + CDN; risk not documented. |
| Infrastructure as code | T3 | 3 | railway.json pins start/healthcheck config only; the rest is dashboard state. | 3 | Pages config in repo; Supabase config is console state. |
2 Security & Compliance 15% ND 6F8 7 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| Auth via proven provider/library; MFA available; session expiry | T1 | 6 | Supabase Auth (proven provider) ✓; MFA not offered; session expiry platform defaults. | 6 | Supabase Auth ✓; MFA not offered; authenticated flows not live-exercised in the audit. |
| Secrets in a manager — never in code or client bundles | T1 | 7 | Railway variables / Supabase stores; only the publishable key reaches the browser. | 7 | Only the publishable key in the client bundle; no secret-prefix matches in served assets. |
| OWASP Top 10 pass incl. per-endpoint authz (IDOR) | T1 | 5 | Anon-callable SECURITY DEFINER RPC surface found 07-31; checkpoint-family EXECUTE revoked from anon same day. No structured scan. | 8 | Every negative test as anon denied: opportunities, prime_awards, opportunity_documents, vet_directory all permission-denied; RLS-filtered tables returned empty arrays (correct signature). |
| TLS everywhere; security headers (CSP, HSTS) | T1 | 5 | TLS via Railway ✓; security headers not evidenced. | 3 | TLS ✓, but all six headers absent (HSTS/CSP/XFO/XCTO/referrer/permissions) — structural to GitHub Pages. Plus no SRI on the one external script holding the session (highest-risk finding). |
| Dependency scanning + patch cadence | T1 | 2 | None configured. | 4 | Unassessed — no repo access; capped on absent evidence. |
| Row-level security / tenant isolation verified with negative tests | T1 | 7 | RLS on all 16 tables; impersonation probes run 07-31 asserting effects, not just exceptions. | 9 | RLS verified with negative tests across the surface; my_plan() non-forgeable; vet_directory opt-in + field-masked + paywalled — correct SECURITY DEFINER use. |
| Least-privilege access for humans and services; offboarding | T2 | 5 | View write-grants and TRUNCATE revoked 07-31; dead-grant sweep run; offboarding process none. | 6 | is_admin closed at the privilege layer (no UPDATE grant) ✓; dead anon INSERT/UPDATE/DELETE grants remain on 3 tables; billing.* RLS-off mitigated only by exposed-schemas setting. |
| Pen test or structured external review | T3 | 3 | This AI audit is the only structured review. | 4 | This AI audit is the only structured review; deeper than NodeDough's (function bodies + grants read). |
| SOC 2 / ISO track if buyers ask | T3 | 1 | Not on the roadmap. | 2 | Not on the roadmap; likely to matter for gov-adjacent buyers. |
3 Observability & Operations 10% ND 4F8 4 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| Structured, centralized, searchable logs — no PII/secrets in logs | T1 | 4 | Railway platform logs only; not structured, retention short, PII posture unreviewed. | 3 | No centralized app logging; static origin logs not accessible. |
| Error tracking with alerting (Sentry-class) | T1 | 1 | None. | 1 | None — zero analytics or error tooling matches in source. |
| Uptime monitoring from outside your infra | T1 | 2 | None for nodedough.com. | 2 | None evidenced for scan.fedm8.com. |
| Alerts tied to user-facing symptoms | T2 | 1 | No alerting at all. | 1 | No alerting at all. |
| Metrics dashboard: latency, error rate, saturation, traffic | T2 | 2 | Railway service metrics only. | 2 | Fastly cache stats only, not surfaced. |
| Incident process: severity levels, runbooks, postmortems | T2 | 2 | None written. | 2 | None written. |
| Distributed tracing where warranted | T3 | n/a | n/a — single service, not warranted at this scale. | n/a | n/a — static + Supabase, not warranted. |
4 Performance & Scalability 10% ND 5F8 6 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| Load test at 3–5× expected launch peak | T1 | 2 | Never run. | 3 | Never run; DB-side capacity unknown under load. |
| Core Web Vitals green on key pages | T1 | 4 | Not measured — no evidence either way (capped). | 8 | Landing: 31 ms TTFB, 294 ms full load, 6.3 KB transfer — measured in audit. |
| DB indexed for hot queries; no N+1 on hot paths | T1 | 5 | PK/FK indexes present; no hot-query analysis on record. | 6 | Pre-aggregated rollups (award_naics_state, 605 NAICS codes) show deliberate design; no formal query analysis. |
| CDN / static asset caching | T1 | 4 | Railway direct serve; no CDN. | 8 | Fastly CDN caching confirmed working. |
| Rate limiting on auth, API and checkout | T1 | 3 | Supabase platform defaults only; nothing app-level. | 3 | Supabase platform defaults only; nothing app-level. |
| Horizontal scaling path documented and tested | T2 | 2 | Undocumented. | 3 | Static tier scales by default; DB path undocumented. |
| Capacity planning reviewed quarterly | T3 | 1 | Never done. | 1 | Never done. |
5 Billing & Subscription Infrastructure 15% ND 3F8 4 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| Billing via Stripe / Paddle / Chargebee — never custom | T1 | 1 | No processor integrated; upgrade is “Coming soon”. | 5 | Stripe integrated and well-architected, but has never run — 0 webhook events, 0 checkout attempts, both stripe_price_id NULL so checkout cannot open today. |
| Every webhook handled (created / paid / failed / canceled / changed) | T1 | 1 | No webhooks exist. | 4 | Handler exists (verify_jwt:false is correct for Stripe), but signature verification and event coverage unconfirmed — code review required before first charge. |
| Webhook handlers idempotent — replay-tested | T1 | 1 | n/a — nothing to replay. | 5 | Idempotency by primary key on Stripe event id + attempts counter — right design, replay never exercised. |
| Full lifecycle tested: trial→convert, up/downgrade, cancel, resubscribe | T1 | 1 | No lifecycle exists. | 2 | Untested end to end; framework requires a test-mode run as evidence. |
| Entitlements enforced server-side; plan change reflects in seconds | T1 | 7 | assert_paid_feature gating in the DB — the right shape, confirmed in audit. | 8 | my_plan() reads auth.uid() + subscriptions, non-forgeable; negative-tested as anon (returned “free”). |
| Tax handling for actual sales jurisdictions | T1 | 1 | None. | 2 | Not configured; Stripe Tax not enabled. |
| Dunning: retries, card reminders, update-payment prompts | T2 | 1 | None. | 1 | None. |
| Grace periods + involuntary-churn recovery | T2 | 1 | None. | 1 | None. |
| Billing state reconciliation job — DB vs processor truth | T2 | 1 | None. | 2 | rejected_client_price status shows server-side price resolution; no reconciliation job. |
| Revenue recognition / accounting export | T3 | 1 | None. | 1 | None. |
6 Pricing & Packaging 10% ND 5F8 5 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| Pricing tested with ≥ 20 real prospects | T1 | 2 | $5/mo · $50/yr set by gut feel; zero prospect interviews. | 2 | Basic/Pro pricing never prospect-tested; both paid tiers are waitlists. |
| Anchored against named competitors | T1 | 3 | No comparison doc. | 3 | No comparison doc; gov-data competitors exist and are unpriced-against. |
| Tier structure maps to a real value metric | T1 | 7 | Tiers map to real limits (nodes/features) — confirmed in audit. | 6 | Free/Basic/Pro map to data access depth (opportunities → awards); coherent. |
| Free trial or freemium decision deliberate, with conversion hypothesis | T1 | 4 | Invite-gated beta is deliberate; no written conversion hypothesis. | 6 | Free tier live by explicit strategy (“Free is live today; Basic and Pro are waitlists”); hypothesis implicit, not documented. |
| Annual/monthly mix with discount rationale | T2 | 6 | $50/yr ≈ 2 months free — present, rationale undocumented. | 3 | Monthly only on the published tiers. |
| Price experimentation + grandfathering plan | T3 | 1 | None. | 2 | sellable flag machinery would support it; no policy. NOTE: Pro held sellable=false by a 07-28 note whose condition (real awards data) now looks satisfied — 692,699 rows live. Highest-value commercial item: confirm FM-3 and flip. |
7 Conversion Funnel & Growth 10% ND 4F8 4 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| Landing states problem, outcome and price; loads fast | T1 | 6 | Clear landing with pricing ✓; load speed unmeasured. | 7 | States problem and price plainly; 294 ms full load. |
| Signup → activation instrumented end-to-end | T1 | 1 | No analytics at all. | 1 | Zero instrumentation — no GA/PostHog/Segment/Plausible in source. Waitlist table has 0 rows while the site invites “Notify me”: either no signups or a silently failing form, and no way to tell. Test the form manually. |
| Defined activation moment and time-to-value target | T1 | 2 | Not defined. | 2 | Not defined. |
| Onboarding drives to activation | T1 | 3 | Some empty states; no checklist or sample data. | 3 | Search works logged-out (free tier); no guided onboarding. |
| Checkout friction audit | T1 | 1 | No checkout exists. | 2 | Checkout cannot open (NULL price ids); nothing to audit. |
| Funnel conversion baselines set; weekly review | T2 | 1 | Nothing measured. | 1 | Nothing measured. |
| Lifecycle email: welcome, trial-ending, win-back | T2 | 1 | None. | 1 | None — and the waitlist that would feed it may be broken. |
8 Retention & Revenue Health 5% ND 3F8 3 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| MRR, ARR, churn, LTV:CAC tracked from day one | T1 | 2 | Pre-revenue; audit_log only, no metrics. | 2 | Pre-revenue; nothing tracked. |
| Voluntary vs involuntary churn separated | T2 | 1 | n/a until billing exists. | 1 | n/a until billing runs. |
| At-risk signals defined | T2 | 2 | audit_log could feed this; nothing defined. | 1 | Nothing defined. |
| Cancellation flow captures reason + offers alternatives | T2 | 1 | No subscription to cancel. | 1 | No subscription to cancel. |
| NRR tracked; expansion revenue path | T3 | 1 | None. | 2 | Basic→Pro upgrade path exists structurally; untracked. |
9 Legal & Trust 5% ND 2F8 5 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| ToS + Privacy Policy reviewed against actual data practices | T1 | 1 | Absent entirely — blocks any paid launch on its own. | 6 | Present on site; review against actual data practices (veteran PII, CAGE/UEI) not evidenced. |
| Refund/cancellation policy published; click-to-cancel | T1 | 1 | Absent. | 3 | Not published; audit requires it written with a working cancel flow before charging anyone. |
| GDPR/CCPA basics: consent, export, deletion on request | T1 | 2 | No process; undo-deletion RPC family not even deployed live. | 4 | No documented process; sensitive directory is opt-in with field masking, which helps but isn't a rights process. |
| PCI scope minimized — processor-hosted fields | T1 | n/a | n/a — no card data anywhere yet. | 8 | Card data never touches their servers; prices resolved server-side, client-supplied amounts refused. |
| DPA available for business customers | T2 | 1 | None. | 2 | None; B2B/gov buyers will ask. |
10 Support & Customer Success 5% ND 3F8 3 ▸
| Criterion | Tier | NodeDough — AI rating & evidence | FedM8 Scan — AI rating & evidence | ||
|---|---|---|---|---|---|
| Support channel with committed response time; billing fastest | T1 | 2 | No support channel. | 3 | Contact email only; no committed response time. |
| Docs/FAQ covering the top 10 predicted questions | T1 | 2 | None. | 3 | Some in-app explanation; no docs/FAQ section. |
| Status page or incident comms plan | T2 | 1 | None. | 1 | None. |
| Feedback loop from support → product backlog | T2 | 2 | None formalized. | 2 | None formalized. |
Source audits: NodeDough 2026-07-31 · FedM8 Scan 2026-07-31 ·
framework: /framework/ready · library: /framework.
Criterion ratings are AI-derived from audit evidence and inherit the audits' scope limits (FedM8: authenticated flows,
CI/CD and edge-function source unassessed). Re-rate on re-audit — dated runs stay immutable. Not legal advice.