Skip to content

feat: column lineage, worker ad-hoc commands and UI pages - #1384

Merged
kvlonge merged 142 commits into
mainfrom
feat/combined-lineage-workers
Nov 9, 2026
Merged

kvlonge merged 142 commits into
mainfrom
feat/combined-lineage-workers

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Why

One pull request for ready work: one full Verify run, each part its own changelog entry.

Changes

  • Snapshots publish column lineage from native edges; catalog node pages show it.
  • Ad-hoc test, seed, audit and freshness run on workers from the verified project; checks-only runs no longer mark unrun nodes successful.
  • The UI uses the website's logos and favicon via a $website alias; changes to them run the UI job.
  • Overview: / shows live runs, checks, nodes, snapshots and problems; a partial viewer gets a plain message.
  • Maintenance shows synced renames, old-name views and clean-ups instead of mock data.
  • Person pages give and remove roles and disable people; Locations rows test a connection.
  • The control client is regenerated for the run commands, and make check-ci checks it.

main (0.203.0) is merged in.

Verification

  • make check-ci passes on the head, including the client check.
  • Orchestration lib tests pass, including ad-hoc, worker and snapshot.
  • UI: vitest (130), svelte-check, vite build.
  • A logo change selects only the UI job.
  • Each part passed its own audit.
  • Hygiene scans are clean.

DuckShop: no new case; no project shape, data value or lifecycle sequence is involved.

BEGIN_COMMIT_OVERRIDE
feat: publish column lineage and show it on catalog node pages
feat: run test, seed, audit and freshness ad-hoc commands on workers
fix: run every ad-hoc verb from the worker's verified project
fix(ui): show the approved logos and favicon from the website
ci: run the UI checks when the website logos or favicon change
feat(ui): show the Overview from live runs, checks, models and deploys
feat(ui): tell a partial viewer why the Overview is empty
feat(ui): show renames, old names and clean-ups on the Maintenance page
feat(ui): give and remove roles and disable people from the admin pages
feat(ui): test a location's warehouse connection from the Locations page
ci: check the generated control client in make check-ci
END_COMMIT_OVERRIDE

…use Recall relations portably

SQL Server's render_create_function stripped a table function's SELECT and
wrapped it in BEGIN RETURN (...) END, which the engine rejects. A TABLE return
now renders RETURNS TABLE AS RETURN (<query>).

sqb recall schema --backend warehouse matched state relations with
LIKE '\_sqlbuild\_%' ESCAPE '\', which ClickHouse cannot parse. A prefix
comparison with SUBSTRING needs no escape in any dialect.
A native lint response can report that the engine does not parse the project's
dialect yet. Each such file now gets one L007 warning carrying the engine's
reason, instead of looking lint-clean. A non-string reason is rejected as an
invalid response.
…n and refuse WITH source expressions

render_create_schema doubled quotes only in the sys.schemas lookup, so a schema
name with a quote broke the EXEC string. render_merge now ends with the
semicolon SQL Server requires. A source expression starting with WITH cannot
sit in a derived table on SQL Server, so it now fails with A715 and a rewrite
hint instead of a warehouse syntax error.
… of SQL library probes

The unknown-function check (B101) asked the SQL library's parser which
built-in node each unaccepted call spelling becomes, and took DuckDB's
accepted names from the library's function catalogue. The check now reads
a table of the 41 rejected spellings, each with its argument count and the
spelling the dialect accepts. Every DuckDB row was confirmed unknown to
DuckDB 2.0.0. The call scan takes the analysis dialect name, so analysis
off the library can run it unchanged.

Findings are identical on every DuckDB and Snowflake query of the compiler
differential corpus and on every candidate spelling at 0 to 9 arguments.
The workspace no longer depends on the library's function-catalogue crate
directly; resolved features are unchanged.
…le and rules run

compile and rules run kept only selected Rule codes, so an unavailable dialect
looked clean there. L007 now passes through as a warning-severity Rule
diagnostic in compile and is left out of rules run's failing-finding count.
counts_toward_exit owns the exemption.
The plan and build rules gate failed on any finding, so an L007-only project
could not plan. Rule exceptions also validate every finding's code as a rule
code and rejected L007 with an invalid-lifecycle error. The gate now counts only
findings that count toward exit, and L007 passes through rule exceptions
unsuppressed. An end-to-end test replays a cached finding as L007 and as a rule
code through compile, rules run, plan and build.
…g issues

A same-run time ratio cannot see one store round trip per node: that cost is
linear. Tests now count the statements each task issues, and the wide listing
must read builds 100 nodes per statement: 17 statements for 1,000 nodes and 37
for 3,000 on SQLite and PostgreSQL, 1,008 with one node per statement. The
ratio check stays and now guards super-linear growth only.
The dynamic column contract proof parses pivot SQL with SQLQuack's shared
parser (DuckDB, MotherDuck, Snowflake) instead of Polyglot. DuckDB trees
match Polyglot's exactly; a Snowflake aggregate keeps its argument in a
call's argument list, which the proof now reads. Other dialects keep the
existing unsupported-dialect message.
Local scenario capture no longer asks Polyglot to read warehouse column
types. Postgres types go through sqlquack-syntax-postgres's type parser,
and Snowflake and BigQuery types through their SQLQuack cast-target
parse, behind one native function (parse_warehouse_type). DuckDB and
MotherDuck spellings pass through unchanged. Databricks nested types map
recursively to DuckDB's LIST, MAP and STRUCT, and a nested spelling that
cannot be mapped is refused with a named message instead of falling back
to JSON. Other types keep their integer width or fall back to VARCHAR.
SQL Server has no SQLQuack type parser, so its information_schema names
reached the generic fallback, which held datetime2, smalldatetime,
datetimeoffset and uniqueidentifier as VARCHAR. A SQL Server pre-mapper
now maps them to TIMESTAMP, TIMESTAMPTZ and UUID, bit to BOOLEAN, money
and smallmoney to exact decimals, and SQL Server's 8-byte float to
DOUBLE.

