v1.1 #3

Merged
xavier merged 38 commits from dev into main 2026-08-14 06:39:59 +02:00
Owner
No description provided.
native-tls: add v2 spec for in-process TLS termination (TLS_CERT_FILE / TLS_KEY_FILE)
Some checks failed
release / build + scan + publish (push) Successful in 53s
CI / pnpm gate (typecheck, lint, build, test) (push) Failing after 1m21s
3b66f953d0
Adds docs/specs/native-tls.md defining optional native TLS termination so the single image can serve encrypted traffic without a reverse proxy. Operators arm it via two _FILE-only env vars (TLS_CERT_FILE public chain + TLS_KEY_FILE private key); both-or-neither semantics with fail-fast on partial config, and missing both yields no native TLS (unchanged v1 behavior). The private key inherits the existing _FILE convention's file-content + fail-fast disciplines (path may appear in boot errors, contents never).

Native TLS is a fourth deployment shape, orthogonal to TRUSTED_PROXIES -- a topology matrix documents the direct / MITM-re-encrypt / MITM-plaintext / TLS-passthrough cases. Also wires the two knobs into deployment-config.md (inventory + _FILE convention section) and indexes the spec in README. v2 phase, independent of i18n.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
backlog.md = unversioned funnel (raw + refined, optional [raw], no status).
rejected.md = declined-ideas memorial (REJECTED line, revivable, check-before-proposing).
vX.Y.md = execution file (Scope layer frozen by Principal, Plan layer appended by PM, closed on ship).
Governance: promote / reject / drop exits; add = Principal-only, remove = Principal decides.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
docs: open v1.1/v1.2/v2.0 scopes; route deferred spec items to backlog/rejected
All checks were successful
release / build + scan + publish (push) Successful in 1m1s
CI / pnpm gate (typecheck, lint, build, test) (push) Successful in 1m24s
7c92c0551e
Adds vX.Y scope files for v1.1 (SQL/inspection), v1.2 (connection profiles), v2.0 (i18n + TLS). Populates backlog.md and rejected.md from the spec Scope-boundary sweep and reconciles ~12 spec files to cross-link them instead of bare '(v1)' tags. Also: SQL hard-limit 2 GB -> 1 GB (ADR #11); connection profiles deferred v1 -> v1.2; captures the no-proxy-permanent-storage and no-local-accounts/delegated-auth principles; single-folder download-selection constraint recorded.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
CSP widenings per ADR #25 §3 so duckdb-wasm can init in v1.1:
worker-src gains 'blob:' (duckdb-wasm spawns workers from Blob URLs at
runtime, unlike v1.0's same-origin metadata worker), and script-src gains
'wasm-unsafe-eval' (the modern, narrow CSP keyword for WASM compilation —
strictly narrower than 'unsafe-eval'; Chrome 96+, Firefox 101+). Both are
load-bearing and pinned in the test suite so a future edit can't widen
script-src to the broad 'unsafe-eval'.

SQL_QUERY_LIMIT_SIZE default tuned 2 GB -> 1 GB per ADR #11, to stay
safely under WASM heap ceilings; operator-overridable (env still wins).
ADR #11's status stays "default subject to change" pending the heap-
validation finding from the duckdb-wasm engine task (v1.1-T4).

Tests updated to the new directive map + 1 GB default. References:
ADR #25 §3 (CSP widening), ADR #11 (SQL limit tuning), ADR #08 (duckdb-wasm pin).

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Add the v1.1 dependency set to packages/web (no app code imports these
yet — the SQL engine lands in T4, the editor UI in T6; the build is
unchanged at ~959 kB main bundle):

- @duckdb/duckdb-wasm pinned EXACTLY 1.32.0 (ADR #08; the npm 'latest'
  tag points to a dev build — 1.33.1-dev as of Aug 2026). Pin asserted
  by scripts/check-duckdb-pin.mjs.
- CodeMirror 6 SQL-editor stack (ADR #13): @uiw/react-codemirror 4.25.11
  + @codemirror/{view,state,lang-sql}, all at the architect-pinned
  versions (view/state 6.7.1, lang-sql 6.10.0).
- SheetJS vendored 0.20.3 (vendor/xlsx-0.20.3.tgz, referenced via file:)
  — a deliberate SECURITY UPGRADE over the CVE-laden, unmaintained npm
  xlsx@0.18.5 (CVE-2023-30533, CVE-2024-22363). The maintained CE ships
  only via cdn.sheetjs.com; vendoring is the reproducible-builds path.

pnpm-workspace.yaml: extend minimumReleaseAgeExclude for the pnpm 11.20.0
'Invalid time value' bug (detectMinReleaseAgeViolation crashes during
fresh registry resolution — same class of bug as the existing
yauzl/rate-limit/helmet excludes). The 5 new registry deps
(@codemirror/*, @uiw/react-codemirror, @duckdb/duckdb-wasm) are added
(security-neutral — all genuinely >7d old); the duckdb-wasm age-exclude
is orthogonal to ADR #08's exact-pin rule. The xlsx exclude comment is
corrected: a file: dep does not consult the npm registry (verified at
install), so that entry is belt-and-braces, not load-bearing.

scripts/check-duckdb-pin.mjs: refresh the now-stale header comment —
duckdb-wasm is installed (pinned 1.32.0 in packages/web) and exercised
by the SQL engine (ADR #31); the gate now actively guards the live pin
rather than watching for the package's arrival. Logic unchanged.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Implements the T4 duckdb-wasm SQL engine under packages/web/src/sql/:
a dedicated SQL Worker (ADR #31 §1) distinct from the metadata Worker
(ADR #19), instantiated via Vite's ?url idiom with the MVP bundle
selected at runtime. Session-persistent AsyncDuckDB singleton with a
per-query register/drop cycle for heap isolation, serialized through a
shared mutex (ADR #31 §3, §7). Source bytes are buffered through the
existing fetchS3Range Range Gateway (not DuckDB's HTTP backend — ADR
#31 §4) so credential headers ride the existing fetch path.

Cancellation is defense-in-depth (ADR #31 §5, mirroring ADR #19): L1
(cooperative conn.cancelSent()) is unavailable on the MVP materialized
query() path so L2 (worker.terminate() + null singleton) fires
unconditionally on abort; the L1 seam is in place for a future switch
to the streaming send() path. Read-only prefix guard runs before any
I/O. The new useSqlStore bypasses the transfer slot (ADR #04).

Web-side SQL cap aligned to 1 GB per ADR #11 (DEFAULT_CONFIG + login
fixture + session-config test + the stale shared comment fix).

Three review minors applied:
  - oversize error mapping: loadSourceBuffer now runs through
    mapExecutionError in both executeRunQuery and executeDescribeSource
    so a lying-backend SqlSourceTooLargeError surfaces {kind:'oversize'}
    instead of leaking through as {kind:'execution'}.
  - read-only-guard docstring corrected: the guard is prefix-only by
    design (CTE-prefixed DML / EXPLAIN ANALYZE <DML> slip past); the
    no-DDL-can-succeed + ephemeral in-memory DB properties make it
    sufficient. Logic unchanged.
  - cancel->terminate test now asserts dropFile was attempted, locking
    the leak-free-on-cancel invariant from the try/finally.

ADR #31 zero-new-shared-types invariant preserved: the only shared
change is a stale-comment fix.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Data Inspector (packages/web/src/data-inspection/): ADR #30 frontend-enforced row-alignment via align-rows.ts pure helper with a JSON-array bracket-depth counter; CSV/TSV/JSON schema via shared duckdb describeBuffer, Parquet via v1.0 hyparquet footer, xlsx via vendored SheetJS metadata-only; wired into Inspector with v1.0 metadata disabled for tabular keys to avoid a double-fetch.

SQL Runner UI (packages/web/src/components/sql-runner/): CodeMirror 6 editor, paginated results, CSV+Parquet export via coordinator exportQuery, warn/limit size gates, single/multi/blocked mode indicator, cancel-with-L2-cost copy, /sql route + TopBar entry + "Open in SQL Runner" bulk action.

Both reuse the T4 duckdb engine under a shared mutex (ADR #31 §7), bypass the transfer slot (ADR #04), honor the read-only guard, and render untrusted S3 strings as React text children only.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Adds a minio-init sidecar to docker-compose.e2e.yml provisioning two MinIO IAM users (alice/bob) with disjoint per-bucket policies + seeded marker objects; new minio-iam-routing.spec.ts logs two browser contexts in with the different credentials and asserts per-request credential routing isolation (each context sees only its authorized bucket; a cross-context bucket op returns unauthorized/401 — the MinIO IAM denial relayed via mapS3Error); the proxy's per-endpoint authorized-buckets guard is intentionally unconfigured on the shared stack (configuring it would break the other specs) — per-user isolation is enforced at the MinIO IAM layer (ADR #01).

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
README: SQL_QUERY_LIMIT_SIZE 2 GB -> 1 GB (ADR #11) + drop the stale 'not yet available' markers; roadmap v1.1 bullet made accurate (Data Inspector + in-browser SQL via duckdb-wasm). CONTRIBUTING: non-rotting ADR-latest reference, present-tense duckdb wording, new 'pnpm install Invalid time value' playbook (disable minimumReleaseAge -> install -> restore -> verify --frozen-lockfile). AGENTS.md: matching duckdb reword (AGENTS.md <-> CONTRIBUTING.md kept consistent). Documenter follow-up to the v1.1 implementation (T1-T7).

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
docs(plans): close out v1.1 doc/arch tracker — all items resolved
Some checks failed
CI / pnpm gate (typecheck, lint, build, test) (push) Successful in 1m49s
release / build + scan + publish (push) Failing after 40s
49510aabfd
Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
fix(docker): re-admit vendored xlsx tarball stripped from build context
All checks were successful
CI / pnpm gate (typecheck, lint, build, test) (push) Successful in 1m27s
release / build + scan + publish (push) Successful in 1m50s
ffffa70eb0
release.yml's docker build failed at 'pnpm install --frozen-lockfile' with
ENOENT on /app/vendor/xlsx-0.20.3.tgz. Two compounding causes:

1. .dockerignore '**/*.tgz' (F3 skeleton, predates the v1.1-T2 vendoring)
   stripped the vendored SheetJS tarball — a file: dependency of
   packages/web — from the build context.
2. The Dockerfile copied vendor/ only at the bulk 'COPY . .', after the
   install that resolves it (and the bulk copy is filtered by .dockerignore
   anyway).

ci.yml (no Docker) was unaffected — it installs against the host checkout
where the tarball is present.

Fix:
- .dockerignore: add '!vendor/*.tgz' below '**/*.tgz' (last-match-wins) to
  re-admit the vendored tarball while still excluding host .tgz noise.
- Dockerfile: COPY vendor/xlsx-0.20.3.tgz before each 'pnpm install'
  (builder + runtime), joining the manifests-only cache layer.

Verified: full 'docker build' completes; both installs succeed with no
ENOENT; xlsx bundles (dist/assets/xlsx-*.js). The runtime COPY is required
because xlsx is a prod dep (--prod still resolves the file: reference).

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Adds docs/specs/selection-model.md (decoupled selected/highlighted states; plain-click/checkbox/Ctrl/Shift gestures; action-bar and SQL-button target rules) and the editable-editor requirement; sql-query.md entry/exit lifecycle, default query SELECT * FROM '<last-compatible-file>' on every re-entry, gated TopBar SQL button, and Back-to-browser + auto-close-on-empty; cross-references in ui-shell/object-operations/object-metadata + README index. Reopens v1.1 scope in docs/plans/v1.1.md with Wave F: F1 selection model, F2 SQL lifecycle, F3 editor bug (F3 sequenced last so an architect escalation on the CodeMirror pin cannot block F1/F2).

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Decouple the object list into a single highlight (inspection target) and a multi selection (bulk-action target) per docs/specs/selection-model.md. Add a range anchor; implement the asymmetric gesture coupling (plain click -> highlight only; checkbox and Ctrl/Cmd -> toggle selection + set highlight + anchor; Shift -> range-select loaded object rows from the anchor, replacing selection outside the range, folders excluded). Navigation/Clear reset highlight + anchor + selection via clearAll(). Keep O(1) Map membership on the virtualized hot path (new Map ref on mutation). Rewrite the prior separate-gesture JSDoc to point at the spec as source of truth; the reversal is a code-level UX note, not an ADR. Deprecated back-compat aliases retained for F1-T2 wiring. Tests: 84 in selection-store.test.ts (+57).

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Wire the F1-T1 store into the list UI and Inspector per docs/specs/selection-model.md. BucketPage: handleRowGesture dispatches Shift->rangeShift, Ctrl/Cmd->toggleCtrl, else->highlight (modifiers read off the click event only, so CodeMirror shortcuts are not captured); effectiveObjects drives the action-bar target (selection -> highlighted -> hidden) and retargets download/delete/SQL; tint = highlighted OR selected; checkbox = selection mark (aria); navigation/Clear reset via clearAll(). Inspector target rebound to s.highlighted (decoupled from the multi-selection). Remove the deprecated back-compat aliases (selection, select, clear, clearSelected, toggleSelected) now that all callers are migrated; removeSelected retained (ObjectOpsDialog). DownloadDialog post-confirm clear migrated clearSelected->clearAll (spec-aligned; pinned by a test). Prune stale comments referencing the removed APIs.

Tests: +jsdom wiring in bucket-page.test.tsx and download-dialog.test.tsx; new tests/e2e/selection-gestures.spec.ts Playwright pass (plain-click inspects without altering selection, Ctrl/Cmd, Shift range, no-anchor fallback, Clear/navigation reset, action-bar visibility). Web unit 1175 pass; typecheck/lint/build clean; e2e 33 pass / 5 skip / 0 fail.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Make the TopBar SQL control conditionally enabled per docs/specs/sql-query.md + ui-shell.md + selection-model.md: enabled when the effective selection contains >=1 SQL-compatible file (that compatible subset is the source set), else when the highlighted file is compatible (single source; size resolved from the TanStack Query LIST cache since ListSelection carries no size; cache miss disables, no crash), else disabled with the tooltip 'Select or highlight a CSV, TSV, TAB, TXT, JSON, or Parquet file to query'. Click snapshots the effective sources into useSqlStore.setSources before navigate('/sql') — identical effect to the action-bar entry point. Selection-derived sources are sorted by key (localeCompare) to match the action-bar ordering exactly, so the two entry points agree (F2-T2 will reconcile both to true insertion order for the default-query rule). Promote QUERYABLE_EXTS/isQueryableExt/aliasFromKey into a new shared module sql/compatibility.ts (re-exported via the sql barrel) and refactor BucketPage to import them (pure extraction, no behavior change).

Tests: +topbar gating tests (enabled/disabled states, verbatim tooltip, click snapshot + navigate, cache-miss fallback, case-insensitivity, nested-key alias, shared-module parity, and a >=2-source sorted-order regression guard). Web unit 1195 pass; typecheck/lint/build/duckdb-pin clean.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Pre-fill the SQL editor with SELECT * FROM '<alias>' on every (re)entry to /sql per docs/specs/sql-query.md (Default query on (re)entry). The alias targets the LAST source = the most recently selected compatible file (insertion order of the snapshot), with a lexicographically-greatest-alias fallback for the indeterminate case. A mount-only effect in SqlRunner writes the default once per entry (route mount) and does not re-fire on in-workbench source changes, so a stale prior query is not retained across visits while user edits are preserved while remaining in the workbench. Adds pure helpers lastSourceAlias / fallbackLexicographicallyGreatestAlias / defaultSqlForSources to sql-store.

Ordering reconciliation: the spec defines 'last' as insertion order, but F2-T1 had both SQL entry points sort the snapshot by key, discarding toggle order. Reconcile both entry points to true insertion order — TopBar.computeEffectiveSqlources no longer key-sorts; BucketPage.handleOpenInSqlRunner iterates selectedKeys directly (insertion order) with the highlight fallback. Both entry points remain byte-identical for the same selection ('identical effect'). The action-bar's bulkObjects key-sort for delete/download is intentionally left intact (stable-UX, unrelated to SQL).

Tests: +sql-store helper tests, +sql-runner default-query lifecycle (entry re-writes, in-workbench edits preserved on chip add/remove), updated topbar ordering test to insertion order, +bucket-page reconciliation guards proving SQL=insertion while delete/download=key-sorted. Web unit 1223 pass; typecheck/lint/build/duckdb-pin clean. Note: alias single-quote escaping is a latent spec gap (S3 keys may contain apostrophes); implementation follows the spec's literal template — flagged as a non-blocking spec follow-up.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Make the SQL Runner leave-able and prevent a dead no-source state per docs/specs/sql-query.md (Exit + Auto-close on empty context; success criteria 97-99). Add a SqlOrigin {bucket,prefix} captured at entry (extend setSources with an optional origin arg, backward-compatible); both entry points (TopBar + action-bar) pass {bucket,prefix}. Add a 'Back to browser' control in SqlToolbar (always available; navigates to the origin; leaves sources still loaded). Auto-close: removing the LAST source chip commits setSources([]) then navigates back to the origin list view before any dead 'no source selected' state can paint; non-last chip removal shrinks without closing. Both exits share one leaveToOrigin helper (useNavigate; '/' fallback when origin is null).

Tests: +jsdom (origin capture from both entry points, Back-to-browser always-available + navigates + leaves sources loaded, auto-close single + multi-chip chain, origin preservation across mid-chain removals, setSources backward-compat); new tests/e2e/sql-runner.spec.ts Playwright smoke (default-query pre-fill via both entry points, Back-to-browser, leaves-sources-loaded, auto-close single + multi) structured with a clean F3 insertion point. Web unit 1251 pass; typecheck/lint/build/duckdb-pin clean; e2e 34 pass / 5 skip / 0 fail.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Fix the dead SQL editor. Root cause (proven via a controlled bypassCSP A/B): the proxy's strict style-src 'self' CSP blocked CodeMirror 6's runtime-injected <style>/inline styles (the .cm-cursor caret rules + the editor-height rule), collapsing the editor to one line (~56px) with an invisible caret — the 'dead editor' appearance. The editor machinery itself (focus, keystrokes, controlled-value round-trip) was functional; the user-visible defect was the collapsed height + invisible caret. NOT the dual-@codemirror/view version pin (that is a separate latent defect — it costs SQL syntax highlighting, not editability — and remains architect/ADR territory; no dependency was re-pinned here).

Fix: widen style-src to 'self' 'unsafe-inline' in packages/proxy/src/security-headers.ts — the standard CodeMirror 6 posture (StyleModule mints dynamic instance-scoped class names at runtime, so per-rule hashes/nonces are impractical; style-src 'unsafe-inline' does not enable script injection). This extends ADR #25's v1.1 CSP-widening theme; an inline pointer is left for the architect to record the entry (ADR update is architect-owned). Updates the module-header + constant JSDoc rationale and the security-header tests.

Regression guards: jsdom 'editor mounts' smoke gains an 'accepts input' assertion (controlled-input wiring); new real-browser Playwright block at the F3 insertion point in tests/e2e/sql-runner.spec.ts asserts caret border-left-width > 0, editor height > 150px, and that keystrokes modify .cm-content (measured: caret 1px, height 299px, input works). Proxy 713 pass, web 1252 pass; typecheck/lint/build/duckdb-pin clean; e2e 43 pass / 5 skip / 0 fail.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Supported sources now list the full implemented set (CSV/TSV/TAB/TXT/JSON/JSONL/NDJSON/Parquet incl. .parq) instead of CSV/Parquet/JSON. The default-query alias is embedded as a SQL-escaped string literal (single quotes doubled) so basenames like it's.csv yield runnable SQL. Syntax highlighting is recorded as out of v1.1.0 (deferred to v1.1.1, blocked on the dual @codemirror/view pin); the editor stays editable. These are spec aligns to shipped behavior + the F2-T2 escaping follow-up; no behavior change beyond the escaping fix the PM will implement.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
The default SELECT * FROM '<alias>' now embeds the alias as a SQL-escaped string literal: each single quote is doubled, so a basename like it's.csv yields the runnable SELECT * FROM 'it''s.csv' instead of broken SQL. F2-T2 (047600d) interpolated the alias raw; the spec (sql-query.md "Default query on (re)entry" + success criterion, updated in 96dde1d) now requires escaping. Only the alias interpolation changes; no other behavior.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
v1.1.md: Wave F status flipped to COMPLETE — all six F-tasks committed (a8d2f5e, 7d9f335, 2680f31, 047600d, b659bbb, ad800ae) plus the F2-T2 escaping follow-up (ddaab45); latest gate 2115 tests green. The SQL syntax-highlighting residual is recorded as deferred to v1.1.1 (dual @codemirror/view pin), with the CSP/ADR #25 and dual-pin questions routed to the architect by the Principal. backlog.md: the @codemirror/view dual-version item retagged [improvement][raw] -> [bug], confirmed user-visible defect (highlighting dropped, editor still editable), targeted v1.1.1, re-pin flagged architect/ADR territory.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
ADR #25 addendum (status stays Active): resolves the style-src 'unsafe-inline' verify-at-impl caveat ADR #25 anticipated. Records the F3-T1 evidence (CodeMirror 6 runtime styles; bypassCSP A/B proved CSP, not the dual pin, caused the dead editor) and the threat rationale (styles-only; script-src stays strict; img-src/font-src/frame-ancestors neutralize CSS-exfil/clickjacking). Opens docs/plans/v1.1.1.md with a single scope item — restore SQL syntax highlighting by resolving the dual @codemirror/view pin (6.7.1 pinned + 6.43.8 transitive); the re-pin ADR + verification are part of v1.1.1 execution. The item is promoted out of backlog.md (cut/paste/delete per the plan lifecycle).

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
docs(plans): drop v1.0.1 plan (shipped — plan-lifecycle)
All checks were successful
CI / pnpm gate (typecheck, lint, build, test) (push) Successful in 1m20s
release / build + scan + publish (push) Successful in 46s
5b8a887406
Per the docs/plans/ lifecycle, a vX.Y.md execution file is deleted when its release ships — git at the ship tag is the permanent record, and the working tree holds only active versions. v1.0.1 has shipped (its features are in HEAD), so the file is removed.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
- Vendor parquet/json/icu (x wasm_eh + wasm_mvp) for duckdb core v1.4.3
  (inside duckdb-wasm 1.32.0) under packages/web/public/duckdb-extensions/,
  SHA-pinned via extensions.json.
- New scripts/fetch-duckdb-extensions.mjs (deterministic) and
  scripts/check-duckdb-extensions-pin.mjs (CI gate, wired into check + ci.yml
  alongside check:duckdb-pin).
- Engine init points duckdb at the vendored set via SET custom_extension_repository
  (same-origin); no runtime fetch to extensions.duckdb.org.

ADR #32 section 4 pseudocode (registerFileBuffer -> INSTALL -> LOAD -> SET
autoinstall_extensions=false) proved unimplementable in duckdb-wasm 1.32.0:
WASM_LOADABLE_EXTENSIONS disables INSTALL-from-path and autoinstall_extensions
is not a valid setting. Replaced with SET custom_extension_repository, verified
0 third-party fetches under Playwright Firefox 153. Erratum recorded in ADR #32
section 4. Closes the mobile-Firefox parquet-query regression.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
v1.1.md: add F4 (vendored duckdb-wasm extensions, ADR #32) and F5
(panel-scoped source registry, ADR #33) scope items + Plan-layer task
breakdown (wave order F4 -> F5-T1 -> F5-T2). F4 marked done (63be1ab)
with the ADR #32 section 4 erratum mechanism (SET custom_extension_repository).
v1.1.1.md: broaden from single-item to two-item patch (add the duckdb-wasm
autocomplete extension alongside the CodeMirror pin fix).
backlog.md: seed the external-data-sources [feature] [raw] item
(iceberg/vortex/external S3/catalogs) per the Principal sketch.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Replace the per-query register/drop cycle (ADR #31 section 3, superseded)
with a panel-scoped registry (ADR #33): sources load once when the SQL
Runner opens, stay for the panel lifetime, drop on exit.

- duckdb-coordinator: module-level registeredSources map; new
  ensureSourcesRegistered (idempotent, per-source + cumulative cap gate,
  partial-success-safe) / dropSources / dropAllSources; runQuery and
  exportQuery reshaped to ensure -> run (no per-query register/drop);
  L2 cancel (worker.terminate) and teardown invalidate the registry via
  onRegistryInvalidated.
- sql-store: sourceStatus map (idle/loading/ready/error) + loadSources;
  setSources diffs the registry; run() awaits load before execute;
  subscribes to invalidation (statuses -> idle).
- SqlRunner: mount triggers loadSources; unmount drops all sources
  (covers back-to-browser + auto-close-on-empty).
- Inspector describeBuffer/describeSource stays per-call (ADR #30);
  shared mutex, 1 GB cap value, and ADR #31 sections 1/2/4/5/7/8/10
  unchanged.

The 1 GB cap (ADR #11) is re-scoped per-query -> per-panel; value
unchanged. Latent alias-collision with the Inspector one-shot drop is
unreachable in v1.1 (Runner unmounts before any Inspector run) and routed
as a follow-up.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Presentation half of the panel-scoped source registry (ADR #33 sections 4/6),
layering on the F5-T1 store state (committed c8132b9). Behavior was already
correct without this UI (runQuery ensures sources internally); these are
presentational affordances.

- SourceChips: per-source status badge (loading pulse dot / ready checkmark /
  idle ring / error bang), shape-coded not color-only, role=img with
  accessible name + tooltip. Auto-close-on-empty and the no-in-workbench-picker
  rule (F2-T3) preserved.
- SqlToolbar: Run disabled only while a QUERIED source is loading (enabled on
  ready/idle/error so the click is the reload/retry trigger — no post-cancel or
  retry deadlock); the gate reads only queried sources (single = sources[0],
  multi = all), mirroring the store sourcesForQuery selector. A Preparing
  sources / Re-preparing sources transient (role=status, aria-live=polite)
  surfaces the panel-entry pre-load and the post-L2-cancel re-register.
- Tests: 10 cases (4 Run-gating, 3 re-preparing transient, 3 per-source badge),
  mutation-checked.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
COMPONENTS.md SQL Runner coordinator: the runQuery/exportQuery
"errors on a registry miss" line was wrong vs ADR #33 section 2.
Corrected to: internally call ensureSourcesRegistered first (idempotent;
registry hit -> straight to SQL; miss -> fetches via loadSourceBuffer,
covering L2-cancel recovery and the Run-clicked-before-mount-load race).

DECISIONS.md ADR #33 Consequences: appended a forward-risk note on the
alias collision between the Runner registry and the Inspector per-call
registers (same basename namespace). Latent and unreachable in v1.1
(Runner unmounts before any Inspector run); records the fix shape
(per-caller alias prefix) if a future split-view design lands. No code
change for v1.1.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Pre-existing (ships in v1.0.1), benign Zod allowsEval probe fires a CSP
securitypolicyviolation on the strict CSP. Surfaced during the v1.1
pre-tag F4 dual-engine re-verification; unrelated to F4/F5. One-line
jitless fix; candidate for v1.1.1 or v1.1 GA (Principal's call).

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Principal decision (Option A refined): the one-line globalConfig.jitless
= true fix is isolated in its own v1.1.2, NOT bundled into v1.1.1
(which stays frozen at CodeMirror highlight + autocomplete). Promote
the Zod allowsEval [bug] entry out of backlog into v1.1.2 scope. Scope
layer only; Plan layer appended when v1.1.2 execution is greenlit.
Architect-owned ADR #25 clarifying note flagged for execution time.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
docs(specs): sql-query — cover ADR #33 panel-scoped source lifecycle
All checks were successful
CI / pnpm gate (typecheck, lint, build, test) (push) Successful in 1m52s
release / build + scan + publish (push) Successful in 2m39s
abd2c14782
Add the 'Source pre-load lifecycle (panel-scoped)' section: pre-load on entry, per-source status badges (idle/loading/ready/error), Run-button gating on queried-source readiness, 'Re-preparing sources…' transient for L2-cancel recovery, and the cap-scope reinterpretation (per-panel for the Runner, per-call for the Inspector, value unchanged at 1 GB). Aligns the spec with the shipped F5-T1/F5-T2 code (commits c8132b9 + ea218a2) and ADR #33 (which supersedes ADR #31 §3's per-query register/drop cycle).

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
chore: rename compose files to compose.{h1,e2e,e2e.dropdown}.yaml
Some checks failed
CI / pnpm gate (typecheck, lint, build, test) (pull_request) Failing after 1m31s
CI / pnpm gate (typecheck, lint, build, test) (push) Failing after 1m51s
release / build + scan + publish (push) Successful in 49s
756bbd5b37
Standardize naming ahead of v1.1 tag. Renames three compose files and updates all 19 reference sites (AGENTS.md, CONTRIBUTING.md, docs/, packages/proxy/, tests/e2e/) via repo-wide replace. No executable code touched — stacks are managed externally; references lived in comments/docs/configs. typecheck + lint green.

Co-Authored-By: Xavier's assistant <assistant@gijoe88.com>
xavier merged commit 756bbd5b37 into main 2026-08-14 06:39:59 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
xavier/s3-vedrfolnir!3
No description provided.