Repository Public
1# Codex federation rule reference23> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.45A federation rule decides which verified workload identities may act as one6ChatGPT user or service account. OpenAI evaluates only the rule named by the7Codex process. It does not search every rule for a match.89Each rule has one target principal and can accept one or many upstream10identities. To accept a set of subjects in one rule, use a trailing-prefix11subject or a CEL condition. You can also create more than one rule for the same12principal.1314## Rule model1516| Part | Purpose |17| --------------------- | --------------------------------------------------------------- |18| Provider | Defines the issuer and signing keys OpenAI trusts. |19| Workspace | Limits the resulting access to one managed ChatGPT workspace. |20| Principal | Selects one existing user or service account in that workspace. |21| Identity checks | Restrict which verified identity tokens may use the rule. |22| Scopes | Optionally narrow the existing Codex OAuth scopes. |23| Access token lifetime | Limits the OpenAI access token to 60 through 3,600 seconds. |2425The principal and its workspace membership must exist before exchange. A rule26does not create a user, service account, or membership when a workload connects.2728## How identity checks combine2930A rule can use these checks:3132| Check | Behavior | Use it for |33| ------------------ | --------------------------------------------------------------------- | -------------------------------------------------------- |34| Subject | Exact `sub` value or one trailing `*` prefix. | One workload identity or a controlled subject namespace. |35| Accepted audiences | One through 32 audience strings. The token must contain at least one. | Tokens minted specifically for OpenAI. |36| Exact claims | Up to 32 exact top-level scalar claim values. | Stable strings, numbers, true/false values, or null. |37| CEL condition | A boolean expression over the verified claim map named `assertion`. | Lists, nested claims, or a set of allowed values. |3839Set at least one subject, exact-claim, or CEL check. An accepted40audience alone does not identify a workload. If you configure more than one41check type, each one must pass.4243Provider verification happens first. A rule cannot override the provider's44issuer, signature, expiry, assertion-lifetime, replay, or provider-level CEL45checks.4647## Subject matching4849Use an exact subject whenever one stable `sub` identifies the workload:5051```text52repo:example-company/payments:environment:production53```5455One trailing `*` performs a prefix match:5657```text58system:serviceaccount:production:codex-*59```6061The wildcard must be the last character and must follow a non-empty prefix.62OpenAI does not accept `*`, `repo:*:production`, or `repo/*/main`.6364Do not use a broad prefix when a more stable claim can separate privileged65workloads. For example, a GitHub rule should match a repository,66workflow file, ref, or protected environment rather than every repository67owned by one organization.6869## Exact claims7071Exact claims compare top-level JWT claims without converting their types. A72string matches only the same string, a boolean matches only the same boolean,73and a number matches the same numeric value. Lists and objects are not supported74as exact values.7576For example:7778```json79{80 "repository": "example-company/payments",81 "ref": "refs/heads/main",82 "environment": "production"83}84```8586Do not include `sub` in the exact-claims map. Use the subject field or CEL.87Use CEL for nested provider claims and list membership.8889## CEL conditions9091CEL conditions receive the complete verified JWT claim map as `assertion` and92must return `true` or `false`. OpenAI supports a bounded CEL subset so rule93evaluation stays predictable.9495To allow a set of exact subjects in one rule:9697```text98assertion.sub in [99 "repo:example-company/payments:environment:production",100 "repo:example-company/billing:environment:production"101]102```103104To require a repository and one of two refs:105106```text107assertion.repository == "example-company/payments" &&108assertion.ref in ["refs/heads/main", "refs/heads/release"]109```110111To read a nested or optional claim:112113```text114has(assertion.environment) &&115assertion.environment == "production"116```117118Supported helpers include `has`, `size`, `contains`, `startsWith`, and119`endsWith`. Regular-expression matching, collection iteration macros such as120`all` or `exists`, arbitrary functions, and identifiers other than `assertion`121are not supported. Keep expressions short and prefer exact checks when they122can express the same policy.123124An absent claim, unsupported operation, non-boolean result, or evaluation error125rejects the exchange.126127## Audience matching128129The provider can set one expected audience. A rule can instead set one or more130accepted audiences. When a rule has an audience list, at least one value in the131token's `aud` claim must appear in that list.132133Use a dedicated audience for OpenAI when your provider supports one. SPIFFE134JWT-SVID rules must set an accepted audience. An OIDC rule must also set one if135the provider does not define a provider-level audience.136137Audience matching and identity checks are cumulative. A matching audience does138not compensate for a subject, exact-claim, or CEL check that does not pass.139140## Principal cardinality141142One rule maps to exactly one principal:143144```text145many accepted external identities -> one federation rule -> one OpenAI principal146```147148This supports workload replicas, jobs, or approved subjects acting as the same149user or service account. It does not let one rule choose a different150principal based on claims. Create separate rules when workloads need different151principals, workspaces, scopes, or token lifetimes.152153More than one rule may target the same principal. Use separate rules when you need154independent lifecycle controls or clearer audit attribution for each workload.155156## Scopes and authorization157158The rule can narrow the OAuth scopes in the issued access token. It cannot grant159permissions the target principal or workspace does not already have.160161When you omit scopes, OpenAI uses the standard Codex scopes: `openid`,162`profile`, `email`, and Codex local access. If you set scopes through the Admin163API, include `chatgpt.workspace.feature.allow-codex-local-access.access` and use164only those four supported values.165166Choose the least-privilege principal and workspace permissions first. Treat167rule scopes as a second restriction, not the main authorization boundary.168169## Token lifetime170171Set the OpenAI access token lifetime from 60 through 3,600 seconds. OpenAI uses172the shorter of:173174- The remaining lifetime of the upstream identity token.175- The rule's configured access-token lifetime.176177Shorter lifetimes reduce how long an issued token can outlive a policy edit,178but increase exchange frequency. A 10-minute lifetime is a practical starting179point unless your workload needs a different balance.180181## Replay protection182183Provider-level replay protection uses the JWT `jti` claim. When an administrator184turns on **Prevent assertion replay** and the token has a non-empty `jti`, OpenAI185accepts that `jti` only once for that provider until the assertion expires.186187The workload must get a new assertion with a new `jti` before every exchange,188including retries after an exchange whose outcome is unknown. Assertions without189`jti` remain usable but do not receive replay protection. Empty, null, or190non-string `jti` values do not pass validation.191192## Changes, disablement, and archival193194Ordinary edits to identity checks, scopes, or token lifetime apply to new exchanges.195Access tokens issued before the edit can remain valid until their existing TTL196ends.197198Disabling a rule or provider blocks new exchanges and revokes OpenAI access199tokens issued through it. Archiving does the same and cannot be undone.200Changing provider trust, such as issuer or JWKS settings, revokes issued tokens201before the new trust configuration becomes active.202203Use disablement for an emergency stop or a temporary pause. Archive a resource204only when you no longer need it.205206## Limits207208| Resource | Limit |209| --------------------------------------- | ------------------- |210| Non-archived providers per organization | 50 |211| Non-archived rules per provider | 50 |212| Exact claims per rule | 32 |213| Accepted audiences per rule | 32 unique values |214| Subject length | 4,096 bytes |215| Exact-claim map or CEL condition | 16 KiB |216| Access token lifetime | 60 to 3,600 seconds |217218Create separate providers for trust boundaries that need independent issuer,219key, replay, or lifecycle controls. Create separate rules under one provider220for workloads that share trust but need different principals or access policy.