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
2 changes: 1 addition & 1 deletion Cargo.lock

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

16 changes: 16 additions & 0 deletions crates/graphql-orm-ai/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ 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.97.1] - 2026-09-04

Persistent schema module: **0.64.0** (unchanged from 0.97.0).

### Fixed

- Remote GraphQL tool authorization failures now remain `Forbidden`, allowing
the existing safe application-tool boundary to report the non-retryable
`authorization_denied` result instead of mislabelling the failure as resolver
validation.
- Principal reauthorization failures now remain `ReauthorizationFailed`
rather than being collapsed into a resolver failure.

There is no database, data, table, column, index, constraint, backfill,
protected-payload, GraphQL SDL, backup, or restore migration.

## [0.97.0] - 2026-09-03

Persistent schema module: **0.64.0** (unchanged from 0.96.2).
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.97.0"
version = "0.97.1"
edition = "2024"
authors = ["Toby Martin <toby@dastari.net>"]
description = "Project-agnostic AI agent runtime for graphql-orm applications"
Expand Down
15 changes: 15 additions & 0 deletions crates/graphql-orm-ai/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ 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.97.0 to 0.97.1: preserve remote tool authorization failures

Adopt `graphql-orm-ai` 0.97.1 from one reviewed full monorepo revision. Hosts
do not need to change their trait implementations. A
`ToolExecutionError::Authorization` now becomes `AiError::Forbidden`, and
`ToolExecutionError::Reauthorization` becomes
`AiError::ReauthorizationFailed`. The existing application-tool failure
classifier therefore exposes an authorization denial as the content-free,
non-retryable `authorization_denied` envelope instead of
`resolver_validation_failed`. Reauthorization failures remain outside that
safe retry envelope.

The AI schema module remains **0.64.0**. There is no database, data, GraphQL
SDL, protected-payload, backup, restore, or data backfill migration.

## 0.96.2 to 0.97.0: recoverable application-tool result budgets

Adopt `graphql-orm-ai` 0.97.0 and `graphql-orm-ai-tool-profiles` 0.11.0 from
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.97.0", 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.97.1", default-features = false, features = ["sqlite"] }
```

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

# Implementation Status

`graphql-orm-ai` is at crate version `0.97.0` with AI schema module
`graphql-orm-ai` is at crate version `0.97.1` with AI schema module
`0.64.0`. It uses workspace `graphql-orm` `0.30.0`, backend-neutral
`graphql-orm-ai-tool-profiles` `0.11.0`, and external `agql-auth`
`0.19.0` at `1d2e9fe2e1576105212a7b340a11abf8cad0382d`.
Expand Down
2 changes: 2 additions & 0 deletions crates/graphql-orm-ai/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,8 @@ impl AiRuntime {

fn map_tool_execution_error(error: ToolExecutionError) -> AiError {
match error {
ToolExecutionError::Reauthorization => AiError::ReauthorizationFailed,
ToolExecutionError::Authorization => AiError::Forbidden,
ToolExecutionError::ResultBudgetExceeded => AiError::ResultBudgetExceeded,
_ => AiError::ToolExecutionFailed,
}
Expand Down
49 changes: 48 additions & 1 deletion crates/graphql-orm-ai/tests/runtime_contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ impl AuthenticatedGraphqlExecutor for Executor {
context: GraphqlRequestContext,
request: ToolGraphqlRequest,
) -> Result<ToolGraphqlResponse, ToolExecutionError> {
if request
.variables
.get("rejectAuthorization")
.and_then(serde_json::Value::as_bool)
.unwrap_or(false)
{
return Err(ToolExecutionError::Authorization);
}
if request
.variables
.get("rejectReauthorization")
.and_then(serde_json::Value::as_bool)
.unwrap_or(false)
{
return Err(ToolExecutionError::Reauthorization);
}
if request
.variables
.get("rejectOversizedResult")
Expand Down Expand Up @@ -224,7 +240,9 @@ fn runtime() -> AiRuntime {
"properties": {
"emitUnknown": { "type": "boolean" },
"emitOversizedResult": { "type": "boolean" },
"rejectAuthorization": { "type": "boolean" },
"rejectOversizedResult": { "type": "boolean" },
"rejectReauthorization": { "type": "boolean" },
"incompleteAuthorization": { "type": "boolean" }
},
"additionalProperties": false
Expand Down Expand Up @@ -409,7 +427,7 @@ async fn runtime_rejects_invalid_arguments_and_non_disclosed_resolver_fields() {
current_request(&runtime, json!({"incompleteAuthorization": true})),
)
.await,
Err(AiError::ToolExecutionFailed)
Err(AiError::Forbidden)
));

let mut stale_schema = current_request(&runtime, json!({}));
Expand Down Expand Up @@ -446,6 +464,35 @@ async fn runtime_preserves_result_budget_failures_from_transport_and_descriptor_
}
}

#[tokio::test]
async fn runtime_preserves_authorization_and_reauthorization_failures() {
let runtime = runtime();
open_runtime(&runtime);
let principal_reference = principal(&["records:read"]).reference();
let tool_id = AiToolId::parse("records.current").expect("tool ID");

assert!(matches!(
runtime
.execute_tool(
&principal_reference,
&tool_id,
current_request(&runtime, json!({"rejectAuthorization": true})),
)
.await,
Err(AiError::Forbidden)
));
assert!(matches!(
runtime
.execute_tool(
&principal_reference,
&tool_id,
current_request(&runtime, json!({"rejectReauthorization": true})),
)
.await,
Err(AiError::ReauthorizationFailed)
));
}

#[test]
fn runtime_builder_requires_every_security_boundary() {
let result = AiRuntime::builder().build();
Expand Down

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

2 changes: 1 addition & 1 deletion docs/reference/workspace-packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ changes.
| Package | Version | Path | Default features | Direct internal dependencies |
| --- | --- | --- | --- | --- |
| `graphql-orm` | `0.30.0` | `crates/graphql-orm` | `sqlite` | `graphql-orm-macros`, `graphql-orm-operation-catalog`, `graphql-orm-router-protocol` (dev-only) |
| `graphql-orm-ai` | `0.97.0` | `crates/graphql-orm-ai` | `sqlite` | `graphql-orm`, `graphql-orm-ai-tool-profiles`, `graphql-orm-storage` |
| `graphql-orm-ai` | `0.97.1` | `crates/graphql-orm-ai` | `sqlite` | `graphql-orm`, `graphql-orm-ai-tool-profiles`, `graphql-orm-storage` |
| `graphql-orm-ai-tool-profiles` | `0.11.0` | `crates/graphql-orm-ai-tool-profiles` | none | `graphql-orm-operation-catalog`, `graphql-orm-router-protocol` (dev-only) |
| `graphql-orm-backup` | `0.7.2` | `crates/graphql-orm-backup` | `local` | `graphql-orm` (optional), `graphql-orm-storage` |
| `graphql-orm-macros` | `0.30.0` | `crates/graphql-orm-macros` | `sqlite` | none |
Expand Down
Loading