The fallback keeps 4-byte floats (FLOAT, FLOAT4, REAL) as FLOAT instead
of widening them to DOUBLE. A panic in the warehouse type parser now
surfaces as the ValueError capture already falls back on.
The ad-hoc launch looked up its new run through the shared runs listing
without clearing it, so a listing started before the launch could answer
without the run and report it missing while it was already queued. The
launch now clears shared listings after its write, as a job launch does.
# Conflicts:
#	crates/sqlbuild-orchestration/src/api/_helpers/authentication/password_sessions.rs
#	ui/src/lib/api/http-client.ts
Workers now run every verb the ad-hoc planner accepts, not only build.

- The planner checks each verb's settings against its own parser. Seed
  runs keep only the selected seeds. Freshness runs take the selected
  sources and the sources upstream of the selection, less those the
  exclusions reach.
- Runs freeze their command. The worker rebuilds that command's argv
  from the frozen settings and selection, and refuses a parse that
  dispatches anything else.
- Test and audit runs report each SQL test or audit the snapshot
  publishes as a check, and each selected node takes the worst result
  of its checks. Seed runs refuse seeds outside the frozen write set
  before connecting. Freshness runs report each source.
- Only build and seed have a write set, so test, audit and freshness
  runs take no write claims.
Test, audit, seed and freshness runs re-read the location's checkout
after the worker verified it against the frozen snapshot. A checkout
that changed in that window could run SQL, audits or seed contents that
were never verified. Every verb now runs from the verified inputs, as
build already did.

A test or audit run that was refused, or that raised, no longer records
an unchecked node as successful. Such nodes are recorded as skipped.
The web UI shipped older copies of the SQLBuild logo and favicon. It now
imports the website's approved files through a $website alias, so a
branding change reaches both, and a unit test rejects image copies or
literal logo paths under ui/.
The UI now imports the website's logo and favicon files, so renaming
or moving them breaks the UI build. Route those three paths to the
fast UI job.
@kvlonge kvlonge added the full-verify Run the full Verify matrix on this pull request label Nov 9, 2026
@kvlonge
kvlonge enabled auto-merge (squash) November 9, 2026 00:40
The Overview, where every sign-in lands, ran only on mock data, so the
server showed "Not available" there. It now reads the runs, checks,
catalog nodes, publications and platform problems the person can
already list: runs and outcomes in the last 24 hours, failed and
unresponsive runs, check outcomes, deployed models and this week's
model changes, and recent deploys.

The server has no project-wide build state, cost or group read yet, so
stale counts, cost and group status stay hidden rather than showing
zeros, as does the activity timeline. Recent deploys show the short
commit.
@kvlonge kvlonge changed the title feat: column lineage, worker ad-hoc commands and UI branding feat: column lineage, worker ad-hoc commands, UI branding and Overview Nov 9, 2026
A person with view on only part of a target signed in to a page error,
because every listing the Overview reads needs view on the whole target.
The client now answers null for that refusal and the page explains it,
naming the target and linking the pages that do not list it. Other
errors still show as errors, and no partial counts are shown.
The partial-view message used whatever data the last load left, so
after switching location it named the new target while that target
loaded, and a failed load never showed its error. The message now
needs a settled, error-free load, and errors show in every state.
The Maintenance page ran only on mock data. It now reads the synced
maintenance history the person can list for the target: renames and
moves, the old-name views kept for them with each recorded step, and
clean-up archives and deletes. Each old-name view takes every fact from
the newest step that records it; a relation recorded without its schema
shows by its bare name.
The client check ran only as its own Verify step, so a stale client
passed make check-ci locally. check-ci now runs it, and Verify runs it
through check-ci after installing the packages.
The person page's role and account controls had no server calls behind
them. Giving a role, removing a manual one, and disabling or enabling a
person now use the server's existing admin endpoints, then read the
result back. The add control offers only what the server accepts:
built-in roles for every location, a location's own roles there, and
admin only for every location.

The page also hides its effective-access and access-checker panels and
the audit "Check this" links where the server has no read for them, and
long audit subjects wrap.
@kvlonge kvlonge changed the title feat: column lineage, worker ad-hoc commands, UI branding and Overview feat: column lineage, worker ad-hoc commands and UI pages Nov 9, 2026
Each location row now has Test connection for people who may test that
location. The UI asks the location through the server's connection-test
request, then reads the result until the location answers or the
request expires, and shows whether it connected. The location reports
no reason, so a failure points to sqb debug in the location.
@kvlonge
kvlonge merged commit 4070f12 into main Nov 9, 2026
52 checks passed
@kvlonge
kvlonge deleted the feat/combined-lineage-workers branch November 9, 2026 02:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

full-verify Run the full Verify matrix on this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant