Meridian · Engineering Reference
Confidential
Technical Happy Paths · Build / Optimize / Polish / Harden

Happy
Paths

Every user story as a full-stack sequence - client to Convex to integration to data - mapped against the real meridian-app and meridian-desk code. Each hop carries an honest status, and each story ends in a build verdict.

Stories
16 mapped
Grounded in
app + desk repos
P0 gaps
5 flagged
Prepared for
m1k3d0w
00

The gap board.

What ships today vs what the live surfaces promise. Status is read straight from the backend code, not the marketing. P0 rows are the load-bearing gaps - everything else optimizes around them.

Built Optimize Polish Harden Not built
StoryCapabilityStatusWhere it stands
V-01Free intakePartialOpen/free flow works; abuse-hardening + legacy billing cleanup
V-02Evidence envelopePartialCapture works; ownership checks + upload validation missing
V-03Trace fundsPartialMonitoring only · real tracing engine + CipherBlade NOT built  P0
V-04LE/IRS kitNot built0 code · generator + templates must be built  P0
V-05Case statusPartialPortal + bell live; status_change notifications never fire
V-06CoordinationPartialApp↔desk bridge missing; cases don't reach operators  P0
C-01Trace report $149Not builtNo commerce; depends on trace engine
C-02LossComply $249Not builtNo commerce; no toolkit artifact
C-03Expert declarationNot builtManual / off-platform
C-04Counsel handoffBuiltGrants + portfolio fully built & server-enforced
N-01Verify/Freeze APINot builtKey mgmt only; no endpoint; keys stored plaintext  P0
N-02Audit trailPartialEvent log exists; not immutable; no Explorer
O-01Case queuePartialUI built; queries unauthenticated; not unified  P0
O-02InvitationsBuiltBuilt + allowlist hardened; invite email + auth gaps remain
The 5 P0s

1. Desk authorization. Every meridian-desk Convex function runs with no auth check - the ops data API is open to anyone with the deployment URL.
2. Trace engine + CipherBlade. V-03/C-01/C-02 all depend on it; live copy already promises it.
3. App↔Desk bridge. Victim cases never reach operators; envelope→case conversion is unwired.
4. LE/IRS kit. Promised on the site, zero code.
5. Nexus API. Key management only, no endpoint, and keys are stored in plaintext.

Reading the diagrams

Each node is one hop, tagged by tier (Client · Convex · Cron · Integration · Data) with a status dot. Hatched nodes are gaps - a hop the happy path needs but the code does not yet make. The four-column verdict under each story is the work queue.

01

The Office · Victim journeys

V-01–V-06
V-01Start without paying upfrontVictim · The Office
As a victim, I want to start without paying upfront, so cost is never the reason I don't act.
Happy path · client → convex → integration → data
Client · 1Open envelope form/scan · destination + incident type
Convex · 2envelopes.createunauthenticated mutation
Convex · 3Return caseCodecapability token MER-XXXX-XXXX
Client · 4createCheckoutSessionlegacy name · no longer charges
Convex · 5markPaid {waived,$0}status → tracing
Data · 6envelopes rowawaiting_payment → tracing
Client · 7Redirect /envelope/sealedconfirmation
Build
Optimize
  • On seal, actually enqueue a trace job · today seal only flips status, nothing runs
Polish
  • Rename createCheckoutSession → sealEnvelope
  • Drop awaiting_payment / paymentStatus enum (no billing exists)
  • Reconcile '90 seconds' copy with real flow
Harden
  • envelopes.create + generateUploadUrl + attachFile are fully open · add rate-limit + captcha
  • Spam / storage-fill abuse vector with no throttle
V-02Package evidence into one envelopeVictim · The Office
As a victim, I want to package my evidence into one envelope, so I hold a credible, organized record.
Happy path · client → convex → integration → data
Client · 1generateUploadUrlunauthenticated
Client · 2PUT file → storageConvex file storage
Convex · 3attachFile / attachNoteno ownership check
Convex · 4documents.save / timelineEventsauthed (registered case)
Data · 5envelopeEvidence / documents+ evidenceItems / timeline
Build
  • Structured export of the full envelope bundle (feeds V-04 kit)
Optimize
  • Server-enforce mime/size · size is client-supplied today
Polish
  • Malware scan + thumbnailing on upload
Harden
  • attach mutations take any envelopeId with no token check → can write evidence to another victim's envelope
