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
3 changes: 3 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,6 @@ Optional retention of LLM prompts and responses linked to audit events.

**Usage ledger**:
Per-attempt records of token usage and cost attribution, linked to the client request they served.

**SSO identity binding**:
An administrator-approved association between a company SSO issuer and subject identity and an OpenGranter principal.
15 changes: 15 additions & 0 deletions contracts/sso-identity-bindings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Pre-registered SSO identity binding read foundation

Issue #486. Plan: [486-sso-identity-bindings](../docs/plans/486-sso-identity-bindings.md).

The contributor selected administrator-pre-registered OIDC issuer/subject bindings and API-specific SSO JWT access tokens for the first human-only management API. Migration `011` stores exact issuer/subject keys mapped to existing IAM principals. Keys use `C` collation, a composite primary key and a restricting principal foreign key. Multiple bindings may name one principal; no binding or human account is created during resolution.

`createPostgresSsoIdentityBindingReader` exposes `resolveHumanPrincipal({ issuer, subject })` to trusted application code after a future access-token verifier establishes identity. This is not JWT verification or authentication. A single parameterized joined query reads current binding/principal kind/active state. Only an active human returns its principal ID; missing mappings, inactive humans and services return `undefined`. No email/username fallback, trimming, case folding, URL normalization or cross-issuer subject matching occurs.

Own required issuer/subject values are captured once before SQL. Local opaque-string bounds are 1–2048 UTF-16 units for issuer and 1–256 for subject, excluding NUL and ill-formed Unicode; exact blanks/Unicode remain identity data. Storage uses character-count checks as a coarse bound; the reader enforces the stricter UTF-16 bound. These are local read bounds, not the selected JWT/access-token claim or issuer-trust profile. Extra caller principal/kind/active/token fields are ignored; projected parameters are frozen and only the validated principal ID is returned.

Invalid inputs throw `InvalidSsoIdentityBindingInput` with message `Invalid SSO identity binding input` before SQL. Duplicate/malformed/inconsistent results, mismatched returned binding keys, malformed principal data or query/result getter failures throw `SsoIdentityBindingUnavailable` with message `SSO identity binding unavailable`. Required result fields must be own properties and are captured once; principal IDs must satisfy the same 1–256 UTF-16, non-NUL, well-formed bound. Errors expose neither raw issuer/subject/driver messages nor causes. Read results are not cached; next calls see changes. Concurrent changes after the statement are not revalidated.

The reader makes no HTTP/key/secret/inference/mutation/audit/usage calls and grants no policy rights. Existing IAM and required decision audit remain necessary at management boundaries. Signature, issuer/audience/algorithm/JWKS/rotation/token-type/expiry/skew checks, access-token versus ID-token rejection, public HTTP authentication/errors/audit and audited binding provisioning remain separate implementation. Current proxy authentication, human/service token lifetimes, discovery/routing and all three OpenRouter pins stay unchanged.

