Skip to content

fix(data): don't treat write-restricted tables as schema drift - #58

Merged
yyyyaaa merged 4 commits into
mainfrom
fix/data-compat-gate-on-meta-query
Nov 3, 2026
Merged

yyyyaaa merged 4 commits into
mainfrom
fix/data-compat-gate-on-meta-query

Conversation

@theothersideofgod

Copy link
Copy Markdown

The schema compatibility check fails every database with a storage module, so the dashboard Storage page shows only SCHEMA_INTROSPECTION_INCOMPATIBLE.

Why

_meta inflection is advisory: it names create/update/delete payload and patch types even for tables the caller cannot write. PostGraphile generates neither the types for an operation the grants do not allow, nor an input field for a column the caller may not write. Two shapes hit this today:

  • Append-only tables. data_room_file_events grants INSERT/SELECT only, and _meta.query.update/.delete are null. The check still reports UpdateDataRoomFileEventPayload, DeleteDataRoomFileEventPayload and DataRoomFileEventPatch missing. data_room_files_chunks has no UPDATE and fails the same way.
  • Platform-owned enum columns. Files tables grant UPDATE only on filename/description/tags. The check reports AppFilePatch.inputFields.status and DataRoomFilePatch.inputFields.status missing.

The Sheets adapter throws on any non-compatible result, so the whole page fails.

Fix

  • Require the create/update/delete payload, input and patch types only when _meta.query declares that operation. This is the same rule checkOperation already applies to the mutations themselves.
  • Accept an enum column that is absent from a create or patch input. One that is present with another type is still drift.

Trade-off: if a writable enum column disappears from an input, it is no longer reported, because _meta carries no per-column privilege. GraphQL validation still rejects such a write.

Before / after

Live tenants. I ran the dashboard's @constructive-io/data@0.7.0 and this branch's build against two local tenants, using each tenant's real _meta and introspection:

Tenant 0.7.0 This branch
data-room tenant (storage endpoint) 7 missing paths, the Storage page error compatible
app-files tenant 1 missing path compatible

Drift detection is unchanged on this branch: removing UpdateAppFilePayload or AppFilePatch (a writable table) is still incompatible.

Unit tests. There are 4 new tests. I swapped in the main source to run them:

  • 3 fail on main and pass here: the append-only table, the enum column absent from the patch input, and the enum column absent from the create input.
  • 1 passes on both: update/delete types are still required when _meta declares the operations. It is a guard, not a reproduction.

The 8 existing tests pass on both.

Suites on this branch: packages/data 157/157 and packages/sheets 369/369, after building @constructive-io/ui. tsc --noEmit passes for data and sheets.

Not verified: the dashboard page with this build installed. The dashboard pins @constructive-io/data@0.7.0 and would need a release and a bump.

🤖 Generated with Claude Code

theothersideofgods and others added 2 commits November 2, 2026 16:40
The schema compatibility check required every advisory `_meta` inflection
type (create/update/delete payloads, create input, patch) and every enum
column in the create and patch inputs, whether or not the caller can
perform that operation. PostGraphile generates neither a type for an
operation the grants do not allow nor an input field for a column the
caller may not write, so append-only tables and platform-owned columns
(a storage files table's `status`) were reported as incompatible and the
Sheets adapter refused the whole endpoint.

Require the create/update/delete types only when `_meta.query` declares
the operation, as `checkOperation` already does for the mutations, and
accept an enum column that is absent from an input while still rejecting
one present with another type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… rule

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tenki-reviewer

tenki-reviewer Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Review complete. No issues found — approved ✅.


This PR makes @constructive-io/data's schema-introspection compatibility checker tolerant of grant-driven schema omissions: mutation payload/input types and enum input fields whose absence is explained by column-level permissions no longer trigger a false incompatibility verdict.

Files Change
packages/data/src/schema-introspection-compatibility.ts Gates create/update/delete payload and input types on _meta.query hints, and treats missing enum input fields as compatible instead of drift.
packages/data/src/__tests__/schema-introspection-compatibility.test.ts Adds coverage for the new grant-driven compatibility paths.
packages/data/README.md Documents the new compatibility behavior.

Two low-confidence residual concerns remain out-of-band: the missing-field early return also fires when inputFields itself is absent (truncated introspection reads as compatible), and a null table.query now silently skips all mutation-type validation; both only degrade diagnostics since GraphQL variable validation still gates actual writes.

Reviewed commit: 95030eb

The upload op creates the files row before the bytes are sent. On a storage
module without confirm-upload nothing ever settles that row, so a failed PUT
left a file listed in the bucket whose download 404s. The upload seam now
discovers the file type's delete-by-id mutation and removes the row it just
created before rethrowing the PUT error. Deduplicated uploads are untouched.

A PUT the browser cannot complete now reports STORAGE_UPLOAD_BLOCKED and names
the bucket's allowed origins (CORS), the usual cause, instead of a generic
network error.
The registry smoke install typechecks Sheets inside a fresh host, where
`.catch(() => undefined)` fails TS7011. Swallow the cleanup error with a
plain try/catch instead.
@yyyyaaa
yyyyaaa merged commit 14b39db into main Nov 3, 2026
6 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.

3 participants