You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
stack-auth (Rust crate) and @cipherstash/auth (npm, v1.0.0) now surface strictly typed errors: every failure carries a stable machine-readable code, a human message, structured per-variant payload (e.g. WORKSPACE_MISMATCH carries expected/actual workspace IDs), and — via miette::Diagnostic — actionable help text. The diagnostic surface also supports a url() per error, which already flows across the FFI boundary into the TS AuthFailure.url field, but no URLs are set yet because there are no pages to point at.
This issue: create a docs page per error code so the libraries can link each failure directly to remediation docs. A follow-up issue in cipherstash-suite will wire the URLs into the code once the pages exist.
Error codes to document
Code
Message
Has help text today
NOT_AUTHENTICATED
Not authenticated
✅ (stash login / CS_CLIENT_ACCESS_KEY)
MISSING_WORKSPACE_CRN
Workspace CRN required with an access key
✅ (CS_WORKSPACE_CRN)
INVALID_ACCESS_KEY
Access key string malformed
✅ (CSAK<key-id>.<secret> format)
INVALID_CRN
Workspace CRN could not be parsed
✅ (crn:<region>:<workspace-id> format)
INVALID_REGION
Unsupported region
✅ (supported-region example)
WORKSPACE_MISMATCH
Token issued for a different workspace
✅ (+ structured expected/actual payload)
EXPIRED_TOKEN
Token expired
—
ACCESS_DENIED
Authorization denied
—
INVALID_GRANT
Grant rejected by server
—
INVALID_CLIENT
Client ID not recognized
—
INVALID_URL
URL could not be parsed
—
INVALID_WORKSPACE_ID
Workspace ID could not be parsed
—
INVALID_TOKEN
JWT could not be decoded
—
REQUEST_ERROR
HTTP request failed
—
SERVER_ERROR
Unexpected auth-server error
—
STORE_ERROR
Token store operation failed (native only)
—
ALREADY_CONSUMED
Consumable handle reused (device-code flow)
—
INTERNAL_ERROR
Internal invariant violated
—
Source of truth: packages/stack-auth/src/error.rs in cipherstash-suite (each per-error struct owns its code, message, and help).
Keeping docs and code in sync
We need a mechanism so these pages and the code can't silently drift:
Immutable identifiers. Assign each error a permanent ID that is never renamed, renumbered, or reused — the docs URL is keyed on it, so it must outlive any refactor of the enum/variant names.
Language-SDK discriminator. The Rust and TS SDKs share the taxonomy today but may diverge (TS adds ALREADY_CONSUMED-style binding-layer failures; Rust has native-only STORE_ERROR). Proposed scheme: a prefix encoding SDK + domain + number, e.g. R-A10 = Rust, auth error docs: PostgreSQL landing page (Proxy / Encryption SDK / Drizzle / Supabase / EQL hub) #10; T-A10 = TypeScript equivalent. Exact scheme open for discussion — the requirement is that the identifier is unambiguous about which SDK's behavior the page describes.
Drift guard.cipherstash-suite already derives its TS error-code unions from error.rs via a source-parsing test; once IDs exist, the same approach can pin the ID ↔ code mapping in code, and ideally CI here can check that every ID referenced by the code has a live page (or the pages are generated from a shared manifest).
Deliverables
One page per error code above, with stable URLs (e.g. /docs/errors/<id>), covering: what it means, common causes, and remediation steps (expanding the existing help text)
Context
stack-auth(Rust crate) and@cipherstash/auth(npm, v1.0.0) now surface strictly typed errors: every failure carries a stable machine-readable code, a human message, structured per-variant payload (e.g.WORKSPACE_MISMATCHcarriesexpected/actualworkspace IDs), and — viamiette::Diagnostic— actionablehelptext. The diagnostic surface also supports aurl()per error, which already flows across the FFI boundary into the TSAuthFailure.urlfield, but no URLs are set yet because there are no pages to point at.This issue: create a docs page per error code so the libraries can link each failure directly to remediation docs. A follow-up issue in
cipherstash-suitewill wire the URLs into the code once the pages exist.Error codes to document
NOT_AUTHENTICATEDstash login/CS_CLIENT_ACCESS_KEY)MISSING_WORKSPACE_CRNCS_WORKSPACE_CRN)INVALID_ACCESS_KEYCSAK<key-id>.<secret>format)INVALID_CRNcrn:<region>:<workspace-id>format)INVALID_REGIONWORKSPACE_MISMATCHexpected/actualpayload)EXPIRED_TOKENACCESS_DENIEDINVALID_GRANTINVALID_CLIENTINVALID_URLINVALID_WORKSPACE_IDINVALID_TOKENREQUEST_ERRORSERVER_ERRORSTORE_ERRORALREADY_CONSUMEDINTERNAL_ERRORSource of truth:
packages/stack-auth/src/error.rsincipherstash-suite(each per-error struct owns its code, message, and help).Keeping docs and code in sync
We need a mechanism so these pages and the code can't silently drift:
ALREADY_CONSUMED-style binding-layer failures; Rust has native-onlySTORE_ERROR). Proposed scheme: a prefix encoding SDK + domain + number, e.g.R-A10= Rust, auth error docs: PostgreSQL landing page (Proxy / Encryption SDK / Drizzle / Supabase / EQL hub) #10;T-A10= TypeScript equivalent. Exact scheme open for discussion — the requirement is that the identifier is unambiguous about which SDK's behavior the page describes.cipherstash-suitealready derives its TS error-code unions fromerror.rsvia a source-parsing test; once IDs exist, the same approach can pin the ID ↔ code mapping in code, and ideally CI here can check that every ID referenced by the code has a live page (or the pages are generated from a shared manifest).Deliverables
/docs/errors/<id>), covering: what it means, common causes, and remediation steps (expanding the existinghelptext)