Sources: [OIDC issuer+subject stability](https://openid.net/specs/openid-connect-core-1_0.html#ClaimStability), [JWT access-token profile](https://www.rfc-editor.org/rfc/rfc9068.html). The OIDC ID-token subject bound is not silently applied as an access-token profile.
6 changes: 3 additions & 3 deletions contracts/sso-management-foundation.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# SSO management foundation: planning status

SSO requirements remain pending implementation. The lifetime caps are now enforced at the existing internal service under the [lifetime contract](proxy-token-lifetimes.md). This is not an implemented public HTTP contract:
SSO JWT verification and public management authentication remain pending implementation. The binding read foundation is delivered under #486, and lifetime caps are enforced at the existing internal service under the [lifetime contract](proxy-token-lifetimes.md). This is not an implemented public HTTP contract:

- Company SSO uses OIDC.
- The first management API authenticates SSO human users only. Service accounts continue using the LLM proxy; service management credentials require a later decision.
- Newly issued proxy tokens have a mandatory expiry and maximum lifetime of 30 days for human owners or 90 days for service owners.
- Existing iam:Manage policy evaluation on the target principal and required metadata decision audit remain in force. SSO authentication supplies identity, not an authorization bypass.

Pending decisions: pre-registration versus first-login identity creation; JWT access-token management authentication versus browser login/server sessions. HTTP paths, authentication profiles, migration handling for existing credentials, and implementation error contracts remain to be specified before their implementation. Recommendations are not requirements until confirmed.
Confirmed on 2026-10-11: administrator-pre-registered issuer/subject bindings and API-specific SSO JWT access tokens; no automatic first-login creation. The [binding read foundation](sso-identity-bindings.md) is implemented under #486. HTTP paths, authentication profiles, migration handling for existing credentials, and implementation error contracts remain to be specified before their implementation. Recommendations are not requirements until confirmed.

The current internal facade, opaque credential primitives, and proxy HTTP endpoints remain as documented in [token management](token-management.md). SSO and the public management API remain pending; internal lifetime enforcement is delivered separately.
The current internal facade, opaque credential primitives, and proxy HTTP endpoints remain as documented in [token management](token-management.md). JWT verification and the public management API remain pending; the binding read foundation and internal lifetime enforcement are delivered separately.
10 changes: 7 additions & 3 deletions docs/PRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Success means unauthorized principals cannot obtain provider credentials or invo
## 3. Initial release scope

1. **Catalog and routes:** Register an OpenRouter upstream and direct OpenAI, Anthropic, and Google Gemini upstreams, their secret references, approved model aliases and routes, and versioned price information. Never redisplay a raw upstream credential in the UI.
2. **Identity:** Distinguish human users from service accounts. Human users sign in through company SSO; issue and revoke service-account credentials. Proxy tokens use an opaque versioned format with a random lookup ID and secret, a stored digest, explicit expiry, and immediate revocation. A trusted internal management coordinator evaluates `iam:Manage` on the token owner's `principal:<id>` before issue or revoke. The SSO protocol, HTTP management API, and maximum token lifetime are undecided.
2. **Identity:** Distinguish human users from service accounts. Human users sign in through company SSO; issue and revoke service-account credentials. Proxy tokens use an opaque versioned format with a random lookup ID and secret, a stored digest, explicit expiry, and immediate revocation. A trusted internal management coordinator evaluates `iam:Manage` on the token owner's `principal:<id>` before issue or revoke. OIDC, pre-registered issuer/subject bindings, API-specific SSO JWT access tokens and owner-specific lifetime caps are selected; the exact token-verification and HTTP management profiles remain pending.
3. **Authorization:** Attach policies to principals and roles. Evaluate principal, action, resource, and supported conditions on every request. Deny by default and give explicit Deny precedence. A PostgreSQL reader can load a principal's direct and inherited policy snapshot from one consistent SQL statement; an internal policy simulator can evaluate a current persisted principal/action/resource and return only the decision and policy versions. Simulation checks IAM only and does not grant execution; public simulator authentication, reader visibility, and access audit remain undecided. Policy-management writes remain separate work.
4. **Gateway and routing:** Provide the core OpenAI-compatible `POST /v1/chat/completions` and `GET /v1/models` shapes. A delegated route sends an authorized request to OpenRouter; a managed route has OpenGranter choose among registered direct OpenAI, Anthropic, and Google Gemini adapters. Both use the same proxy-token, policy, limit, and audit path. The routing controls resemble OpenRouter's: administrator-approved provider allowlists and order, price/latency/throughput preferences, health-aware selection, optional Jev-assisted selection, and bounded fallback. Jev may recommend only a destination that passed all OpenGranter eligibility checks. Fallback may try another authorized candidate of the same route kind; it cannot silently switch between delegated and managed routes. Reject unsupported fields and routing overrides clearly. Delegated text streaming is implemented; direct-provider, tool and complete external-client streaming remain required release work.
5. **Usage:** Record request ID, principal, credential ID, requested alias, route kind, upstream, actual model and provider when known, timestamp, status, latency, input and output tokens, estimated cost, and upstream-reported cost separately. Represent unavailable token usage as unknown.
Expand Down Expand Up @@ -70,7 +70,7 @@ Unrestricted cross-mode fallback, credit resale, every provider-specific API par
| Jev-assisted managed selection | Optional TypeSafe Jev decision over already eligible direct candidates; OpenGranter validates the choice and makes the provider call. The authorized fallback policy is confirmed; the TypeSafe integration target and prompt-disclosure default remain provisional in [the routing contract](routing.md). |
| Delegated IAM | Require permission for the model and every eligible final inference provider; restrict OpenRouter to the authorized provider set before sending |
| Fallback boundary | Within delegated routes or within managed routes, never silently between the two kinds |
| Human sign-in | OIDC company SSO; identity binding and management authentication profile pending |
| Human sign-in | OIDC company SSO; pre-registered issuer/subject binding reader; API-specific JWT verification/HTTP profile pending |
| Deployment | AWS and on-premises support; release order TBD |
| Content audit | Configurable; default, scope, retention, and readers TBD |
| Streaming and monthly limits | Streaming required for external-client compatibility; failure/accounting contracts and monthly limits remain to specify |
Expand Down Expand Up @@ -115,7 +115,7 @@ Require the exact case-insensitive application/json type, preserving existing pa

## Agreed SSO management foundation (implementation pending)

Company SSO uses OIDC. The first management API authenticates SSO human users only; services remain proxy users. New proxy-token lifetime caps are 30 days for human owners and 90 days for service owners, with expiry mandatory. SSO identity binding and management API authentication remain pending decisions. Existing IAM and mandatory decision audit apply. See [planning contract](../contracts/sso-management-foundation.md) and [plan](plans/105-sso-management-foundation.md).
Company SSO uses OIDC. The first management API authenticates SSO human users only; services remain proxy users. New proxy-token lifetime caps are 30 days for human owners and 90 days for service owners, with expiry mandatory. Administrator-pre-registered issuer/subject bindings and API-specific SSO JWT access tokens were confirmed on 2026-10-11; exact token verification and public HTTP authentication remain pending. Existing IAM and mandatory decision audit apply. See [planning contract](../contracts/sso-management-foundation.md) and [plan](plans/105-sso-management-foundation.md).

## Internal proxy-token lifetime enforcement

Expand Down Expand Up @@ -1007,3 +1007,7 @@ Complete administrator snapshots may include own optional non-null benchmarks, r
## Informational model pricing adjustments (#484)

Complete administrator pricing snapshots may include optional finite discount and bounded override rows with optional exact price strings, finite token/time conditions and open UTC day labels. Preserve omission, empty/duplicate rows, exact spelling and order; supplied day arrays require at least one item. Existing nonnegative decimal/scientific price restrictions remain. Only compatible rich discovery publishes these values after complete validation, enabled model/final-provider IAM, existing queries/pages and required private audit. They never apply discounts/conditions, rank routes, calculate billed cost or certify pricing freshness. Publication/refresh, pricing application policy, broader discovery/conformance and #116/#7 remain open. See [plan](plans/484-model-pricing-adjustments.md) and [contract](../contracts/model-pricing-adjustments.md).

## Pre-registered SSO identity read foundation (#486)

Exact issuer/subject bindings resolve only to existing active human principals. Missing mappings, inactive humans and services yield no identity; no account creation or email fallback occurs. A persisted internal reader captures bounded opaque fields once and reloads current state each operation. It does not verify JWTs, authenticate public requests, grant IAM rights or mutate configuration. Existing policy/audit and proxy behavior remain required. See [plan](plans/486-sso-identity-bindings.md) and [contract](../contracts/sso-identity-bindings.md).
8 changes: 6 additions & 2 deletions docs/acceptance.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,14 @@ The PostgreSQL migration runner applies versions `001` through `008` in order, r

- OIDC-authenticated human management callers still pass existing iam:Manage policy checks; authentication does not grant management authority. Service-account management authentication is excluded from the first slice.
- New human-owner proxy tokens cannot exceed 30 days; new service-owner tokens cannot exceed 90 days. Expiry remains mandatory.
- Identity binding and management authentication scenarios await the remaining planning answers. SSO scenarios remain pending implementation; internal lifetime cap scenarios are covered separately below.
- Administrator-pre-registered issuer/subject bindings and API-specific SSO JWT access tokens are confirmed. Binding reader scenarios are implemented under #486; JWT verification/public HTTP authentication remain pending. Internal lifetime caps are covered separately below.

## Internal proxy-token lifetime caps

- For both persisted owner kinds, exact maximum future expiry succeeds and one millisecond beyond fails without credential or lifecycle writes; caller kind/cap fields cannot widen it.
- Policy Deny and decision-audit failure stop before target-kind lookup. Missing/malformed/duplicate/unavailable owner data fails safely after authorized decision persistence.
- Cap validation and credential creation use one issuance timestamp. Previously issued long-lived credentials remain revocable.
- These scenarios concern the trusted internal service; SSO identity binding and public management authentication remain pending.
- These scenarios concern the trusted internal service; the SSO binding reader is delivered under #486, while JWT verification and public management authentication remain pending.

## Token-management operation snapshots

Expand Down Expand Up @@ -1418,3 +1418,7 @@ Root/nested/row/index getters and array length are captured once; inherited opti
Public and actual OpenRouter1.4.18/OpenAI7.23.0 sockets preserve finite signed/fractional/extreme discounts/conditions, exact decimal spelling, all override fields, empty/duplicate rows, blank/future/duplicate day labels, omission and SDK field mappings. Verify 64-row/day, 128-unit price and 256-UTF-16 day boundaries; reject supplied empty day arrays, null/undefined/nonfinite/malformed/unknown fields, holes and inherited required base prices privately, including disabled/denied catalog entries. Authentication precedes catalog; model/provider/implicit Deny, fresh page policy, required failures, private events/errors and basic/legacy/query/order behavior remain unchanged.

Root/price/condition/row/day/index getters and array lengths are read once; inherited optional getters stay unread, custom iterators never execute, inherited hole fillers reject, and audit mutation cannot alter output. Non-enumerable own required prices remain captured rather than omitted. PostgreSQL list/route snapshots remain deeply frozen, retain approved routes and fixed failures. Migrated JSONB preserves spelling/duplicates and no-backfill behavior; oversized aggregate snapshots reject without replacing the previous row. See [plan](plans/484-model-pricing-adjustments.md) and [contract](../contracts/model-pricing-adjustments.md).

## Pre-registered SSO identity binding cases (#486)

Verify migrated uniqueness/FK/restricted deletion, exact issuer/subject case/Unicode/whitespace matching, cross-issuer separation and multiple bindings for one principal without automatic creation. Current missing/inactive/service identities yield no human; next-call mapping/kind/active changes take effect. Public reader tests cover own field/getter capture, source mutation across SQL awaits, frozen parameterization, ignored forged caller state, malformed/duplicate/mismatched results and fixed claim-free errors before SQL for invalid input. No JWT verification, policy grant, audit append or HTTP management flow is certified. See [plan](plans/486-sso-identity-bindings.md) and [contract](../contracts/sso-identity-bindings.md).
3 changes: 3 additions & 0 deletions docs/adr/0008-pre-registered-sso-management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Pre-registered SSO identities and API access tokens

The contributor selected administrator-pre-registered issuer/subject bindings and API-specific SSO JWT access tokens for the first human-only management API on 2026-10-11. This trades automatic first-login onboarding and browser session state for explicit identity enrollment and an API authentication boundary; changing it later would change provisioning and client login flows. SSO identity supplies no IAM bypass. Exact token verification and HTTP profiles remain separate decisions. See [plan](../plans/486-sso-identity-bindings.md).
Loading
Loading