Skip to content

POST /api/v1/admin/orgs/:slug/oidc-bindings

This page is auto-generated from src/admin/routes.ts. Do not edit by hand — see docs/dev/docs-auto-sync.md.

:warning: Heuristic extraction — not a contract. Response shapes below are mined from c.json(...) literals in the handler via an AST walker. Computed fields, ternaries, and non-literal returns are shown as placeholders. Refer to the linked source file for the authoritative behaviour.

POST /api/v1/admin/orgs/:slug/oidc-bindings

Section titled “POST /api/v1/admin/orgs/:slug/oidc-bindings”

Requires the following capability(ies):

  • oidc:w

Other middleware observed on this route (heuristic):

  • requireCapability
  • adminBodyLimit

POST /api/v1/admin/orgs/:slug/oidc-bindings — create a binding. Body: { “issuer”: “https://token.actions.githubusercontent.com”, “sub_pattern”: “repo:acme/payments:ref:refs/heads/main”, “repository_id”: “12345”, “event_names”: [“pull_request”, “push”], “origin”: “org_admin” | “team_admin”, “project_id”?: ”…”, “team_id”?: ”…” // required iff origin = team_admin }

Validation:

  • issuer MUST be in the static allowlist (src/auth/oidc/issuers.ts).
  • sub_pattern is required (non-empty, no whitespace).
  • repository_id is required when the issuer config sets requiresRepositoryId (GH Actions: true).
  • event_names entries must be strings; empty array = any event.
  • origin MUST be in OIDC_BINDING_ORIGINS minus ‘platform_admin’ on the customer-facing surface.
  • team_admin origin requires team_id; the team must belong to this tenant. The origin-envelope check (does an org_admin binding cover the proposed sub+repo?) lands here too.

Conflicts: the unique partial index on (tenant_id, issuer, sub_pattern, COALESCE(repository_id, ”)) WHERE revoked_at IS NULL turns a duplicate create into a 409 — the existing active binding stays in place.

{
"error": "Org not found"
}
{
"error": "Invalid JSON body"
}
{
"error": "Body must be a JSON object"
}
{
"error": "issuer is required (string)"
}
{
"error": <template-string>
}
{
"error": "sub_pattern is required (string)"
}
{
"error": "sub_pattern must be 1..1024 chars with no whitespace / control characters"
}
{
"error": "repository_id must be a positive integer string"
}
{
"error": "repository_id must be a positive integer or its string form"
}
{
"error": "event_names must be an array of strings"
}
{
"error": "every event_names entry must be a non-whitespace 1..64-char string"
}
{
"error": "origin is required (string)"
}
{
"error": "origin must be 'org_admin' or 'team_admin' on this surface"
}
{
"error": "project_id must be a string"
}
{
"error": "project_id not found for this org"
}
{
"error": "team_id must be a string"
}
{
"error": "team_id not found for this org"
}
{
"error": "team_id is required for origin=team_admin"
}
{
"error": "team_admin binding falls outside any active org_admin envelope — ask an org admin to expand the trust envelope first"
}

Shape not a JSON literal — passed through from a variable or expression. See source.

{
"error": "An active binding already exists for this (issuer, sub, repository_id)"
}
  • File: src/admin/routes.ts
  • Line: 6394