Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ This file is the authoritative user-facing release chronology. The former
[release-notes ledger](docs/archive/2026/graphql-orm-release-notes.md) is retained
for historical context.

## 0.26.0 - 2026-08-22

Companion macros crate: `graphql-orm-macros` **0.26.0**. Generated ORM and
database behavior are unchanged.

- Aligned the optional `auth-agql` bridge to generic `agql-auth` 0.18.0 at
merged full revision `527d15d28e3c295a6f6b5e6d74559a7aecdc1322`, retaining
one public auth type universe for direct consumers.
- The upstream release adds a typed authorization-role claim and issuer hook,
explicit unknown-role expansion errors, and independent catalogue lifetime
validation. The ORM bridge remains a projection of an accepted principal;
database policy and generated resolver behavior are unchanged.

No database, GraphQL SDL, generated-code, or stored-data migration is required.

## 0.25.1 - 2026-08-22

Companion macros crate: `graphql-orm-macros` **0.25.1**. Generated ORM and
Expand Down
13 changes: 7 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ license = "MIT"
repository = "https://github.com/Dastari/graphql-orm"

[workspace.dependencies]
agql-auth = { git = "https://github.com/Dastari/agql-auth.git", rev = "b792241b7d9bb46bad81dde4534ae5b39857f614", version = "0.17.1" }
agql-auth = { git = "https://github.com/Dastari/agql-auth.git", rev = "527d15d28e3c295a6f6b5e6d74559a7aecdc1322", version = "0.18.0" }
arc-swap = "1.7"
async-graphql = { version = "7", features = ["dataloader", "uuid"] }
async-graphql-parser = "7"
Expand All @@ -37,7 +37,7 @@ cynic-parser = { version = "=0.11.2", features = ["pretty"] }
futures = "0.3"
getrandom = "0.3"
graphql-composition = "=0.12.2"
graphql-orm = { path = "crates/graphql-orm", version = "0.25.1", default-features = false }
graphql-orm = { path = "crates/graphql-orm", version = "0.26.0", default-features = false }
graphql-orm-ai-tool-profiles = { path = "crates/graphql-orm-ai-tool-profiles", version = "0.9.0" }
graphql-orm-backup = { path = "crates/graphql-orm-backup", version = "0.7.1", default-features = false }
graphql-orm-operation-catalog = { path = "crates/graphql-orm-operation-catalog", version = "0.3.0" }
Expand All @@ -62,5 +62,6 @@ thiserror = "2"
tokio = { version = "1" }
tokio-stream = { version = "0.1", features = ["sync"] }
tokio-util = { version = "0.7", features = ["compat"] }
tracing = "0.1"
uuid = { version = "1", features = ["v4"] }
url = "2"
10 changes: 10 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ supersedes: []
`graphql-orm` is distributed from GitHub only. Use a reviewed full 40-character commit in `rev`;
neither the runtime nor macros crate is published to crates.io.

## 0.25.1 to 0.26.0: agql-auth 0.18.0 alignment

Git consumers using `auth-agql` must align direct `agql-auth` dependencies to
0.18.0 at merged revision `527d15d28e3c295a6f6b5e6d74559a7aecdc1322`.
Adopt aligned `graphql-orm` and `graphql-orm-macros` 0.26.0 from the same
reviewed monorepo revision. The bridge remains projection-only. Hosts adopting
typed authorization-role grants follow the upstream issuer/resource-server
rollout; no ORM schema, migration, generated-code, database-policy, or
stored-data change is required.

## 0.25.0 to 0.25.1: agql-auth 0.17.1 alignment

Git consumers using `auth-agql` must align direct `agql-auth` dependencies to
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ schema changes explicitly.

Packages are distributed from this repository, not crates.io. Pin the reviewed
release revision, not a moving branch or tag. The current coordinated
`graphql-orm` version is 0.25.1. Replace the placeholder below with the final
`graphql-orm` version is 0.26.0. Replace the placeholder below with the final
reviewed full SHA for the release:

```toml
[dependencies]
graphql-orm = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.25.1", default-features = false, features = ["sqlite"] }
graphql-orm = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.26.0", default-features = false, features = ["sqlite"] }
```

Choose exactly the backend support needed by each service. Cargo can unify
Expand Down
13 changes: 13 additions & 0 deletions crates/graphql-orm-ai/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ checkpoint facts. For the current workspace baseline and active gates, use the
[implementation status](docs/implementation-status.md) and the central
[AI production-readiness plan](../../docs/plans/active/ai-production-readiness/README.md).

## [0.91.0] - 2026-08-22

Persistent schema module: **0.63.0** (unchanged from 0.90.1).

### Changed

- Aligned the public `agql-auth` type universe to 0.18.0 at merged revision
`527d15d28e3c295a6f6b5e6d74559a7aecdc1322`. Consumers using re-exported
principal types must resolve the same full revision.
- The additive typed authorization-role metadata is available through the
shared principal type. AI authorization, principal rehydration, providers,
persistence, GraphQL SDL, backup, and restore behavior are unchanged.

## [0.90.1] - 2026-08-22

Persistent schema module: **0.63.0** (unchanged from 0.90.0).
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-ai/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graphql-orm-ai"
version = "0.90.1"
version = "0.91.0"
edition = "2024"
authors = ["Toby Martin <toby@dastari.net>"]
description = "Project-agnostic AI agent runtime for graphql-orm applications"
Expand Down
9 changes: 9 additions & 0 deletions crates/graphql-orm-ai/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ they describe. For the current workspace baseline and active delivery gates,
use [implementation status](docs/implementation-status.md) and the central
[AI production-readiness plan](../../docs/plans/active/ai-production-readiness/README.md).

## 0.90.1 to 0.91.0: agql-auth 0.18.0 type-universe alignment

Adopt `graphql-orm-ai` 0.91.0 from one reviewed full monorepo revision and
align every direct `agql-auth` dependency to version 0.18.0 at merged revision
`527d15d28e3c295a6f6b5e6d74559a7aecdc1322`. The new typed authorization-role
metadata is additive to the public principal type. The schema module remains
**0.63.0**; no database, data, provider, GraphQL SDL, protected-payload,
backup, restore, or runtime migration is required.

## 0.90.0 to 0.90.1: agql-auth 0.17.1 type-universe alignment

Adopt `graphql-orm-ai` 0.90.1 from one reviewed full monorepo revision and
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-ai/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ for AI, ORM, storage, backup, and tool-profile packages:

```toml
[dependencies]
graphql-orm-ai = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.90.1", default-features = false, features = ["sqlite"] }
graphql-orm-ai = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.91.0", default-features = false, features = ["sqlite"] }
```

Exactly one persistence backend is required: `sqlite` (default), `postgres`,
Expand Down
6 changes: 3 additions & 3 deletions crates/graphql-orm-ai/docs/implementation-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ supersedes: []

# Implementation Status

`graphql-orm-ai` is at crate version `0.90.1` with AI schema module
`0.63.0`. It uses workspace `graphql-orm` `0.25.1`, backend-neutral
`graphql-orm-ai` is at crate version `0.91.0` with AI schema module
`0.63.0`. It uses workspace `graphql-orm` `0.26.0`, backend-neutral
`graphql-orm-ai-tool-profiles` `0.9.0`, and external `agql-auth`
`0.17.1` at `b792241b7d9bb46bad81dde4534ae5b39857f614`.
`0.18.0` at `527d15d28e3c295a6f6b5e6d74559a7aecdc1322`.

Completed stateless local-provider turns can carry a proof-bearing contained
native-item refusal after authoritative usage settlement. Those runs close as
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graphql-orm-macros"
version = "0.25.1"
version = "0.26.0"
edition = "2024"
authors = ["Toby Martin"]
description = "Procedural macros for async-graphql and ORM-backed entities, relations, and CRUD operations."
Expand Down
4 changes: 2 additions & 2 deletions crates/graphql-orm-macros/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ macro/runtime versions aligned:

```toml
[dependencies]
graphql-orm = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.25.1", default-features = false, features = ["sqlite"] }
graphql-orm = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.26.0", default-features = false, features = ["sqlite"] }
```

Direct use is supported for tooling that needs the macro package:

```toml
graphql-orm-macros = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.25.1", default-features = false, features = ["sqlite"] }
graphql-orm-macros = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.26.0", default-features = false, features = ["sqlite"] }
```

The direct dependency still requires a compatible `graphql-orm` runtime in the
Expand Down
19 changes: 19 additions & 0 deletions crates/graphql-orm-router/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,25 @@ supersedes: []

# Changelog

## 0.4.0 - 2026-08-22

- Aligned the optional adapter to generic `agql-auth` 0.18.0 at merged revision
`527d15d28e3c295a6f6b5e6d74559a7aecdc1322` and expand only the distinct typed
`authorization_roles` claim. Application roles keep their existing meaning.
- Role-catalogue URLs and request headers can be sourced from named environment
variables. Header values are omitted from file configuration and diagnostics.
- Role-catalogue fetch is lazy and uses configurable bounded exponential retry
backoff rather than becoming a startup dependency. Unknown role IDs trigger
an immediate refresh and fail the affected request.
- Failed refresh preserves the last signature-verified snapshot past its soft
age or signed expiry, with warning logs and a process-local stale-serve
counter. Signed maximum lifetime, clock leeway, and local refresh age are
independent settings.

No descriptor, GraphQL schema, membership, or stored-data migration is
required. Issuers adopting compact grants must emit the typed
`authorization_roles` claim before relying on this expansion path.

## 0.3.1 - 2026-08-22

- Aligned the optional resource-server adapter to `agql-auth` 0.17.1 at merged
Expand Down
3 changes: 2 additions & 1 deletion crates/graphql-orm-router/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graphql-orm-router"
version = "0.3.1"
version = "0.4.0"
edition = "2024"
rust-version = "1.90"
description = "Federated GraphQL router for graphql-orm and project-neutral subgraphs"
Expand Down Expand Up @@ -31,6 +31,7 @@ serde = { workspace = true }
serde_json = { workspace = true }
sha2 = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
url = { workspace = true }

[target.'cfg(unix)'.dependencies]
Expand Down
21 changes: 21 additions & 0 deletions crates/graphql-orm-router/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ supersedes: []

# graphql-orm-router migration guide

## 0.3.1 to 0.4.0

Align direct `agql-auth` consumers to 0.18.0 at merged revision
`527d15d28e3c295a6f6b5e6d74559a7aecdc1322`. Issuers place catalogue-backed
grants in the distinct `authorization_roles` claim; ordinary application
`roles` are no longer an expansion input.

Deploy resource-server support before minting that claim. Configure a literal
`url` or `urlFromEnv`, and load any request credentials with
`requestHeadersFromEnv`. `maximumSignedLifetimeSeconds` and
`clockSkewLeewaySeconds` validate newly fetched signatures independently of
the local `cacheTtlSeconds` refresh age. Optional `retryBackoffSeconds` and
`maximumRetryBackoffSeconds` bound lazy-fetch retries. The role catalogue is no longer a
startup readiness gate. Until the lazy fetch succeeds, role-bearing requests
fail closed while direct-scope-only requests continue. After one successful
verification, refresh failures preserve the last-good snapshot and surface
warning/metric signals.

No schema or stored-data migration is implied. Roll back only after restoring
expanded direct scopes and allowing typed compact tokens to expire.

## 0.3.0 to 0.3.1

Align direct `agql-auth` consumers to 0.17.1 at reviewed full revision
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-router/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ This unpublished package is Git-only:

```toml
[dependencies]
graphql-orm-router = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.3.1" }
graphql-orm-router = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.4.0" }
```

Enable `auth-agql` only when adapting a separately configured
Expand Down
41 changes: 27 additions & 14 deletions crates/graphql-orm-router/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,33 @@ array. JWKS uses HTTPS. Plain HTTP is accepted only for loopback when
`cacheTtlSeconds`, `refreshIntervalSeconds`, `requestTimeoutMs`,
`maxJwksBytes`, and `leewaySeconds`. `acceptLegacyScopes` defaults false.

