Skip to content

Data viewer: read-only db.inspect() + a /viewer route over the demo store#25

Merged
pango07 merged 3 commits into
mainfrom
feat/data-viewer
Jul 11, 2026
Merged

Data viewer: read-only db.inspect() + a /viewer route over the demo store#25
pango07 merged 3 commits into
mainfrom
feat/data-viewer

Conversation

@pango07

@pango07 pango07 commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Builds the read-only web UI from the §14 roadmap ("non-engineers love to see their data"), and adds the one core primitive it needs.

Core: db.inspect(version?) (Design §13)

A read-only, format-agnostic projection of the otherwise-private manifest — version, committedAt, formatVersion, and per-table chunks with row counts and primary-key / partition zone-map min/max. Deliberately a derived shape, not the raw Manifest, so on-store format evolution can't break the contract.

  • Reads manifest metadata only — strictly lighter than export() (which also reads every chunk).
  • Returns no blob URLs — the private-data invariant holds.
  • Resolves any retained past version exactly as asOf does (throws VERSION_NOT_FOUND if pruned).
  • Documented in §13 as the deliberate exception to "resist growing the surface" (justified the same way export() is), and §14.

Viewer (test-lab app)

  • app/api/inspect + app/api/viewer-rows — paged rows with asOf time travel and pruned-vs-scanned stats. Table and sort identifiers are whitelisted against the code-first schema and page bounds coerced to ints, so no user values reach the SQL string (and the parser rejects statement stacking regardless).
  • app/viewer — table browser (paged, click-to-sort), a version scrubber (time travel, commits on release so it doesn't hammer Blob), and a chunk/zone-map internals panel. Linked from the home header.

Scrubbing the demo store is itself a demo of the architecture: at an early version customers is a single 6-row chunk on format 3; at the live head it's 3 chunks on format 4 — copy-on-write and format evolution, made visible.

Verification

  • bunx tsc --noEmit — clean
  • bun run lint — clean
  • bunx next build — green (all three routes registered)
  • bun scripts/api-smoke.ts35/35 against the real Blob store, including 5 new inspect() assertions (current + past-version time travel, zone-map presence, loud failure on an unretained version)
  • Routes exercised live against the demo store: current + past inspect, viewer-rows with real zone maps and pruning stats, unknown-table guard → 400, pruned version → 404

Rebased onto main (2.6.0 secondary indexes) — no conflicts; inspect() coexists with the new index code.

🤖 Generated with Claude Code

…tore

Adds db.inspect(version?) to the core surface (Design §13): a read-only,
format-agnostic projection of the otherwise-private manifest — version,
committedAt, formatVersion, and per-table chunks with row counts and
primary-key/partition zone-map min/max. Deliberately a derived shape, not the
raw Manifest, so on-store format evolution can't break the contract. Reads
manifest metadata only (lighter than export()), returns no blob URLs, and
resolves any retained past version exactly as asOf does.

Builds the read-only web UI from the §14 roadmap in the test-lab app:
- app/api/inspect + app/api/viewer-rows (paged rows with asOf time travel and
  pruned-vs-scanned stats; table/sort identifiers whitelisted against the
  code-first schema, so no user values reach the SQL string)
- app/viewer: table browser (paged, click-to-sort), a version scrubber (time
  travel), and a chunk/zone-map internals panel; linked from the home header

Verified: tsc clean, lint clean, next build green, api-smoke 35/35 against the
real Blob store (5 new inspect assertions), and the routes exercised live
against the demo store incl. past-version time travel and the injection guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
larva-db Ready Ready Preview, Comment Jul 11, 2026 7:00am

Request Review

…keletons

Fetch the viewer's data with @tanstack/react-query (provider scoped to the
/viewer route via a route layout). Both queries use placeholderData:
keepPreviousData so the table never collapses during a fetch.

The table structure is now always on screen: /api/inspect returns each table's
schema (columns/types/pk/partition, via a shared app/lib/viewer helper), so the
client draws headers and tabs from the schema before any row loads. Row cells
and chunk rows fall back to skeleton loaders while the page/version/table they
belong to is in flight — pagination keeps the previous page (keepPreviousData),
while a table or version switch shows skeletons under the correct new headers
(guarded by matching table+version, so stale rows never paint under new columns).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 2.6.0 is already on npm; the new public API needs a minor bump or the
  main-push publish job fails on the duplicate version
- api.mdx: inspect() in the surface block + its own section (incl. the
  tier-A visibility note: durable-but-unfolded appends appear at fold,
  like any cross-instance reader)
- test-lab.mdx: the /viewer walkthrough
- CLAUDE.md: inspect added to the §13 surface invariant

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pango07 pango07 merged commit c3eaa5d into main Jul 11, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant