Repository navigation
Add typed runtime GraphQL mutations with committed output authorization [skip ci] - #115
Merged
Merged
Conversation
1 of 2 tasks
… [skip ci] Owner-authorized C reconciliation. Exact tested C tree retained, including corrected aliases/filter intent, protected cursors, lossless scalars and approved custom-directive rejection. Actions remain paused.
Retain exact tested reconciliation tree 8e9228b. No source deviation.
Dastari
changed the base branch from
feat/runtime-graphql-reads-20261009
to
main
October 12, 2026 00:06
Dastari
marked this pull request as ready for review
October 12, 2026 00:06
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implement D on accepted C/B: typed runtime GraphQL create/update/exact-key delete delegate to B's pinned state-machine transactions, independent intent/preimage/result authority and guarded atomic journal hooks. Every validated response-key group commits before returning a successful payload. Scalar return projections retain C's corrected alias identity and lossless wire forms; CAS authorization retains requested capabilities before empty-list constant lowering.
Base:
9d4cca34cb04ab0fd27c8313215001591f495c43(#114), containing accepted B04a1216aff86141ff6500b1dd0bf9adb4b0c6447(#113).Head:
3a59d08be5b663ac952de418eb02dc6321ee08e7.ORM/macros: aligned unpublished 0.43.0. Enable
sqlite,runtime-graphqlorpostgres,runtime-graphqlwith default features disabled. This implementation awaits exact-head review; it is not an adoptable release.D1 correction
The reviewed D head
e1568ec29cb5b25750cd7f90c39114b26e32be74allowed the locked dynamic executor's repeated resolver occurrences to start duplicate transactions. Repeated create reproduces constraint errors; repeated CAS could commit then report a redundant conflict. The new regression failed on that implementation before the correction.Each validated response key now has one request-scoped execution attempt and a terminal payload/error. Preflight merges inline/fragment payload fields, preserves first-occurrence document order and authorizes their complete projection. The first invocation executes B's transaction, guarded journal and post-commit authority once; repeats reuse its immutable captured result. The framework's response-object merger combines the selected fields. Distinct aliases remain separate serial transactions, even for the same record.
A dropped operation guard records a terminal nonretryable error, so an extension catching a resolver timeout and continuing to a repeat cannot restart work. After confirmed commit the error is
mutation_payload_canceledwithoutcome: "committed"; before confirmation it ismutation_outcome_unknownwithoutcome: "unknown", including possible COMMIT cancellation. Neither promises rollback or permits blind retries. Normal denial/error/timeout results are cached too. Each occurrence may report the cached sanitized error at its own location.Budgets reserve one group, not every repeated occurrence: four conservative ORM statements, one materialized node and the merged response shape. Document/fragment limits still count every occurrence. Host hooks bound their own extra I/O. Tests check one-group bounds (3 rejected/4 admitted), two-alias bounds (7 rejected/8 admitted), node limits and response capacity.
Owned SQLite/PostgreSQL regressions execute create/update/delete repeats, successful and stale CAS, named and inline fragments, merged scalar aliases, projection denial, distinct aliases in reverse lexical order, journal failures, post-commit denial/error/timeout, and canceled hooks/output authority while the executor continues. They assert single write-intent admission, journal invocation/row and post-commit check, current committed state and undisclosed denied values. Fresh requests do not reuse execution outcomes. Invalid conflicting repeats are still rejected by original GraphQL validation before writes.
No framework upgrade/fork, public interface change, data migration or changes to A–C are required.
Approved post-commit output contract
RuntimeReadAuthority::authorize_mutation_resultis object-safe and defaults to denial. Existing C-only implementations remain source-compatible. It supplements projection authorization before selection and B's transaction-bound result authorization.The callback receives schema/collection identity, mutation action, selected projection and immutable transaction-captured record.
RuntimeMutationRecordKind::DeletedPreimageidentifies delete output; ORM performs no post-commit reread. Internal policy/key fields stay unloaded, and serialization iterates only the selected projection after approval. Hosts must deny if policy-required values are absent.Explicit/default denial returns
mutation_payload_denied; other callback/encoding/budget errors returnmutation_payload_failed; the bounded callback timeout returnsmutation_payload_timeout. These sanitized errors containextensions.outcome = "committed"andextensions.retryable = false, with no protected values. They do not undo the write/journal. No callback runs for no-record/typename-only payloads. Whole-request cancellation or transport loss after commit may deliver no response: clients must reconcile state rather than infer rollback or retry blindly.Public APIs and executable example
RuntimeGraphqlOptions::with_mutations(RuntimeGraphqlMutationOptions); configurable action enablement, mutation limits and post-commit authorization timeout (default five seconds).mutation_rootandmutation_field; typed create/update/key inputs, existing recursive filters for CAS, schema fingerprint validation and scalar-only record payloads.with_mutation_environment,with_write_authority,with_mutation_hook.RuntimeMutationOutputCheck,RuntimeMutationRecordKindand the default-deny callback above.The compiled
crates/graphql-orm/examples/runtime_graphql_reads.rsnow demonstrates C/D together: protected reads, typed create, CAS update, exact-key delete, typed private journal inserts in the transaction, and explicit post-commit public-record release. The external repository consumer executes that same example without a direct async-graphql dependency.Local verification
Actions remain paused; skip-CI commits; CARGO_BUILD_JOBS=2; sequential backend lanes; disk scratch. SQLite resources are test-owned. PostgreSQL fixtures start isolated disposable servers and verify container identity/ownership before cleanup.
serde_jsondirectly. The final example uses graphql-orm's re-export and passed. No extra direct dependency was added.Commands (all build commands use the two-job environment):
Clippy/Rustdoc were repeated sequentially on PostgreSQL. MSSQL scoped Clippy targets the library and unsupported-backend test; its Rustdoc lane also passed. Hosted checks were not dispatched or rerun.
Compatibility, limitations and integration
No data migration or static API/SDL change. Non-generated create keys are required; generated fields are excluded and keys cannot be patched. Defaults remain omitted from GraphQL SDL; nullable omission/null stay distinct. Enabled create/update actions with no writable input fields reject with
unsupported_capability(GraphQL disallows empty input objects); hosts may disable those actions. Nested/bulk writes, new upsert semantics and nested relation return payloads are not provided. Custom-directive factories retain C's explicit composition-time rejection.Each distinct runtime mutation response-key group is a separate transaction; there is no whole-operation atomicity or durable event replay. Host hooks own and bound their additional I/O. The host owns policy-only revision validation, policy pinning, schema/DDL fencing, transport and outcome reconciliation. Default output denial intentionally means a committed write can yield a committed payload error.
Digibase handoff after exact-head review and owner release: retain the accepted C setup, enable mutations, compose the mutation root, attach the certified environment and pinned B write authority, install the guarded journal hook, and explicitly implement the new output callback. Validate complete public/policy revision independently of the ORM fingerprint. Run downstream SQLite/PostgreSQL null/default/key/CAS/journal and committed-output denial/cancellation contracts before adoption.
Final owner-controlled #112 → A → B → C → D reconciliation must still execute successful PostgreSQL string/CAS behavior. No merge, publication, immutable release identity or downstream adoption is claimed. Sibling repositories and predecessor worktrees remain untouched. T3 native linking attempts return
Authentication required.Documentation impact
Explanation: D updates the approved contract, runtime GraphQL reference, executable host example, compatibility/migration notes, changelog, versions/locks and inventory. D1 additionally documents response-key grouping, ordering, merged budgets and terminal cancellation outcomes; existing 0.43.0 versions and locks are unchanged by this correction. Post-commit denial, deleted preimages, hidden fields and cancellation/transport uncertainty are explicit.