V-03Trace where my funds wentVictim · The Office
As a victim, I want to trace where my funds went, so I understand whether recovery is plausible.
Happy path · client → convex → integration → data
Client · 1Add wallet/case watchauthed
Convex · 2walletWatches.addWatchBTC/ETH regex validation
Cron · 3checkAllWatches (hourly)internalAction sweep
Integration · 4blockstream.info / cloudflare-ethfree public APIs · monitoring only
Convex · 5recordCheck → notify on changemarker diff
Gap · 6Fund-flow TRACE + CipherBladeno tracing engine, no CipherBlade call
Build
  • Real on-chain TRACING engine + CipherBlade integration · live copy says 'FlashTrace · CipherBlade-powered' but no CipherBlade call exists
  • Multi-chain: TRON / USDT-TRC20 (envelope advertises it; monitor can't see it)
Optimize
  • Move off free public RPC (rate-limited, no SLA) to keyed providers
Polish
  • Surface trace results as a flow/hop graph in the portal, not just a notification
Harden
  • API failures silently skipped · add retry/backoff/alerting
  • Baseline-marker race can miss the first activity event
V-04Ready-to-file LE & IRS kitVictim · The Office
As a victim, I want a ready-to-file law-enforcement and IRS kit, so I can report without legal expertise.
Happy path · client → convex → integration → data
Client · 1Case + evidence + timelineinputs already captured
Gap · 2Kit generator actionno code exists
Gap · 3PDF render + jurisdiction templatesIC3 / FTC / IRS forms · none
Data · 4documents (store generated kit)store exists, unused for this
Build
  • The kit generator itself · pre-formatted LE/IRS filings, IC3/FTC templates, jurisdiction guidance. Currently 0 code; live copy overpromises
Optimize
  • Pre-fill from envelope/case fields
Polish
  • Branded PDF + e-sign block
Harden
  • PII handling on generated docs + access control on download
V-05Status on my caseVictim · The Office
As a victim, I want status on my case, so I am never left in the dark.
Happy path · client → convex → integration → data
Client · 1Portal live subscriptionscases.get + statusHistory + listMy
Convex · 2Notification bellunreadCount / markRead / markAllRead
Convex · 3wallet_activity notificationsfired by monitor
Gap · 4status_change notificationstype declared, NEVER inserted
Data · 5notifications / statusHistorybuilt
Build
  • Wire status_change → notification (on status patch, insert notification) so victims are actually told when their case moves
Optimize
  • Email/SMS fan-out on critical status (Resend is wired for auth only)
Polish
  • Per-type notification preferences
Harden
  • App case status is manual today; with no desk→app pipeline the timeline rarely moves (see V-06)
V-06Be connected to the right peopleVictim · The Office
As a victim, I want to be connected to the right people, so coordination happens for me, not by me.
Happy path · client → convex → integration → data
Client · 1Victim case in appConvex dataset A
Gap · 2app ⇎ desk syncseparate Convex datasets, no bridge
Convex · 3desk contacts + dispatchescoordination on seeded data only
Gap · 4desk contacts/dispatchesnot linked to live victim cases
Build
  • App↔Desk case bridge · victim cases never reach operators automatically
  • Envelope→case conversion: linkedCaseId/linkedUserId fields exist, no mutation wires it
Optimize
  • SLA timers on dispatches
Polish
  • Surface coordination/recovery status back into the victim portal
Harden
  • Cross-system identity + audit when data does bridge
02

The Coalition · Counsel journeys

C-01–C-04
C-01Court-admissible forensic trace reportCounsel · The Coalition
As an attorney, I want a court-admissible forensic trace report, so I can support filings and motions. ($149)
Happy path · client → convex → integration → data
Client · 1Select productmarketing pricing page
Gap · 2Checkoutpayments only does free envelope seal
Gap · 3Trace report generatordepends on V-03 engine
Build
  • Stripe commerce for counsel products + the trace-report artifact generator
  • Depends on V-03 trace engine
Optimize
Polish
  • Court-admissible formatting + chain-of-custody page
Harden
  • Payment + entitlement + secure delivery
C-02Loss-documentation toolkitCounsel · The Coalition
As a firm, I want a loss-documentation toolkit, so I can standardize intake and compliance. ($249)
Happy path · client → convex → integration → data
Client · 1Select toolkitmarketing pricing page
Gap · 2Checkoutno commerce wired
Gap · 3Toolkit artifactno generator
Build
  • Commerce + the toolkit artifact (templates, intake forms, compliance checklist)
Optimize
  • Reuse the kit engine from V-04
Polish
  • Firm-branded export
Harden
  • Entitlement + license scope
C-03Expert declaration on demandCounsel · The Coalition
As counsel, I want an expert declaration on demand, so I can introduce qualified testimony. (custom scope)
Happy path · client → convex → integration → data
Client · 1Request declarationcustom-scope intake
Gap · 2Scoping + fulfilmentmanual / off-platform
Gap · 3Signed declaration deliveryno product surface
Build
  • Productize: request → scope → signed-declaration delivery (today fully manual)
Optimize
  • Template library of declaration types
Polish
  • E-signature + notarization flow
Harden
  • Expert identity / credential handling
C-04Refer a client into the OfficeCounsel · The Coalition
As counsel, I want to refer a client into the Office, so evidence is handled before I engage.
Happy path · client → convex → integration → data
Client · 1grantAccess(case, email)authed + ownership-checked
Convex · 2counselGrants insertlinks existing user by email
Convex · 3registerCounselclaims pending grants by email
Convex · 4listPortfolio / getCaseAsCounselserver-enforced read-only
Data · 5counselGrants / counselProfilesbuilt
Build
Optimize
  • Notify counsel on grant · no email is sent today
Polish
  • Counsel verification flow (verified flag set out-of-band/manual)
Harden
  • Grant audit log + revoke propagation
03

Nexus & Console · Institution + Operator

N-01–O-02
N-01Verify an address via APIInstitution · Nexus
As a compliance team, I want to verify an address via API, so I can block disbursement in real time.
Happy path · client → convex → integration → data
Client · 1apiKeys.createdesk issues mnx_ key
Gap · 2keyHash = plaintext keycomment admits 'would be hashed'
Gap · 3Public HTTP endpointhttp.ts mounts auth only · none
Gap · 4verify / freeze + address intelno logic exists
Build
  • The actual Nexus API: key-auth verify-address + freeze endpoints, rate-limit enforcement, request logging
Optimize
  • Usage metering · requestCount/rateLimit fields exist but are unused
Polish
  • 'mnx_' key prefix is a MicronDelta/Nexus leftover · rebrand
Harden
  • Hash API keys at rest (stored plaintext today) + scope enforcement + rotation
N-02Immutable audit trailInstitution · Nexus
As an institution, I want an immutable audit trail, so my actions are defensible to regulators.
Happy path · client → convex → integration → data
Convex · 1activityLog insertson key/invite/case events
Gap · 2Append-only / hash-chainregular mutable table · not WORM
Gap · 3Public Explorer surfacenone
Data · 4activityLog tablemutable
Build
  • Append-only audit store (hash-chained or external WORM) + Explorer read surface
Optimize
  • Structured event schema shared across all surfaces
Polish
  • Export / verify endpoint
Harden
  • Tamper-evidence · an admin mutation could delete log rows today
O-01Unified case queueOperator · Console
As an operator, I want a unified case queue, so I can triage intake by recoverability.
Happy path · client → convex → integration → data
Client · 1Console queuecases.list / stats / get
Gap · 2No auth on queriesgetAuthUserId never called
Gap · 3Desk seeded cases onlynot the live app victim cases
Data · 4desk casesseparate dataset
Build
  • Unify with live app victim cases (the V-06 bridge)
Optimize
  • Recoverability scoring · priority field exists, scoring logic does not
Polish
  • Saved views / filters
Harden
  • Add authorization to ALL desk queries/mutations · the data API is open to anyone with the deployment URL
O-02Manage invitationsOperator · Console
As an operator, I want to manage invitations, so console access stays invite-only.
Happy path · client → convex → integration → data
Client · 1invitations.send / resend / listconsole
Convex · 2STAFF_ALLOWLIST default-denygates signUp flow (deployed)
Gap · 3No invite email sentDB record + activity only
Data · 4invitations / activityLogbuilt
Build
Optimize
  • Auto follow-ups · followUpCount field exists, unused
Polish
  • Actually email the partner the invite link (today only a DB row)
  • STAFF_ALLOWLIST is empty → onboarding blocked until set
Harden
  • invitations.send/list also lack auth checks (same desk-wide authz gap as O-01)