A scripted, interactive verification that the SDK → API → SPA loop actually works. Run this once before declaring a release. ~10 minutes start to finish.
The pieces have all been built and unit-tested, but only a human at a terminal can confirm Supabase + Vercel + the SDK actually talk to each other.
- Docker running (Supabase local uses it)
- Node 20+, Python 3.13+,
openssl - Supabase CLI:
brew install supabase/tap/supabase - Vercel CLI:
npm install -g vercel - Repo cloned,
git statusclean
The test passes if every numbered step below produces the expected output. Fail = file an issue with the step number and the actual output.
cd /path/to/monora-sdk
rm -rf node_modules monora-node/node_modules platform/app/node_modules
rm -rf monora-node/dist platform/app/dist
rm -rf examples/agent_causal_proof/wal examples/agent_causal_proof/output
rm -f .env.local platform/app/.env.local
supabase stop --no-backup 2>/dev/null || truenpm ci
npm --prefix monora-node ci && npm --prefix monora-node run build
npm --prefix platform/app ci --include=dev
python3 -m venv .venv && .venv/bin/pip install -e .
.venv/bin/pip install requests pyyaml cryptographyExpected: No npm ERR!, no pip resolution errors. monora-node/dist/causal_proof.js exists.
.venv/bin/python -m pytest tests/test_agent.py tests/test_causal_proof.py tests/test_hasher.py tests/test_signing.py tests/test_wal.py tests/test_verification.py --no-header
cd monora-node && npx jest src/agent.test.ts src/causal_proof.test.ts src/pdf_report.test.ts && cd ..Expected: 144+ passed (Python), 12 passed (Node).
node examples/agent_causal_proof/node/run.jsExpected (tail):
Verified: YES ✓
Root: LLM call: classify_intent
Chain:
1. llm_call:classify_intent … conf=100%
2. tool_call:crm.getOpportunities … conf=100%
3. decision:correlate_signals … conf=100%
4. outcome:renewal_at_risk … conf=100%
examples/agent_causal_proof/output/proof.json and proof.html exist.
In terminal A:
./scripts/dev.shExpected:
▶ Booting Supabase…then a table of local Supabase URLs.✓ Wrote .env.local and platform/app/.env.local▶ Booting vercel dev…followed by> Ready! Available at http://localhost:3000.
Leave this terminal running.
Open http://localhost:3000 in a browser.
- Click Sign Up.
- Email: anything (e.g.
you@example.com), password ≥ 8 chars. - Expected: redirected to
/traceswith an empty trace inbox. Top-right shows your email + Sign Out.
In terminal B:
./scripts/seed.sh you@example.comExpected:
✓ Seeded.
project_id: <uuid>
api_key (prefix): mnr_…
.env.local now has MONORA_API_KEY=mnr_… and MONORA_DEMO_PROJECT_ID=<uuid>.
./scripts/keygen.shExpected: ✓ Wrote MONORA_SIGNING_KEY to .env.local (HMAC-SHA256, 256-bit).
node examples/agent_causal_proof/hosted/run.jsExpected (tail):
▶ Shipping events to http://127.0.0.1:54321/functions/v1/ingest-events
▶ Signing: hmac-sha256 (MONORA_SIGNING_KEY set) ← if you ran step 7; else "disabled"
▶ Running 4-step agent on trace trc_hosted_<…>
✓ Agent emitted 4 events; outcome evt_…
Done. Open the SPA to see the trace:
http://localhost:3000/traces
Refresh http://localhost:3000/traces.
Expected:
- A new row appears matching the
Trace IDprinted in step 8. - Integrity badge: ✓ verified.
- Event count: 4.
Click into the trace.
Expected:
- 4 numbered chain steps render:
llm_call:classify_intent,tool_call:crm.getOpportunities,decision:correlate_signals,outcome:renewal_at_risk. - Green ✓ HASH CHAIN VERIFIED banner at top.
- Each step shows inputs/outputs/latency/confidence.
Click Download PDF.
Expected:
- ~2-3 second delay (Puppeteer cold start), then the PDF downloads.
- PDF opens cleanly. Header: "Causal Proof of Record". Same chain rendered with the integrity banner.
Click Create share link.
Expected:
- URL copied to clipboard or shown. Form:
http://localhost:3000/share/share_<random>. - Open it in an incognito window.
- Proof renders without a sign-in wall.
In Supabase Studio (http://127.0.0.1:54323):
- Open the SQL editor.
- Run:
update public.organization_members set role = 'auditor' where user_id = (select id from auth.users limit 1); - Refresh the SPA — note nothing breaks immediately because cached JWT still has owner-level access. Sign out and back in.
- Try API Keys page → "New" button.
- Expected: the request 403s with
Your role (auditor) is not authorized for this action.(read-only paths like Trace Inbox + Proof Viewer + Share Link creation still work.) - Reset:
update public.organization_members set role = 'owner' where user_id = (select id from auth.users limit 1);, sign out, sign back in.
In Supabase Studio SQL editor:
update public.proof_events
set body = body || '{"outputs": "TAMPERED"}'::jsonb
where event_type = 'decision'
and trace_id = '<trace id from step 8>';Reload the Proof Viewer page.
Expected:
- Red banner: ✗ INTEGRITY CHECK FAILED — LOG MAY BE COMPROMISED.
- The failing step is highlighted with a red border.
- Confidence drops to 0.0% on the tampered step.
- Re-downloading the PDF carries the failure forward.
Terminal A: Ctrl-C.
Expected: ▶ Stopping Supabase… then a clean exit.
- Fresh install works (Phase 1 of the workspace + SDK build pipeline)
- Unit tests pass (regression detection)
- Local-WAL demo works (SDK in isolation)
- Local Supabase + Vercel boot cleanly (
scripts/dev.sh) - Auth + RLS round-trip (signup → owner → first signup gets role)
- API key minting end-to-end (
scripts/seed.sh) - HTTPS sink ships events to the Edge Function
- Edge Function writes
proof_events+ upsertstrace_summaries -
GET /api/traceslists the trace -
GET /api/proofs/.../...builds the proof fromproof_events -
POST /api/proofs/.../pdfrenders Puppeteer PDF -
POST /api/share-linksmints +GET /api/share/:tokenresolves - RBAC denies cross-role writes
- Tamper detection works against live DB
Take a screenshot, attach terminal A's logs and the browser console, and file an issue with the step number.