Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
1f058be
fix: conceal CLI secrets and honor the requested bind address
rrrodzilla Sep 24, 2026
f636f0e
fix: route GraphQL mutations through the canonical write pipeline
rrrodzilla Sep 24, 2026
b4c819b
fix: enforce schema-aware tenant boundaries and invitation scope
rrrodzilla Sep 24, 2026
6870c99
fix: authorize write inputs before rules and validate final fields
rrrodzilla Sep 24, 2026
4ef1945
fix: add tenant isolation regressions and warn on empty access grants
rrrodzilla Sep 24, 2026
6a83608
fix: enforce concrete Cedar authorization for GraphQL reads and deletes
rrrodzilla Sep 24, 2026
a075ce0
test: cover incomplete create authorization and optional rule bindings
rrrodzilla Sep 24, 2026
049d4fa
test: cover tenant boundaries in PostgreSQL and GraphQL
rrrodzilla Sep 24, 2026
aec3636
docs: describe canonical GraphQL mutation behavior and integration
rrrodzilla Sep 24, 2026
955a194
fix: refuse tenant count certification when metadata column is missing
rrrodzilla Sep 24, 2026
b7c5961
fix: preserve fail-closed bindings on CEL conversion errors
rrrodzilla Sep 24, 2026
a998351
fix: align replacement rules with persisted optional field values
rrrodzilla Sep 24, 2026
73658ed
fix: reauthorize input after denied fields are removed
rrrodzilla Sep 24, 2026
2de99bd
docs: clarify runtime tenant normalization and grant diagnostics
rrrodzilla Sep 24, 2026
d703c1f
feat: make schema migrations explicit and preserve renamed fields
rrrodzilla Sep 24, 2026
9cdb1af
fix: classify GraphQL integrity violations as conflicts
rrrodzilla Sep 24, 2026
1aac552
ci: exercise migration and GraphQL security regressions
rrrodzilla Sep 24, 2026
2aa0131
docs: document v0.45.0 security fixes and migration requirements
rrrodzilla Sep 24, 2026
a52c955
refactor: validate schema transitions in the migration planner
rrrodzilla Sep 24, 2026
322385c
test: verify schema update refusal preserves stored data
rrrodzilla Sep 24, 2026
c2a92a1
test: import migration backend trait for write fixtures
rrrodzilla Sep 24, 2026
c9b7376
fix: preserve rename constraints and atomic migration batches
rrrodzilla Sep 24, 2026
def12d8
chore(release): prepare v0.45.0 and align library versions
rrrodzilla Sep 24, 2026
e7ce380
test: pass migration steps to GraphQL fixture backends
rrrodzilla Sep 24, 2026
a061685
docs: define field rename hints in the DSL reference
rrrodzilla Sep 24, 2026
cfc2bb2
fix: restore denied replacement fields through map entries
rrrodzilla Sep 24, 2026
ceccc19
fix: preflight tenant topology and classify lossy migrations
rrrodzilla Sep 24, 2026
8965187
test: use the string default variant in safety regression
rrrodzilla Sep 24, 2026
d2294b0
test: scope backend trait imports to write fixtures
rrrodzilla Sep 24, 2026
1effc00
fix: validate exact custom policy bundles before schema mutations
rrrodzilla Sep 24, 2026
4135145
fix: validate runtime schema annotations before migrations
rrrodzilla Sep 24, 2026
520835a
fix: require lossless runtime schema validation
rrrodzilla Sep 24, 2026
144c254
test: cover preflight refusal before schema writes
rrrodzilla Sep 24, 2026
79e244d
ci: exercise runtime migration and policy preflight guards
rrrodzilla Sep 24, 2026
eeb66fd
docs: explain policy preflight and runtime tenancy boundaries
rrrodzilla Sep 24, 2026
575d21b
fix: express tenant presence guard safely for Cedar validation
rrrodzilla Sep 24, 2026
ed28f30
refactor: name the runtime tenant topology model
rrrodzilla Sep 24, 2026
eca5b5e
test: verify transactional manual tenant migration workflow
rrrodzilla Sep 24, 2026
4f5bba8
fix: authorize provisional updates before final required validation
rrrodzilla Sep 24, 2026
88f2306
fix: expose tenant and server-managed audit inputs in GraphQL
rrrodzilla Sep 24, 2026
624c8ef
test: reject null only after denied write inputs are removed
rrrodzilla Sep 24, 2026
0abe8a7
fix: return concrete GraphQL values without abstract type wrappers
rrrodzilla Sep 24, 2026
5d0dcc9
fix: serialize schema commits with immutable validated policies
rrrodzilla Sep 24, 2026
a6c9061
fix: finalize runtime relation constraints before policy publication
rrrodzilla Sep 24, 2026
edc1cc7
fix: guard relation pairing against concurrent schema changes
rrrodzilla Sep 24, 2026
1536fe5
ci: run complete regression and lint gates on runners
rrrodzilla Sep 24, 2026
b776ee2
docs: describe atomic schema changes for custom backends
rrrodzilla Sep 24, 2026
9ed0d6d
ci: publish upgrade notes and verify release version
rrrodzilla Sep 24, 2026
abc5d4b
fix: persist runtime schema changes atomically across backends
rrrodzilla Sep 24, 2026
6ed21eb
fix: commit prepared schema storage through atomic backend operation
rrrodzilla Sep 24, 2026
cb70666
test: verify failed schema commit rolls back prior destructive steps
rrrodzilla Sep 24, 2026
54a844c
refactor: keep schema change failure payload compact
rrrodzilla Sep 24, 2026
2b0bfaf
test: compare loaded atomic records directly
rrrodzilla Sep 24, 2026
1c88993
fix: preserve object data during transactional SurrealDB renames
rrrodzilla Sep 24, 2026
a1b3065
ci: collect all regression failures and retain build caches
rrrodzilla Sep 24, 2026
56c31e7
test(authz): exercise actual provisional policy diagnostics
rrrodzilla Sep 24, 2026
5595230
fix: preserve omitted SQL Server fields during entity updates
rrrodzilla Sep 24, 2026
48a283f
docs: document SQL Server partial update preservation
rrrodzilla Sep 24, 2026
a50e9a5
test: declare tenant ownership in isolation fixtures
rrrodzilla Sep 24, 2026
0dc4ef5
build: align release toolchain and documentation with SurrealDB 3.3
rrrodzilla Sep 24, 2026
bda51e4
ci: validate the SurrealDB CLI before release
rrrodzilla Sep 24, 2026
32faad6
fix: pin live schema authorization for GraphQL reads
rrrodzilla Sep 24, 2026
4da9479
docs: describe live GraphQL authorization snapshots
rrrodzilla Sep 24, 2026
b790446
refactor: remove stale GraphQL authorization definition captures
rrrodzilla Sep 24, 2026
a9878d6
fix: route GraphQL deletion through canonical entity pipeline
rrrodzilla Sep 24, 2026
a0f75e8
docs: finalize mutation and server compatibility notes
rrrodzilla Sep 24, 2026
4b05f02
fix: use SurrealDB 3.3 transaction-safe storage engine
rrrodzilla Sep 24, 2026
5f17703
fix: honor operator visibility in GraphQL relation reads
rrrodzilla Sep 24, 2026
59bcebb
style: format changed Rust modules with the release toolchain
rrrodzilla Sep 24, 2026
cd06259
refactor: use native SurrealDB value conversions directly
rrrodzilla Sep 24, 2026
7ce1eb1
fix: validate remote SurrealDB version before session setup
rrrodzilla Sep 24, 2026
797ef37
fix: read absent SurrealDB metadata as an empty registry
rrrodzilla Sep 24, 2026
c9e1b86
fix: emit SurrealDB 3.3 flexible field syntax
rrrodzilla Sep 24, 2026
55b177a
fix: bind metadata writes and verify SurrealDB statement results
rrrodzilla Sep 25, 2026
a5c77c5
fix: require concrete Cedar authorization for canonical mutations
rrrodzilla Sep 25, 2026
146bcc8
fix: preserve to-many relation values when decoding SurrealDB records
rrrodzilla Sep 25, 2026
efe2fed
docs: clarify canonical authorization and relation guarantees
rrrodzilla Sep 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .Codex/plans/migration-safety.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Migration safety (#167, #174, #175, #176)

1. Centralize validation of tenant transitions and rename hints in DiffEngine. Reject tenant annotation transitions before any DDL or metadata write, requiring a manual migration/backfill and matching metadata. Preserve backend integrity until automatic backfill is available.
2. Add typed FieldAnnotation::RenamedFrom with DSL parsing and display, retained in signed serialized schemas. Collect active hints centrally, validate missing/ambiguous/conflicting sources, and retain no-op hints on repeat apply.
3. Preflight serve migrations before executing user schema changes; require explicit allow-destructive-migrations opt-in. Gate runtime schema PUT with explicit body opt-in and preserve existing schema annotations.
4. Reconcile PostgreSQL relation foreign keys consistently at schema persistence/startup checkpoints, after tables exist, using explicit restrictive delete behavior and idempotent checks. Validate existing data and report failures. Translate 23503 into typed conflict errors.
5. Reject empty PostgreSQL UPDATE fields before emitting SQL.

Tests: DSL roundtrip and invalid rename hints, repeat apply, tenant add/remove/root-parent refusal, startup/runtime destructive refusals, PostgreSQL fresh/add/backfill/cyclic FK behavior and deletion/write error mapping; nextest and clippy, cross-backend compilation. No dependencies required. Public annotation and error variants warrant minor release; root owns version bump.

## Atomic runtime schema persistence followup

Add apply_schema_change(name, steps, optional definition) to SchemaBackend and dynamic adapter with unsupported default. Each supported backend executes schema DDL, required validation, metadata upsert/delete, and integrity reconciliation in a single transaction. Extract existing statement/connection helpers to preserve rename behavior. PostgreSQL uses transaction-local metadata and strict FK finalization; cache invalidates only after commit. Runtime DELETE keeps its existing registry-only semantics (parent decision). Add focused rollback contracts exercising failure after DDL and metadata-only/deletion paths, run focused nextest and Clippy only; CI owns broad gates.

## SurrealDB transactional rename visibility

Measured SELECT snapshots show REMOVE FIELD followed by UPDATE in the same transaction discards unrelated FLEXIBLE object data. Individual statements in separate transactions do not. Preserve one transaction: copy to fully defined destination, temporarily relax source required/default constraints, unset old values while source definition still exists, defer only rename-source definition removals until all data writes finish. Regression must retain unrelated nested data and verify a later write still works, besides renamed nested data and metadata rollback.

## SQL Server sparse update parity

CI exposed that SQL Server replaces its entire JSON payload on EntityStore::update, unlike PostgreSQL/SurrealDB and the runtime's field-filtered partial update path. Implement one bound JSON_MODIFY UPDATE with OUTPUT inserted row, preserving omitted values and explicit tagged nulls without a read/modify/write race. Clarify trait semantics, retain rename regression, and add SQL Server direct null/empty-update checks. Run focused SQL Server integration tests only.

## Supported SurrealDB engine correction

Reproduced simultaneous successful attachment clears on the 2.6 Mem engine even with explicit transactions. SurrealKV0.9.3 advances commit oracle before index publication; snapshots can mix old data with the newer conflict watermark. Latest2.6.4 uses identical engine; no compatible SurrealKV0.9 patch exists. Upgrade the backend SDK to stable3.3.0, whose Mem engine uses SurrealMX0.27 completed-commit watermark. Adapt native value/error APIs without changing entity semantics, add multi-thread competing clear/replace regression, run focused CAS and migration tests. Root approved supported upgrade over local mutex or vendored engine fork.
2 changes: 1 addition & 1 deletion .github/workflows/cel-kani.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/rust-toolchain@1.97.1
- name: Install build prerequisites
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Install pinned integer solver
Expand Down
16 changes: 12 additions & 4 deletions .github/workflows/mssql-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ on:
pull_request:
paths:
- "crates/schema-forge-mssql/**"
- "crates/schema-forge-core/**"
- "crates/schema-forge-backend/**"
- "crates/schema-forge-cli/Cargo.toml"
- "crates/schema-forge-acton/Cargo.toml"
- "Cargo.lock"
Expand All @@ -23,7 +25,7 @@ jobs:
- uses: actions/checkout@v6

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.97.1

- name: Install Protocol Buffers compiler
shell: pwsh
Expand Down Expand Up @@ -79,14 +81,20 @@ jobs:
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler libkrb5-dev

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.97.1

- name: Rust cache
uses: Swatinem/rust-cache@v2

- name: Install nextest
run: cargo install cargo-nextest --locked

- name: Run SQL Server integration test
env:
TEST_NAME: ${{ matrix.test }}
run: >-
cargo test --package schema-forge-mssql --test sql_server
"$TEST_NAME" -- --ignored --exact --nocapture
cargo nextest run --package schema-forge-mssql --test sql_server
--run-ignored only -E "test(=$TEST_NAME)"
- name: Deny SQL Server lints
if: matrix.version == 2019
run: cargo clippy -p schema-forge-mssql --all-targets -- -D warnings
39 changes: 27 additions & 12 deletions .github/workflows/postgres-conditional.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name: PostgreSQL conditional mutations
on:
pull_request:
paths:
- "crates/schema-forge-core/**"
- "crates/schema-forge-dsl/**"
- "crates/schema-forge-surrealdb/**"
- "crates/schema-forge-backend/**"
- "crates/schema-forge-postgres/**"
- "crates/schema-forge-acton/**"
Expand All @@ -17,7 +20,7 @@ permissions:
jobs:
conditional:
runs-on: ubuntu-24.04
timeout-minutes: 40
timeout-minutes: 60
services:
postgres:
image: postgres:16
Expand All @@ -41,27 +44,39 @@ jobs:
- uses: actions/checkout@v6
- name: Install system dependencies
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler libkrb5-dev postgresql-client
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/rust-toolchain@1.97.1
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- name: Install nextest
run: cargo install cargo-nextest --locked
- name: Run storage concurrency cases
run: cargo nextest run -p schema-forge-backend -p schema-forge-postgres --run-ignored all
run: cargo nextest run -p schema-forge-backend -p schema-forge-postgres --run-ignored all --no-fail-fast
- name: Prepare disposable HTTP namespace
run: psql -X -v ON_ERROR_STOP=1 -c 'CREATE SCHEMA conditional_http'
- name: Run complete runtime and schema suites
run: cargo nextest run -p schema-forge-acton -p schema-forge-surrealdb -p schema-forge-core -p schema-forge-dsl --features schema-forge-acton/postgres,schema-forge-acton/graphql --no-fail-fast
- name: Run HTTP authorization and concurrency cases
if: ${{ !cancelled() }}
env:
SCHEMAFORGE_TEST_POSTGRES_DISPOSABLE: "1"
SCHEMAFORGE_TEST_POSTGRES_URL: postgres://schemaforge:schemaforge-test@localhost:5432/schemaforge_test?options=-csearch_path%3Dconditional_http
run: cargo nextest run -p schema-forge-acton --features postgres --test conditional_entities --run-ignored all
- name: Run audit authorization and bounded verification regressions
run: cargo nextest run -p schema-forge-acton --features postgres --test audit_api
- name: Run exact authorized count policy and paging regressions
run: |
cargo nextest run -p schema-forge-acton --features postgres --lib --test authorization_context -E 'test(authz::read_scope) | binary(authorization_context)'
cargo nextest run -p schema-forge-acton --features postgres --test auth_demo -E 'test(readable_paging)'
- name: Check CLI preparation behavior
run: cargo nextest run -p schema-forge-cli --no-default-features --features postgres -E 'test(explicit_revision_preparation)'
run: cargo nextest run -p schema-forge-acton --features postgres,graphql --test conditional_entities --run-ignored only --no-fail-fast
- name: Check CLI preparation and security behavior
if: ${{ !cancelled() }}
run: cargo nextest run -p schema-forge-cli --no-default-features --features postgres --no-fail-fast
- name: Check SurrealDB CLI integration
if: ${{ !cancelled() }}
run: cargo nextest run -p schema-forge-cli --no-fail-fast
- name: Deny runtime and backend lints
if: ${{ !cancelled() }}
run: cargo clippy -p schema-forge-acton -p schema-forge-surrealdb -p schema-forge-core -p schema-forge-dsl -p schema-forge-backend -p schema-forge-postgres --features schema-forge-acton/postgres,schema-forge-acton/graphql --all-targets -- -D warnings
- name: Deny CLI lints
if: ${{ !cancelled() }}
run: cargo clippy -p schema-forge-cli --no-default-features --features postgres --all-targets -- -D warnings
- name: Deny SurrealDB CLI lints
if: ${{ !cancelled() }}
run: cargo clippy -p schema-forge-cli --all-targets -- -D warnings
- name: Clean disposable HTTP namespace
if: always()
run: psql -X -v ON_ERROR_STOP=1 -c 'DROP SCHEMA IF EXISTS conditional_http CASCADE'
25 changes: 23 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
- uses: actions/checkout@v6

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.97.1

- name: Install Linux system build dependencies
if: runner.os == 'Linux'
Expand All @@ -76,6 +76,13 @@ jobs:
- name: Verify Rust toolchain
run: rustc --version && cargo --version

- name: Verify release tag matches CLI version
shell: bash
run: |
PACKAGE_ID="$(cargo pkgid --locked -p schema-forge-cli)"
PACKAGE_VERSION="${PACKAGE_ID##*#}"
test "$TAG_NAME" = "v${PACKAGE_VERSION##*@}"

- name: Install cosign
uses: sigstore/cosign-installer@v3

Expand Down Expand Up @@ -119,7 +126,7 @@ jobs:
# Points rust-embed at the verified console bundle (build.rs re-exports
# it for the `#[folder = "$SCHEMAFORGE_CONSOLE_DIST"]` interpolation).
SCHEMAFORGE_CONSOLE_DIST: ${{ github.workspace }}/console-dist
run: cargo build --release --package schema-forge-cli --no-default-features --features ${{ matrix.backend }},embedded-console
run: cargo build --locked --release --package schema-forge-cli --no-default-features --features ${{ matrix.backend }},embedded-console

- name: Sign and verify Windows binary (Sigstore keyless)
if: runner.os == 'Windows'
Expand Down Expand Up @@ -170,6 +177,19 @@ jobs:
contents: write
id-token: write
steps:
- uses: actions/checkout@v6

- name: Prepare release notes from changelog
env:
TAG_NAME: ${{ github.ref_name }}
run: |
awk -v version="${TAG_NAME#v}" '
index($0, "## [" version "]") == 1 { found = 1; next }
found && /^## \[/ { exit }
found { print }
' CHANGELOG.md > RELEASE_NOTES.md
test -s RELEASE_NOTES.md

- uses: actions/download-artifact@v8
with:
merge-multiple: true
Expand All @@ -192,6 +212,7 @@ jobs:
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
body_path: RELEASE_NOTES.md
generate_release_notes: true
files: |
schemaforge-*.tar.gz
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/site-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler libkrb5-dev

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@1.97.1

- name: Rust cache
uses: Swatinem/rust-cache@v2
Expand Down
78 changes: 78 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,84 @@ is pre-1.0; breaking changes bump the **minor** version per

## [Unreleased]

## [0.45.0] - 2026-09-24

### Security and correctness

- Tenant scope applies only to tenanted schemas. Tenant roots are authorized by
their own identity, including legacy roots with NULL metadata. Unattributed
child records fail closed for tenant users, and PUT/PATCH cannot move a record
to another tenant unless the caller is a platform administrator. Invitations
validate both the configured tenant type and the caller's effective scope.
- Field write authorization precedes defaults, computed expressions, validation
rules, and hooks. Retained caller input is reauthorized after denied fields
are removed. Rules see optional absent fields as null; required fields are
checked after server-supplied values are available. Filtered empty PATCH
requests no longer emit invalid SQL. PUT rules and persisted optional values
now agree: PUT clears omitted writable optional fields and preserves denied
or server-managed fields. PATCH remains a partial update.
- SurrealDB uses the supported 3.3 storage engine, correcting a concurrency race
that could let two conditional writes both succeed.
- SQL Server updates merge supplied fields atomically, preserving omitted fields
and explicit nulls. Concurrent updates to different fields no longer replace
each other's stored values.
- Canonical mutation handlers enforce concrete Cedar authorization before
operator policies and hooks. An operator policy can further restrict access
but cannot bypass tenant or Cedar checks.
- GraphQL creates, updates, and deletes share the REST mutation pipeline. GraphQL reads,
relations, and deletes enforce concrete Cedar decisions. Each request captures
matching live definitions and policies, so runtime field restrictions also
govern existing GraphQL fields. Nested relations honor operator visibility
restrictions, and SurrealDB to-many relations retain their record references.
Unproven raw
GraphQL totals are withheld instead of disclosing counts of inaccessible rows.
- CLI help hides secret environment values, including database and server URLs.
`serve --host` controls the actual listener and accepts validated IPv4/IPv6
addresses. The default listener is now the documented `127.0.0.1`.

### Schema migrations

- Declare field renames with `@renamed_from("old_name")` to preserve data instead
of dropping and recreating a field. Rename hints are validated before migration
and remain valid after the rename completes.
- `serve` preflights startup plans and refuses destructive changes unless
`--allow-destructive-migrations` is supplied. Runtime schema PUT requires
`allow_destructive_migrations: true` for destructive plans, including lossy
type conversions. Proposed tenant hierarchies and custom Cedar policies are
validated before application schema changes.
- PostgreSQL to-one relation foreign keys are installed consistently for fresh,
altered, and legacy schemas. Missing targets or orphan references fail schema
administration clearly. Integrity violations return HTTP 409
`foreign_key_violation` rather than 502, without exposing SQL or row values.
- Automatic changes to an existing schema's tenancy are refused because row
ownership cannot be inferred safely. The
[migration guide](docs/migrations/safe-schema-changes.md) documents explicit
ownership backfill, constraint changes, and metadata updates.
- Explicit empty access lists produce diagnostics; documentation clarifies that
within access annotations, empty and omitted role lists grant access to every
authenticated user.

### Upgrade notes

Source builds use Rust 1.97.1. SurrealDB deployments require a stable 3.x server at version 3.3 or newer. Upgrade remote servers before
connecting this release; embedded development databases use the bundled engine.

Review pending schema changes before restarting. Destructive startup migrations
now require deliberate opt-in. PostgreSQL schema administration repairs missing
foreign keys and can require cleanup of existing orphan references. Tenanted
children created by a platform administrator require an explicit tenant.
Runtime changes to tenant topology require offline schema application and a
restart so the actor and HTTP middleware activate the same configuration.

Rust embedders must update the schema-aware tenant helper and rule-binding call
signatures. GraphQL registration now requires initialized
`AppState<SchemaForgeConfig>`; see [GraphQL writes](docs/graphql-writes.md).
The backend trait adds a defaulted `finalize_schema_migrations` operation for
completing batch migration integrity checks. Custom backends must implement
the atomic `apply_schema_change` operation to support runtime schema creation
and updates; the default refuses these operations rather than applying a
partial migration.

## [0.44.2] - 2026-09-10

### Fixed
Expand Down
Loading
Loading