Add SQL support #71
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/mcp-beaver#71
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Engineer read by Angie (
claudeseat), 2026-08-19. This issue isautonomy/async-consultrole/directorwith an empty body, so it is not mine to build or to scope. Recording the technical context the consult would need, because the answer is less like#70than the neighbouring titles suggest.SQL is not a near neighbour of the graphql epic
Both read as "another upstream flavour". They are not the same size.
#70adds a node to a grammar that already produces the request it needs. A GraphQL call is an HTTP POST with a JSON body, so the whole existing engine underneath it (base-url, auth, rate limit, cache, confirmations, pins, restrictions,fail-when) applies unchanged.SQL has no transport here to attach to. Measured across both trees:
v0.154.0:grep -rn "database/sql\|pgx\|sqlite\|mysql"over the whole module returns nothing. The guarded-execution engine ishttp/opcore, and its unit of work isDescriptorplus an HTTP request.main: the only transport ininternal/mcpserverisnet/http.So a
sqlgrant is not a new node on an existing request. It is a second execution engine beside the HTTP one, with its own connection lifecycle, pooling, credential shape, and cancellation. Every guardfile control listed above would need a second meaning or an explicit refusal.The questions the consult probably turns on
Offered as the engineering shape of the decision, not as a recommendation, since scope here is the director's.
#84is already about proving the second half. Grants enumerate operations. A SQL surface either enumerates fixed statements (which is a stored-query feature, closer to#70than to "SQL support") or accepts caller SQL, which is the opposite of deny-by-absence and would be this product's first reachable-by-construction surface.#70comment above), asqlgrant type is umbra's guarded-execution half, and mcp-beaver would own only the projection of a result set into tool content. But umbra taking a database driver is a materially bigger call than umbra takingencoding/xmlwas, and that is a question for umbra's own charter rather than an implementation detail of this issue.Status
I did not write a body, retitle, relabel, or scope this. It stays where it is at
priority/P4autonomy/async-consultawaiting the human consult its label names. The read above is meant to make that consult cheaper, not to preempt it.Delivered. Closing. Angie (engineer,
claudeseat).This was an empty-bodied
autonomy/async-consultrole/directorissue. Kai's "let's teach umbra graphql and sql" was that consult, so the design questions I recorded above got answered rather than deferred.What shipped
umbra#308(8b098f7, releasedv0.159.0) -database <driver> { value ... }at wrap level,sql { statement ...; param ...; max-rows ... }per grant.5802a9a- pin umbrav0.159.0. No code change: params project atLocationBodylike graphql variables.178ffcc- register thepgxdriver, so asqlgrant runs rather than only lints.The design question this issue turned on
I flagged it above: a query language is the one place deny-by-absence can quietly break, because a tool taking a SQL string reaches every table its credential can see. That would have been this product's first reachable-by-construction surface.
Named statements with bound parameters instead. The guardfile authors each statement; the caller supplies only declared parameters, which bind as placeholders and are never interpolated. Same shape
graphqltook for documents, and the same shape grants have always had.Fails closed at build on stacked statements, a placeholder set that is not
$1..$N, a count disagreeing with the params, a non-binding param type, asqlblock beside any HTTP construct, a grant with no wrap-leveldatabase, and a reading verb whose statement mutates. That last one walks a leadingWITHfor a hiddenDELETE, so a CTE cannot smuggle a write behindcan list.Zero dependency growth in umbra
umbra opens the named
database/sqldriver and imports none, so it stays policy-free and driver-agnostic. The choice of reachable databases is made in the consumer binary. mcp-beaver links Postgres only (pgx), on Kai's call: it is what the fleet runs, and every extra driver is image weight for a database nobody has. MySQL or SQLite later is one import.Verified, and not
Verified through a served mcp-beaver: a sql guardfile's
tools/listoffers exactly the declared params with the statement absent, and a call now reaches a real pgx connection attempt rather than an unregistered-driver error. umbra's own end-to-end ran against real SQLite throughdatabase/sql, where a bounded read reportedtruncated,ada'; DROP TABLE orders; --bound as a value and matched nothing, and the table was intact afterwards.Not verified: a successful round trip against a real Postgres. Docker's daemon is down on this host and the running instances are in the sirens namespaces, where connecting an agent is a DevOps action rather than an engineering one. Worth one real call before a sql guardfile ships to a cluster.
No deployed consumer yet
Nothing in
coilyco-bridge/deploydeclares asqlgrant. This is capability ahead of demand, which is how it was asked for. Reopening is cheap if "SQL support" meant something wider than a guarded query surface.