Skip to content

id-375 research — market

Nothing on the market does what ast-dataflow’s Supabase layer does. The scan found zero products that statically join a Postgres/Supabase schema to type-checker-resolved TypeScript usage sites — no eslint-plugin-supabase exists, SafeQL/pgTyped/sqlx-ts only check raw SQL strings (not supabase-js builder chains), Knip/ts-prune never touch DB columns, DB-side tools (Azimutt, pg_stat_*, splinter) infer “unused” from runtime stats with no code evidence, and the entire “audit my vibe-coded Supabase app” market (supabase-security-mcp, Vibe App Scanner, CheckVibe, Suparbase) is security/RLS-shaped with explicitly no schema-vs-code coverage. The genuinely commoditised part is the generic symbol layer: callers/references/importers are well served by Serena MCP, mcp-ts-morph, scip-typescript, and LSPs, and dead-exports by Knip. Verdict: extract and position the standalone package as a Supabase schema-coverage/wiring auditor (“which columns are built but never wired?”) — column-reads, column-writes, type-drift-detect, flow-trace, confidence tiers, and the planned schema-coverage report are the product; the generic queries are supporting infrastructure, not the pitch.

What ast-dataflow is (baseline for comparison)

Section titled “What ast-dataflow is (baseline for comparison)”

12 shipped CLI queries confirmed in code at /Users/liamj/Documents/development/canonical/tools/ast-dataflow/queries/ (callers, column-reads, column-writes, dead-exports, enum-uses, flow-trace, importers, reexport-chain, references, string-literal-uses, type-drift-detect, type-evolution; all imported in tools/ast-dataflow/cli.ts:3-18). Spec: knowledge-hub-docs-site/.../specs/id-50-ast-dataflow-tool/PRODUCT.md:104-207 (query surface), :223-229 (exact/wildcard/indirect confidence tiers). Distinctives: ts-morph type-checker resolution; supabase-js chain awareness (.from('t').select('…'), .insert/.update/.upsert, RPC payloads — PRODUCT.md:142-158); .select('*') wildcard tier; JSONL agent-friendly output; type-drift-detect with CI baseline ratchet (ROADMAP.md:157, :300). The “schema-coverage report” is not yet in the id-50 spec dir (grep found no mention) — it is planned per Liam’s brief.

Category 1 — Unused/dead DB column detection (schema-vs-code)

Section titled “Category 1 — Unused/dead DB column detection (schema-vs-code)”

No shipping product does code-side column coverage. Confirmed gap.

Category 2 — TS static analysis of supabase-js query chains

Section titled “Category 2 — TS static analysis of supabase-js query chains”

No eslint-plugin-supabase exists (direct npm/GitHub search returned nothing; only generic typescript-eslint setups in Supabase starters). The raw-SQL checkers all skip builder chains:

Overlap verdict: column-reads, column-writes, type-drift-detect, and DB-sink flow-trace have no market equivalent.

Category 3 — Knip / ts-prune / dead-code tools

Section titled “Category 3 — Knip / ts-prune / dead-code tools”
  • Kniphttps://knip.dev/ — unused files/exports/deps/enum members via module-graph mark-and-sweep. No DB column dimension (explicitly absent from docs/comparison page https://knip.dev/explanations/comparison-and-migration ). ts-prune archived Dec 2023 ( https://github.com/nadeesha/ts-prune ). Overlap: dead-exports duplicates Knip’s headline; but KH data shows the complement value — 54 Knip-flagged symbols → 52 confirmed dead, 2 barrel-chain false positives (ROADMAP.md:210-226), and Knip has known as const enum false positives (#989, #703; ROADMAP.md:91). Gap Knip leaves: type-checker verification, barrel-chain explanation, and the entire DB axis.

Category 4 — AI-era “audit my Supabase app” tooling

Section titled “Category 4 — AI-era “audit my Supabase app” tooling”

The market exists and is growing, but is entirely security-shaped:

Gap: the “built-but-not-wired” audit for vibe coders is an unoccupied niche. Every player answers “is my app secure?”; nobody answers “is everything I built actually connected?” — which is precisely the failure mode of AI-generated Supabase apps (migration applied, UI written, wiring forgotten).

Category 5 — ts-morph / type-checker-resolved analyzer CLIs

Section titled “Category 5 — ts-morph / type-checker-resolved analyzer CLIs”

The generic symbol layer IS well served — this is where duplication risk lives:

So: for generic callers/references, ast-dataflow is a fourth entrant in a served market. For the composed, Supabase-aware, coverage-report surface, it has no competitor in any category searched.

Extract it, but as a Supabase schema-coverage auditor, not a generic AST query tool. The differentiated core — worth building the standalone package around:

  1. The schema-coverage report is the product. Join generated database.types.ts (or live schema via Supabase CLI/MCP) with type-checker-resolved column-reads/column-writes to produce a per-table, per-column matrix: read-sites, write-sites, wildcard-only, never-touched — each with file:line evidence and exact/wildcard/indirect confidence. No product in any of the five categories does this. It directly answers the vibe-coder question “I asked the AI to build X — is X actually wired up?”
  2. Keep as differentiators: supabase-js chain analysis (select/insert/update/upsert/RPC payloads), the wildcard .select('*') tier, confidence tagging, JSONL/CI-friendly output, type-drift-detect’s baseline-ratchet gate, and flow-trace to DB sinks.
  3. Design in the scope caveat: static coverage only proves “unused in this codebase” — Supabase tables can be hit by edge functions, other clients, or direct PostgREST. The report should state its corpus scope per column, and a future roadmap item can merge DB-side runtime signal (pg_stat_statements / Azimutt-style) as a second evidence column. That hybrid would be unique in the market.
  • Generic find-references/callers as the pitch — Serena MCP, mcp-ts-morph, scip-typescript, and every LSP own this. Keep callers/references/importers as internal primitives and supporting CLI verbs, not the marketing.
  • Dead-export detection as the headline — Knip owns it. Ship dead-exports as the “Knip verifier” (the 54→52+2 false-positive story is the right frame).
  • Security auditing — crowded (supabase-security-mcp, Vibe App Scanner, CheckVibe, splinter/get_advisors). Do not add RLS checks; instead be the complementary “wiring” audit those tools explicitly don’t do.
  • SQL-side linting — Postgres Language Server + splinter own it.
  • Autofix/rename execution — mcp-ts-morph and IDEs do it; PRODUCT.md’s no-autofix invariant (PRODUCT.md:90-92) stays correct for the standalone tool.
  • Delivery: npx <tool> audit one-shot CLI first, thin MCP wrapper second. The vibe-coder market comparators are all MCP/agent-delivered — this audience lives in Cursor/Claude Code and will not maintain a CLI habit — but the CLI is what CI and agents-via-Bash need, and the internal OQ1/OQ-R4 finding (CLI-via-Bash caused zero agent friction across 11 sessions) says the MCP layer can stay thin. Ship both entry points over one library.
  • Lead command: a single audit / coverage verb producing the human-readable schema-coverage report (with --json for agents); the 12 queries become subcommands for power users.
  • Naming: pick a wiring/coverage metaphor, not an AST one — “ast-dataflow” describes the mechanism, which this audience doesn’t care about. Candidates: supawire / wiredup / schemacover / supacoverage. The supa- prefix is community-conventional (supa_audit, suparbase) but check Supabase brand guidelines before locking it; a Supabase-neutral name keeps the door open for Drizzle/Kysely adapters later, since those ecosystems have the identical gap.
  • Portability groundwork already exists: R-WP10 found the tool 95% portable with a 4-file fix (--tsconfig flag etc., ROADMAP.md:121, :131) and HANDOVER.md:86 already anticipates package extraction (test co-location plan). Fold that in during extraction.
  • Marketing wedge: the CADO research number (63%+ of retrieved columns unused in DB-backed apps) plus the AI-era twist (“your agent built the table, wrote the UI, and forgot the wire”) is the story; the security scanners’ own positioning (“we don’t do this”) confirms the open lane.