`roleScopeCatalogue` is optional and requires `auth-agql`. It accepts `url`,
`audience`, `cacheTtlSeconds`, `maxBodyBytes`, and
`allowInsecureLoopbackHttp`. Its URL is HTTPS-only except for explicit
loopback development, has no credentials/query/fragment, and uses the
authentication request timeout and refresh interval. The refresh interval must
be shorter than the catalogue TTL. Startup verifies the RS256 signature with
the JWKS cache and binds the exact catalogue, issuer, audience, purpose, and
signed lifetime before readiness.

When configured, well-formed token roles expand through the current verified
catalogue and are unioned with direct token scopes. Unknown roles grant
nothing. Role-bearing credentials fail closed when no current verified
catalogue exists; direct-scope-only credentials do not depend on that optional
authority source.
`roleScopeCatalogue` is optional and requires `auth-agql`. Select exactly one
of literal `url` or `urlFromEnv`. Request headers are loaded only through
`requestHeadersFromEnv`; values never appear in JSON or diagnostics. Optional
bounds are `cacheTtlSeconds`, `maximumSignedLifetimeSeconds`,
`clockSkewLeewaySeconds`, `retryBackoffSeconds`,
`maximumRetryBackoffSeconds`, and `maxBodyBytes`. Its URL is HTTPS-only except for
explicit loopback development. The literal `allowInsecureLoopbackHttp` flag or
`allowInsecureLoopbackHttpFromEnv` can opt into that development exception,
but both cannot be set together.

JWKS remains the startup authentication dependency. The role catalogue is
fetched lazily on the first authorization-role-bearing request and retried with
bounded exponential backoff as well as by the ordinary authentication refresh
loop. A fetch verifies the RS256 signature
with the JWKS cache and binds the exact catalogue, issuer, audience, purpose,
and independently configured signed lifetime. `cacheTtlSeconds` is only the
soft refresh age; it does not cap issuer lifetime.

When configured, the distinct typed `authorization_roles` claim expands
through the last signature-verified catalogue and is unioned with direct token
scopes. Application `roles` are not expanded. Unknown authorization roles fail
explicitly and request an immediate refresh. A failed refresh preserves and
continues serving the last verified snapshot past its soft age or signed
expiry, increments `role_scope_stale_serve_total`, and emits rate-limited warning
logs. A role-bearing credential fails closed only when no verified snapshot is
available or its role remains unknown; direct-scope-only credentials do not
depend on the optional authority source.

The router validates RS256 public keys only. Configuration has no private-key,
token-signing, session, refresh-token, or RSA-decryption field.
Expand Down
10 changes: 7 additions & 3 deletions crates/graphql-orm-router/docs/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ supersedes: []
5. Execute a representative authenticated query and subscription before
accepting traffic.

Startup is fail closed. JWKS initialization, all source fetches, descriptor
Startup is fail closed for JWKS initialization, all source fetches, descriptor
binding, complete composition, authorization-catalog validation, and runtime
construction finish before the public listener binds. Do not treat liveness as
readiness.
construction before the public listener binds. The optional role-scope
catalogue is deliberately not a startup dependency: its first fetch is lazy,
and only authorization-role-bearing requests fail while no verified snapshot
exists. Do not treat liveness as readiness.

The optional admin listener provides authenticated `GET /_router/status`,
`GET /_router/metrics`, `POST /_router/refresh`,
Expand Down Expand Up @@ -59,6 +61,8 @@ Hive Prometheus exporter adds execution histograms and the pinned subscription
counters
`hive.router.subscriptions.clients.lagged_messages_total` and
`hive.router.subscriptions.subgraphs.dropped_messages_total`.
Embedding hosts can also read `role_scope_stale_serve_total` from the JWKS
provider and alert on any non-zero increase; stale serves emit warning logs.

## Reload and recovery

Expand Down
Loading