Skip to content

Standardize attestation error envelopes#753

Open
lloydmak99 wants to merge 2 commits into
mainfrom
fix/attestation-error-envelope
Open

Standardize attestation error envelopes#753
lloydmak99 wants to merge 2 commits into
mainfrom
fix/attestation-error-envelope

Conversation

@lloydmak99

@lloydmak99 lloydmak99 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Problem

Fixes #657.

GET /v1/signature/{chat_id} returned a non-standard error shape:

{ "error": "Signature not found: ..." }

Other API errors use the shared envelope with error.message, error.type, error.param, and error.code, so clients that normalize errors through response.error.message needed a signature-endpoint special case.

The issue thread also called out the same local string-only envelope on GET /v1/attestation/report, plus invalid nonce/signing parameter errors being reported as HTTP 503 instead of client-side 400s.

Change

  • Replaced the attestation route-local ErrorResponse { error: String } with the shared crate::models::ErrorResponse envelope.
  • Mapped /v1/signature/{chat_id} errors into standard envelopes:
    • missing signatures return 404 with type: not_found_error
    • invalid parameters return 400 with type: invalid_request_error
    • internal/provider/repository failures return 500 with type: internal_server_error
  • Added route-level signing_algo validation for /v1/signature/{chat_id} so unsupported algorithms return 400 before repository lookup.
  • Mapped /v1/attestation/report invalid client parameters to 400, including nonce and signing algorithm errors, while preserving 503 for provider unavailability.
  • Updated OpenAPI schema registration to use the shared error model.
  • Added focused unit tests for the signature 404 envelope, invalid attestation nonce status/param mapping, invalid signing_algo, and supported algorithms.

What Else Is Needed

Tests

  • cargo test -p api --lib attestation
  • cargo fmt --all -- --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo test --lib --bins

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@lloydmak99 lloydmak99 temporarily deployed to Cloud API test env June 9, 2026 23:47 — with GitHub Actions Inactive
@claude

claude Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review: Standardize attestation error envelopes

Traced the change end-to-end against services::attestation (AttestationError variants, get_chat_signature normalization, ErrorResponse/ErrorDetail in models.rs). The mapping is consistent and well-tested. No critical issues.

Verified correct

  • validate_signing_algo mirrors the service exactly — accepts None/ecdsa/ed25519 case-insensitively; the service defaults Noneecdsa and lowercases, so the route gate can't reject a value the service would have accepted.
  • Removed routes::attestation::ErrorResponse has no remaining references; OpenAPI body = ErrorResponse now resolves to the shared crate::models::ErrorResponse, which is already registered as a component.
  • Status mapping matches the issue intent: signature 404 not_found_error, invalid params 400 invalid_request_error, provider unavailability preserved as 503, internal/repo as 500.

Non-blocking notes

  • invalid_parameter_name infers the param field by substring-matching the service's error message text ("nonce", "signing algorithm", "signing address"). This couples the route to service wording — if a service message is reworded, the param silently drops to None with no compile-time signal. The unit tests pin the current strings, so it's safe today; consider having the service carry the param name structurally if this grows.
  • "service_unavailable" is a new type string — the rest of the codebase uses OpenAI-style names (invalid_request_error, not_found_error, internal_server_error). Minor consistency nit; clients normalizing on error.type will see a value with no precedent here.
  • Intentional breaking change worth calling out in release notes: GET /v1/signature/{chat_id} and /v1/attestation/report error bodies move from { "error": "<string>" } to the nested { "error": { "message", "type", ... } }. This is the whole point of /v1/signature/{chat_id} returns non-standard error envelope: {"error": "string"} instead of {"error": {message, type, ...}} #657, but any client reading response.error as a string must update.

✅ Approved — clean, scoped, and well-covered by the added tests.

@PierreLeGuen PierreLeGuen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the attestation error-envelope changes against the linked issue, the route diff, the shared ErrorResponse model, service AttestationError sources, OpenAPI schema registration, docs references, and relevant tests/CI metadata.

No substantive issues found. Local checks run: cargo test -p api routes::attestation::tests and cargo fmt --all -- --check. GitHub reports Security audit, Lint, and Test Suite passing.

@Evrard-Nil Evrard-Nil left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Reviewed independently at f464a01 (built, clippy, unit tests — green). Safe to approve.

  • Standardizes both attestation endpoints onto the shared OpenAI-compatible ErrorResponse { error: { message, type, param, code } } (drops the route-local {error: String}) — now consistent with the rest of cloud-api.
  • Upstream-auth-masking invariant SAFE: the only backend-wrapping variant, ProviderError (attestation report path, services/attestation/mod.rs:764), still maps to 503 (attestation.rs:392-397) — a backend 401/403/407 during attestation never surfaces as client 4xx. The signature endpoint can only yield SignatureNotFound/RepositoryError, so no backend error reaches it. Error message body is byte-identical to pre-PR (e.to_string()) — no new info-leak surface.
  • The 503→400 change for invalid client params (bad nonce / unsupported signing_algo, via the new pre-lookup validate_signing_algo) is a correctness improvement (stops blaming our backend for client mistakes).
  • The string→object error-body shape change is intentional/documented (#657) and aligns attestation with every other endpoint; no e2e asserts on the old shape; 4 new unit tests pass; CI green.
  • NIT only: ClientError is a dead variant (never constructed) — harmless.

LGTM.

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.

/v1/signature/{chat_id} returns non-standard error envelope: {"error": "string"} instead of {"error": {message, type, ...}}

3 participants