Shell Heuristics · application docs

publisher · enricher-v2 · corpus

Frontend

What exists today, what each page shows, what it reads from. Then a goals scaffold for tankbottoms.eth to fill in.

Live URL

https://postcrime.atsignhandle.xyz → Cloudflare → node-eighteen:7850 (fraud_fraud-search).

Two extra hostnames to know:

  • fraud-stats-miner (swarm-internal :3200) — read-only JSON for /stats panels.
  • fraud-db-broker (swarm-internal :3100) — single rw, search-ui never talks to it.

Current routes (from search-ui/src/routes/)

Route Source file What it shows Reads from
/ +page.svelte + +page.server.ts Landing — list of agencies (SEC + DOJ), expandable into sources, expandable into doc summaries. Doc summary card shows: title, kind, published_at, case_number, byte_size, page_count, summary_one_sentence. corpus.db direct (SSR) via /api/docs.
/[source] [source]/+page.svelte Per-source listing with kind + year filters. corpus.db SSR.
/doc/[id] doc/[id]/+page.svelte Single document detail. Renders body, PDF preview (via /api/proxy-pdf or /api/pdf/[...path]), related anchors from reference_filing_json. corpus.db SSR + /api/document/[id]/pages.
/scheme scheme/+page.svelte Index of classified schemes (top-10 by count). corpus.db SSR.
/scheme/[slug] scheme/[slug]/+page.svelte Per-scheme drilldown — every doc classified into that scheme, with chart bundle. /api/scheme/[slug]/bundle.json.
/stats stats/+page.svelte Multi-panel D3 dashboard. See "Stats panels" below. fraud-stats-miner + /stats/api/*.

/api/* endpoints (server-only)

  • /api/docs — paged doc summary rows.
  • /api/search — FTS5-backed search across documents.
  • /api/document/[id] — single doc.
  • /api/document/[id]/pages — per-page summaries.
  • /api/proxy-pdf, /api/pdf/[...path] — PDF byte streaming.
  • /api/scheme/[slug]/bundle.json — per-scheme JSON bundle (docs + chart data).

Stats panels (/stats)

D1–D4 from the 2026-05-18 push:

Panel Source What it shows
D1 — calendar heatmap /stats/api/calendar Filings per day, faceted by source.
D2 — entity force network /stats/api/entities-graph Co-occurrence graph of entities across documents.
D3 — Sankey scheme → outcome /stats/api/sankey Triples-derived flow from scheme to outcome (plea / settlement / judgment).
D4 — scheme × amount circle pack /stats/api/pack Top classified schemes weighted by case_facts.monetary_amount.
Cross-corpus accomplices /stats/api/cross-corpus Force-directed cross-corpus join. Scaffolded, DB empty — TODO(schema) markers in docs/refactor/edgar-indexer-schema.md.
Status chips (top of page) $lib/components/StatusChip.svelte + $lib/synthetic/placeholders.ts Synthetic placeholders for service health — GAP: not wired to real /stats data yet.

Plus the earlier panels: gpumon trend, gpumon barlist, gpumon heatmap, microcap heatmap (full-width), classified schemes (top-10).

What the frontend does NOT have (yet)

GAP: per-entity pages — there is no /entity/[id] route. Anyone investigating "every doc mentioning Cane Clark" has to go via /api/search?q=Cane%20Clark.

GAP: per-person pages — same. No /person/[name].

GAP: per-CIK pages — no /cik/[cik]. Cross-link to EDGAR fingerprint signals doesn't exist in this UI.

GAP: timeline view — D1 is a heatmap; there is no thread-style timeline ("Cane filed S-1 → opinion letter → Reg S → death-spiral note → SEC complaint").

GAP: money-flow view — no Sankey from defendant → amount → recipient. D3 is scheme→outcome only.

GAP: case-facts tablecase_facts rows aren't surfaced as a sortable table anywhere.

GAP: signal-detail pages — the four NDJSON fingerprint signals (edgarizer_fingerprint, reg_s_issuance, promissory_note_clauses, opinion_letter_presence) have no UI. They live as 99 / 102 / 58 / 1.5 MB NDJSONs on disk only.

GAP: DLQ inspectorfraud.dlq has no UI; you must rabbitmqctl or attach an ad-hoc consumer.

GAP: enricher queue depth — there is no /admin or /ops page showing fraud.rows depth, workflow_runs pending counts, or per-workflow throughput.


Goals — tankbottoms.eth to expand

Below is a structured outline of investigation surfaces this UI could grow. Each bullet has a placeholder paragraph (TODO:) for tankbottoms.eth to fill in with intent + acceptance criteria.

/entity/[id] — entity detail

  • TODO: What does the entity card show? Canonical name, aliases, kinds (person/org), all known CIKs, all known tickers, list of mentions sorted by date?
  • TODO: Should it surface the EDGAR fingerprint hits (cross-link by CIK)?
  • TODO: Need a "network neighbours" mini-graph here?

/person/[slug] — person detail (subtype of entity)

  • TODO: Different from entity how? Officer/director history? Cross-company relationships? Bar admission status?
  • TODO: What's the source of truth for person identity — entities rows, or a curated roster (ciks-banana/roster.json)?

/cik/[cik] — issuer detail

  • TODO: Card shape: name, SIC code, all forms ever filed (timeline), every fingerprint hit, every linked entity (officers / counsel / agent / auditor).
  • TODO: Cross-link into corpus.db documents where this CIK is mentioned?
  • TODO: Do we need a separate "shell-score" composite computed from the four NDJSON signals?

/signal/[name] — fingerprint signal viewer

  • TODO: One page per fingerprint (edgarizer_fingerprint, reg_s_issuance, promissory_note_clauses, opinion_letter_presence).
  • TODO: Sort: by score, by CIK, by accession date. Filter: agent-CIK prefix, form type, year window.
  • TODO: Should hits link out to the actual EDGAR filing URL or to a local-mirrored copy?

/network/[seed] — network graph from a seed

  • TODO: Start from a CIK, person, or law firm. Expand by N hops over shared officer / counsel / agent / opinion-letter signer.
  • TODO: Highlight nodes that have an EDGAR fingerprint hit.
  • TODO: Save / share network views?

/timeline/[case-or-cik] — chronological strip

  • TODO: Start date, end date. Each row = one document or one event (S-1 filed, opinion letter signed, complaint filed, plea entered).
  • TODO: Source-faceted (EDGAR vs DOJ vs SEC).
  • TODO: Link to evidence-pack export?

/money-flow/[case] — money Sankey

  • TODO: Defendant → instrument (note / Reg S issuance / pump) → recipient.
  • TODO: Bound by case_facts.monetary_amount and any extracted dollar figures from triples.

/case-facts — sortable facts table

  • TODO: Columns: defendant, first-act, plea, sentence, dollar amount, scheme, link to source doc.
  • TODO: CSV export?
  • TODO: Filter by scheme / year / state-of-prosecution.

/ops — operator dashboard

  • TODO: Queue depth (fraud.rows, fraud.dlq).
  • TODO: Per-workflow pending / running / done / failed counts (from workflow_runs).
  • TODO: Live gpumon backend health (already on /stats partially, expand here).
  • TODO: Migration status (which 2026-05-* migrations have been applied to the live broker?).

/evidence/[case] — evidence-pack export

  • TODO: Given a case, package all source documents + extracted case-facts + classification + chain-of-custody hashes into a single ZIP or IPFS upload.
  • TODO: Reuses the bun-ipfs flow at *********/bun-ipfs.

Cross-cutting UX TODOs

  • TODO: Dark / light parity (current site is mostly dark — verify on print).
  • TODO: Mobile layout for /stats panels (most D3 panels overflow).
  • TODO: Persistent search filters (deep-link query strings already work; verify all panels respect them).
  • TODO: Replace the $lib/synthetic/placeholders.ts mock chips with real broker / queue / gpumon health.