{
  "openapi": "3.1.1",
  "info": {
    "title": "QAudit Admin API",
    "description": "The QAudit **Admin API** is the operator-facing management side of QAudit: the\nautomated path for organization and tenant lifecycle, emitter provisioning,\ncredential issuance, signing-key rotation, and scoped support sessions. It is a\nstandalone service, a sibling of the Audit Gateway and the Data API.\n\n```mermaid\nflowchart LR\n  OP[\"Quadient operator\"] --> WG[Web Gateway]\n  WG -->|Bearer| ADMIN[Admin API]\n  ADMIN -->|qaudit.* events| GW[Audit Gateway]\n  GW --> EV[(Audit events)]\n```\n\n### Who calls it\n\nA Quadient operator, through a tool that authenticates to the API. The future\nAdmin Console (a separate consumer) is one such tool, the way the Data Viewer\nconsumes the Data API.\n\n### Authenticating\n\nThe Admin API validates the `Bearer` JWT it receives: a Quadient SSO token\nrelayed by the Admin Console BFF, or an Admin API credential's QAudit access\ntoken from the auth service's `client_credentials` grant, presented as\n`Authorization: Bearer <jwt>`. The login flow itself runs in the Admin Console\nBFF; this service only validates the relayed token.\n\n### Resource hierarchy\n\nAn organization is the identity, credential, and signing boundary; tenants are\nsub-scopes within it. An organization's resources, its tenants, signing keys,\ndata credentials, and support sessions, hang off\n`/organizations/{organization_id}`. Two platform-wide surfaces sit outside any\nsingle organization: the emitter registry at `/system/emitters`, and Admin API\ncredentials at `/admin/credentials`.\n\n### Credential capability model\n\nQAudit has two kinds of API credential. An **organization credential**\n(`/organizations/{organization_id}/credentials`) is data-only: it grants Data\nAPI read access scoped to its organization and carries no capability flag. An\n**Admin API credential** (`/admin/credentials`) is bound to no organization and\ngrants Admin API access at an `admin` access level, either `read-only` (the list\nand get endpoints) or `read-write` (reads and mutations). Either secret is shown\nonce, at issuance or rotation, and is stored only as a hash.\n\n### Auditing\n\nEvery mutating operation is recorded as a `qaudit.*` audit event; reads, lists,\nand fetches emit no event.\n\n### Errors\n\nError responses use problem details (`application/problem+json`, RFC 9457): a\n`status`, a short `title`, and a `detail`. A `400` additionally lists per-field\nvalidation messages.\n\n### Sections\n\n- **Organizations**: create and edit organizations, and read their signing keys.\n- **Tenants**: add and edit the tenants within an organization.\n- **Organization credentials** / **Admin API credentials**: issue, rotate, and\n  revoke the two credential kinds.\n- **Emitters**: provision, rotate, and revoke the applications that submit events.\n- **Support sessions**: open a scope-bound session into an organization's data.\n",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.admin.demo.qaudit.cloud.serensia.net/"
    }
  ],
  "paths": {
    "/v1/organizations": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "List organizations",
        "description": "Lists organizations, newest first, each with its display name, creation time, and current signing key (version + fingerprint). Narrow with `search` (a case-insensitive match on the display name) and the `created_after` / `created_before` window. Page with `page` / `page_size`.",
        "operationId": "ListOrganizations",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive substring match on the organization display name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_after",
            "in": "query",
            "description": "Only organizations created at or after this instant (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_before",
            "in": "query",
            "description": "Only organizations created at or before this instant (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number; defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Page size; defaults to 50 and is clamped to a maximum.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationPage"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Organizations"
        ],
        "summary": "Create an organization",
        "description": "Creates an organization: provisions its per-organization Ed25519 signing key and opens its access-trail chain (whose first event is `qaudit.organization.created.v1`), with the signing key, chain, and `cfg` row written atomically. Tenants are added afterwards through the tenant endpoint. An optional `slug` sets the organization's subdomain label; an omitted slug is derived from the organization id. Returns the created organization, and `409` when the slug is taken.",
        "operationId": "CreateOrganization",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrganizationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get an organization",
        "description": "Returns one organization by id, with its current signing key (version + fingerprint). Responds `404` when no such organization exists.",
        "operationId": "GetOrganization",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Organizations"
        ],
        "summary": "Edit an organization",
        "description": "Edits an organization. This is a partial update: an omitted field is left unchanged (neither the display name nor the slug can be cleared). The change is audited on the organization's chain before it is applied; if it cannot be audited the organization is left unchanged. Renaming the slug stops the previous subdomain resolving and signs out the organization's live sessions. Responds `404` when no such organization exists, and `409` when the new slug is taken.",
        "operationId": "UpdateOrganization",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateOrganizationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/signing-keys": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "List an organization's signing keys",
        "description": "Returns the organization's signing keys (newest version first), each with its public key material so an operator can share it with the organization, for example during onboarding. The private key never leaves Vault. Responds `404` when no such organization exists.",
        "operationId": "ListOrganizationSigningKeys",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/OrganizationSigningKeyDetails"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/signing-keys/{version}/pem": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Download an organization signing key (PEM)",
        "description": "Returns the organization's signing key, by version, as a PEM-encoded public key, the most compatible format to hand to the organization. Responds `404` when no such organization or version exists.",
        "operationId": "DownloadOrganizationSigningKeyPem",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "version",
            "in": "path",
            "description": "Signing-key version.",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/x-pem-file": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/signing-keys/{version}/jws": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Download an organization signing key (JWS attestation)",
        "description": "Returns the organization's signing key, by version, as a compact JWS attesting the key under QAudit's identity (signed by the root key), so the organization can verify its provenance. Responds `404` when no such organization or version exists, `503` when attestation is not configured on this deployment.",
        "operationId": "DownloadOrganizationSigningKeyJws",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "version",
            "in": "path",
            "description": "Signing-key version.",
            "required": true,
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/jwt": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/signing-key/rotate": {
      "post": {
        "tags": [
          "Organizations"
        ],
        "summary": "Rotate an organization's signing key",
        "description": "Rotates the organization's signing key to a new version. Generates the new key version, records its public key, and writes a `qaudit.signing-key.rotated.v1` event to the organization's chain synchronously (the source of truth), then propagates the event to each of the organization's tenant chains in the background. Each per-chain write is transparent to emitters: the chain is briefly frozen, the event written, then the chain resumes and any buffered events drain. The new public key is read back through the signing-key endpoints. Responds `202` once the new version is recorded and the organization chain is written, `404` when no such organization exists, and `503` when the rotation could not be written.",
        "operationId": "RotateOrganizationSigningKey",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization whose signing key to rotate.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningKeyRotationResult"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/signing-key/recover": {
      "post": {
        "tags": [
          "Organizations"
        ],
        "summary": "Recover an organization's lost signing key",
        "description": "Starts recovering an organization's signing key when its current key was lost and can no longer sign, for example an organization onboarded after the point a Vault restore rolled back to. Generates a fresh key version and starts a background job that writes a `qaudit.signing-key.recovered.v1` event, signed by the platform root key (not the lost key), to the organization's chain and each of its tenant chains, advancing every chain to the new version; existing events still verify against their recorded public keys. Because an organization can have very many tenants, the fan-out runs as a tracked job: this responds `202` with the job and its progress, which the recovery-status endpoints report. At most one recovery runs per organization: a second attempt while one is running responds `409` and points at it. It also refuses with `409` when the current key still resolves and every chain is on it, because a normal rotation applies then. Responds `404` when no such organization exists.",
        "operationId": "RecoverOrganizationSigningKey",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization whose signing key to recover.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningKeyRecoveryDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/signing-key/recoveries": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "List an organization's signing-key recoveries",
        "description": "Returns the organization's signing-key recovery jobs, newest first, each with its recovered version, status, and how many tenant chains it has moved to the new version. Responds `404` when no such organization exists.",
        "operationId": "ListOrganizationSigningKeyRecoveries",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number; defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Page size; defaults to 50 and is clamped to a maximum.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningKeyRecoveryPage"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/signing-key/recoveries/{recovery_id}": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get a signing-key recovery",
        "description": "Returns one signing-key recovery job by id, with its status and progress (total tenant chains and how many are on the recovered version), the poll target for a progress bar. Responds `404` when no such recovery exists for the organization.",
        "operationId": "GetOrganizationSigningKeyRecovery",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "recovery_id",
            "in": "path",
            "description": "Identifier of the recovery job.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningKeyRecoveryDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/oidc-providers": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "List an organization's OIDC providers",
        "description": "Lists the OIDC login providers configured for the organization, each with its label, issuer, and client id. The client secret is held in Vault and is never returned. Responds `404` when no such organization exists.",
        "operationId": "ListOrganizationOidcProviders",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/OidcProvider"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Organizations"
        ],
        "summary": "Add an OIDC provider to an organization",
        "description": "Adds an OIDC login provider. The client secret, when supplied, is written to Vault; the non-secret fields are stored on the organization. The change is audited on the organization's chain before it is applied; if it cannot be audited nothing is stored. Responds `404` when no such organization exists, `400` for an invalid request, and `503` when the change could not be audited or stored.",
        "operationId": "AddOrganizationOidcProvider",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOidcProviderRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OidcProvider"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/oidc-providers/{provider_id}": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get an organization's OIDC provider",
        "description": "Returns one OIDC provider by id. Responds `404` when no such organization or provider exists.",
        "operationId": "GetOrganizationOidcProvider",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "provider_id",
            "in": "path",
            "description": "Identifier of the OIDC provider.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OidcProvider"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Organizations"
        ],
        "summary": "Edit an organization's OIDC provider",
        "description": "Edits an OIDC provider. This is a partial update: an omitted field is left unchanged (the label, issuer, and client id cannot be cleared), and a supplied non-empty client secret rotates the value in Vault. The change is audited on the organization's chain before it is applied. Responds `404` when no such organization or provider exists, `400` for an invalid request, and `503` when the change could not be audited or stored.",
        "operationId": "UpdateOrganizationOidcProvider",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "provider_id",
            "in": "path",
            "description": "Identifier of the OIDC provider.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateOidcProviderRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OidcProvider"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Organizations"
        ],
        "summary": "Remove an organization's OIDC provider",
        "description": "Removes an OIDC provider and its Vault-held client secret. The change is audited on the organization's chain before it is applied. Responds `404` when no such organization or provider exists, and `503` when the change could not be audited.",
        "operationId": "RemoveOrganizationOidcProvider",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "provider_id",
            "in": "path",
            "description": "Identifier of the OIDC provider.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/tenants": {
      "get": {
        "tags": [
          "Tenants"
        ],
        "summary": "List an organization's tenants",
        "description": "Lists the organization's tenants, ordered by display name. Narrow with `search` (a case-insensitive match on the display name and tenant id) and the `onboarded_from` / `onboarded_to` window. Page with `page` / `page_size`. Responds `404` when no such organization exists.",
        "operationId": "ListTenants",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive substring matched against the display name and tenant id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "onboarded_from",
            "in": "query",
            "description": "Only tenants onboarded at or after this instant (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "onboarded_to",
            "in": "query",
            "description": "Only tenants onboarded at or before this instant (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number; defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Page size; defaults to 50 and is clamped to a maximum.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPage"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Tenants"
        ],
        "summary": "Add a tenant",
        "description": "Adds a tenant to the organization: opens its access-trail chain (whose first event is `qaudit.tenant.created.v1`, embedding the organization's current signing key), with the chain and `cfg` row written atomically. The `tenant_id` is caller-supplied: non-empty, unique within the organization, and may not start with the reserved `_` prefix. Returns the created tenant.",
        "operationId": "CreateTenant",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTenantRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tenant"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/tenants/{tenant_id}": {
      "get": {
        "tags": [
          "Tenants"
        ],
        "summary": "Get a tenant",
        "description": "Returns one tenant of the organization by id. Responds `404` when no such tenant belongs to the organization.",
        "operationId": "GetTenant",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "tenant_id",
            "in": "path",
            "description": "Opaque tenant identifier.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tenant"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Tenants"
        ],
        "summary": "Edit a tenant",
        "description": "Edits a tenant. This is a partial update: an omitted display name is left unchanged (it cannot be cleared). The change is audited on the tenant's chain before it is applied; if it cannot be audited the tenant is left unchanged. Responds `404` when no such tenant belongs to the organization.",
        "operationId": "UpdateTenant",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "tenant_id",
            "in": "path",
            "description": "Opaque tenant identifier.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTenantRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tenant"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/tenants/{tenant_id}/overview": {
      "get": {
        "tags": [
          "Tenants"
        ],
        "summary": "Get a tenant's operational overview",
        "description": "Returns an operator's read-only view of a tenant's operational state: its identity, the signing-key version its chain head was signed under against the organization's current version, and its data-pack figures. Responds `404` when no such tenant belongs to the organization.",
        "operationId": "GetTenantOverview",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "tenant_id",
            "in": "path",
            "description": "Opaque tenant identifier.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOverview"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/tenants/{tenant_id}/activity/events": {
      "get": {
        "tags": [
          "Tenants"
        ],
        "summary": "Get a tenant's event activity over a window",
        "description": "Returns a per-bucket event-count series for a tenant's chain over a window of whole UTC days [`from`, `to`], bucketed by ingestion time (`receipt_ts`). The resolution is derived from the window length: hourly for short windows, then daily, weekly, and monthly as it widens. With `names` (repeat the parameter per name) each bucket counts only those event names; without it, all events. Empty buckets are zero-filled. Responds `404` when no such tenant belongs to the organization.",
        "operationId": "GetTenantActivity",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "tenant_id",
            "in": "path",
            "description": "Opaque tenant identifier.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "Window start, an inclusive UTC day.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "Window end, an inclusive UTC day.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "names",
            "in": "query",
            "description": "Event names to count; all events when omitted. Repeat the parameter for several names.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantActivity"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/tenants/{tenant_id}/activity/events/names": {
      "get": {
        "tags": [
          "Tenants"
        ],
        "summary": "List the event names present in a tenant's activity window",
        "description": "Returns the distinct event names on a tenant's chain within the window of whole UTC days [`from`, `to`], each with its count over that window, ordered by count descending. Narrow with `search` (a case-insensitive substring of the name) and page with `page` / `page_size`. Responds `404` when no such tenant belongs to the organization.",
        "operationId": "ListTenantEventNames",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "tenant_id",
            "in": "path",
            "description": "Opaque tenant identifier.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "Window start, an inclusive UTC day.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "Window end, an inclusive UTC day.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive substring matched against the event name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number; defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Page size; defaults to 25 and is clamped to a maximum.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantEventNamePage"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/credentials": {
      "get": {
        "tags": [
          "Organization credentials"
        ],
        "summary": "List an organization's credentials",
        "description": "Lists the organization's credentials, newest first, with their lifecycle status and (when revoked) the revocation. The full secret is never returned; each credential carries only its non-secret key prefix, to help recognize it. Page with `page` / `page_size`, narrow to a lifecycle state with `status` (`active`, `expired`, `revoked`), and match names with `search`. The response's `counts` reports how many credentials match the search in each status, independent of the `status` filter.",
        "operationId": "ListOrganizationCredentials",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number; defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Page size; defaults to 50 and is clamped to a maximum.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Narrow to a lifecycle status: active, expired, or revoked.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive match on the credential name.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationCredentialPage"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Organization credentials"
        ],
        "summary": "Issue an organization credential",
        "description": "Issues a data-only credential scoped to this organization and returns the secret once, in the response body: it is never shown again and only its hash is stored. The issuance is audited on the organization's chain; if it cannot be audited the credential is not created.",
        "operationId": "IssueOrganizationCredential",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IssueOrganizationCredentialRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssuedOrganizationCredential"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/credentials/{credential_id}": {
      "get": {
        "tags": [
          "Organization credentials"
        ],
        "summary": "Get an organization credential",
        "description": "Returns one of the organization's credentials by id. The full secret is never returned; the credential carries only its non-secret key prefix, to help recognize it. Responds `404` when no such credential belongs to the organization.",
        "operationId": "GetOrganizationCredential",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "credential_id",
            "in": "path",
            "description": "Identifier of the credential.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationCredential"
                }
              }
            }
          },
          "404": {
            "description": "Not Found"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/credentials/{credential_id}/rotate": {
      "post": {
        "tags": [
          "Organization credentials"
        ],
        "summary": "Rotate an organization credential",
        "description": "Regenerates the credential's secret in place (same id and name) and returns the new secret once; the previous secret stops working immediately. The optional `expires_at` in the body renews the credential at the same time: omit it to keep the current expiry, or set it (must be in the future) to reschedule. Rotating a revoked credential, or an expired one without a new future `expires_at`, is rejected. The rotation is audited on the organization's chain before the secret changes; if it cannot be audited the secret is left unchanged.",
        "operationId": "RotateOrganizationCredential",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "credential_id",
            "in": "path",
            "description": "Identifier of the credential.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/RotateCredentialRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssuedOrganizationCredential"
                }
              }
            }
          },
          "404": {
            "description": "Not Found"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/credentials/{credential_id}/revoke": {
      "post": {
        "tags": [
          "Organization credentials"
        ],
        "summary": "Revoke an organization credential",
        "description": "Revokes the credential; it stops working immediately and the revocation is terminal. Supply an optional `reason` in the request body to record why; it is stored on the credential and carried on the audit event. The revocation is audited on the organization's chain.",
        "operationId": "RevokeOrganizationCredential",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Identifier of the organization.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "credential_id",
            "in": "path",
            "description": "Identifier of the credential.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/RevokeCredentialRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/credentials": {
      "get": {
        "tags": [
          "Admin API credentials"
        ],
        "summary": "List Admin API credentials",
        "description": "Lists the Admin API credentials, newest first, with their admin access level, lifecycle status, and (when revoked) the revocation. The full secret is never returned; each credential carries only its non-secret key prefix, to help recognize it. Page with `page` / `page_size`, narrow to a lifecycle state with `status` (`active`, `expired`, `revoked`), and match names with `search`. The response's `counts` reports how many credentials match the search in each status, independent of the `status` filter.",
        "operationId": "ListAdminCredentials",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number; defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Page size; defaults to 50 and is clamped to a maximum.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Narrow to a lifecycle status: active, expired, or revoked.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive match on the credential name.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminCredentialPage"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Admin API credentials"
        ],
        "summary": "Issue an Admin API credential",
        "description": "Issues an Admin API credential carrying the requested `admin` access level (`read-only` or `read-write`), which is required. Returns the secret once, in the response body: it is never shown again and only its hash is stored. The issuance is audited on the system chain; if it cannot be audited the credential is not created.",
        "operationId": "IssueAdminCredential",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IssueAdminCredentialRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssuedAdminCredential"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/HttpValidationProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/credentials/{credential_id}": {
      "get": {
        "tags": [
          "Admin API credentials"
        ],
        "summary": "Get an Admin API credential",
        "description": "Returns an Admin API credential by id. The full secret is never returned; the credential carries only its non-secret key prefix, to help recognize it. Responds `404` when no such Admin API credential exists.",
        "operationId": "GetAdminCredential",
        "parameters": [
          {
            "name": "credential_id",
            "in": "path",
            "description": "Identifier of the credential.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminCredential"
                }
              }
            }
          },
          "404": {
            "description": "Not Found"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/credentials/{credential_id}/rotate": {
      "post": {
        "tags": [
          "Admin API credentials"
        ],
        "summary": "Rotate an Admin API credential",
        "description": "Regenerates the credential's secret in place (same id, name, and access level) and returns the new secret once; the previous secret stops working immediately. The optional `expires_at` in the body renews the credential at the same time: omit it to keep the current expiry, or set it (must be in the future) to reschedule. Rotating a revoked credential, or an expired one without a new future `expires_at`, is rejected. The rotation is audited on the system chain before the secret changes; if it cannot be audited the secret is left unchanged.",
        "operationId": "RotateAdminCredential",
        "parameters": [
          {
            "name": "credential_id",
            "in": "path",
            "description": "Identifier of the credential.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/RotateCredentialRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssuedAdminCredential"
                }
              }
            }
          },
          "404": {
            "description": "Not Found"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/credentials/{credential_id}/revoke": {
      "post": {
        "tags": [
          "Admin API credentials"
        ],
        "summary": "Revoke an Admin API credential",
        "description": "Revokes the credential; it stops working immediately and the revocation is terminal. Supply an optional `reason` in the request body to record why; it is stored on the credential and carried on the audit event. The revocation is audited on the system chain.",
        "operationId": "RevokeAdminCredential",
        "parameters": [
          {
            "name": "credential_id",
            "in": "path",
            "description": "Identifier of the credential.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/RevokeCredentialRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/system/emitters": {
      "get": {
        "tags": [
          "Emitters"
        ],
        "summary": "List the emitter registry",
        "description": "Lists emitters, newest first, including platform-managed rows so operators see everything that is emitting. Narrow with `search` (a case-insensitive match on the name and emitter id), `managed_by` (`operator` or `platform`), and `status` (`active` or `revoked`); page with `page` / `page_size`. The response's `counts` reports how many emitters match in each kind, independent of the `managed_by` filter but honoring `status`.",
        "operationId": "ListEmitters",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive substring matched against the name and emitter id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_from",
            "in": "query",
            "description": "Only emitters created at or after this instant (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_to",
            "in": "query",
            "description": "Only emitters created at or before this instant (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "managed_by",
            "in": "query",
            "description": "Restrict to operator- or platform-managed rows: `operator` or `platform`; omit for both.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Restrict to a lifecycle state: `active` or `revoked`; omit for both.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number; defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Page size; defaults to 50 and is clamped to a maximum.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmitterPage"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Emitters"
        ],
        "summary": "Provision an emitter",
        "description": "Issues the emitter's mTLS cert and inserts its registry row, atomically. Supply a `csr` to have the leaf signed from it (no private key is returned), or omit it to receive a platform-generated keypair as a PKCS#12 bundle. The cert is returned once. The new row is operator-managed. The provisioning is audited on the system chain; if it cannot be audited the emitter is not created.",
        "operationId": "ProvisionEmitter",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProvisionEmitterRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmitterWithCertificate"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "502": {
            "description": "Bad Gateway",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/system/emitters/{emitter_id}": {
      "get": {
        "tags": [
          "Emitters"
        ],
        "summary": "Get an emitter",
        "description": "Returns one emitter by id. Responds `404` when no such emitter exists.",
        "operationId": "GetEmitter",
        "parameters": [
          {
            "name": "emitter_id",
            "in": "path",
            "description": "The emitter's opaque identifier.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Emitter"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Emitters"
        ],
        "summary": "Edit an emitter",
        "description": "Edits an emitter. This is a partial update: an omitted field is left unchanged, and sending `description` as null clears it (the name cannot be cleared). The change is audited on the system chain before it is applied; if it cannot be audited the emitter is left unchanged. Responds `404` when no such emitter exists, `403` for a platform-managed row, `409` for a revoked row (revocation is terminal). Cert rotation is a separate operation (`POST /system/emitters/{emitter_id}/cert`).",
        "operationId": "UpdateEmitter",
        "parameters": [
          {
            "name": "emitter_id",
            "in": "path",
            "description": "The emitter's opaque identifier.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateEmitterRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Emitter"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/system/emitters/{emitter_id}/cert": {
      "post": {
        "tags": [
          "Emitters"
        ],
        "summary": "Rotate an emitter's cert",
        "description": "Issues a fresh mTLS cert for the emitter and replaces the cert metadata on its row; the previous cert stops authorizing as soon as the row points at the new one. Supply a `csr` to have the leaf signed from it (no private key is returned), or omit it to receive a platform-generated keypair as a PKCS#12 bundle. The cert is returned once. The rotation is audited on the system chain before it is applied. Responds `404` when no such emitter exists, `403` for a platform-managed row, `409` for a revoked row (revocation is terminal).",
        "operationId": "RotateEmitterCert",
        "parameters": [
          {
            "name": "emitter_id",
            "in": "path",
            "description": "The emitter's opaque identifier.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmitterCertRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmitterWithCertificate"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "502": {
            "description": "Bad Gateway",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/system/emitters/{emitter_id}/revoke": {
      "post": {
        "tags": [
          "Emitters"
        ],
        "summary": "Revoke an emitter",
        "description": "Revokes the emitter; its cert stops authorizing immediately and the revocation is terminal. Supply an optional `reason` in the request body to record why; it is carried on the audit event. The revocation is audited on the system chain. Responds `404` when no such emitter exists or it is already revoked, `403` for a platform-managed row.",
        "operationId": "RevokeEmitter",
        "parameters": [
          {
            "name": "emitter_id",
            "in": "path",
            "description": "The emitter's opaque identifier.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/RevokeEmitterRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/support-sessions": {
      "post": {
        "tags": [
          "Support sessions"
        ],
        "summary": "Open a support session",
        "description": "Opens a scoped, time-bound support session against the organization: audits the opening on the organization's chain (`qaudit.support.session.opened.v1`), mints a short-lived grant for the calling operator, and returns `201` with a redirect to the Data Viewer at the organization scope. The session auto-closes when the grant expires. Requires an operator session (a human operator); responds `404` when no such organization exists, `503` when the opening could not be audited.",
        "operationId": "OpenSupportSession",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Organization the session grants a view of.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OpenSupportSessionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupportSessionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Support sessions"
        ],
        "summary": "List active support sessions",
        "description": "Lists the organization's currently-active support sessions, most recently opened first, each with its operator, reason, ticket reference, opened-at, and expiry. A session that has expired or closed is no longer active and is not returned; the audit history lives on the chain.",
        "operationId": "ListSupportSessions",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Organization whose active sessions to list.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SupportSession"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/support-sessions/{support_session_id}/grant": {
      "post": {
        "tags": [
          "Support sessions"
        ],
        "summary": "Resume an active support session",
        "description": "Re-acquires the grant for an already-open support session, for the operator who opened it: re-mints a support token capped at the session's existing expiry and returns `200` with a fresh redirect to the Data Viewer (so an operator who lost the grant can regain access for the remaining window). The session's audited open/close window is unchanged, and no new event is recorded. Requires an operator session; responds `403` when the caller is not the operator who opened the session, `404` when no active session with that id exists for the organization, and `503` when a token could not be issued.",
        "operationId": "ResumeSupportSession",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Organization the session grants a view of.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "support_session_id",
            "in": "path",
            "description": "Identifier of the session to resume.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupportSessionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/support-sessions/{support_session_id}": {
      "get": {
        "tags": [
          "Support sessions"
        ],
        "summary": "Get an active support session",
        "description": "Returns one active support session by id. Responds `404` when no active session with that id exists for the organization, including once the session has expired or closed (live state, not history).",
        "operationId": "GetSupportSession",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Organization the session belongs to.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "support_session_id",
            "in": "path",
            "description": "Identifier of the support session.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupportSession"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/ignore-events/preview": {
      "post": {
        "tags": [
          "Ignore events"
        ],
        "summary": "Count what a formula would exclude",
        "description": "Counts the organization's events a formula matches, without writing anything: the total, a breakdown per chain and per event name, and a sample of the matched events. The count is a snapshot as of `counted_before`; a write bounds its own set by its own date, so anything matching that arrives in between is excluded too. Responds `400` when the formula does not parse or uses a construct that cannot be resolved against a single event, and `404` when no such organization exists.",
        "operationId": "PreviewIgnoreEvent",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Organization whose events the formula is counted over.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreviewIgnoreEventRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IgnoreEventPreview"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/organizations/{organization_id}/ignore-events": {
      "post": {
        "tags": [
          "Ignore events"
        ],
        "summary": "Exclude events from KPI computation",
        "description": "Records a `qaudit.events.ignored.v1` event on the organization's access-trail chain, excluding every event the formula matches that was received before the declaration itself. The declaration's own date is the bound, stamped server-side, and the count it carries is the server's count of that set. **This cannot be undone**: an ignore event cannot itself be ignored or withdrawn, so a formula reaching further than intended permanently excludes real events. Requires an operator session (a human operator); responds `400` when the formula is unusable or matches no event, `404` when no such organization exists, `503` when the declaration could not be recorded.",
        "operationId": "CreateIgnoreEvent",
        "parameters": [
          {
            "name": "organization_id",
            "in": "path",
            "description": "Organization whose events are excluded.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateIgnoreEventRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IgnoreEvent"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/products": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "List products",
        "description": "Lists products, newest first, each with its name, description, and creation/edit times. Page with `page` / `page_size`.",
        "operationId": "ListProducts",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number; defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Page size; defaults to 50 and is clamped to a maximum.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductPage"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Create a product",
        "description": "Creates a product with an auto-generated id and opens its status chain, which records its availability. The creation is audited on the system chain (`qaudit.product.created.v1`); if it cannot be audited the product is not created. Returns the created product.",
        "operationId": "CreateProduct",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProductRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/products/{product_id}": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Get a product",
        "description": "Returns one product by id. Responds `404` when no such product exists.",
        "operationId": "GetProduct",
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "description": "Identifier of the product.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Products"
        ],
        "summary": "Edit a product",
        "description": "Edits a product. This is a partial update: an omitted field is left unchanged, and sending `description` as null clears it (the name cannot be cleared). The change is audited on the system chain (`qaudit.product.updated.v1`) before it is applied; if it cannot be audited the product is left unchanged. Responds `404` when no such product exists.",
        "operationId": "UpdateProduct",
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "description": "Identifier of the product.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProductRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/v1/products/{product_id}/emitters": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "List a product's emitters",
        "description": "Lists the emitters owned by the product, newest first, using the same filters as the global emitter list: narrow with `search` (a case-insensitive match on the name and emitter id) and `status` (`active` or `revoked`), and page with `page` / `page_size`. Responds `404` when no such product exists.",
        "operationId": "ListProductEmitters",
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "description": "Identifier of the product.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive substring matched against the name and emitter id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_from",
            "in": "query",
            "description": "Only emitters created at or after this instant (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_to",
            "in": "query",
            "description": "Only emitters created at or before this instant (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Restrict to a lifecycle state: `active` or `revoked`; omit for both.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "1-based page number; defaults to 1.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Page size; defaults to 50 and is clamped to a maximum.",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductEmitterPage"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Provision an emitter for a product",
        "description": "Issues the emitter's mTLS cert, inserts its registry row, and records the product as its owner. Supply a `csr` to have the leaf signed from it (no private key is returned), or omit it to receive a platform-generated keypair as a PKCS#12 bundle. The cert is returned once. The new row is operator-managed and also appears in the global emitter list. The provisioning is audited on the system chain; if it cannot be audited the emitter is not created. Responds `404` when no such product exists.",
        "operationId": "ProvisionProductEmitter",
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "description": "Identifier of the product.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProvisionEmitterRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmitterWithCertificate"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "502": {
            "description": "Bad Gateway",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AdminCapability": {
        "enum": [
          "read-only",
          "read-write"
        ],
        "description": "A credential's Admin API access level. AdminCapability.ReadOnly may call the\nread endpoints (list / get); AdminCapability.ReadWrite may also mutate (issue,\nrotate, revoke, and the other management operations). An authenticated\noperator session is always full read/write. A credential with no Admin API\naccess carries no level (a `null``Admin`)."
      },
      "AdminCredential": {
        "required": [
          "credential_id",
          "name",
          "key_prefix",
          "admin",
          "status",
          "creation"
        ],
        "type": "object",
        "properties": {
          "credential_id": {
            "type": "string",
            "description": "Credential identifier.",
            "example": "00000000-0000-0000-0000-000000000000"
          },
          "name": {
            "type": "string",
            "description": "Operator-facing label."
          },
          "key_prefix": {
            "type": "string",
            "description": "The non-secret leading fragment of the key, kept to help recognize it. The full key is never stored.",
            "example": "qa_AbCdEf"
          },
          "admin": {
            "description": "Admin API access level (`read-only` or `read-write`).",
            "$ref": "#/components/schemas/AdminCapability"
          },
          "status": {
            "description": "Lifecycle status as of the response.",
            "$ref": "#/components/schemas/ApiCredentialStatus"
          },
          "creation": {
            "description": "When the credential was issued, and by whom.",
            "$ref": "#/components/schemas/CredentialCreation"
          },
          "expiration": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Scheduled end of validity; absent when it never expires.",
                "$ref": "#/components/schemas/CredentialExpiration"
              }
            ]
          },
          "revocation": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "When the credential was revoked, by whom, and why; absent while not revoked.",
                "$ref": "#/components/schemas/CredentialRevocation"
              }
            ]
          },
          "last_used_at": {
            "type": [
              "null",
              "string"
            ],
            "description": "Last time the key authenticated a request; absent if never used.",
            "format": "date-time"
          }
        },
        "description": "An Admin API credential: a key bound to no organization, carrying an Admin API\naccess level (`admin`). The secret is never returned and only its hash is\nstored; the response carries the non-secret key prefix (the first few\ncharacters) to help recognize the key."
      },
      "AdminCredentialPage": {
        "required": [
          "items",
          "total",
          "page",
          "page_size",
          "counts"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminCredential"
            },
            "description": "The credentials on this page, newest first."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total matches across all pages, for the filtered status.",
            "format": "int32"
          },
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The 1-based page number.",
            "format": "int32"
          },
          "page_size": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The page size applied.",
            "format": "int32"
          },
          "counts": {
            "description": "Per-status match counts for the current search, independent of the status filter.",
            "$ref": "#/components/schemas/CredentialStatusCounts"
          }
        },
        "description": "One page of Admin API credentials: the rows for the filtered status, the total\nmatch count for paging, and the per-status counts for the current search\n(across all statuses) so the caller can badge each status view."
      },
      "ApiCredentialStatus": {
        "enum": [
          "active",
          "expired",
          "revoked"
        ],
        "description": "Lifecycle status of an API credential. Precedence is ApiCredentialStatus.Revoked\n&gt; ApiCredentialStatus.Expired &gt; ApiCredentialStatus.Active: revocation is terminal,\nexpiry is a renewable time bound."
      },
      "CreateIgnoreEventRequest": {
        "required": [
          "formula",
          "explanation"
        ],
        "type": "object",
        "properties": {
          "formula": {
            "type": "string",
            "description": "The formula naming the events to exclude, in the selection-predicate grammar.\nRequired, and must be the formula the count was previewed for."
          },
          "explanation": {
            "type": "string",
            "description": "Why the events are corrupted. Required, non-empty, and shown to the customer\nwherever an excluded event or an affected indicator appears, so it is the whole\nof the justification they get."
          }
        },
        "description": "Request to write an ignore event: the declaration that the events the formula\nnames are corrupted and must be left out of KPI computation. The bound closing\nthe matched set is the declaration's own date, stamped server-side, so it is not\na field a caller supplies."
      },
      "CreateOidcProviderRequest": {
        "required": [
          "display_name",
          "issuer_url",
          "client_id"
        ],
        "type": "object",
        "properties": {
          "display_name": {
            "type": "string",
            "description": "The provider's login-button label. Required, non-empty."
          },
          "issuer_url": {
            "type": "string",
            "description": "The provider's OIDC issuer URL. Required; an absolute URL."
          },
          "client_id": {
            "type": "string",
            "description": "The provider's OIDC client id at that issuer. Required, non-empty."
          },
          "client_secret": {
            "type": [
              "null",
              "string"
            ],
            "description": "The provider's OIDC client secret, stored in Vault. Optional; omit for a public client."
          }
        },
        "description": "Request to add an OIDC login provider to an organization. The client secret is\nwrite-only: it is stored in Vault and never returned by a read. Omit it for a\npublic client (PKCE only)."
      },
      "CreateOrganizationRequest": {
        "required": [
          "display_name",
          "slug"
        ],
        "type": "object",
        "properties": {
          "display_name": {
            "type": "string",
            "description": "The organization's display name, shown wherever the organization is identified. Required, non-empty."
          },
          "slug": {
            "type": "string",
            "description": "The organization's addressing slug, its subdomain label. Required; names the organization in its subdomain. Matches `^[a-z0-9_-]+$` and is unique."
          }
        },
        "description": "Request to create an organization. Creating one provisions its signing key and\nopens its access-trail chain; tenants are added afterwards through the tenant\nendpoint."
      },
      "CreateProductRequest": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The product's name, shown wherever the product is identified. Required, non-empty."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "An optional description of the product."
          },
          "probe_url": {
            "type": [
              "null",
              "string"
            ],
            "description": "The product's status probe URL, the address QAudit polls to observe the product's\navailability. Optional: omit or send `null` to create the product unpolled. When set,\nmust be an `https` URL that does not resolve to a private, loopback, link-local, or\ncloud-metadata address."
          }
        },
        "description": "Request to create a product. Creating one opens the product's status chain, which\nrecords its availability."
      },
      "CreateTenantRequest": {
        "required": [
          "tenant_id",
          "display_name"
        ],
        "type": "object",
        "properties": {
          "tenant_id": {
            "type": "string",
            "description": "The tenant's opaque identifier. Required, non-empty, unique within the\norganization, and may not start with the reserved `_` prefix\n(reserved for platform-written chains)."
          },
          "display_name": {
            "type": "string",
            "description": "The tenant's display name. Required, non-empty."
          }
        },
        "description": "Request to add a tenant to an organization. Creating one opens the tenant's\nchain (its genesis `qaudit.tenant.created.v1`)."
      },
      "CredentialCreation": {
        "required": [
          "at"
        ],
        "type": "object",
        "properties": {
          "at": {
            "type": "string",
            "description": "When the credential was issued.",
            "format": "date-time",
            "example": "2026-06-07T12:00:00+00:00"
          },
          "actor": {
            "type": [
              "null",
              "string"
            ],
            "description": "The actor that issued it; absent when the issuance was unattributed.",
            "example": "user:operator-abc-123"
          }
        },
        "description": "When a credential was issued, and by whom. The actor is the flat tag\n    `\"{kind}:{id}\"` (`user:{subject}` or `credential:{id}`); absent\n    when the issuance was unattributed."
      },
      "CredentialExpiration": {
        "required": [
          "at"
        ],
        "type": "object",
        "properties": {
          "at": {
            "type": "string",
            "description": "Scheduled end of validity.",
            "format": "date-time",
            "example": "2026-12-31T00:00:00+00:00"
          }
        },
        "description": "When a credential's validity ends. Present only when the credential has a scheduled expiry."
      },
      "CredentialRevocation": {
        "required": [
          "at"
        ],
        "type": "object",
        "properties": {
          "at": {
            "type": "string",
            "description": "When the credential was revoked.",
            "format": "date-time",
            "example": "2026-06-08T09:00:00+00:00"
          },
          "actor": {
            "type": [
              "null",
              "string"
            ],
            "description": "The actor that revoked it; absent when the revocation was unattributed.",
            "example": "credential:00000000-0000-0000-0000-000000000000"
          },
          "reason": {
            "type": [
              "null",
              "string"
            ],
            "description": "Why it was revoked, or absent when no reason was recorded."
          }
        },
        "description": "When a credential was revoked, by whom, and why. Present only on a\n    revoked credential. The actor is the flat tag `\"{kind}:{id}\"`\n    (`user:{subject}` or `credential:{id}`); absent when the revocation\n    was unattributed."
      },
      "CredentialStatusCounts": {
        "required": [
          "active",
          "expired",
          "revoked"
        ],
        "type": "object",
        "properties": {
          "active": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Credentials usable now.",
            "format": "int32"
          },
          "expired": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Credentials past their expiry but not revoked.",
            "format": "int32"
          },
          "revoked": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Revoked credentials.",
            "format": "int32"
          }
        },
        "description": "How many credentials match the current search in each lifecycle status,\nindependent of the status the page is filtered to. Lets a caller badge the\nactive / expired / revoked views with their counts at once."
      },
      "Emitter": {
        "required": [
          "emitter_id",
          "name",
          "privileged",
          "managed_by",
          "cert_thumbprint",
          "cert_serial",
          "created_at"
        ],
        "type": "object",
        "properties": {
          "emitter_id": {
            "type": "string",
            "description": "The emitter's opaque identifier.",
            "example": "pa-prod"
          },
          "name": {
            "type": "string",
            "description": "Short human-facing label.",
            "example": "PA production emitter"
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Operator-facing context for the row, or `null`."
          },
          "privileged": {
            "type": "boolean",
            "description": "Whether the emitter may write reserved chains, such as the system chain."
          },
          "managed_by": {
            "description": "Who owns mutations to this row: `operator` rows are managed here;\n`platform` rows are managed by the platform itself and are read-only\n(mutating one responds `403`).",
            "$ref": "#/components/schemas/EmitterManagedBy"
          },
          "cert_thumbprint": {
            "type": "string",
            "description": "Lower-case hex SHA-256 thumbprint of the emitter's mTLS cert."
          },
          "cert_serial": {
            "type": "string",
            "description": "The mTLS cert's serial number."
          },
          "cert_not_after": {
            "type": [
              "null",
              "string"
            ],
            "description": "When the mTLS cert expires (ISO 8601), or `null` when the cert does not expire.",
            "format": "date-time"
          },
          "revoked_at": {
            "type": [
              "null",
              "string"
            ],
            "description": "When the emitter was revoked (ISO 8601), or `null` while it is active.",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "description": "When the row was created (ISO 8601).",
            "format": "date-time"
          }
        },
        "description": "An emitter-registry row: an application authenticated to submit events, with\nits mTLS identity and authorization config. The private key and the issued\ncert artifact are returned only at provision / rotation time, never here."
      },
      "EmitterCertArtifact": {
        "required": [
          "certificate_pem",
          "ca_chain_pem",
          "thumbprint"
        ],
        "type": "object",
        "properties": {
          "certificate_pem": {
            "type": "string",
            "description": "The issued leaf certificate, PEM-encoded."
          },
          "ca_chain_pem": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The issuing CA chain, leaf-to-root, PEM-encoded."
          },
          "pkcs12_base64": {
            "type": [
              "null",
              "string"
            ],
            "description": "The PKCS#12 bundle (leaf + private key + chain), base64-encoded — present\nonly in the platform-generated keypair mode. Shown once: the private key is\nnever stored server-side and cannot be retrieved later, so the caller must\ncapture it from this response (lose it and the emitter must be rotated)."
          },
          "thumbprint": {
            "type": "string",
            "description": "Lower-case hex SHA-256 thumbprint of the issued leaf."
          },
          "not_after": {
            "type": [
              "null",
              "string"
            ],
            "description": "When the issued leaf expires (ISO 8601), or `null` when it does not expire.",
            "format": "date-time"
          }
        },
        "description": "The issued mTLS cert handed back at provision / rotation, shown once. In the\ncaller-CSR mode it carries the signed leaf and the issuing chain (no private\nkey); in the platform-generated keypair mode it additionally carries the\nPKCS#12 bundle (leaf + private key + chain), base64-encoded."
      },
      "EmitterCertRequest": {
        "type": "object",
        "properties": {
          "csr": {
            "type": [
              "null",
              "string"
            ],
            "description": "A PEM-encoded PKCS#10 certificate signing request. When present, the leaf\nis signed from it and no private key is returned. When absent, a keypair is\ngenerated and returned as a PKCS#12 bundle."
          }
        },
        "description": "Selects the cert-provisioning mode on provision and on cert rotation: supply\na `csr` to have the leaf signed from it, so the private key never crosses\nthe network (the recommended default), or omit it to receive a\nplatform-generated keypair as a PKCS#12 bundle."
      },
      "EmitterCounts": {
        "required": [
          "operator",
          "platform"
        ],
        "type": "object",
        "properties": {
          "operator": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Operator-managed emitters.",
            "format": "int32"
          },
          "platform": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Platform-managed emitters.",
            "format": "int32"
          }
        },
        "description": "How many emitters match the current search in each kind, independent of the\n`managed_by` filter the page is narrowed to. Lets a caller badge the\noperator-managed and platform-managed views with their counts at once."
      },
      "EmitterManagedBy": {
        "enum": [
          "operator",
          "platform"
        ],
        "description": "Who owns mutations to an emitter-registry row (ADR-0027). Determines whether\nthe row is operator-managed through the Admin API or platform-managed by\nplatform-internal automation (in which case it is read-only to operators)."
      },
      "EmitterPage": {
        "required": [
          "items",
          "total",
          "page",
          "page_size",
          "counts"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Emitter"
            },
            "description": "The emitters on this page, newest first."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total emitters across all pages.",
            "format": "int32"
          },
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The 1-based page number.",
            "format": "int32"
          },
          "page_size": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The page size applied.",
            "format": "int32"
          },
          "counts": {
            "description": "How many emitters match the search in each kind, independent of the\n`managed_by` filter, so a caller can badge both kind views at once.",
            "$ref": "#/components/schemas/EmitterCounts"
          }
        },
        "description": "One page of the emitter registry: the rows plus the total count. Includes\nplatform-managed rows so operators see everything that is emitting."
      },
      "EmitterWithCertificate": {
        "required": [
          "emitter",
          "certificate"
        ],
        "type": "object",
        "properties": {
          "emitter": {
            "description": "The emitter's current registry row.",
            "$ref": "#/components/schemas/Emitter"
          },
          "certificate": {
            "description": "The issued cert artifact.",
            "$ref": "#/components/schemas/EmitterCertArtifact"
          }
        },
        "description": "An emitter together with a freshly issued cert artifact — the response to a\nprovision and to a cert rotation. The cert is shown once."
      },
      "HttpValidationProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": [
              "null",
              "string"
            ]
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "instance": {
            "type": [
              "null",
              "string"
            ]
          },
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        }
      },
      "IgnoreEvent": {
        "required": [
          "event_id",
          "tenant_id",
          "formula",
          "explanation",
          "matched_count",
          "date"
        ],
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "description": "The ignore event's id, which every excluded event points back to.",
            "format": "uuid"
          },
          "tenant_id": {
            "type": "string",
            "description": "The reserved chain it was recorded on."
          },
          "formula": {
            "type": "string",
            "description": "The formula it carries."
          },
          "explanation": {
            "type": "string",
            "description": "The operator's explanation."
          },
          "matched_count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "How many events it excluded.",
            "format": "int64"
          },
          "date": {
            "type": "string",
            "description": "When it was recorded, which is also the exclusive bound closing the matched set.",
            "format": "date-time"
          }
        },
        "description": "A written ignore event, as it now stands on the organization's access-trail chain.\nReturned once, by the write: the declaration lives on the chain from then on, and\nis read there."
      },
      "IgnoreEventCount": {
        "required": [
          "key",
          "count"
        ],
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "The chain's `tenant_id` or the `event_name`, depending on which breakdown this belongs to."
          },
          "count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "How many matched events carry it.",
            "format": "int64"
          }
        },
        "description": "One line of a preview breakdown: a chain or an event name, and how many of its events the formula matches."
      },
      "IgnoreEventMatch": {
        "required": [
          "event_id",
          "tenant_id",
          "event_name",
          "date",
          "receipt_ts"
        ],
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "description": "The event's id.",
            "format": "uuid"
          },
          "tenant_id": {
            "type": "string",
            "description": "The chain it is on."
          },
          "event_name": {
            "type": "string",
            "description": "Its versioned event name."
          },
          "date": {
            "type": "string",
            "description": "Its business date, asserted by the emitter.",
            "format": "date-time"
          },
          "receipt_ts": {
            "type": "string",
            "description": "When the Gateway accepted it; the instant the bound applies to.",
            "format": "date-time"
          }
        },
        "description": "One matched event in a preview sample: enough to recognise it and look it up, without its payload."
      },
      "IgnoreEventPreview": {
        "required": [
          "formula",
          "counted_before",
          "matched_count",
          "by_tenant",
          "by_event_name",
          "sample"
        ],
        "type": "object",
        "properties": {
          "formula": {
            "type": "string",
            "description": "The formula the count was taken over, as submitted."
          },
          "counted_before": {
            "type": "string",
            "description": "The exclusive receipt bound the count was taken at.",
            "format": "date-time"
          },
          "matched_count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "How many events the formula matches.",
            "format": "int64"
          },
          "by_tenant": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IgnoreEventCount"
            },
            "description": "The match count per chain, most matches first."
          },
          "by_event_name": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IgnoreEventCount"
            },
            "description": "The match count per event name, most matches first."
          },
          "sample": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IgnoreEventMatch"
            },
            "description": "A few of the matched events, in ingest order."
          }
        },
        "description": "What a formula would exclude, as a snapshot taken at CountedBefore.\nA declaration's bound is its own date, so writing this formula excludes these\nevents plus anything matching it that arrives before the write lands."
      },
      "IssueAdminCredentialRequest": {
        "required": [
          "name",
          "admin"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Operator-facing label so the credential is recognizable in a list.",
            "example": "platform automation"
          },
          "admin": {
            "description": "Admin API access level to grant. Required (`read-only` or `read-write`).",
            "$ref": "#/components/schemas/AdminCapability"
          },
          "expires_at": {
            "type": [
              "null",
              "string"
            ],
            "description": "Optional scheduled expiry; omit for a credential that never expires.",
            "format": "date-time"
          }
        },
        "description": "Request body to issue an Admin API credential. `admin` grants Admin API\naccess and is required (`read-only` or `read-write`)."
      },
      "IssuedAdminCredential": {
        "required": [
          "credential",
          "secret"
        ],
        "type": "object",
        "properties": {
          "credential": {
            "description": "The issued (or rotated) credential's metadata.",
            "$ref": "#/components/schemas/AdminCredential"
          },
          "secret": {
            "type": "string",
            "description": "The secret, shown once. Store it now; it cannot be retrieved later."
          }
        },
        "description": "The response to issuing or rotating an Admin API credential: the credential\nmetadata plus the one-time secret. The secret is shown only here,\nnever again, and is stored only as a hash."
      },
      "IssuedOrganizationCredential": {
        "required": [
          "credential",
          "secret"
        ],
        "type": "object",
        "properties": {
          "credential": {
            "description": "The issued (or rotated) credential's metadata.",
            "$ref": "#/components/schemas/OrganizationCredential"
          },
          "secret": {
            "type": "string",
            "description": "The secret, shown once. Store it now; it cannot be retrieved later."
          }
        },
        "description": "The response to issuing or rotating an organization credential: the credential\nmetadata plus the one-time secret. The secret is shown only here,\nnever again, and is stored only as a hash."
      },
      "IssueOrganizationCredentialRequest": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Operator-facing label so the credential is recognizable in a list.",
            "example": "SIG production integration"
          },
          "expires_at": {
            "type": [
              "null",
              "string"
            ],
            "description": "Optional scheduled expiry; omit for a credential that never expires.",
            "format": "date-time"
          }
        },
        "description": "Request body to issue an organization credential. Organization credentials are\ndata-only by definition (they grant Data API access to their organization), so\nthe body carries no capability flags."
      },
      "OidcProvider": {
        "required": [
          "provider_id",
          "display_name",
          "issuer_url",
          "client_id"
        ],
        "type": "object",
        "properties": {
          "provider_id": {
            "type": "string",
            "description": "Provider identifier; the opaque segment in the Data Viewer login path.",
            "example": "00000000-0000-0000-0000-000000000000"
          },
          "display_name": {
            "type": "string",
            "description": "The provider's login-button label.",
            "example": "Serensia SSO"
          },
          "issuer_url": {
            "type": "string",
            "description": "The provider's OIDC issuer URL.",
            "example": "https://idp.example.com/realms/serensia"
          },
          "client_id": {
            "type": "string",
            "description": "The provider's OIDC client id at that issuer.",
            "example": "qaudit-data-viewer"
          }
        },
        "description": "An OIDC login provider configured for an organization: one \"Log in with …\"\nchoice the Data Viewer presents. Carries the provider's label, issuer, and\nclient id. The client secret is held in Vault and is never returned."
      },
      "OpenSupportSessionRequest": {
        "required": [
          "ticket_reference",
          "reason"
        ],
        "type": "object",
        "properties": {
          "ticket_reference": {
            "type": "string",
            "description": "The support ticket the session is opened against."
          },
          "reason": {
            "type": "string",
            "description": "The operator's declared reason for the session (a free-text audit annotation; it does not restrict access)."
          }
        },
        "description": "Request to open a support session."
      },
      "Organization": {
        "required": [
          "organization_id",
          "display_name",
          "slug",
          "created_at"
        ],
        "type": "object",
        "properties": {
          "organization_id": {
            "type": "string",
            "description": "Organization identifier.",
            "example": "00000000-0000-0000-0000-000000000000"
          },
          "display_name": {
            "type": "string",
            "description": "The organization's display name, shown wherever the organization is identified."
          },
          "slug": {
            "type": "string",
            "description": "The organization's addressing slug; names the organization in its subdomain.",
            "example": "serensia"
          },
          "created_at": {
            "type": "string",
            "description": "When the organization was created.",
            "format": "date-time",
            "example": "2026-06-07T12:00:00+00:00"
          }
        },
        "description": "An organization: the identity, credential, and signing boundary that tenants\nlive inside. Carries its display name and when it was created. The signing\nkeys are read through the signing-keys endpoint, not on this resource."
      },
      "OrganizationCredential": {
        "required": [
          "credential_id",
          "organization_id",
          "name",
          "key_prefix",
          "status",
          "creation"
        ],
        "type": "object",
        "properties": {
          "credential_id": {
            "type": "string",
            "description": "Credential identifier.",
            "example": "00000000-0000-0000-0000-000000000000"
          },
          "organization_id": {
            "type": "string",
            "description": "The organization this credential reads.",
            "example": "00000000-0000-0000-0000-000000000000"
          },
          "name": {
            "type": "string",
            "description": "Operator-facing label."
          },
          "key_prefix": {
            "type": "string",
            "description": "The non-secret leading fragment of the key, kept to help recognize it. The full key is never stored.",
            "example": "qa_AbCdEf"
          },
          "status": {
            "description": "Lifecycle status as of the response.",
            "$ref": "#/components/schemas/ApiCredentialStatus"
          },
          "creation": {
            "description": "When the credential was issued, and by whom.",
            "$ref": "#/components/schemas/CredentialCreation"
          },
          "expiration": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "Scheduled end of validity; absent when it never expires.",
                "$ref": "#/components/schemas/CredentialExpiration"
              }
            ]
          },
          "revocation": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "description": "When the credential was revoked, by whom, and why; absent while not revoked.",
                "$ref": "#/components/schemas/CredentialRevocation"
              }
            ]
          },
          "last_used_at": {
            "type": [
              "null",
              "string"
            ],
            "description": "Last time the key authenticated a request; absent if never used.",
            "format": "date-time"
          }
        },
        "description": "An organization credential: a credential scoped to a single organization.\nOrganization credentials are data-only by definition, so no capability is\nreported here. The secret is never returned and only its hash is stored; the\nresponse carries the non-secret key prefix (the first few characters) to help\nrecognize the key."
      },
      "OrganizationCredentialPage": {
        "required": [
          "items",
          "total",
          "page",
          "page_size",
          "counts"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrganizationCredential"
            },
            "description": "The credentials on this page, newest first."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total matches across all pages, for the filtered status.",
            "format": "int32"
          },
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The 1-based page number.",
            "format": "int32"
          },
          "page_size": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The page size applied.",
            "format": "int32"
          },
          "counts": {
            "description": "Per-status match counts for the current search, independent of the status filter.",
            "$ref": "#/components/schemas/CredentialStatusCounts"
          }
        },
        "description": "One page of organization credentials: the rows for the filtered status, the\ntotal match count for paging, and the per-status counts for the current search\n(across all statuses) so the caller can badge each status view."
      },
      "OrganizationPage": {
        "required": [
          "items",
          "total",
          "page",
          "page_size"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Organization"
            },
            "description": "The organizations on this page, newest first."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total organizations across all pages.",
            "format": "int32"
          },
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The 1-based page number.",
            "format": "int32"
          },
          "page_size": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The page size applied.",
            "format": "int32"
          }
        },
        "description": "One page of organizations: the rows plus the total count so a caller can render\npage numbers."
      },
      "OrganizationSigningKeyDetails": {
        "required": [
          "version",
          "created_at",
          "fingerprint",
          "public_key"
        ],
        "type": "object",
        "properties": {
          "version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The signing key's version (1 at creation; higher after rotation).",
            "format": "int32"
          },
          "created_at": {
            "type": "string",
            "description": "When this key version was created.",
            "format": "date-time",
            "example": "2026-06-08T12:00:00+00:00"
          },
          "fingerprint": {
            "type": "string",
            "description": "Lowercase hex SHA-256 of the public key, to recognize it.",
            "example": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
          },
          "public_key": {
            "type": "string",
            "description": "The raw 32-byte Ed25519 public key, base64-encoded."
          }
        },
        "description": "One of an organization's signing keys, with its raw public key material, so an\noperator can hand the public key to the organization (for example during\nonboarding, or to help an integrator not yet driving the API). The private key\nnever leaves Vault. Verifiers that drive the API resolve keys from the Data\nAPI's JWKS instead."
      },
      "PatchOfstring": {
        "type": [
          "null",
          "string"
        ]
      },
      "PreviewIgnoreEventRequest": {
        "required": [
          "formula"
        ],
        "type": "object",
        "properties": {
          "formula": {
            "type": "string",
            "description": "The formula naming the events to exclude, in the selection-predicate grammar,\nevaluated against each event's flat payload fields. The envelope keys are\npayload fields, so `tenant_id = \"acme\"` narrows to one chain and\n`event_name = \"qaudit.invoice.received.v1\"` to one kind of event. Required."
          }
        },
        "description": "Request to count what a formula would exclude, without writing anything."
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": [
              "null",
              "string"
            ]
          },
          "title": {
            "type": [
              "null",
              "string"
            ]
          },
          "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "instance": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "Product": {
        "required": [
          "product_id",
          "name",
          "managed_by",
          "probe_mode",
          "created_at",
          "updated_at"
        ],
        "type": "object",
        "properties": {
          "product_id": {
            "type": "string",
            "description": "Product identifier.",
            "example": "00000000-0000-0000-0000-000000000000"
          },
          "name": {
            "type": "string",
            "description": "The product's name, shown wherever the product is identified."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "The product's description, or `null` when it has none."
          },
          "managed_by": {
            "description": "Who manages the product: `operator` (operator-created and managed) or `platform`\n(the platform's own QAudit product). A client renders a platform product's management\nsurfaces, its status probe and its emitters, as read-only.",
            "$ref": "#/components/schemas/ProductManagedBy"
          },
          "probe_mode": {
            "description": "How QAudit observes the product's availability: `probe` (reachability polling) or\n`self-monitored` (the QAudit product itself, set at bootstrap). This is a display value\nfor the monitoring mode; a product's read-only-ness is carried by ProductManagedBy Product.ManagedBy.",
            "$ref": "#/components/schemas/ProductProbeMode"
          },
          "probe_url": {
            "type": [
              "null",
              "string"
            ],
            "description": "The status probe URL QAudit fetches, or `null` when the product has no probe and is\nnot polled."
          },
          "created_at": {
            "type": "string",
            "description": "When the product was created.",
            "format": "date-time",
            "example": "2026-06-07T12:00:00+00:00"
          },
          "updated_at": {
            "type": "string",
            "description": "When the product was last edited; equal to `created_at` until first edited.",
            "format": "date-time",
            "example": "2026-06-07T12:00:00+00:00"
          }
        },
        "description": "A product: a public, operator-managed label that names an application emitting into\nQAudit, whose availability QAudit records on the product's own status chain. Carries\nthe name and description an operator manages, and when it was created and last edited."
      },
      "ProductEmitterPage": {
        "required": [
          "items",
          "total",
          "page",
          "page_size"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Emitter"
            },
            "description": "The product's emitters on this page, newest first."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total emitters owned by the product across all pages, after the filter.",
            "format": "int32"
          },
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The 1-based page number.",
            "format": "int32"
          },
          "page_size": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The page size applied.",
            "format": "int32"
          }
        },
        "description": "One page of a product's owned emitters: the rows plus the total count. The same emitter\nshape as the global registry; a product owns operator-managed emitters only, so there is no\nper-kind count here."
      },
      "ProductManagedBy": {
        "enum": [
          "operator",
          "platform"
        ],
        "description": "Who manages a product, mirroring an emitter's managed-by distinction (ADR-0070).\nProductManagedBy.Operator products are created and managed by operators through the Admin API;\nProductManagedBy.Platform is the platform's own product (the QAudit product), set at bootstrap and\nmanaged by the platform. A client renders a platform product's management surfaces (its status\nprobe and its emitters) as read-only."
      },
      "ProductPage": {
        "required": [
          "items",
          "total",
          "page",
          "page_size"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            },
            "description": "The products on this page, newest first."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total products across all pages.",
            "format": "int32"
          },
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The 1-based page number.",
            "format": "int32"
          },
          "page_size": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The page size applied.",
            "format": "int32"
          }
        },
        "description": "One page of products: the rows plus the total count so a caller can render page numbers."
      },
      "ProductProbeMode": {
        "enum": [
          "probe",
          "self-monitored"
        ],
        "description": "How QAudit observes a product's availability when the product carries a status probe URL\n(ADR-0070, T-52). The mode selects what QAudit does with the URL it fetches."
      },
      "ProvisionEmitterRequest": {
        "required": [
          "emitter_id",
          "name",
          "cert"
        ],
        "type": "object",
        "properties": {
          "emitter_id": {
            "type": "string",
            "description": "The emitter's opaque identifier. Required, non-empty, unique."
          },
          "name": {
            "type": "string",
            "description": "The emitter's display name. Required, non-empty."
          },
          "description": {
            "type": [
              "null",
              "string"
            ],
            "description": "Operator-facing context for the emitter. Optional."
          },
          "privileged": {
            "type": "boolean",
            "description": "Whether this emitter may write reserved chains, such as the system chain.\nDefaults to `false`; reserved-chain authorization is granted explicitly."
          },
          "cert": {
            "description": "The cert-provisioning mode (caller CSR or platform-generated keypair).",
            "$ref": "#/components/schemas/EmitterCertRequest"
          }
        },
        "description": "Request to provision an emitter: issue its mTLS cert and insert its registry\nrow, atomically. The new row is operator-managed."
      },
      "RevokeCredentialRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "type": [
              "null",
              "string"
            ],
            "description": "Why the credential is being revoked. Optional.",
            "example": "key suspected compromised"
          }
        },
        "description": "Request body to revoke a credential. The `reason` is optional; when given\nit is recorded on the credential and carried on the audit event."
      },
      "RevokeEmitterRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "type": [
              "null",
              "string"
            ],
            "description": "Why the emitter is being revoked. Optional.",
            "example": "cert suspected compromised"
          }
        },
        "description": "Request body to revoke an emitter. The `reason` is optional; when given it\nis carried on the audit event recording the revocation."
      },
      "RotateCredentialRequest": {
        "type": "object",
        "properties": {
          "expires_at": {
            "type": [
              "null",
              "string"
            ],
            "description": "The credential's new expiry, when renewing. Optional; must be in the future.",
            "format": "date-time",
            "example": "2027-01-01T00:00:00+00:00"
          }
        },
        "description": "Optional request body to rotate a credential. `expires_at` renews the\ncredential at the same time as rotating it: omit it to keep the current expiry,\nor set it (must be in the future) to reschedule. The body itself is optional; a\nrotate with no body keeps the expiry."
      },
      "SigningKeyRecoveryDetails": {
        "required": [
          "recovery_id",
          "organization_id",
          "signing_key_version",
          "status",
          "total_chains",
          "recovered_chains",
          "failure_reason",
          "started_at",
          "updated_at",
          "completed_at"
        ],
        "type": "object",
        "properties": {
          "recovery_id": {
            "type": "string",
            "description": "Unique id of the recovery job.",
            "format": "uuid"
          },
          "organization_id": {
            "type": "string",
            "description": "The organization being recovered.",
            "format": "uuid"
          },
          "signing_key_version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The recovered signing-key version the chains move to.",
            "format": "int32"
          },
          "status": {
            "type": "string",
            "description": "The job's state: `running`, `completed`, or `failed`."
          },
          "total_chains": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Every chain the organization owns, its access chain and each tenant chain, to recover.",
            "format": "int32"
          },
          "recovered_chains": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "How many chains are on the recovered version so far.",
            "format": "int32"
          },
          "failure_reason": {
            "type": [
              "null",
              "string"
            ],
            "description": "Why the job failed, when its status is `failed`; otherwise `null`."
          },
          "started_at": {
            "type": "string",
            "description": "When the recovery was started.",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "description": "When its progress was last advanced.",
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "null",
              "string"
            ],
            "description": "When it finished, or `null` while it runs.",
            "format": "date-time"
          }
        },
        "description": "A signing-key recovery job and its progress: the recovered version now in force and how\nmany of the organization's chains have been moved to it, so a caller can show a progress\nbar. The recovered public key is read back through the signing-key endpoints."
      },
      "SigningKeyRecoveryPage": {
        "required": [
          "items",
          "total",
          "page",
          "page_size"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SigningKeyRecoveryDetails"
            },
            "description": "The recoveries on this page, newest first."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total recoveries across all pages.",
            "format": "int32"
          },
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The 1-based page number.",
            "format": "int32"
          },
          "page_size": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The page size applied.",
            "format": "int32"
          }
        },
        "description": "One page of an organization's signing-key recoveries: the jobs plus the total count so a\ncaller can render page numbers."
      },
      "SigningKeyRotationResult": {
        "required": [
          "organization_id",
          "signing_key_version"
        ],
        "type": "object",
        "properties": {
          "organization_id": {
            "type": "string",
            "description": "The organization whose key was rotated.",
            "format": "uuid"
          },
          "signing_key_version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The new signing-key version this rotation introduced.",
            "format": "int32"
          }
        },
        "description": "Response to a signing-key rotation: the organization and the new key version\nnow in force. The new public key is read back through the signing-key endpoints."
      },
      "SupportSession": {
        "required": [
          "support_session_id",
          "organization_id",
          "operator_subject",
          "operator_name",
          "reason",
          "ticket_reference",
          "opened_at",
          "expires_at"
        ],
        "type": "object",
        "properties": {
          "support_session_id": {
            "type": "string",
            "description": "Identifier of the session.",
            "format": "uuid"
          },
          "organization_id": {
            "type": "string",
            "description": "The organization the session grants a view of.",
            "format": "uuid"
          },
          "operator_subject": {
            "type": "string",
            "description": "The operator (OIDC subject) the session was opened for."
          },
          "operator_name": {
            "type": [
              "null",
              "string"
            ],
            "description": "The operator's display name at open time, or `null` when the issuer supplied none."
          },
          "reason": {
            "type": "string",
            "description": "The operator's declared reason (a free-text audit annotation)."
          },
          "ticket_reference": {
            "type": "string",
            "description": "The support ticket the session was opened against."
          },
          "opened_at": {
            "type": "string",
            "description": "When the session was opened.",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "description": "When the grant expires and the session auto-closes.",
            "format": "date-time"
          }
        },
        "description": "An active support session as listed/fetched by an operator (the wire resource)."
      },
      "SupportSessionGrant": {
        "required": [
          "redirect_url",
          "expires_at"
        ],
        "type": "object",
        "properties": {
          "redirect_url": {
            "type": "string",
            "description": "The Data Viewer support-grant handoff to redirect the browser to."
          },
          "expires_at": {
            "type": "string",
            "description": "When the grant expires and the session auto-closes.",
            "format": "date-time"
          }
        },
        "description": "The grant issued when a support session is opened or resumed: the one-time Data\nViewer handoff that carries the grant token, and when the grant expires. The\ngrant is returned only at issuance, mirroring how credential issuance returns a\none-time secret."
      },
      "SupportSessionResponse": {
        "required": [
          "session",
          "grant"
        ],
        "type": "object",
        "properties": {
          "session": {
            "description": "The session (the same shape the list/get return).",
            "$ref": "#/components/schemas/SupportSession"
          },
          "grant": {
            "description": "The grant issued for the session: the one-time Data Viewer handoff and its expiry.",
            "$ref": "#/components/schemas/SupportSessionGrant"
          }
        },
        "description": "The response to opening or resuming a support session: the session resource and\nthe grant issued for it."
      },
      "Tenant": {
        "required": [
          "tenant_id",
          "display_name",
          "onboarded_at"
        ],
        "type": "object",
        "properties": {
          "tenant_id": {
            "type": "string",
            "description": "Opaque tenant identifier, used as the `tenant_id` on the event surfaces.",
            "example": "acme-eu"
          },
          "display_name": {
            "type": "string",
            "description": "Human-readable tenant name.",
            "example": "Acme Europe"
          },
          "onboarded_at": {
            "type": "string",
            "description": "When the tenant was onboarded (ISO 8601).",
            "format": "date-time",
            "example": "2026-01-15T09:30:00+00:00"
          }
        },
        "description": "A tenant of an organization: a sub-scope with its own opaque id, display name,\nand chain. The owning organization is the one in the route, so it is not\nrepeated here."
      },
      "TenantActivity": {
        "required": [
          "from",
          "to",
          "resolution",
          "buckets",
          "total"
        ],
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "description": "The window's first UTC day (inclusive).",
            "format": "date",
            "example": "2026-06-01"
          },
          "to": {
            "type": "string",
            "description": "The window's last UTC day (inclusive).",
            "format": "date",
            "example": "2026-06-07"
          },
          "resolution": {
            "description": "The bucket resolution derived from the window length.",
            "$ref": "#/components/schemas/TenantActivityResolution"
          },
          "buckets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantActivityBucket"
            },
            "description": "The per-bucket series, zero-filled across the whole window, in time order."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The window total: the sum of the bucket counts.",
            "format": "int64"
          }
        },
        "description": "A tenant's event activity over a window of whole UTC days: a per-bucket\nevent-count series (bucketed by ingestion time, `receipt_ts`) at a\nresolution derived from the window length, plus the window total. With a name\nfilter, the counts include only the selected event names."
      },
      "TenantActivityBucket": {
        "required": [
          "bucket",
          "count"
        ],
        "type": "object",
        "properties": {
          "bucket": {
            "type": "string",
            "description": "The bucket's inclusive lower bound in UTC.",
            "format": "date-time",
            "example": "2026-06-01T00:00:00+00:00"
          },
          "count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The bucket's event count (of the names in view).",
            "format": "int64"
          }
        },
        "description": "One bucket of the activity series: its UTC start and its event count."
      },
      "TenantActivityResolution": {
        "enum": [
          "hour",
          "day",
          "week",
          "month"
        ],
        "description": "The bar grain an activity window renders at, derived from its length. Serialized\nlower-case by the host's global `JsonStringEnumConverter` (kebab-case-lower)."
      },
      "TenantEventNameCount": {
        "required": [
          "name",
          "count"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The versioned event name.",
            "example": "qaudit.invoice.received.v1"
          },
          "count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "How many events of this name fall in the window.",
            "format": "int64",
            "example": 1280
          }
        },
        "description": "An event name and its count within the activity window."
      },
      "TenantEventNamePage": {
        "required": [
          "items",
          "total",
          "page",
          "page_size"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantEventNameCount"
            },
            "description": "The event names on this page, ordered by window count descending."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total distinct names in the window (after the search filter).",
            "format": "int32"
          },
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The 1-based page number.",
            "format": "int32"
          },
          "page_size": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The page size applied.",
            "format": "int32"
          }
        },
        "description": "One page of the distinct event names present on a tenant's chain within an\nactivity window, each with its count over that window, ordered by count\ndescending. The menu the activity graph's name filter is chosen from."
      },
      "TenantOverview": {
        "required": [
          "tenant_id",
          "display_name",
          "onboarded_at",
          "signing_key",
          "packs"
        ],
        "type": "object",
        "properties": {
          "tenant_id": {
            "type": "string",
            "description": "Opaque tenant identifier.",
            "example": "acme-eu"
          },
          "display_name": {
            "type": "string",
            "description": "Human-readable tenant name.",
            "example": "Acme Europe"
          },
          "onboarded_at": {
            "type": "string",
            "description": "When the tenant was onboarded (ISO 8601).",
            "format": "date-time",
            "example": "2026-01-15T09:30:00+00:00"
          },
          "signing_key": {
            "description": "The signing-key version the chain head was signed under, against the current version.",
            "$ref": "#/components/schemas/TenantOverviewSigningKey"
          },
          "packs": {
            "description": "The tenant's data-pack figures.",
            "$ref": "#/components/schemas/TenantOverviewPacks"
          }
        },
        "description": "An operator's read-only view of a tenant's operational state: its identity, the\nsigning-key version its chain head was signed under against the organization's\ncurrent version, and its data-pack figures."
      },
      "TenantOverviewPacks": {
        "required": [
          "total",
          "building",
          "ready",
          "failed"
        ],
        "type": "object",
        "properties": {
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Packs whose resolved chain is this tenant.",
            "format": "int64"
          },
          "building": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Packs still building.",
            "format": "int64"
          },
          "ready": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Packs that finished building.",
            "format": "int64"
          },
          "failed": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Packs whose build failed.",
            "format": "int64"
          },
          "last_built_at": {
            "type": [
              "null",
              "string"
            ],
            "description": "When the most recent ready pack finished building, or `null` when none is ready.",
            "format": "date-time"
          }
        },
        "description": "The tenant's data-pack figures: the total, the per-status split, and the last build time."
      },
      "TenantOverviewSigningKey": {
        "type": "object",
        "properties": {
          "head_version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The version the chain head was signed under, or `null` when the chain is empty.",
            "format": "int32"
          },
          "current_version": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "description": "The organization's current (highest) signing-key version, or `null` when it has no keys.",
            "format": "int32"
          }
        },
        "description": "The signing-key versions for the tenant: the version its chain head was signed\nunder, against the organization's current version. A head version below the\ncurrent one marks a chain whose head predates a key rotation."
      },
      "TenantPage": {
        "required": [
          "items",
          "total",
          "page",
          "page_size"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tenant"
            },
            "description": "The tenants on this page, ordered by display name."
          },
          "total": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "Total tenants across all pages.",
            "format": "int32"
          },
          "page": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The 1-based page number.",
            "format": "int32"
          },
          "page_size": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "integer",
              "string"
            ],
            "description": "The page size applied.",
            "format": "int32"
          }
        },
        "description": "One page of an organization's tenants: the rows plus the total count so a\ncaller can render page numbers."
      },
      "UpdateEmitterRequest": {
        "type": "object",
        "properties": {
          "name": {
            "description": "The emitter's display name; omit to leave it unchanged. Non-empty when supplied.",
            "$ref": "#/components/schemas/PatchOfstring"
          },
          "description": {
            "description": "The emitter's description; omit to leave it unchanged, or send null to clear it.",
            "$ref": "#/components/schemas/PatchOfstring"
          }
        },
        "description": "Request to edit an emitter (a partial update): an omitted field is left unchanged, and\nsending `description` as `null` clears it. The name cannot be cleared. Cert\nrotation is a separate operation (`POST /system/emitters/{emitter_id}/cert`)."
      },
      "UpdateOidcProviderRequest": {
        "type": "object",
        "properties": {
          "display_name": {
            "description": "The provider's login-button label; omit to leave it unchanged. Non-empty when supplied.",
            "$ref": "#/components/schemas/PatchOfstring"
          },
          "issuer_url": {
            "description": "The provider's OIDC issuer URL; omit to leave it unchanged. An absolute http(s) URL when supplied.",
            "$ref": "#/components/schemas/PatchOfstring"
          },
          "client_id": {
            "description": "The provider's OIDC client id at that issuer; omit to leave it unchanged. Non-empty when supplied.",
            "$ref": "#/components/schemas/PatchOfstring"
          },
          "client_secret": {
            "description": "A new OIDC client secret to store in Vault; omit to keep the current secret.",
            "$ref": "#/components/schemas/PatchOfstring"
          }
        },
        "description": "Request to edit an organization's OIDC login provider (a partial update): an omitted\nfield is left unchanged, and the label, issuer, and client id cannot be cleared. A\nsupplied non-empty client secret rotates the value in Vault; omit it to keep the current."
      },
      "UpdateOrganizationRequest": {
        "type": "object",
        "properties": {
          "display_name": {
            "description": "The organization's display name; omit to leave it unchanged. Non-empty when supplied.",
            "$ref": "#/components/schemas/PatchOfstring"
          },
          "slug": {
            "description": "The organization's addressing slug; omit to leave it unchanged. Matches `^[a-z0-9_-]+$`, is unique, and renaming it stops the previous subdomain resolving.",
            "$ref": "#/components/schemas/PatchOfstring"
          }
        },
        "description": "Request to edit an organization (a partial update): an omitted field is left unchanged.\nNeither the display name nor the addressing slug can be cleared."
      },
      "UpdateProductRequest": {
        "type": "object",
        "properties": {
          "name": {
            "description": "The product's name; omit to leave it unchanged. Non-empty when supplied.",
            "$ref": "#/components/schemas/PatchOfstring"
          },
          "description": {
            "description": "The product's description; omit to leave it unchanged, or send null to clear it.",
            "$ref": "#/components/schemas/PatchOfstring"
          },
          "probe_url": {
            "description": "The product's status probe URL — the address QAudit polls to observe the product's\navailability. Must be an `https` URL that does not resolve to a private, loopback,\nlink-local, or cloud-metadata address. Omit to leave it unchanged, or send null to clear\nit and stop polling.",
            "$ref": "#/components/schemas/PatchOfstring"
          }
        },
        "description": "Request to edit a product (a partial update). Each field is optional: an omitted field\nis left unchanged, and sending `description` as `null` clears it. The name\ncannot be cleared."
      },
      "UpdateTenantRequest": {
        "type": "object",
        "properties": {
          "display_name": {
            "description": "The tenant's display name; omit to leave it unchanged. Non-empty when supplied.",
            "$ref": "#/components/schemas/PatchOfstring"
          }
        },
        "description": "Request to edit a tenant (a partial update): an omitted display name is left unchanged."
      }
    },
    "securitySchemes": {
      "Bearer": {
        "type": "http",
        "description": "A QAudit access token presented as `Authorization: Bearer <jwt>`. An operator session is an OIDC access token from the configured identity provider, relayed by the Web Gateway. An Admin API credential obtains its token from the auth service's `client_credentials` grant, carrying the Admin API scope (`qaudit.admin.read`, `qaudit.admin.write`).",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      },
      "ClientCredentials": {
        "type": "oauth2",
        "description": "Mint a QAudit access token from an Admin API credential: present its id as `client_id` and its secret as `client_secret`. The token carries the Admin API scope the credential's capability allows (`qaudit.admin.read`, `qaudit.admin.write`).",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://auth.demo.qaudit.cloud.serensia.net/token",
            "scopes": { }
          }
        }
      }
    }
  },
  "security": [
    {
      "Bearer": [ ]
    },
    {
      "ClientCredentials": [ ]
    }
  ],
  "tags": [
    {
      "name": "Organizations",
      "description": "Organizations: the identity, credential, and signing boundary that tenants live inside. Each carries a display name and a per-organization Ed25519 signing key (provisioned at creation). Creating an organization provisions its signing key and opens its access-trail chain; tenants are added separately. An organization's signing keys are read through its signing-keys endpoint."
    },
    {
      "name": "Tenants",
      "description": "Tenants: the sub-scopes within an organization, each with its own opaque id, display name, and access-trail chain. Adding a tenant opens its chain (whose first event is `qaudit.tenant.created.v1`); editing one is audited on the tenant's own chain."
    },
    {
      "name": "Organization credentials",
      "description": "Credentials scoped to a single organization. An organization credential is **data-only** by definition: it grants read access to its organization's data. The secret is shown once, at issuance or rotation, and is stored only as a hash. Every mutation (issue, rotate, revoke) is audited on the organization's own chain."
    },
    {
      "name": "Admin API credentials",
      "description": "Credentials bound to no single organization, carrying an `admin` access level (`read-only` or `read-write`) that grants Admin API access to manage the platform. An Admin API credential reaches the Admin API only; it has no data-read access. The secret is shown once and is stored only as a hash. Every mutation is audited on the system chain."
    },
    {
      "name": "Emitters",
      "description": "Emitters: the applications authenticated to submit events to QAudit, each holding an mTLS client cert and a registry row. An emitter is a root, system-scoped resource bound to no single organization. Provisioning issues the cert in one of two modes: supply a `csr` to have it signed (the private key never leaves the caller), or omit it to receive a platform-generated PKCS#12 bundle. Platform-managed rows (the platform's own internal emitters) are listed but read-only: mutating one responds `403`. Every mutation is audited on the system chain."
    },
    {
      "name": "Products",
      "description": "Products: the public, operator-managed labels that name the applications emitting into QAudit (for example Serensia PA), whose availability QAudit records. A product is a root resource bound to no single organization; it holds a name and description and owns a status chain that carries its availability. Creating a product opens that chain; editing a product's name or description is audited on the system chain (`qaudit.product.created.v1` / `qaudit.product.updated.v1`). A product also owns the emitters it emits through: list and provision them under `/v1/products/{product_id}/emitters`, where a provisioned emitter is an ordinary registry row that also appears in the global emitter list."
    },
    {
      "name": "Support sessions",
      "description": "Support sessions: how a Quadient operator views one organization's data. Opening a session mints a short-lived, scope-bound grant for the operator and returns a redirect to the Data Viewer at that organization. A session is time-bound: it auto-closes when the grant expires, with no explicit close. Both the opening and the closing are audited on the organization's chain (`qaudit.support.session.opened.v1` / `qaudit.support.session.closed.v1`)."
    },
    {
      "name": "Ignore events",
      "description": "Ignore events: how corrupted events are left out of KPI computation. An operator writes one formula in the selection-predicate grammar, and every event of the organization that the formula matches, received before the declared bound, stops counting towards any indicator. Nothing is removed from any chain and no signature or chain link changes: the events stay readable, marked as excluded, and chain verification is unaffected. The declaration is recorded on the organization's own access-trail chain (`qaudit.events.ignored.v1`), so the customer reads it where they already read operator activity. **It cannot be undone** — an ignore event cannot itself be ignored or withdrawn — which is why the preview endpoint exists: count what a formula reaches before writing it."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Tenancy",
      "tags": [
        "Organizations",
        "Tenants"
      ]
    },
    {
      "name": "Credentials & access",
      "tags": [
        "Organization credentials",
        "Admin API credentials"
      ]
    },
    {
      "name": "Platform resources",
      "tags": [
        "Emitters",
        "Products"
      ]
    },
    {
      "name": "Support",
      "tags": [
        "Support sessions",
        "Ignore events"
      ]
    }
  ]
}