{
  "openapi": "3.1.0",
  "info": {
    "title": "Applications (Alpha)",
    "description": "The Alpha registry for external tools and applications that integrate with the platform. It covers the global tool-provider and registration catalog, tenant-scoped publishers and application installations, OAuth2/JWKS client metadata, credential-authorization mapping, provider onboarding, provider-member/invite team membership, per-student app credentials, renderer capabilities for curriculum delivery, webhook callbacks with delivery receipts, and provider-management principal minting with platform JWKS.",
    "version": "1.0"
  },
  "tags": [
    {
      "name": "App Credential",
      "description": "A student's issued credential handle for a registered application. Reads expose existence, status, and timestamps — the secret value never serializes (rule)."
    },
    {
      "name": "Application",
      "description": "Tenant-scoped INSTALLATION row for an external app. There is no separate applicationInstallation entity — application remains the sole installation row and keeps existing ids/FKs (authClient, appCredential, rendererCapability, webhookEndpoint). kind discriminates vendor_installation | tenant_org | platform_internal; only vendor installations pin registrationRevisionId. ownerKind is retained as a compatibility/deprecation alias (publisher ↔ vendor_installation). Display/scope authority: global registration/revision wins for vendor_installation; local fields win for tenant_org/platform_internal."
    },
    {
      "name": "Auth Client",
      "description": "OAuth2/JWKS client metadata for a registered application. Stores redirect URIs, callback URLs, granted permission scopes, and an opaque auth-provider reference — never secrets or key material."
    },
    {
      "name": "Credential authorization",
      "description": "Durable credential-authorization mapping. Binds an authClient to provider/registration/application with mode, effective permissions, status, expiry, reviewVersion, and mappingVersion. Token issuance and cached audience validation fail when status is suspended, expired, or superseded. Sandbox grants use the pinned sandbox role set; live grants are tenant-admin granted and tenant-wide in v1 (school-admin grants out of scope)."
    },
    {
      "name": "Provider invite",
      "description": "Tenant-scoped pending invitation onto a global toolProvider team (APP-ECOSYSTEM-SEAMS §3). Accept creates or activates the corresponding providerMember for the calling principal."
    },
    {
      "name": "Provider member",
      "description": "Tenant-scoped vendor-team membership mapping for a global toolProvider (APP-ECOSYSTEM-SEAMS §3). Portal Cognito remains the identity pool; this row stores principal (Cognito sub), email, role, and status used to authorize provider mutations. Unique principal per provider (unique index on providerId + principal); rows remain tenant-scoped under RLS."
    },
    {
      "name": "Provider onboarding",
      "description": "Durable PROVIDER ONBOARDING saga receipt. Idempotent orchestration spanning global catalog, sandbox tenant registry, applications rows, Cognito, DynamoDB mapping, and Secrets Manager. Natural key is operationId; same operationId replays to the same terminal state. Stage machine + compensations + orphan reconciliation live in the authored hook."
    },
    {
      "name": "Publisher",
      "description": "A tenant-scoped operational registry row for an external publisher, vendor, or internal app owner. Retained after E2 global-catalog migration as the tenant-local record; links to the global toolProvider via nullable toolProviderId. Applications still FK to publisher; downstream entities still FK to application."
    },
    {
      "name": "Renderer Capability",
      "description": "A registered renderer capability within a tenant. Declares which content kinds the renderer accepts, its integration protocol and endpoint, and lifecycle state. Curriculum imports this read-only to validate rendererRef on delivery components."
    },
    {
      "name": "Tool provider",
      "description": "Global (tenantScoped:false) vendor organization identity for the provider catalog (§B1 / E2). Portal-managed. Tenant-local `publisher` rows may link here via `toolProviderId`. Verified contact + lifecycle/status + ownership metadata live here; generated CRUD is operator-facing — provider self-service mutations go through authored handlers that accept the provider-management principal."
    },
    {
      "name": "Tool registration",
      "description": "Global (tenantScoped:false) catalog row for an app a vendor publishes (§B1 / E2). Holds display metadata only; security-sensitive URLs/scopes/config live on immutable toolRegistrationRevision. Owner FK to toolProvider. LTI client_id is deferred (§C)."
    },
    {
      "name": "Tool registration revision",
      "description": "Immutable, versioned security-sensitive registration config (§B1 / E2). URL set, requested scope ceiling, and config schema changes create a NEW revision. Lifecycle: published / retired / emergency suspended. Tenant installations pin a revision via application.registrationRevisionId. LTI placements/client_id deferred (§C)."
    },
    {
      "name": "Webhook Delivery Receipt",
      "description": "Receipt-is-an-entity record for each outbound webhook delivery attempt sequence. Stores delivery status, attempt count, timestamps, and diagnostic codes — never the event payload body."
    },
    {
      "name": "Webhook Endpoint",
      "description": "Registered external HTTP callback endpoint for webhook event delivery, scoped to an application and optional auth client."
    }
  ],
  "paths": {
    "/applications/v1/app-credential": {
      "get": {
        "operationId": "listAppCredentials",
        "summary": "List app credentials",
        "description": "Returns all app credential records for the authenticated tenant with cursor pagination. Credential secret values are never returned — only existence, status, and timestamps.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "App Credential"
        ],
        "parameters": [
          {
            "name": "studentSourcedId",
            "in": "query",
            "description": "Filter by student.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "studentSourcedId",
              "operator": "eq"
            }
          },
          {
            "name": "applicationId",
            "in": "query",
            "description": "Filter by application.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "applicationId",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by credential status.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "rotated",
                "revoked"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AppCredential"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createAppCredential",
        "summary": "Issue an app credential",
        "description": "Issues a new app credential for a student/application pair. The secret material is provisioned by the auth seam; only the opaque reference is stored.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "App Credential"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAppCredentialRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppCredential"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (app_credential_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/app-credential/{studentSourcedId}/{applicationId}": {
      "get": {
        "operationId": "getAppCredential",
        "summary": "Get an app credential",
        "description": "Returns a single app credential record by its composite key (studentSourcedId, applicationId). The secret value is never returned.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "App Credential"
        ],
        "parameters": [
          {
            "name": "studentSourcedId",
            "in": "path",
            "required": true,
            "description": "The student sourcedId.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "applicationId",
            "in": "path",
            "required": true,
            "description": "The application identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppCredential"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (app_credential_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteAppCredential",
        "summary": "Delete an app credential",
        "description": "Permanently removes an app credential record. The underlying secret material is revoked through the auth seam.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "App Credential"
        ],
        "parameters": [
          {
            "name": "studentSourcedId",
            "in": "path",
            "required": true,
            "description": "The student sourcedId.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "applicationId",
            "in": "path",
            "required": true,
            "description": "The application identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (app_credential_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateAppCredential",
        "summary": "Update an app credential",
        "description": "Updates mutable fields of an existing app credential.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "App Credential"
        ],
        "parameters": [
          {
            "name": "studentSourcedId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "applicationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAppCredentialRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppCredential"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (app_credential_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/app-credential/issue": {
      "post": {
        "operationId": "issueAppCredential",
        "summary": "Issue a new app credential for a student/application pair",
        "description": "Creates an appCredential for the given student and application. Validates the application exists and is active. Delegates secret generation to the auth seam — secretRef is never returned.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "App Credential"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "studentSourcedId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "FK to oneroster:user — the student."
                  },
                  "applicationId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "FK to application — must be active."
                  }
                },
                "required": [
                  "studentSourcedId",
                  "applicationId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppCredential"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppCredential"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (application_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (credential_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/app-credential/{studentSourcedId}/{applicationId}/rotate": {
      "post": {
        "operationId": "rotateAppCredential",
        "summary": "Rotate an app credential",
        "description": "Rotates the secretRef via the auth seam and updates lastRotatedAt. The credential must be in active status. Never returns secretRef.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "App Credential"
        ],
        "parameters": [
          {
            "name": "studentSourcedId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "applicationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppCredential"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (credential_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (credential_not_active).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/app-credential/{studentSourcedId}/{applicationId}/revoke": {
      "post": {
        "operationId": "revokeAppCredential",
        "summary": "Revoke an app credential",
        "description": "Sets credential status to revoked and records revokedAt. Cannot revoke an already-revoked credential.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "App Credential"
        ],
        "parameters": [
          {
            "name": "studentSourcedId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "applicationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppCredential"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (credential_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (credential_already_revoked).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/application": {
      "get": {
        "operationId": "listApplications",
        "summary": "List applications",
        "description": "Returns all application registrations for the authenticated tenant with cursor pagination.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Application"
        ],
        "parameters": [
          {
            "name": "publisherId",
            "in": "query",
            "description": "Filter by publisher.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "publisherId",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by lifecycle status.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "pending_review",
                "active",
                "suspended",
                "retired"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "sandboxMode",
            "in": "query",
            "description": "Filter by sandbox mode.",
            "schema": {
              "type": "string",
              "enum": [
                "sandbox",
                "production"
              ]
            },
            "x-filter": {
              "column": "sandboxMode",
              "operator": "eq"
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "description": "Return only applications updated since this timestamp.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "x-filter": {
              "column": "updatedAt",
              "operator": "gte"
            }
          },
          {
            "name": "owningOrgSourcedId",
            "in": "query",
            "description": "Filter by one or more owning org sourcedIds (G19 `in`). Org-bound principals get this rewritten in onListQuery from AuthContext.orgBindings[].orgId — not a substitute for detail-read org enforcement.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "x-filter": {
              "column": "owningOrgSourcedId",
              "operator": "in"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Application"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createApplication",
        "summary": "Create an application",
        "description": "Registers a new application within the authenticated tenant.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Application"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApplicationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Application"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (application_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/application/{applicationId}": {
      "get": {
        "operationId": "getApplication",
        "summary": "Get an application",
        "description": "Returns a single application registration by its applicationId.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Application"
        ],
        "parameters": [
          {
            "name": "applicationId",
            "in": "path",
            "required": true,
            "description": "The application identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Application"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (application_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateApplication",
        "summary": "Update an application",
        "description": "Updates an existing application registration.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Application"
        ],
        "parameters": [
          {
            "name": "applicationId",
            "in": "path",
            "required": true,
            "description": "The application identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateApplicationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Application"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (application_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteApplication",
        "summary": "Delete an application",
        "description": "Deletes an application registration. Only permitted when no auth clients, credentials, or webhook endpoints reference this application.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Application"
        ],
        "parameters": [
          {
            "name": "applicationId",
            "in": "path",
            "required": true,
            "description": "The application identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (application_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/application/register": {
      "post": {
        "operationId": "registerApplication",
        "summary": "Register a new application with optional initial auth client",
        "description": "Registers a new application, validates the publisherId FK points to an active publisher, and optionally provisions the first authClient for the application. Ordinary registration stays on applications:write (publishers included). When initialAuthClient is supplied, Cognito credential issuance requires admin or system (same operator gate as registerAuthClient) AND the shared installation eligibility rule (active application, not suspended/expired). Newly registered applications are draft, so initialAuthClient is rejected until the installation is eligible — omit credentials and use registerAuthClient after activation. Returns the created application entity.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Application"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "applicationId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "The application identifier."
                  },
                  "publisherId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "FK to publisher — must be active."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512,
                    "description": "Canonical application name."
                  },
                  "displayName": {
                    "type": "string",
                    "maxLength": 512,
                    "description": "Human-readable name."
                  },
                  "ownerKind": {
                    "type": "string",
                    "enum": [
                      "publisher",
                      "tenant_org",
                      "platform_internal"
                    ],
                    "description": "Ownership discriminator (compatibility)."
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "vendor_installation",
                      "tenant_org",
                      "platform_internal"
                    ],
                    "description": "Installation kind. Derived from ownerKind when omitted."
                  },
                  "registrationRevisionId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Pinned global revision for vendor_installation."
                  },
                  "owningOrgSourcedId": {
                    "type": "string",
                    "maxLength": 256,
                    "description": "Required when ownerKind is tenant_org."
                  },
                  "sandboxMode": {
                    "type": "string",
                    "enum": [
                      "sandbox",
                      "production"
                    ],
                    "description": "Operating mode."
                  },
                  "attribution": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "type": "string",
                        "maxLength": 256
                      },
                      "logoUri": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 2048
                      },
                      "homepageUrl": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 2048
                      },
                      "privacyUrl": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 2048
                      },
                      "termsUrl": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 2048
                      },
                      "category": {
                        "type": "string",
                        "maxLength": 256
                      }
                    }
                  },
                  "allowedScopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 128
                    }
                  },
                  "approvedScopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 128
                    }
                  },
                  "initialAuthClient": {
                    "type": "object",
                    "properties": {
                      "clientId": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256,
                        "description": "Client identifier for the initial auth client."
                      },
                      "redirectUris": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "uri",
                          "maxLength": 2048
                        }
                      },
                      "callbackUrls": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "uri",
                          "maxLength": 2048
                        }
                      },
                      "grantedScopes": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 128
                        }
                      }
                    },
                    "required": [
                      "clientId"
                    ],
                    "description": "Optional initial auth client to provision via Cognito. Requires admin or system; publishers must omit this field."
                  }
                },
                "required": [
                  "applicationId",
                  "publisherId",
                  "name",
                  "ownerKind"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Application"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Application"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (publisher_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (application_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/application/{applicationId}/status": {
      "post": {
        "operationId": "setApplicationStatus",
        "summary": "Set application lifecycle status",
        "description": "Transitions the application status with validation of allowed transitions. Cannot activate from retired.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Application"
        ],
        "parameters": [
          {
            "name": "applicationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "pending_review",
                      "active",
                      "suspended",
                      "retired"
                    ],
                    "description": "The target status."
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Application"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (application_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (illegal_status_transition).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/auth-client": {
      "get": {
        "operationId": "listAuthClients",
        "summary": "List auth clients",
        "description": "Returns all auth client registrations for the authenticated tenant with cursor pagination.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Auth Client"
        ],
        "parameters": [
          {
            "name": "applicationId",
            "in": "query",
            "description": "Filter by application.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "applicationId",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by lifecycle status.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "suspended",
                "retired"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AuthClient"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createAuthClient",
        "summary": "Create an auth client",
        "description": "Registers a new OAuth2/JWKS client within the authenticated tenant.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Auth Client"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAuthClientRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthClient"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (auth_client_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/auth-client/{clientId}": {
      "get": {
        "operationId": "getAuthClient",
        "summary": "Get an auth client",
        "description": "Returns a single auth client registration by its clientId.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Auth Client"
        ],
        "parameters": [
          {
            "name": "clientId",
            "in": "path",
            "required": true,
            "description": "The client identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthClient"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (auth_client_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateAuthClient",
        "summary": "Update an auth client",
        "description": "Updates an existing auth client registration.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Auth Client"
        ],
        "parameters": [
          {
            "name": "clientId",
            "in": "path",
            "required": true,
            "description": "The client identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAuthClientRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthClient"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (auth_client_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteAuthClient",
        "summary": "Delete an auth client",
        "description": "Deletes an auth client registration. Only permitted when no webhook endpoints reference this client.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Auth Client"
        ],
        "parameters": [
          {
            "name": "clientId",
            "in": "path",
            "required": true,
            "description": "The client identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (auth_client_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/auth-client/register": {
      "post": {
        "operationId": "registerAuthClient",
        "summary": "Register a new auth client for an application",
        "description": "Creates a new auth client with applicationId FK validation — the application must exist and be active. Delegates credential provisioning to the auth seam. Returns clientSecret once on the same-request response. Do not use the platform Idempotency-Key response cache (it would persist and replay clientSecret); duplicate clientId remains a durable 409 via Postgres identity.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Auth Client"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "clientId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "Stable external client identifier."
                  },
                  "applicationId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "FK to application — must be active."
                  },
                  "redirectUris": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri",
                      "maxLength": 2048
                    },
                    "description": "Registered redirect URIs."
                  },
                  "callbackUrls": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri",
                      "maxLength": 2048
                    },
                    "description": "Registered callback URLs."
                  },
                  "jwksUri": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048,
                    "description": "Optional public JWKS URI."
                  },
                  "grantedScopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 128
                    },
                    "description": "Permission slugs granted to this client."
                  },
                  "serviceRoles": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 128
                    },
                    "description": "External service-role catalog names (e.g. contentWriter). Required for vendor-created clients; system/admin are rejected. Omitted roles no longer default to system. Sandbox issuance ignores caller-selected roles and uses the pinned sandbox set."
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "sandbox",
                      "live"
                    ],
                    "description": "Credential mode. sandbox → pinned sandbox role set; live → intersect requested roles with registration ceiling × approved scopes after a granted credentialAuthorization."
                  },
                  "providerId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Global toolProvider id for credential-authorization mapping."
                  },
                  "registrationId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional toolRegistration id for scope-ceiling intersection."
                  }
                },
                "required": [
                  "clientId",
                  "applicationId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthClient"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (application_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (auth_client_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/auth-client/{clientId}/rotate": {
      "post": {
        "operationId": "rotateAuthClient",
        "summary": "Rotate auth client credential",
        "description": "Rotates via create-new-Cognito-client-then-retire with a documented overlap window. Updates authProviderRef and lastRotatedAt. Client secret is stored in Secrets Manager and returned once on this response when the hook attaches it (OpenAPI entity schema may strip it until the register/rotate response schema gains an explicit clientSecret field — see docs/AUTH-CLIENT-ISSUANCE.md).\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Auth Client"
        ],
        "parameters": [
          {
            "name": "clientId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthClient"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (auth_client_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/credential-authorization": {
      "get": {
        "operationId": "listCredentialAuthorizations",
        "summary": "List credential authorizations",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Credential authorization"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "granted",
                "denied",
                "suspended",
                "expired",
                "superseded"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "mode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "sandbox",
                "live"
              ]
            },
            "x-filter": {
              "column": "mode",
              "operator": "eq"
            }
          },
          {
            "name": "applicationId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "applicationId",
              "operator": "eq"
            }
          },
          {
            "name": "authClientId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "authClientId",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CredentialAuthorization"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createCredentialAuthorization",
        "summary": "Create credential authorization (operator)",
        "description": "Low-level create. Prefer requestLiveCredentialGrant / onboardProvider.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Credential authorization"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCredentialAuthorizationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialAuthorization"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/credential-authorization/{authorizationId}": {
      "get": {
        "operationId": "getCredentialAuthorization",
        "summary": "Get a credential authorization",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Credential authorization"
        ],
        "parameters": [
          {
            "name": "authorizationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialAuthorization"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (credential_authorization_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateCredentialAuthorization",
        "summary": "Update credential authorization (operator)",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Credential authorization"
        ],
        "parameters": [
          {
            "name": "authorizationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCredentialAuthorizationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialAuthorization"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (credential_authorization_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteCredentialAuthorization",
        "summary": "Delete credential authorization (operator)",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Credential authorization"
        ],
        "parameters": [
          {
            "name": "authorizationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (credential_authorization_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/credential-authorization/request-live": {
      "post": {
        "operationId": "requestLiveCredentialGrant",
        "summary": "Request a live credential grant",
        "description": "Vendor/portal requests a live (tenant-wide) credential grant. Creates a pending credentialAuthorization; tenant-admin grant/deny follows. Intersects requested roles/scopes with registration revision ceiling and application approved scopes server-side. Rejects system/admin. Sandbox mode is rejected here (use onboardProvider).\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Credential authorization"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "authorizationId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "providerId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "registrationId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "applicationId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256
                  },
                  "authClientId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256
                  },
                  "requestedRoles": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 128
                    }
                  },
                  "requestedScopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 128
                    }
                  },
                  "expiresAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "authorizationId",
                  "providerId",
                  "applicationId",
                  "authClientId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialAuthorization"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialAuthorization"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Problem (invalid_arguments).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (conflict).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/credential-authorization/{authorizationId}/grant": {
      "post": {
        "operationId": "grantLiveCredential",
        "summary": "Grant a pending live credential (tenant-admin)",
        "description": "v1: tenant administrator grants a pending live credential. Grant is explicitly tenant-wide. School-admin grants are out of scope. Flips mapping + DynamoDB authorization status so token issuance can succeed.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Credential authorization"
        ],
        "parameters": [
          {
            "name": "authorizationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expiresAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialAuthorization"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (credential_authorization_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (conflict).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/credential-authorization/{authorizationId}/deny": {
      "post": {
        "operationId": "denyLiveCredential",
        "summary": "Deny a pending live credential (tenant-admin)",
        "description": "v1: tenant administrator denies a pending live credential request. Portal polls status=denied.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Credential authorization"
        ],
        "parameters": [
          {
            "name": "authorizationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "denialReason": {
                    "type": "string",
                    "maxLength": 1024
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialAuthorization"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (credential_authorization_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (conflict).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/credential-authorization/{authorizationId}/suspend": {
      "post": {
        "operationId": "suspendCredentialAuthorization",
        "summary": "Suspend a credential authorization",
        "description": "Suspends the grant. Token issuance and cached audience validation fail within the documented TTL. Also blocks authored catalog access via ownershipPrincipal for the linked Cognito client.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Credential authorization"
        ],
        "parameters": [
          {
            "name": "authorizationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialAuthorization"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (credential_authorization_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (conflict).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider-invite": {
      "get": {
        "operationId": "listProviderInvites",
        "summary": "List provider invites",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider invite"
        ],
        "parameters": [
          {
            "name": "providerId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "providerId",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "accepted",
                "revoked",
                "expired"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProviderInvite"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createProviderInvite",
        "summary": "Create a provider invite",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider invite"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; a completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProviderInviteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderInvite"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderInvite"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — an operation with this Idempotency-Key is already in progress (60s lock).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider-invite/{inviteId}": {
      "get": {
        "operationId": "getProviderInvite",
        "summary": "Get a provider invite",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider invite"
        ],
        "parameters": [
          {
            "name": "inviteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderInvite"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_invite_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateProviderInvite",
        "summary": "Update a provider invite",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider invite"
        ],
        "parameters": [
          {
            "name": "inviteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProviderInviteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderInvite"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_invite_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteProviderInvite",
        "summary": "Delete a provider invite",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider invite"
        ],
        "parameters": [
          {
            "name": "inviteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_invite_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider/{providerId}/invites": {
      "post": {
        "operationId": "createProviderInviteForProvider",
        "summary": "Create an invite for a provider",
        "description": "Alpha surface: owner creates a pending invite. Accept is a separate operation.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider invite"
        ],
        "parameters": [
          {
            "name": "providerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; a completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "inviteId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 320
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "developer"
                    ]
                  },
                  "expiresAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "email",
                  "role",
                  "expiresAt"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderInvite"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderInvite"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — an operation with this Idempotency-Key is already in progress (60s lock).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider/{providerId}/invites/{inviteId}/accept": {
      "post": {
        "operationId": "acceptProviderInvite",
        "summary": "Accept a provider invite",
        "description": "Calling principal accepts a pending invite: creates or reactivates an active providerMember and marks the invite accepted.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider invite"
        ],
        "parameters": [
          {
            "name": "providerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "inviteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "inviteId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "providerId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "memberId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "principal": {
                      "type": "string"
                    },
                    "email": {
                      "type": "string",
                      "format": "email"
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "owner",
                        "admin",
                        "developer"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "invited",
                        "active",
                        "removed"
                      ]
                    }
                  },
                  "required": [
                    "inviteId",
                    "providerId",
                    "memberId",
                    "principal",
                    "email",
                    "role",
                    "status"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_invite_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (provider_invite_not_acceptable).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider-member": {
      "get": {
        "operationId": "listProviderMembers",
        "summary": "List provider members",
        "description": "Operator-facing list of membership rows for the authenticated tenant.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "providerId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "providerId",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "invited",
                "active",
                "removed"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "role",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "owner",
                "admin",
                "developer"
              ]
            },
            "x-filter": {
              "column": "role",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProviderMember"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createProviderMember",
        "summary": "Create a provider member",
        "description": "Operator-facing create. Portal member management uses the nested provider routes.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; a completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProviderMemberRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderMember"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderMember"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (provider_member_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider-member/{memberId}": {
      "get": {
        "operationId": "getProviderMember",
        "summary": "Get a provider member",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "memberId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderMember"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_member_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateProviderMember",
        "summary": "Update a provider member",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "memberId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProviderMemberRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderMember"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_member_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteProviderMember",
        "summary": "Delete a provider member",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "memberId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_member_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider/{providerId}/members": {
      "get": {
        "operationId": "listProviderMembersForProvider",
        "summary": "List members for a provider",
        "description": "Alpha surface: list membership rows for one provider. Active members with developer+ may read; operator/system bypasses.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "providerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "invited",
                "active",
                "removed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of members to return on this page (clamped server-side to api.pagination.maxPageSize).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Opaque pagination cursor — pass the previous page's nextCursor to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "memberId": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "providerId": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "principal": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string",
                            "format": "email"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "owner",
                              "admin",
                              "developer"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "invited",
                              "active",
                              "removed"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "memberId",
                          "providerId",
                          "principal",
                          "email",
                          "role",
                          "status"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createProviderMemberForProvider",
        "summary": "Create a provider member",
        "description": "Alpha surface: owner (or operator) adds an active member for the provider.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "providerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; a completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "memberId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "principal": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 320
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "developer"
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "invited",
                      "active",
                      "removed"
                    ],
                    "default": "active"
                  }
                },
                "required": [
                  "principal",
                  "email",
                  "role"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderMember"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderMember"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (provider_member_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider/{providerId}/members/{memberId}": {
      "get": {
        "operationId": "getProviderMemberForProvider",
        "summary": "Get one provider member",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "providerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "memberId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderMember"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_member_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateProviderMemberForProvider",
        "summary": "Update a provider member",
        "description": "Alpha surface: owner (or operator) updates role/email/status.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "providerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "memberId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 320
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "developer"
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "invited",
                      "active",
                      "removed"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderMember"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_member_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider/{providerId}/members/{memberId}/remove": {
      "post": {
        "operationId": "removeProviderMemberForProvider",
        "summary": "Remove a provider member",
        "description": "Alpha surface: owner (or operator) soft-removes a member (status=removed).\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider member"
        ],
        "parameters": [
          {
            "name": "providerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "memberId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderMember"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_member_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider-onboarding": {
      "get": {
        "operationId": "listProviderOnboardings",
        "summary": "List provider onboarding sagas",
        "description": "Operator list of durable onboarding saga receipts.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider onboarding"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "running",
                "completed",
                "failed",
                "replaced"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "operationId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "operationId",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProviderOnboarding"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createProviderOnboarding",
        "summary": "Create onboarding receipt (operator)",
        "description": "Low-level receipt create. Prefer onboardProvider.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider onboarding"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProviderOnboardingRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderOnboarding"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider-onboarding/{id}": {
      "get": {
        "operationId": "getProviderOnboarding",
        "summary": "Get a provider onboarding saga",
        "description": "Returns the durable saga receipt. Does not re-display clientSecret unless the protected response receipt is still present (hook-owned).\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider onboarding"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderOnboarding"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_onboarding_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateProviderOnboarding",
        "summary": "Update onboarding receipt (operator)",
        "description": "Operator repair path. Prefer reconcileProviderOnboardingOrphans for convergence.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider onboarding"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProviderOnboardingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderOnboarding"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_onboarding_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteProviderOnboarding",
        "summary": "Delete onboarding receipt (operator)",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider onboarding"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (provider_onboarding_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider-onboarding/onboard": {
      "post": {
        "operationId": "onboardProvider",
        "summary": "Run provider onboarding saga",
        "description": "Portal-workload authored door for the durable PROVIDER ONBOARDING saga. Creates or resumes by operationId: toolProvider → provisionSandboxTenant → sandbox publisher/application → sandbox authClient (pinned sandbox role set) → credentialAuthorization mapping. Returns clientSecret while the protected response receipt exists. On completed replay when that receipt is gone (process/replica restart), retires the uncertain Cognito client/mapping and issues a replacement secret under a new receipt — never re-derives or re-displays the old secret. Same operationId is deterministic. Idempotency is the durable operationId in the request body — do not use the platform Idempotency-Key response cache (it would store clientSecret).\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider onboarding"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "operationId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Durable operation id (idempotency key for the saga)."
                  },
                  "displayName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512
                  },
                  "verifiedContactEmail": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 320
                  },
                  "ownershipPrincipal": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512
                  },
                  "legalName": {
                    "type": "string",
                    "maxLength": 512
                  },
                  "sandboxTenantId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional client-supplied sandbox tenant id. When omitted, derived deterministically from operationId."
                  },
                  "sandboxSlug": {
                    "type": "string",
                    "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$",
                    "minLength": 3,
                    "maxLength": 80,
                    "description": "Optional sandbox tenant slug. When omitted, derived from operationId."
                  }
                },
                "required": [
                  "operationId",
                  "displayName",
                  "verifiedContactEmail",
                  "ownershipPrincipal"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "operationId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "stage": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "toolProviderId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "sandboxTenantId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "publisherId": {
                      "type": "string"
                    },
                    "applicationId": {
                      "type": "string"
                    },
                    "authClientId": {
                      "type": "string"
                    },
                    "cognitoClientId": {
                      "type": "string"
                    },
                    "credentialAuthorizationId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "responseReceiptId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "clientSecret": {
                      "type": "string",
                      "description": "Same one-shot secret when the protected receipt is alive; otherwise a replacement secret after retire-and-replace (never the lost original)."
                    },
                    "seedContract": {
                      "type": "object",
                      "properties": {
                        "orgSourcedId": {
                          "type": "string"
                        },
                        "teacherSourcedId": {
                          "type": "string"
                        },
                        "studentSourcedId": {
                          "type": "string"
                        },
                        "contentId": {
                          "type": "string",
                          "format": "uuid"
                        }
                      },
                      "required": [
                        "orgSourcedId",
                        "teacherSourcedId",
                        "studentSourcedId",
                        "contentId"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "operationId",
                    "stage",
                    "status",
                    "toolProviderId",
                    "sandboxTenantId",
                    "publisherId",
                    "applicationId",
                    "authClientId",
                    "cognitoClientId",
                    "credentialAuthorizationId",
                    "responseReceiptId",
                    "seedContract"
                  ],
                  "description": "Idempotent replay of a completed saga (same shape as 201). When the protected response receipt is still present, returns the same clientSecret; when it is gone, retires the uncertain client and returns a replacement clientSecret under a new responseReceiptId.",
                  "additionalProperties": false
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "operationId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "stage": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "toolProviderId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "sandboxTenantId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "publisherId": {
                      "type": "string"
                    },
                    "applicationId": {
                      "type": "string"
                    },
                    "authClientId": {
                      "type": "string"
                    },
                    "cognitoClientId": {
                      "type": "string"
                    },
                    "credentialAuthorizationId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "responseReceiptId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "clientSecret": {
                      "type": "string",
                      "description": "One-shot secret from the protected response receipt. On completed replay with a missing receipt, the saga retires the uncertain client and returns a replacement secret instead of omitting or re-deriving the old one."
                    },
                    "seedContract": {
                      "type": "object",
                      "properties": {
                        "orgSourcedId": {
                          "type": "string"
                        },
                        "teacherSourcedId": {
                          "type": "string"
                        },
                        "studentSourcedId": {
                          "type": "string"
                        },
                        "contentId": {
                          "type": "string",
                          "format": "uuid"
                        }
                      },
                      "required": [
                        "orgSourcedId",
                        "teacherSourcedId",
                        "studentSourcedId",
                        "contentId"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "operationId",
                    "stage",
                    "status",
                    "toolProviderId",
                    "sandboxTenantId",
                    "publisherId",
                    "applicationId",
                    "authClientId",
                    "cognitoClientId",
                    "credentialAuthorizationId",
                    "responseReceiptId",
                    "seedContract"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (conflict).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/provider-onboarding/reconcile-orphans": {
      "post": {
        "operationId": "reconcileProviderOnboardingOrphans",
        "summary": "Reconcile orphaned onboarding resources",
        "description": "Operator orphan reconciler: resumes running sagas, retires orphaned Cognito clients/secrets left by mid-stage failures, and converges receipts to a terminal state.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Provider onboarding"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "operationId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional: reconcile a single operation. When omitted, scans running/failed receipts."
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 200,
                    "default": 50
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "reconciled": {
                      "type": "integer"
                    },
                    "retiredCognitoClients": {
                      "type": "integer"
                    },
                    "operations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "operationId": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "status": {
                            "type": "string"
                          },
                          "stage": {
                            "type": "string"
                          },
                          "action": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "operationId",
                          "status",
                          "stage"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "reconciled",
                    "retiredCognitoClients",
                    "operations"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/publisher": {
      "get": {
        "operationId": "listPublishers",
        "summary": "List publishers",
        "description": "Returns all publisher registrations for the authenticated tenant with cursor pagination.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Publisher"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Optional status filter.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "active",
                "suspended",
                "retired"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Publisher"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createPublisher",
        "summary": "Create a publisher",
        "description": "Registers a new publisher within the authenticated tenant. Optimistic replays use the idempotency engine when an Idempotency-Key header is supplied.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Publisher"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; a completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePublisherRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Publisher"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Publisher"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (publisher_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/publisher/{publisherId}": {
      "get": {
        "operationId": "getPublisher",
        "summary": "Get a publisher",
        "description": "Returns a single publisher registration by its publisherId.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Publisher"
        ],
        "parameters": [
          {
            "name": "publisherId",
            "in": "path",
            "required": true,
            "description": "The publisher identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Publisher"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (publisher_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updatePublisher",
        "summary": "Update a publisher",
        "description": "Updates an existing publisher registration.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Publisher"
        ],
        "parameters": [
          {
            "name": "publisherId",
            "in": "path",
            "required": true,
            "description": "The publisher identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePublisherRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Publisher"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (publisher_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deletePublisher",
        "summary": "Delete a publisher",
        "description": "Deletes a publisher registration. Only permitted when no applications reference this publisher.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Publisher"
        ],
        "parameters": [
          {
            "name": "publisherId",
            "in": "path",
            "required": true,
            "description": "The publisher identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (publisher_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/renderer-capability": {
      "get": {
        "operationId": "listRendererCapabilities",
        "summary": "List renderer capabilities",
        "description": "Returns renderer capability registrations for the authenticated tenant, with optional filtering by accepted content kind and lifecycle state.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Renderer Capability"
        ],
        "parameters": [
          {
            "name": "acceptedContentKinds",
            "in": "query",
            "description": "Filter to renderers that accept this content kind (matches any element in the acceptedContentKinds array).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lifecycleState",
            "in": "query",
            "description": "Filter by lifecycle state.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "active",
                "deprecated",
                "retired"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RendererCapability"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createRendererCapability",
        "summary": "Create a renderer capability",
        "description": "Registers a new renderer capability within the authenticated tenant.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Renderer Capability"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRendererCapabilityRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RendererCapability"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (renderer_capability_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/renderer-capability/{rendererRef}": {
      "get": {
        "operationId": "getRendererCapability",
        "summary": "Get a renderer capability",
        "description": "Returns a single renderer capability registration by its rendererRef.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Renderer Capability"
        ],
        "parameters": [
          {
            "name": "rendererRef",
            "in": "path",
            "required": true,
            "description": "The renderer capability identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RendererCapability"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (renderer_capability_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateRendererCapability",
        "summary": "Update a renderer capability",
        "description": "Updates an existing renderer capability registration.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Renderer Capability"
        ],
        "parameters": [
          {
            "name": "rendererRef",
            "in": "path",
            "required": true,
            "description": "The renderer capability identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateRendererCapabilityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RendererCapability"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (renderer_capability_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteRendererCapability",
        "summary": "Delete a renderer capability",
        "description": "Deletes a renderer capability registration. Only permitted when no curriculum delivery components reference this rendererRef.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Renderer Capability"
        ],
        "parameters": [
          {
            "name": "rendererRef",
            "in": "path",
            "required": true,
            "description": "The renderer capability identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (renderer_capability_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/renderer-capability/register": {
      "post": {
        "operationId": "registerRendererCapability",
        "summary": "Register a new renderer capability",
        "description": "Registers a renderer in the capability registry. If applicationId is provided, validates the owning application is active.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Renderer Capability"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rendererRef": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "Natural key — stable renderer reference."
                  },
                  "applicationId": {
                    "type": "string",
                    "maxLength": 256,
                    "description": "Optional FK to owning application — must be active if provided."
                  },
                  "displayName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512,
                    "description": "Human name."
                  },
                  "acceptedContentKinds": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 128
                    },
                    "minItems": 1,
                    "description": "Content kinds this renderer handles."
                  },
                  "integrationProtocol": {
                    "type": "string",
                    "enum": [
                      "alpha_embed",
                      "lti_launch_ref",
                      "external_link"
                    ],
                    "description": "How the renderer is invoked."
                  },
                  "integrationEndpoint": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048,
                    "description": "Registered render endpoint URL."
                  },
                  "playgroundUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048,
                    "description": "Optional validation URL."
                  }
                },
                "required": [
                  "rendererRef",
                  "displayName",
                  "acceptedContentKinds",
                  "integrationProtocol",
                  "integrationEndpoint"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RendererCapability"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RendererCapability"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (application_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (renderer_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/renderer-capability/{rendererRef}/lifecycle": {
      "post": {
        "operationId": "setRendererLifecycleState",
        "summary": "Set renderer lifecycle state",
        "description": "Updates the lifecycle state of a registered renderer capability.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Renderer Capability"
        ],
        "parameters": [
          {
            "name": "rendererRef",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lifecycleState": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "active",
                      "deprecated",
                      "retired"
                    ],
                    "description": "The target lifecycle state."
                  }
                },
                "required": [
                  "lifecycleState"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RendererCapability"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (renderer_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-provider": {
      "get": {
        "operationId": "listToolProviders",
        "summary": "List tool providers",
        "description": "Lists global tool providers. Operator/Cognito path only — provider-management tokens are not accepted by generated CRUD.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Filter by lifecycle status.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "active",
                "suspended",
                "retired"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ToolProvider"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createToolProvider",
        "summary": "Create a tool provider",
        "description": "Registers a global tool provider. Cognito operator path (portal onboarding workload / admin).\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; a completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateToolProviderRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolProvider"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolProvider"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (tool_provider_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-provider/{id}": {
      "get": {
        "operationId": "getToolProvider",
        "summary": "Get a tool provider",
        "description": "Returns one global tool provider by id.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolProvider"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateToolProvider",
        "summary": "Update a tool provider (operator CRUD)",
        "description": "Generated CRUD update. Provider-management principals must use updateToolProviderProfile instead.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateToolProviderRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolProvider"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteToolProvider",
        "summary": "Delete a tool provider",
        "description": "Deletes a provider when no registrations reference it. Operator-only.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-provider/{id}/management-token": {
      "post": {
        "operationId": "mintProviderManagementToken",
        "summary": "Mint a provider-management JWT",
        "description": "Callable only by the portal workload identity. Returns a platform4-signed short-lived JWT (aud=platform4:provider-management, TTL ≤15m) with claims providerId + allowed management ops. Authored verifier path only — generated CRUD never accepts this token.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Target toolProvider id stamped into the token claims.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; a completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "allowedOps": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "provider.profile.read",
                        "provider.profile.write",
                        "registration.read",
                        "registration.write",
                        "revision.publish"
                      ]
                    },
                    "minItems": 1,
                    "description": "Management operations the minted principal may invoke."
                  },
                  "ttlSeconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 900,
                    "description": "Token TTL in seconds; capped at 900 (15 minutes).",
                    "default": 900
                  }
                },
                "required": [
                  "allowedOps"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "jti": {
                      "type": "string"
                    },
                    "providerId": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "required": [
                    "token",
                    "expiresAt",
                    "jti",
                    "providerId"
                  ]
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — an operation with this Idempotency-Key is already in progress (60s lock).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-provider/{id}/status": {
      "post": {
        "operationId": "setToolProviderStatus",
        "summary": "Set provider status (operator-only)",
        "description": "Operator-only lifecycle transition. Provider-management principals are rejected.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "active",
                      "suspended",
                      "retired"
                    ]
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolProvider"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-provider/{id}/transfer-ownership": {
      "post": {
        "operationId": "transferToolProviderOwnership",
        "summary": "Transfer provider ownership (operator-only)",
        "description": "Operator-only ownership transfer. Provider-management principals are rejected.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ownershipPrincipal": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512
                  }
                },
                "required": [
                  "ownershipPrincipal"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolProvider"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-provider/{id}/profile": {
      "post": {
        "operationId": "updateToolProviderProfile",
        "summary": "Update provider profile (authored ownership checks)",
        "description": "Authored mutation with union-principal verification (Cognito M2M OR platform-signed provider-management JWT). Marked public so generated Cognito-only extractAuthContext is skipped; the authored hook reads Authorization via platform request-authorization capture and runs resolveAuthoredCatalogPrincipal + ownership checks. Generated CRUD never accepts provider-management tokens. Cannot change status or ownership.\n\n> **Open:** no authentication required — this operation is public.",
        "tags": [
          "Tool provider"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "displayName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512
                  },
                  "legalName": {
                    "type": "string",
                    "maxLength": 512
                  },
                  "supportUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048
                  },
                  "privacyUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048
                  },
                  "termsUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolProvider"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_provider_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/jwks.json": {
      "get": {
        "operationId": "getPlatformJwks",
        "summary": "Platform JWT JWKS",
        "description": "Public JWKS for platform4-signed tokens (provider-management now; LTI later). Kid discipline + rotation owned by shared/platform-jwt.\n\n> **Open:** no authentication required — this operation is public.",
        "tags": [
          "Tool provider"
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  },
                  "required": [
                    "keys"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-provider/platform-jwt/rotate": {
      "post": {
        "operationId": "rotatePlatformSigningKeys",
        "summary": "Rotate platform JWT signing keys",
        "description": "Operator-only. Rotates the active platform signing key (kid discipline: previous kid remains verifiable for 24h) and persists through the configured durable store (PLATFORM_JWT_STATE_TABLE / PLATFORM_JWT_DURABLE_PATH). Not callable with a provider-management token.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "activeKid": {
                      "type": "string"
                    },
                    "keys": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  },
                  "required": [
                    "activeKid",
                    "keys"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-provider/platform-jwt/revoke-jti": {
      "post": {
        "operationId": "revokeProviderManagementJti",
        "summary": "Revoke a provider-management token jti",
        "description": "Operator or portal workload only. Persists jti denylist revocation through the durable platform JWT store so compromised provider-management tokens fail verify after reload. Not a public endpoint; provider-management tokens cannot call this.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool provider"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "jti": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128,
                    "description": "JWT ID to revoke."
                  },
                  "exp": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Token exp claim (unix seconds) — denylist entry retained until then."
                  }
                },
                "required": [
                  "jti",
                  "exp"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    },
                    "jti": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "revoked",
                    "jti"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-registration": {
      "get": {
        "operationId": "listToolRegistrations",
        "summary": "List tool registrations",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool registration"
        ],
        "parameters": [
          {
            "name": "toolProviderId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "toolProviderId",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "published",
                "suspended",
                "retired"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ToolRegistration"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createToolRegistration",
        "summary": "Create a tool registration",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool registration"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; a completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateToolRegistrationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistration"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistration"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (tool_registration_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-registration/{id}": {
      "get": {
        "operationId": "getToolRegistration",
        "summary": "Get a tool registration",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool registration"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistration"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_registration_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateToolRegistration",
        "summary": "Update display metadata on a registration",
        "description": "Display-only in-place update. URL/scope/config changes must create a new toolRegistrationRevision.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool registration"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateToolRegistrationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistration"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_registration_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteToolRegistration",
        "summary": "Delete a tool registration",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool registration"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_registration_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-registration-revision": {
      "get": {
        "operationId": "listToolRegistrationRevisions",
        "summary": "List registration revisions",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool registration revision"
        ],
        "parameters": [
          {
            "name": "toolRegistrationId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "toolRegistrationId",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "published",
                "retired",
                "suspended"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ToolRegistrationRevision"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createToolRegistrationRevision",
        "summary": "Create an immutable registration revision",
        "description": "Creates a new immutable revision. Existing installations stay pinned to their last approved revision until reapproval.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool registration revision"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; a completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateToolRegistrationRevisionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistrationRevision"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistrationRevision"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "Location": {
                "description": "URI of the created resource (detail route). Persisted on the idempotency row and re-served on replay.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (tool_registration_revision_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-registration-revision/{id}": {
      "get": {
        "operationId": "getToolRegistrationRevision",
        "summary": "Get a registration revision",
        "description": "> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool registration revision"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistrationRevision"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_registration_revision_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-registration-revision/{id}/status": {
      "post": {
        "operationId": "setToolRegistrationRevisionStatus",
        "summary": "Set revision lifecycle status (operator)",
        "description": "Operator-facing lifecycle for published/retired/suspended. Provider principals rejected for emergency suspend of another provider's revision.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Tool registration revision"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "published",
                      "retired",
                      "suspended"
                    ]
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistrationRevision"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_registration_revision_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/tool-registration-revision/publish": {
      "post": {
        "operationId": "publishToolRegistrationRevision",
        "summary": "Publish a new revision (authored ownership checks)",
        "description": "Authored command that creates+publishes a revision. Union-principal verification (Cognito M2M OR provider-management JWT) runs inside the hook via resolveAuthoredCatalogPrincipal; marked public so generated Cognito-only extractAuthContext is skipped. Generated CRUD never accepts provider-management tokens.\n\n> **Open:** no authentication required — this operation is public.",
        "tags": [
          "Tool registration revision"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional client-supplied revision id."
                  },
                  "toolRegistrationId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "oidcInitiationUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048
                  },
                  "redirectUris": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri",
                      "maxLength": 2048
                    },
                    "minItems": 1
                  },
                  "jwksUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048
                  },
                  "targetLinkUris": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri",
                      "maxLength": 2048
                    },
                    "minItems": 1
                  },
                  "requestedScopeCeiling": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 128
                    }
                  },
                  "configSchema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                },
                "required": [
                  "toolRegistrationId",
                  "oidcInitiationUrl",
                  "redirectUris",
                  "jwksUrl",
                  "targetLinkUris",
                  "requestedScopeCeiling"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistrationRevision"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolRegistrationRevision"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Problem (forbidden).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (tool_registration_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — an operation with this Idempotency-Key is already in progress (60s lock).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/webhook-delivery-receipt": {
      "get": {
        "operationId": "listWebhookDeliveryReceipts",
        "summary": "List webhook delivery receipts",
        "description": "Returns delivery receipts for the authenticated tenant with cursor pagination. Supports filtering by endpoint, application, event type, status, and creation time.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Delivery Receipt"
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "query",
            "description": "Filter by target webhook endpoint.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "endpointId",
              "operator": "eq"
            }
          },
          {
            "name": "applicationId",
            "in": "query",
            "description": "Filter by application.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "applicationId",
              "operator": "eq"
            }
          },
          {
            "name": "eventType",
            "in": "query",
            "description": "Filter by event type.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "eventType",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by delivery status.",
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "delivered",
                "retrying",
                "failed",
                "exhausted"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "createdSince",
            "in": "query",
            "description": "Return only receipts created since this timestamp.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "x-filter": {
              "column": "createdAt",
              "operator": "gte"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDeliveryReceipt"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhookDeliveryReceipt",
        "summary": "Create a webhook delivery receipt",
        "description": "Creates a delivery receipt record for a webhook delivery attempt. Used internally by testWebhookEndpoint and the delivery pipeline.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Delivery Receipt"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookDeliveryReceiptRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryReceipt"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/webhook-delivery-receipt/{deliveryId}": {
      "get": {
        "operationId": "getWebhookDeliveryReceipt",
        "summary": "Get a webhook delivery receipt",
        "description": "Returns a single delivery receipt by its deliveryId.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Delivery Receipt"
        ],
        "parameters": [
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "description": "The delivery receipt identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryReceipt"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (webhook_delivery_receipt_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/webhook-endpoint": {
      "get": {
        "operationId": "listWebhookEndpoints",
        "summary": "List webhook endpoints",
        "description": "Returns all webhook endpoint registrations for the authenticated tenant with cursor pagination.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Endpoint"
        ],
        "parameters": [
          {
            "name": "applicationId",
            "in": "query",
            "description": "Filter by owning application.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "applicationId",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by lifecycle status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending_verification",
                "active",
                "paused",
                "failed",
                "retired"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "clientId",
            "in": "query",
            "description": "Filter by owning auth client.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "clientId",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhookEndpoint",
        "summary": "Create a webhook endpoint",
        "description": "Registers a new webhook endpoint within the authenticated tenant.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Endpoint"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookEndpointRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (webhook_endpoint_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/webhook-endpoint/{endpointId}": {
      "get": {
        "operationId": "getWebhookEndpoint",
        "summary": "Get a webhook endpoint",
        "description": "Returns a single webhook endpoint registration by its endpointId.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Endpoint"
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "description": "The webhook endpoint identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (webhook_endpoint_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateWebhookEndpoint",
        "summary": "Update a webhook endpoint",
        "description": "Updates an existing webhook endpoint registration.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Endpoint"
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "description": "The webhook endpoint identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookEndpointRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (webhook_endpoint_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhookEndpoint",
        "summary": "Delete a webhook endpoint",
        "description": "Deletes a webhook endpoint registration. Only permitted when no pending delivery receipts reference this endpoint.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Endpoint"
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "description": "The webhook endpoint identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (webhook_endpoint_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Precondition Failed — the If-Match ETag is stale (the resource was modified); refetch and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/webhook-endpoint/register": {
      "post": {
        "operationId": "registerWebhookEndpoint",
        "summary": "Register an external webhook endpoint",
        "description": "Registers a new webhook callback URL. Validates the owning application exists and is active, the optional clientId FK, and that callbackUrl uses HTTPS.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Endpoint"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "endpointId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "Natural key — stable endpoint identifier."
                  },
                  "applicationId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "FK to application — must be active."
                  },
                  "clientId": {
                    "type": "string",
                    "maxLength": 256,
                    "description": "Optional FK to authClient."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048,
                    "description": "HTTPS callback URL for signed POST delivery."
                  },
                  "eventTypes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 256
                    },
                    "minItems": 1,
                    "description": "Event types to subscribe to."
                  },
                  "grantedScopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 128
                    },
                    "description": "Permission slugs required for deliveries."
                  },
                  "signingMaterialRef": {
                    "type": "string",
                    "maxLength": 512,
                    "description": "Opaque signing material reference from auth seam.",
                    "writeOnly": true
                  }
                },
                "required": [
                  "endpointId",
                  "applicationId",
                  "callbackUrl",
                  "eventTypes"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (application_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (endpoint_already_exists).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/webhook-endpoint/{endpointId}/test": {
      "post": {
        "operationId": "testWebhookEndpoint",
        "summary": "Send a test delivery to a webhook endpoint",
        "description": "Creates a webhookDeliveryReceipt for a synthetic test delivery to the endpoint. Follows the receipt-is-an-entity pattern — the receipt is the response.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Endpoint"
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deliveryId": {
                      "type": "string",
                      "description": "The delivery receipt ID."
                    },
                    "endpointId": {
                      "type": "string",
                      "description": "The webhook endpoint tested."
                    },
                    "applicationId": {
                      "type": "string",
                      "description": "The owning application."
                    },
                    "eventType": {
                      "type": "string",
                      "description": "The synthetic event type."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "delivered",
                        "retrying",
                        "failed",
                        "exhausted"
                      ],
                      "description": "Delivery status."
                    },
                    "attemptCount": {
                      "type": "integer",
                      "description": "Number of delivery attempts."
                    },
                    "lastAttemptAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "lastResponseStatus": {
                      "type": "integer"
                    },
                    "diagnosticCode": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "deliveryId",
                    "endpointId",
                    "applicationId",
                    "eventType",
                    "status",
                    "attemptCount"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (endpoint_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/webhook-endpoint/{endpointId}/pause": {
      "post": {
        "operationId": "pauseWebhookEndpoint",
        "summary": "Pause a webhook endpoint",
        "description": "Sets the endpoint status to paused. Only active endpoints can be paused.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Endpoint"
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (endpoint_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (endpoint_not_active).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/applications/v1/webhook-endpoint/{endpointId}/resume": {
      "post": {
        "operationId": "resumeWebhookEndpoint",
        "summary": "Resume a paused webhook endpoint",
        "description": "Sets the endpoint status back to active. Only paused endpoints can be resumed.\n\n> **Auth required:** a verified bearer token is required.",
        "tags": [
          "Webhook Endpoint"
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (endpoint_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (endpoint_not_paused).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AppCredential": {
        "type": "object",
        "properties": {
          "studentSourcedId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Cross-module FK to oneroster:user.sourcedId identifying the student this credential is issued to. Part of the composite-natural key (tenantId, studentSourcedId, applicationId). Uses composite (tenantId, sourcedId) cross-module FK shape.",
            "x-references": "oneroster:user.sourcedId",
            "x-onDelete": "restrict"
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the application this credential grants access to. Part of the composite-natural key (tenantId, studentSourcedId, applicationId). Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "secretRef": {
            "type": "string",
            "maxLength": 512,
            "description": "Opaque managed reference to the credential secret material (e.g. vault://tenant/app-cred/...). Write-only — never serialized on read responses. The auth seam owns issuing, rotation, and revocation of the underlying secret value. This is the rule: secrets never become schema fields.",
            "writeOnly": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "rotated",
              "revoked"
            ],
            "description": "Lifecycle status of the app credential. Active credentials can authenticate; rotated credentials have been superseded by a new secret; revoked credentials are permanently invalidated.",
            "default": "active"
          },
          "lastRotatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Managed timestamp set by rotateAppCredential. Null until first rotation."
          },
          "revokedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Managed timestamp set when the credential is revoked. Null while credential is active or rotated."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "studentSourcedId",
          "applicationId",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "Application": {
        "type": "object",
        "properties": {
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Stable identifier for this application within the tenant."
          },
          "publisherId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the publisher that owns this application. Composite shape (tenantId, publisherId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "publisher.publisherId",
            "x-onDelete": "restrict"
          },
          "kind": {
            "type": "string",
            "enum": [
              "vendor_installation",
              "tenant_org",
              "platform_internal"
            ],
            "description": "Installation kind. Only vendor_installation carries a registrationRevisionId pin; tenant_org/platform_internal keep NULL revision and local semantics. When omitted on write, hooks derive from ownerKind (publisher→vendor_installation)."
          },
          "registrationRevisionId": {
            "type": "string",
            "format": "uuid",
            "description": "Nullable tenant→global FK pinning the immutable toolRegistrationRevision this tenant approved. Required for vendor_installation; MUST be null for tenant_org/platform_internal.",
            "x-references": "toolRegistrationRevision.id",
            "x-onDelete": "restrict"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Canonical application name. Authority for tenant_org/platform_internal; deprecated mirror for vendor_installation (global toolRegistration.name wins)."
          },
          "displayName": {
            "type": "string",
            "maxLength": 512,
            "description": "Human-readable name. Authority for tenant_org/platform_internal; deprecated mirror for vendor_installation (global toolRegistration.displayName wins)."
          },
          "owningOrgSourcedId": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional cross-module FK to the OneRoster organization that owns this application. Required when ownerKind/kind is tenant_org. Uses the composite (tenantId, sourcedId) cross-module FK shape.",
            "x-references": "oneroster:org.sourcedId",
            "x-onDelete": "restrict"
          },
          "ownerKind": {
            "type": "string",
            "enum": [
              "publisher",
              "tenant_org",
              "platform_internal"
            ],
            "description": "COMPATIBILITY/DEPRECATED alias for ownership discriminator. Prefer `kind`. Mapping: publisher↔vendor_installation, tenant_org↔tenant_org, platform_internal↔platform_internal."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "pending_review",
              "active",
              "suspended",
              "retired"
            ],
            "description": "Operational lifecycle of the installation. Approval state (revision pin / reviewVersion) is separate from operational state.",
            "default": "draft"
          },
          "sandboxMode": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ],
            "description": "Operating mode of the application. Sandbox applications write only to isolated sandbox data; production applications interact with live tenant data.",
            "default": "sandbox"
          },
          "attribution": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "maxLength": 256,
                "description": "Short display label shown in attribution badges and consent prompts."
              },
              "logoUri": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "URI to the application logo for attribution display."
              },
              "homepageUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "Application homepage URL shown in discovery and consent surfaces."
              },
              "privacyUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "Application privacy policy URL displayed during consent and review flows."
              },
              "termsUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "Application terms-of-service URL displayed during consent and review flows."
              },
              "category": {
                "type": "string",
                "maxLength": 256,
                "description": "App category for discovery and classification in the tenant application catalog (e.g. gradebook, assessment, lms, communication)."
              }
            },
            "description": "Display attribution. Authority for tenant_org/platform_internal; deprecated mirror for vendor_installation (global toolRegistration.attribution wins)."
          },
          "allowedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "DEPRECATED mirror of approvedScopes for pre-E2 clients. Authority: application.approvedScopes (intersected with revision.requestedScopeCeiling for vendor_installation); local allowedScopes remains authority only for tenant_org/platform_internal when approvedScopes is empty."
          },
          "approvedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Scopes this tenant approved for the installation. For vendor_installation, effective scopes = approvedScopes ∩ pinned revision.requestedScopeCeiling."
          },
          "approverId": {
            "type": "string",
            "maxLength": 256,
            "description": "Principal id of the tenant administrator who approved the pinned revision / grant."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional grant expiry. Past expiresAt fails the shared eligibility rule."
          },
          "reviewVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonic review counter incremented on each tenant approval of a revision pin."
          },
          "tenantSuspended": {
            "type": "boolean",
            "description": "Independent tenant-side suspension flag. Revision/provider changes cannot clear this; evaluated by the shared eligibility rule.",
            "default": false
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "applicationId",
          "publisherId",
          "name",
          "ownerKind",
          "status",
          "sandboxMode",
          "createdAt",
          "updatedAt"
        ]
      },
      "AuthClient": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. OAuth client identifier, stable and tenant-scoped."
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the application this client authenticates for. Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "description": "Registered redirect URIs for OAuth flows that support redirects. Each must be an absolute HTTPS URI in production."
          },
          "callbackUrls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "description": "Registered callback URLs for app-owned callbacks outside webhook subscriptions. Used by app integrations and inter-service callbacks."
          },
          "grantedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Permission slugs granted to this client. Each slug must exist in the platform or module permission catalogs. Example: events:read, results:write, applications:webhook:manage."
          },
          "serviceRoles": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "External service-role catalog names attached to this SERVICE IDENTITY (the Cognito app client), not the tenant. Stamped onto M2M access tokens by the pre-token Lambda from the DynamoDB mapping store. Vendor-created clients MUST NOT use system/admin — use the explicit catalog (e.g. contentWriter, sandboxVendor). Sandbox clients receive the pinned sandbox role set; omitted serviceRoles no longer default to system."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "retired"
            ],
            "description": "Lifecycle status of the auth client registration. Suspended clients cannot authenticate; retired clients are permanently deactivated.",
            "default": "active"
          },
          "authProviderRef": {
            "type": "string",
            "maxLength": 512,
            "description": "Opaque reference to auth subsystem client material (e.g. vault path or provider-issued handle). Write-only — never serialized on read responses. The auth seam owns issuing, storage, verification, rotation, and revocation of the underlying material.",
            "writeOnly": true
          },
          "jwksUri": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Optional public JWKS URI for clients that publish public keys for token verification."
          },
          "lastRotatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Managed timestamp set when the auth seam rotates the client credential reference. Null until first rotation."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "clientId",
          "applicationId",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "CredentialAuthorization": {
        "type": "object",
        "properties": {
          "authorizationId": {
            "type": "string",
            "format": "uuid",
            "description": "Composite-natural key leg after tenantId. Stable credential-authorization id."
          },
          "providerId": {
            "type": "string",
            "format": "uuid",
            "description": "Global toolProvider this grant belongs to.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "registrationId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional global toolRegistration. Null for sandbox quickstart grants that are not revision-pinned.",
            "x-references": "toolRegistration.id",
            "x-onDelete": "restrict"
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Tenant installation (application) the credential authenticates for.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "authClientId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Logical authClient this grant authorizes.",
            "x-references": "authClient.clientId",
            "x-onDelete": "restrict"
          },
          "mode": {
            "type": "string",
            "enum": [
              "sandbox",
              "live"
            ],
            "description": "Credential mode. Sandbox uses the pinned sandbox role set; live requires tenant-admin grant."
          },
          "effectivePermissions": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Effective module permissions after intersecting requested roles/scopes with registration revision ceiling and application approved scopes."
          },
          "effectiveRoles": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "External service-role catalog names stamped onto the Cognito mapping (never system/admin for vendor-created clients)."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "granted",
              "denied",
              "suspended",
              "expired",
              "superseded"
            ],
            "description": "Grant lifecycle. pending is pollable by the portal; granted enables token issuance; suspended/expired/superseded fail closed on issuance and audience validation.",
            "default": "pending"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional absolute expiry. When past, status is treated as expired for token/aud checks."
          },
          "reviewVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Installation review version captured at grant time.",
            "default": 1
          },
          "mappingVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonic authorization mapping version; increments on grant/deny/suspend/supersede.",
            "default": 1
          },
          "cognitoClientId": {
            "type": "string",
            "maxLength": 512,
            "description": "Cognito app client id mirrored into the DynamoDB mapping for hot-path checks."
          },
          "requestedRoles": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Caller-requested external service roles (ignored/rejected for sandbox; intersected for live)."
          },
          "requestedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Caller-requested scopes intersected with revision ceiling and application approved scopes."
          },
          "denialReason": {
            "type": "string",
            "maxLength": 1024,
            "description": "Optional reason when status=denied."
          },
          "grantedBy": {
            "type": "string",
            "maxLength": 512,
            "description": "Tenant-admin principal that granted a live credential (v1 tenant-wide)."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "authorizationId",
          "providerId",
          "applicationId",
          "authClientId",
          "mode",
          "effectivePermissions",
          "effectiveRoles",
          "status",
          "reviewVersion",
          "mappingVersion",
          "createdAt",
          "updatedAt"
        ]
      },
      "ProviderInvite": {
        "type": "object",
        "properties": {
          "inviteId": {
            "type": "string",
            "format": "uuid",
            "description": "Composite-natural key leg after tenantId. Stable invite id."
          },
          "providerId": {
            "type": "string",
            "format": "uuid",
            "description": "Global toolProvider the invite targets.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Invitee email. Matched at accept time against the calling principal's email when present."
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "developer"
            ],
            "description": "Role granted on accept."
          },
          "invitedBy": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Principal (Cognito sub) of the owner/admin who created the invite."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Invite expiry. Accept after this instant fails closed."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "accepted",
              "revoked",
              "expired"
            ],
            "description": "Invite lifecycle.",
            "default": "pending"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "inviteId",
          "providerId",
          "email",
          "role",
          "invitedBy",
          "expiresAt",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "ProviderMember": {
        "type": "object",
        "properties": {
          "memberId": {
            "type": "string",
            "format": "uuid",
            "description": "Composite-natural key leg after tenantId. Stable membership row id."
          },
          "providerId": {
            "type": "string",
            "format": "uuid",
            "description": "Global toolProvider this membership belongs to.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "principal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Portal Cognito sub (or equivalent stable subject). Unique per provider (with providerId); uniqueness is not tenant-qualified because toolProvider is global."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Member email for display and invite correlation. Not the auth primary key."
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "developer"
            ],
            "description": "Membership role. owner manages members; admin manages apps/credentials; developer is read + credential-request."
          },
          "status": {
            "type": "string",
            "enum": [
              "invited",
              "active",
              "removed"
            ],
            "description": "Membership lifecycle. Only active rows authorize provider mutations. remove sets removed (soft).",
            "default": "active"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "memberId",
          "providerId",
          "principal",
          "email",
          "role",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "ProviderOnboarding": {
        "type": "object",
        "properties": {
          "providerOnboardingId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable saga receipt id. Client-supplied; typically equal to operationId."
          },
          "operationId": {
            "type": "string",
            "format": "uuid",
            "description": "Durable client-supplied operation id. Replays with the same id converge to the same terminal state."
          },
          "stage": {
            "type": "string",
            "enum": [
              "accepted",
              "provider_created",
              "sandbox_tenant_provisioned",
              "sandbox_graph_created",
              "sandbox_credential_issued",
              "authorization_mapped",
              "completed",
              "failed",
              "compensating"
            ],
            "description": "Saga stage machine position. Advances after each successful store write.",
            "default": "accepted"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "completed",
              "failed",
              "replaced"
            ],
            "description": "Terminal-aware saga status. replaced means a prior uncertain client was retired and a replacement issued under a new receipt.",
            "default": "running"
          },
          "ownershipPrincipal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Portal membership subject that owns the provider after onboarding."
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Provider display name used when creating the toolProvider."
          },
          "verifiedContactEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Verified contact email for the provider."
          },
          "legalName": {
            "type": "string",
            "maxLength": 512,
            "description": "Optional legal entity name."
          },
          "toolProviderId": {
            "type": "string",
            "format": "uuid",
            "description": "Created/linked global toolProvider id (filled after provider_created)."
          },
          "sandboxTenantId": {
            "type": "string",
            "format": "uuid",
            "description": "Provisioned sandbox tenant id (filled after sandbox_tenant_provisioned)."
          },
          "publisherId": {
            "type": "string",
            "maxLength": 256,
            "description": "Sandbox-tenant publisher id."
          },
          "applicationId": {
            "type": "string",
            "maxLength": 256,
            "description": "Sandbox-tenant application (installation) id."
          },
          "authClientId": {
            "type": "string",
            "maxLength": 256,
            "description": "Logical sandbox authClient clientId."
          },
          "cognitoClientId": {
            "type": "string",
            "maxLength": 512,
            "description": "Cognito app client id bound to the sandbox credential."
          },
          "credentialAuthorizationId": {
            "type": "string",
            "format": "uuid",
            "description": "Durable credentialAuthorization row id for the sandbox grant."
          },
          "responseReceiptId": {
            "type": "string",
            "format": "uuid",
            "description": "Protected response receipt id. Client secret is returnable only while this receipt exists."
          },
          "lastError": {
            "type": "string",
            "maxLength": 2048,
            "description": "Last failure detail when status=failed or during compensation."
          },
          "seedContract": {
            "type": "object",
            "properties": {
              "orgSourcedId": {
                "type": "string"
              },
              "teacherSourcedId": {
                "type": "string"
              },
              "studentSourcedId": {
                "type": "string"
              },
              "contentId": {
                "type": "string",
                "format": "uuid"
              }
            },
            "description": "Portal-pinned sandbox quickstart fixture ids echoed from E3 provisionSandboxTenant.",
            "additionalProperties": false
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "providerOnboardingId",
          "operationId",
          "stage",
          "status",
          "ownershipPrincipal",
          "displayName",
          "verifiedContactEmail",
          "createdAt",
          "updatedAt"
        ]
      },
      "Publisher": {
        "type": "object",
        "properties": {
          "publisherId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Stable identifier for this publisher within the tenant."
          },
          "toolProviderId": {
            "type": "string",
            "format": "uuid",
            "description": "Nullable FK to the global toolProvider. Set for vendor-linked publishers after backfill; null for purely tenant-local / non-vendor publisher rows.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Human-readable name of the publisher shown in administrative and marketplace surfaces. Compatibility mirror when toolProviderId is set — global toolProvider.displayName is authoritative for vendor identity."
          },
          "legalName": {
            "type": "string",
            "maxLength": 512,
            "description": "Legal entity name for contractual and compliance display purposes."
          },
          "ownerOrgSourcedId": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional FK to the OneRoster organization when the publisher is a tenant org. Uses the composite (tenantId, sourcedId) cross-module FK shape.",
            "x-references": "oneroster:org.sourcedId",
            "x-onDelete": "restrict"
          },
          "contactEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Administrative contact email for the publisher. Not student-facing data."
          },
          "supportUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Publisher support page URL for administrators and end-users."
          },
          "privacyUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Publisher privacy policy URL displayed during consent and review flows."
          },
          "termsUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Publisher terms-of-service URL displayed during consent and review flows."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "suspended",
              "retired"
            ],
            "description": "Lifecycle status of the publisher registration. Draft publishers are not visible to application discovery.",
            "default": "draft"
          },
          "sandbox": {
            "type": "boolean",
            "description": "When true, the publisher and all its applications operate in sandbox isolation — writes do not affect production data.",
            "default": false
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "publisherId",
          "displayName",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "RendererCapability": {
        "type": "object",
        "properties": {
          "rendererRef": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Stable identifier for this renderer capability within the tenant, referenced by curriculum.courseComponent.rendererRef."
          },
          "applicationId": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional intra-module FK to the application that supplies this renderer. A renderer may or may not be provided by a registered application. Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Human-readable renderer name shown to admins and authoring tools for renderer selection and configuration."
          },
          "acceptedContentKinds": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "minItems": 1,
            "description": "Array of governed content-kind enum values this renderer can handle. Used by curriculum at write time to validate renderer/content-kind compatibility. Values are registry strings governed by the content module, not DB FKs, to keep the import graph acyclic."
          },
          "integrationProtocol": {
            "type": "string",
            "enum": [
              "alpha_embed",
              "lti_launch_ref",
              "external_link"
            ],
            "description": "How the renderer integrates with the platform delivery surface. alpha_embed uses the platform iframe embed protocol; lti_launch_ref stores an LTI launch reference; external_link opens a direct URL in a new context."
          },
          "integrationEndpoint": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Registered launch or render endpoint URL. The platform delivery surface calls this URL according to the integrationProtocol when rendering content that names this rendererRef."
          },
          "playgroundUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Optional URL for admin validation and author/test preview of the renderer outside production delivery."
          },
          "lifecycleState": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "deprecated",
              "retired"
            ],
            "description": "Lifecycle state of the renderer capability registration. Draft renderers are not available for curriculum delivery; deprecated renderers serve existing references but cannot be newly assigned; retired renderers are fully disabled.",
            "default": "draft"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "rendererRef",
          "displayName",
          "acceptedContentKinds",
          "integrationProtocol",
          "integrationEndpoint",
          "lifecycleState",
          "createdAt",
          "updatedAt"
        ]
      },
      "ToolProvider": {
        "type": "object",
        "properties": {
          "toolProviderId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable global provider identifier. Client-supplied so seed/backfill migrations can pin deterministic ids."
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Human-readable vendor name shown in portal and catalog surfaces."
          },
          "legalName": {
            "type": "string",
            "maxLength": 512,
            "description": "Legal entity name for contractual and compliance display."
          },
          "verifiedContactEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Verified administrative contact email for the provider. Restricted metadata."
          },
          "supportUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Provider support URL."
          },
          "privacyUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Provider privacy policy URL."
          },
          "termsUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Provider terms-of-service URL."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "suspended",
              "retired"
            ],
            "description": "Provider lifecycle. Emergency suspension denies new credentials/launches/tokens via the installation eligibility rule.",
            "default": "draft"
          },
          "ownershipPrincipal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Stable ownership principal id (portal membership subject or operator id). Ownership transfer is operator-only."
          },
          "sandboxTenantId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional dedicated sandbox tenant id for this provider (filled by E3 sandbox provisioning)."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "toolProviderId",
          "displayName",
          "status",
          "verifiedContactEmail",
          "ownershipPrincipal",
          "createdAt",
          "updatedAt"
        ]
      },
      "ToolRegistration": {
        "type": "object",
        "properties": {
          "toolRegistrationId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable global registration identifier. Client-supplied for deterministic seed/backfill."
          },
          "toolProviderId": {
            "type": "string",
            "format": "uuid",
            "description": "Owning global toolProvider.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Canonical registration name (global catalog authority for vendor installations)."
          },
          "displayName": {
            "type": "string",
            "maxLength": 512,
            "description": "Human-readable display name. Authority for vendor_installation display; local application.displayName is a deprecated mirror."
          },
          "attribution": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "maxLength": 256
              },
              "logoUri": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "homepageUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "privacyUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "termsUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "category": {
                "type": "string",
                "maxLength": 256
              }
            },
            "description": "Display attribution metadata (label, logo, URLs, category). Authority for vendor_installation; local application.attribution is a deprecated mirror."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "suspended",
              "retired"
            ],
            "description": "Registration lifecycle. Suspension feeds the shared installation eligibility rule.",
            "default": "draft"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "toolRegistrationId",
          "toolProviderId",
          "name",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "ToolRegistrationRevision": {
        "type": "object",
        "properties": {
          "toolRegistrationRevisionId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable revision identifier. Client-supplied for deterministic seed/backfill."
          },
          "toolRegistrationId": {
            "type": "string",
            "format": "uuid",
            "description": "Parent global toolRegistration.",
            "x-references": "toolRegistration.id",
            "x-onDelete": "restrict"
          },
          "revisionNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonic revision number within the registration."
          },
          "status": {
            "type": "string",
            "enum": [
              "published",
              "retired",
              "suspended"
            ],
            "description": "Revision lifecycle. Emergency suspended denies use via the shared eligibility rule.",
            "default": "published"
          },
          "oidcInitiationUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "OIDC login initiation URL for this revision."
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "minItems": 1,
            "description": "Exact redirect-URI set for this revision."
          },
          "jwksUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Tool JWKS URL for this revision."
          },
          "targetLinkUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "minItems": 1,
            "description": "Approved target-link URI set (default + exact variants). Used later by deferred LTI resource links."
          },
          "requestedScopeCeiling": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Maximum scopes this revision may request. Issuance intersects with application.approvedScopes."
          },
          "configSchema": {
            "type": "object",
            "description": "Optional JSON Schema / config document describing vendor config for this revision.",
            "additionalProperties": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "toolRegistrationRevisionId",
          "toolRegistrationId",
          "revisionNumber",
          "status",
          "oidcInitiationUrl",
          "redirectUris",
          "jwksUrl",
          "targetLinkUris",
          "requestedScopeCeiling",
          "createdAt",
          "updatedAt"
        ]
      },
      "WebhookDeliveryReceipt": {
        "type": "object",
        "properties": {
          "deliveryId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Server-generated or deterministic delivery identifier for this delivery attempt sequence."
          },
          "endpointId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the webhook endpoint this delivery targets. Composite shape (tenantId, endpointId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "webhookEndpoint.endpointId",
            "x-onDelete": "restrict"
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Denormalized application identity from the endpoint for audit attribution and list filtering without joining through webhookEndpoint.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "eventId": {
            "type": "string",
            "maxLength": 256,
            "description": "Event identity — the unique identifier of the specific event instance being delivered."
          },
          "eventType": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Governed event type slug of the delivered event (e.g. results.lineItem.created). Matches the subscription vocabulary in webhookEndpoint.subscriptions."
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "delivered",
              "retrying",
              "failed",
              "exhausted"
            ],
            "description": "Delivery lifecycle status. Queued when created, delivered on 2xx, retrying on transient failure, failed on permanent failure, exhausted when retry policy limits are reached.",
            "default": "queued"
          },
          "attemptCount": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of delivery attempts made for this receipt. Incremented on each HTTP POST attempt to the callback URL.",
            "default": 0
          },
          "lastAttemptAt": {
            "type": "string",
            "format": "date-time",
            "description": "Managed timestamp of the most recent delivery attempt. Null until first attempt.",
            "readOnly": true
          },
          "nextRetryAt": {
            "type": "string",
            "format": "date-time",
            "description": "Scheduled timestamp for the next retry attempt. Null when status is delivered, failed, or exhausted. Set by the retry policy backoff calculation."
          },
          "lastResponseStatus": {
            "type": "integer",
            "minimum": 100,
            "maximum": 599,
            "description": "Last HTTP status code received from the endpoint, if an attempt reached the callback URL. Null when no response was received (connection timeout, DNS failure)."
          },
          "lastErrorCode": {
            "type": "string",
            "maxLength": 256,
            "description": "Bounded diagnostic error code for the last failed attempt (e.g. connection_timeout, dns_failure, tls_error, http_5xx). Never the full response body or payload."
          },
          "payloadHash": {
            "type": "string",
            "maxLength": 128,
            "description": "Opaque integrity hash of the delivered payload for audit and reconciliation. Not a crypto design — just a diagnostic for verifying payload consistency across retries."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "deliveryId",
          "endpointId",
          "applicationId",
          "eventType",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "endpointId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Stable identifier for this webhook endpoint within the tenant."
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the application that owns this webhook subscription. Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "clientId": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional intra-module FK to the auth client that owns this subscription. When present, deliveries are authenticated via this client's credentials. Composite shape (tenantId, clientId) — tenantId leg is implicit.",
            "x-references": "authClient.clientId",
            "x-onDelete": "restrict"
          },
          "callbackUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "HTTPS URL registered for signed POST delivery. Must be an absolute HTTPS URI in production. When clientId is present, must be one of the registered callback URLs on that auth client."
          },
          "subscriptions": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 256
            },
            "description": "Array of governed event type slugs this endpoint subscribes to. Uses platform-wide event slug vocabulary without FKing into every event-producing module."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_verification",
              "active",
              "paused",
              "failed",
              "retired"
            ],
            "description": "Lifecycle status of the webhook endpoint. Starts as pending_verification until a test delivery succeeds. Active endpoints receive signed deliveries. Paused endpoints are temporarily silenced. Failed endpoints have exceeded retry thresholds. Retired endpoints are permanently deactivated.",
            "default": "pending_verification"
          },
          "signingMaterialRef": {
            "type": "string",
            "maxLength": 512,
            "description": "Opaque auth-subsystem reference to the signing material used for delivery signatures (e.g. HMAC shared secret or asymmetric key handle). Write-only — never serialized on read responses. The auth seam owns issuing and rotation of the actual signing material.",
            "writeOnly": true
          },
          "grantedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Permission slugs required for deliveries to this endpoint. Each slug constrains what event data the endpoint may receive."
          },
          "retryPolicyRef": {
            "type": "string",
            "maxLength": 256,
            "description": "Policy key or reference for retry limits, backoff, timeout, and abandonment thresholds. May resolve to a platform default, tenant policy, or endpoint-level inline config."
          },
          "lastVerifiedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Managed timestamp set when a verification or test delivery succeeds. Null until first successful verification."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "endpointId",
          "applicationId",
          "callbackUrl",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "CreateAppCredentialRequest": {
        "type": "object",
        "description": "Create-AppCredential request body (readOnly/server-managed fields excluded).",
        "required": [
          "studentSourcedId",
          "applicationId",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "studentSourcedId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Cross-module FK to oneroster:user.sourcedId identifying the student this credential is issued to. Part of the composite-natural key (tenantId, studentSourcedId, applicationId). Uses composite (tenantId, sourcedId) cross-module FK shape.",
            "x-references": "oneroster:user.sourcedId",
            "x-onDelete": "restrict"
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the application this credential grants access to. Part of the composite-natural key (tenantId, studentSourcedId, applicationId). Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "secretRef": {
            "type": "string",
            "maxLength": 512,
            "description": "Opaque managed reference to the credential secret material (e.g. vault://tenant/app-cred/...). Write-only — never serialized on read responses. The auth seam owns issuing, rotation, and revocation of the underlying secret value. This is the rule: secrets never become schema fields.",
            "writeOnly": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "rotated",
              "revoked"
            ],
            "description": "Lifecycle status of the app credential. Active credentials can authenticate; rotated credentials have been superseded by a new secret; revoked credentials are permanently invalidated.",
            "default": "active"
          },
          "lastRotatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Managed timestamp set by rotateAppCredential. Null until first rotation."
          },
          "revokedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Managed timestamp set when the credential is revoked. Null while credential is active or rotated."
          }
        }
      },
      "UpdateAppCredentialRequest": {
        "type": "object",
        "description": "Update-AppCredential request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "secretRef": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Opaque managed reference to the credential secret material (e.g. vault://tenant/app-cred/...). Write-only — never serialized on read responses. The auth seam owns issuing, rotation, and revocation of the underlying secret value. This is the rule: secrets never become schema fields.",
            "writeOnly": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "rotated",
              "revoked"
            ],
            "description": "Lifecycle status of the app credential. Active credentials can authenticate; rotated credentials have been superseded by a new secret; revoked credentials are permanently invalidated.",
            "default": "active"
          },
          "lastRotatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Managed timestamp set by rotateAppCredential. Null until first rotation."
          },
          "revokedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Managed timestamp set when the credential is revoked. Null while credential is active or rotated."
          }
        }
      },
      "CreateApplicationRequest": {
        "type": "object",
        "description": "Create-Application request body (readOnly/server-managed fields excluded).",
        "required": [
          "applicationId",
          "publisherId",
          "name",
          "ownerKind",
          "status",
          "sandboxMode"
        ],
        "additionalProperties": false,
        "properties": {
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Stable identifier for this application within the tenant."
          },
          "publisherId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the publisher that owns this application. Composite shape (tenantId, publisherId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "publisher.publisherId",
            "x-onDelete": "restrict"
          },
          "kind": {
            "type": "string",
            "enum": [
              "vendor_installation",
              "tenant_org",
              "platform_internal"
            ],
            "description": "Installation kind. Only vendor_installation carries a registrationRevisionId pin; tenant_org/platform_internal keep NULL revision and local semantics. When omitted on write, hooks derive from ownerKind (publisher→vendor_installation)."
          },
          "registrationRevisionId": {
            "type": "string",
            "format": "uuid",
            "description": "Nullable tenant→global FK pinning the immutable toolRegistrationRevision this tenant approved. Required for vendor_installation; MUST be null for tenant_org/platform_internal.",
            "x-references": "toolRegistrationRevision.id",
            "x-onDelete": "restrict"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Canonical application name. Authority for tenant_org/platform_internal; deprecated mirror for vendor_installation (global toolRegistration.name wins)."
          },
          "displayName": {
            "type": "string",
            "maxLength": 512,
            "description": "Human-readable name. Authority for tenant_org/platform_internal; deprecated mirror for vendor_installation (global toolRegistration.displayName wins)."
          },
          "owningOrgSourcedId": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional cross-module FK to the OneRoster organization that owns this application. Required when ownerKind/kind is tenant_org. Uses the composite (tenantId, sourcedId) cross-module FK shape.",
            "x-references": "oneroster:org.sourcedId",
            "x-onDelete": "restrict"
          },
          "ownerKind": {
            "type": "string",
            "enum": [
              "publisher",
              "tenant_org",
              "platform_internal"
            ],
            "description": "COMPATIBILITY/DEPRECATED alias for ownership discriminator. Prefer `kind`. Mapping: publisher↔vendor_installation, tenant_org↔tenant_org, platform_internal↔platform_internal."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "pending_review",
              "active",
              "suspended",
              "retired"
            ],
            "description": "Operational lifecycle of the installation. Approval state (revision pin / reviewVersion) is separate from operational state.",
            "default": "draft"
          },
          "sandboxMode": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ],
            "description": "Operating mode of the application. Sandbox applications write only to isolated sandbox data; production applications interact with live tenant data.",
            "default": "sandbox"
          },
          "attribution": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "maxLength": 256,
                "description": "Short display label shown in attribution badges and consent prompts."
              },
              "logoUri": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "URI to the application logo for attribution display."
              },
              "homepageUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "Application homepage URL shown in discovery and consent surfaces."
              },
              "privacyUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "Application privacy policy URL displayed during consent and review flows."
              },
              "termsUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "Application terms-of-service URL displayed during consent and review flows."
              },
              "category": {
                "type": "string",
                "maxLength": 256,
                "description": "App category for discovery and classification in the tenant application catalog (e.g. gradebook, assessment, lms, communication)."
              }
            },
            "description": "Display attribution. Authority for tenant_org/platform_internal; deprecated mirror for vendor_installation (global toolRegistration.attribution wins)."
          },
          "allowedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "DEPRECATED mirror of approvedScopes for pre-E2 clients. Authority: application.approvedScopes (intersected with revision.requestedScopeCeiling for vendor_installation); local allowedScopes remains authority only for tenant_org/platform_internal when approvedScopes is empty."
          },
          "approvedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Scopes this tenant approved for the installation. For vendor_installation, effective scopes = approvedScopes ∩ pinned revision.requestedScopeCeiling."
          },
          "approverId": {
            "type": "string",
            "maxLength": 256,
            "description": "Principal id of the tenant administrator who approved the pinned revision / grant."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional grant expiry. Past expiresAt fails the shared eligibility rule."
          },
          "reviewVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonic review counter incremented on each tenant approval of a revision pin."
          },
          "tenantSuspended": {
            "type": "boolean",
            "description": "Independent tenant-side suspension flag. Revision/provider changes cannot clear this; evaluated by the shared eligibility rule.",
            "default": false
          }
        }
      },
      "UpdateApplicationRequest": {
        "type": "object",
        "description": "Update-Application request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "publisherId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the publisher that owns this application. Composite shape (tenantId, publisherId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "publisher.publisherId",
            "x-onDelete": "restrict"
          },
          "kind": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "vendor_installation",
              "tenant_org",
              "platform_internal",
              null
            ],
            "description": "Installation kind. Only vendor_installation carries a registrationRevisionId pin; tenant_org/platform_internal keep NULL revision and local semantics. When omitted on write, hooks derive from ownerKind (publisher→vendor_installation)."
          },
          "registrationRevisionId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Nullable tenant→global FK pinning the immutable toolRegistrationRevision this tenant approved. Required for vendor_installation; MUST be null for tenant_org/platform_internal.",
            "x-references": "toolRegistrationRevision.id",
            "x-onDelete": "restrict"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Canonical application name. Authority for tenant_org/platform_internal; deprecated mirror for vendor_installation (global toolRegistration.name wins)."
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Human-readable name. Authority for tenant_org/platform_internal; deprecated mirror for vendor_installation (global toolRegistration.displayName wins)."
          },
          "owningOrgSourcedId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 256,
            "description": "Optional cross-module FK to the OneRoster organization that owns this application. Required when ownerKind/kind is tenant_org. Uses the composite (tenantId, sourcedId) cross-module FK shape.",
            "x-references": "oneroster:org.sourcedId",
            "x-onDelete": "restrict"
          },
          "ownerKind": {
            "type": "string",
            "enum": [
              "publisher",
              "tenant_org",
              "platform_internal"
            ],
            "description": "COMPATIBILITY/DEPRECATED alias for ownership discriminator. Prefer `kind`. Mapping: publisher↔vendor_installation, tenant_org↔tenant_org, platform_internal↔platform_internal."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "pending_review",
              "active",
              "suspended",
              "retired"
            ],
            "description": "Operational lifecycle of the installation. Approval state (revision pin / reviewVersion) is separate from operational state.",
            "default": "draft"
          },
          "sandboxMode": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ],
            "description": "Operating mode of the application. Sandbox applications write only to isolated sandbox data; production applications interact with live tenant data.",
            "default": "sandbox"
          },
          "attribution": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "label": {
                "type": "string",
                "maxLength": 256,
                "description": "Short display label shown in attribution badges and consent prompts."
              },
              "logoUri": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "URI to the application logo for attribution display."
              },
              "homepageUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "Application homepage URL shown in discovery and consent surfaces."
              },
              "privacyUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "Application privacy policy URL displayed during consent and review flows."
              },
              "termsUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048,
                "description": "Application terms-of-service URL displayed during consent and review flows."
              },
              "category": {
                "type": "string",
                "maxLength": 256,
                "description": "App category for discovery and classification in the tenant application catalog (e.g. gradebook, assessment, lms, communication)."
              }
            },
            "description": "Display attribution. Authority for tenant_org/platform_internal; deprecated mirror for vendor_installation (global toolRegistration.attribution wins)."
          },
          "allowedScopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "DEPRECATED mirror of approvedScopes for pre-E2 clients. Authority: application.approvedScopes (intersected with revision.requestedScopeCeiling for vendor_installation); local allowedScopes remains authority only for tenant_org/platform_internal when approvedScopes is empty."
          },
          "approvedScopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Scopes this tenant approved for the installation. For vendor_installation, effective scopes = approvedScopes ∩ pinned revision.requestedScopeCeiling."
          },
          "approverId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 256,
            "description": "Principal id of the tenant administrator who approved the pinned revision / grant."
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Optional grant expiry. Past expiresAt fails the shared eligibility rule."
          },
          "reviewVersion": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "description": "Monotonic review counter incremented on each tenant approval of a revision pin."
          },
          "tenantSuspended": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Independent tenant-side suspension flag. Revision/provider changes cannot clear this; evaluated by the shared eligibility rule.",
            "default": false
          }
        }
      },
      "CreateAuthClientRequest": {
        "type": "object",
        "description": "Create-AuthClient request body (readOnly/server-managed fields excluded).",
        "required": [
          "clientId",
          "applicationId",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "clientId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. OAuth client identifier, stable and tenant-scoped."
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the application this client authenticates for. Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "description": "Registered redirect URIs for OAuth flows that support redirects. Each must be an absolute HTTPS URI in production."
          },
          "callbackUrls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "description": "Registered callback URLs for app-owned callbacks outside webhook subscriptions. Used by app integrations and inter-service callbacks."
          },
          "grantedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Permission slugs granted to this client. Each slug must exist in the platform or module permission catalogs. Example: events:read, results:write, applications:webhook:manage."
          },
          "serviceRoles": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "External service-role catalog names attached to this SERVICE IDENTITY (the Cognito app client), not the tenant. Stamped onto M2M access tokens by the pre-token Lambda from the DynamoDB mapping store. Vendor-created clients MUST NOT use system/admin — use the explicit catalog (e.g. contentWriter, sandboxVendor). Sandbox clients receive the pinned sandbox role set; omitted serviceRoles no longer default to system."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "retired"
            ],
            "description": "Lifecycle status of the auth client registration. Suspended clients cannot authenticate; retired clients are permanently deactivated.",
            "default": "active"
          },
          "authProviderRef": {
            "type": "string",
            "maxLength": 512,
            "description": "Opaque reference to auth subsystem client material (e.g. vault path or provider-issued handle). Write-only — never serialized on read responses. The auth seam owns issuing, storage, verification, rotation, and revocation of the underlying material.",
            "writeOnly": true
          },
          "jwksUri": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Optional public JWKS URI for clients that publish public keys for token verification."
          },
          "lastRotatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Managed timestamp set when the auth seam rotates the client credential reference. Null until first rotation."
          }
        }
      },
      "UpdateAuthClientRequest": {
        "type": "object",
        "description": "Update-AuthClient request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the application this client authenticates for. Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "redirectUris": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "description": "Registered redirect URIs for OAuth flows that support redirects. Each must be an absolute HTTPS URI in production."
          },
          "callbackUrls": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "description": "Registered callback URLs for app-owned callbacks outside webhook subscriptions. Used by app integrations and inter-service callbacks."
          },
          "grantedScopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Permission slugs granted to this client. Each slug must exist in the platform or module permission catalogs. Example: events:read, results:write, applications:webhook:manage."
          },
          "serviceRoles": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "External service-role catalog names attached to this SERVICE IDENTITY (the Cognito app client), not the tenant. Stamped onto M2M access tokens by the pre-token Lambda from the DynamoDB mapping store. Vendor-created clients MUST NOT use system/admin — use the explicit catalog (e.g. contentWriter, sandboxVendor). Sandbox clients receive the pinned sandbox role set; omitted serviceRoles no longer default to system."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "retired"
            ],
            "description": "Lifecycle status of the auth client registration. Suspended clients cannot authenticate; retired clients are permanently deactivated.",
            "default": "active"
          },
          "authProviderRef": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Opaque reference to auth subsystem client material (e.g. vault path or provider-issued handle). Write-only — never serialized on read responses. The auth seam owns issuing, storage, verification, rotation, and revocation of the underlying material.",
            "writeOnly": true
          },
          "jwksUri": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 2048,
            "description": "Optional public JWKS URI for clients that publish public keys for token verification."
          },
          "lastRotatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Managed timestamp set when the auth seam rotates the client credential reference. Null until first rotation."
          }
        }
      },
      "CreateCredentialAuthorizationRequest": {
        "type": "object",
        "description": "Create-CredentialAuthorization request body (readOnly/server-managed fields excluded).",
        "required": [
          "authorizationId",
          "providerId",
          "applicationId",
          "authClientId",
          "mode",
          "effectivePermissions",
          "effectiveRoles",
          "status",
          "reviewVersion",
          "mappingVersion"
        ],
        "additionalProperties": false,
        "properties": {
          "authorizationId": {
            "type": "string",
            "format": "uuid",
            "description": "Composite-natural key leg after tenantId. Stable credential-authorization id."
          },
          "providerId": {
            "type": "string",
            "format": "uuid",
            "description": "Global toolProvider this grant belongs to.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "registrationId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional global toolRegistration. Null for sandbox quickstart grants that are not revision-pinned.",
            "x-references": "toolRegistration.id",
            "x-onDelete": "restrict"
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Tenant installation (application) the credential authenticates for.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "authClientId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Logical authClient this grant authorizes.",
            "x-references": "authClient.clientId",
            "x-onDelete": "restrict"
          },
          "mode": {
            "type": "string",
            "enum": [
              "sandbox",
              "live"
            ],
            "description": "Credential mode. Sandbox uses the pinned sandbox role set; live requires tenant-admin grant."
          },
          "effectivePermissions": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Effective module permissions after intersecting requested roles/scopes with registration revision ceiling and application approved scopes."
          },
          "effectiveRoles": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "External service-role catalog names stamped onto the Cognito mapping (never system/admin for vendor-created clients)."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "granted",
              "denied",
              "suspended",
              "expired",
              "superseded"
            ],
            "description": "Grant lifecycle. pending is pollable by the portal; granted enables token issuance; suspended/expired/superseded fail closed on issuance and audience validation.",
            "default": "pending"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional absolute expiry. When past, status is treated as expired for token/aud checks."
          },
          "reviewVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Installation review version captured at grant time.",
            "default": 1
          },
          "mappingVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonic authorization mapping version; increments on grant/deny/suspend/supersede.",
            "default": 1
          },
          "cognitoClientId": {
            "type": "string",
            "maxLength": 512,
            "description": "Cognito app client id mirrored into the DynamoDB mapping for hot-path checks."
          },
          "requestedRoles": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Caller-requested external service roles (ignored/rejected for sandbox; intersected for live)."
          },
          "requestedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Caller-requested scopes intersected with revision ceiling and application approved scopes."
          },
          "denialReason": {
            "type": "string",
            "maxLength": 1024,
            "description": "Optional reason when status=denied."
          },
          "grantedBy": {
            "type": "string",
            "maxLength": 512,
            "description": "Tenant-admin principal that granted a live credential (v1 tenant-wide)."
          }
        }
      },
      "UpdateCredentialAuthorizationRequest": {
        "type": "object",
        "description": "Update-CredentialAuthorization request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "registrationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Optional global toolRegistration. Null for sandbox quickstart grants that are not revision-pinned.",
            "x-references": "toolRegistration.id",
            "x-onDelete": "restrict"
          },
          "effectivePermissions": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Effective module permissions after intersecting requested roles/scopes with registration revision ceiling and application approved scopes."
          },
          "effectiveRoles": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "External service-role catalog names stamped onto the Cognito mapping (never system/admin for vendor-created clients)."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "granted",
              "denied",
              "suspended",
              "expired",
              "superseded"
            ],
            "description": "Grant lifecycle. pending is pollable by the portal; granted enables token issuance; suspended/expired/superseded fail closed on issuance and audience validation.",
            "default": "pending"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Optional absolute expiry. When past, status is treated as expired for token/aud checks."
          },
          "reviewVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Installation review version captured at grant time.",
            "default": 1
          },
          "mappingVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonic authorization mapping version; increments on grant/deny/suspend/supersede.",
            "default": 1
          },
          "cognitoClientId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Cognito app client id mirrored into the DynamoDB mapping for hot-path checks."
          },
          "requestedRoles": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Caller-requested external service roles (ignored/rejected for sandbox; intersected for live)."
          },
          "requestedScopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Caller-requested scopes intersected with revision ceiling and application approved scopes."
          },
          "denialReason": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1024,
            "description": "Optional reason when status=denied."
          },
          "grantedBy": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Tenant-admin principal that granted a live credential (v1 tenant-wide)."
          }
        }
      },
      "CreateProviderInviteRequest": {
        "type": "object",
        "description": "Create-ProviderInvite request body (readOnly/server-managed fields excluded).",
        "required": [
          "inviteId",
          "providerId",
          "email",
          "role",
          "invitedBy",
          "expiresAt",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "inviteId": {
            "type": "string",
            "format": "uuid",
            "description": "Composite-natural key leg after tenantId. Stable invite id."
          },
          "providerId": {
            "type": "string",
            "format": "uuid",
            "description": "Global toolProvider the invite targets.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Invitee email. Matched at accept time against the calling principal's email when present."
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "developer"
            ],
            "description": "Role granted on accept."
          },
          "invitedBy": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Principal (Cognito sub) of the owner/admin who created the invite."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Invite expiry. Accept after this instant fails closed."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "accepted",
              "revoked",
              "expired"
            ],
            "description": "Invite lifecycle.",
            "default": "pending"
          }
        }
      },
      "UpdateProviderInviteRequest": {
        "type": "object",
        "description": "Update-ProviderInvite request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Invitee email. Matched at accept time against the calling principal's email when present."
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "developer"
            ],
            "description": "Role granted on accept."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Invite expiry. Accept after this instant fails closed."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "accepted",
              "revoked",
              "expired"
            ],
            "description": "Invite lifecycle.",
            "default": "pending"
          }
        }
      },
      "CreateProviderMemberRequest": {
        "type": "object",
        "description": "Create-ProviderMember request body (readOnly/server-managed fields excluded).",
        "required": [
          "memberId",
          "providerId",
          "principal",
          "email",
          "role",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "memberId": {
            "type": "string",
            "format": "uuid",
            "description": "Composite-natural key leg after tenantId. Stable membership row id."
          },
          "providerId": {
            "type": "string",
            "format": "uuid",
            "description": "Global toolProvider this membership belongs to.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "principal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Portal Cognito sub (or equivalent stable subject). Unique per provider (with providerId); uniqueness is not tenant-qualified because toolProvider is global."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Member email for display and invite correlation. Not the auth primary key."
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "developer"
            ],
            "description": "Membership role. owner manages members; admin manages apps/credentials; developer is read + credential-request."
          },
          "status": {
            "type": "string",
            "enum": [
              "invited",
              "active",
              "removed"
            ],
            "description": "Membership lifecycle. Only active rows authorize provider mutations. remove sets removed (soft).",
            "default": "active"
          }
        }
      },
      "UpdateProviderMemberRequest": {
        "type": "object",
        "description": "Update-ProviderMember request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "principal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Portal Cognito sub (or equivalent stable subject). Unique per provider (with providerId); uniqueness is not tenant-qualified because toolProvider is global."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Member email for display and invite correlation. Not the auth primary key."
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "developer"
            ],
            "description": "Membership role. owner manages members; admin manages apps/credentials; developer is read + credential-request."
          },
          "status": {
            "type": "string",
            "enum": [
              "invited",
              "active",
              "removed"
            ],
            "description": "Membership lifecycle. Only active rows authorize provider mutations. remove sets removed (soft).",
            "default": "active"
          }
        }
      },
      "CreateProviderOnboardingRequest": {
        "type": "object",
        "description": "Create-ProviderOnboarding request body (readOnly/server-managed fields excluded).",
        "required": [
          "providerOnboardingId",
          "operationId",
          "stage",
          "status",
          "ownershipPrincipal",
          "displayName",
          "verifiedContactEmail"
        ],
        "additionalProperties": false,
        "properties": {
          "providerOnboardingId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable saga receipt id. Client-supplied; typically equal to operationId."
          },
          "operationId": {
            "type": "string",
            "format": "uuid",
            "description": "Durable client-supplied operation id. Replays with the same id converge to the same terminal state."
          },
          "stage": {
            "type": "string",
            "enum": [
              "accepted",
              "provider_created",
              "sandbox_tenant_provisioned",
              "sandbox_graph_created",
              "sandbox_credential_issued",
              "authorization_mapped",
              "completed",
              "failed",
              "compensating"
            ],
            "description": "Saga stage machine position. Advances after each successful store write.",
            "default": "accepted"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "completed",
              "failed",
              "replaced"
            ],
            "description": "Terminal-aware saga status. replaced means a prior uncertain client was retired and a replacement issued under a new receipt.",
            "default": "running"
          },
          "ownershipPrincipal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Portal membership subject that owns the provider after onboarding."
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Provider display name used when creating the toolProvider."
          },
          "verifiedContactEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Verified contact email for the provider."
          },
          "legalName": {
            "type": "string",
            "maxLength": 512,
            "description": "Optional legal entity name."
          },
          "toolProviderId": {
            "type": "string",
            "format": "uuid",
            "description": "Created/linked global toolProvider id (filled after provider_created)."
          },
          "sandboxTenantId": {
            "type": "string",
            "format": "uuid",
            "description": "Provisioned sandbox tenant id (filled after sandbox_tenant_provisioned)."
          },
          "publisherId": {
            "type": "string",
            "maxLength": 256,
            "description": "Sandbox-tenant publisher id."
          },
          "applicationId": {
            "type": "string",
            "maxLength": 256,
            "description": "Sandbox-tenant application (installation) id."
          },
          "authClientId": {
            "type": "string",
            "maxLength": 256,
            "description": "Logical sandbox authClient clientId."
          },
          "cognitoClientId": {
            "type": "string",
            "maxLength": 512,
            "description": "Cognito app client id bound to the sandbox credential."
          },
          "credentialAuthorizationId": {
            "type": "string",
            "format": "uuid",
            "description": "Durable credentialAuthorization row id for the sandbox grant."
          },
          "responseReceiptId": {
            "type": "string",
            "format": "uuid",
            "description": "Protected response receipt id. Client secret is returnable only while this receipt exists."
          },
          "lastError": {
            "type": "string",
            "maxLength": 2048,
            "description": "Last failure detail when status=failed or during compensation."
          },
          "seedContract": {
            "type": "object",
            "properties": {
              "orgSourcedId": {
                "type": "string"
              },
              "teacherSourcedId": {
                "type": "string"
              },
              "studentSourcedId": {
                "type": "string"
              },
              "contentId": {
                "type": "string",
                "format": "uuid"
              }
            },
            "description": "Portal-pinned sandbox quickstart fixture ids echoed from E3 provisionSandboxTenant.",
            "additionalProperties": false
          }
        }
      },
      "UpdateProviderOnboardingRequest": {
        "type": "object",
        "description": "Update-ProviderOnboarding request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "stage": {
            "type": "string",
            "enum": [
              "accepted",
              "provider_created",
              "sandbox_tenant_provisioned",
              "sandbox_graph_created",
              "sandbox_credential_issued",
              "authorization_mapped",
              "completed",
              "failed",
              "compensating"
            ],
            "description": "Saga stage machine position. Advances after each successful store write.",
            "default": "accepted"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "completed",
              "failed",
              "replaced"
            ],
            "description": "Terminal-aware saga status. replaced means a prior uncertain client was retired and a replacement issued under a new receipt.",
            "default": "running"
          },
          "ownershipPrincipal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Portal membership subject that owns the provider after onboarding."
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Provider display name used when creating the toolProvider."
          },
          "verifiedContactEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Verified contact email for the provider."
          },
          "legalName": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Optional legal entity name."
          },
          "toolProviderId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Created/linked global toolProvider id (filled after provider_created)."
          },
          "sandboxTenantId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Provisioned sandbox tenant id (filled after sandbox_tenant_provisioned)."
          },
          "publisherId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 256,
            "description": "Sandbox-tenant publisher id."
          },
          "applicationId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 256,
            "description": "Sandbox-tenant application (installation) id."
          },
          "authClientId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 256,
            "description": "Logical sandbox authClient clientId."
          },
          "cognitoClientId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Cognito app client id bound to the sandbox credential."
          },
          "credentialAuthorizationId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Durable credentialAuthorization row id for the sandbox grant."
          },
          "responseReceiptId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Protected response receipt id. Client secret is returnable only while this receipt exists."
          },
          "lastError": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2048,
            "description": "Last failure detail when status=failed or during compensation."
          },
          "seedContract": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "orgSourcedId": {
                "type": "string"
              },
              "teacherSourcedId": {
                "type": "string"
              },
              "studentSourcedId": {
                "type": "string"
              },
              "contentId": {
                "type": "string",
                "format": "uuid"
              }
            },
            "description": "Portal-pinned sandbox quickstart fixture ids echoed from E3 provisionSandboxTenant.",
            "additionalProperties": false
          }
        }
      },
      "CreatePublisherRequest": {
        "type": "object",
        "description": "Create-Publisher request body (readOnly/server-managed fields excluded).",
        "required": [
          "publisherId",
          "displayName",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "publisherId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Stable identifier for this publisher within the tenant."
          },
          "toolProviderId": {
            "type": "string",
            "format": "uuid",
            "description": "Nullable FK to the global toolProvider. Set for vendor-linked publishers after backfill; null for purely tenant-local / non-vendor publisher rows.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Human-readable name of the publisher shown in administrative and marketplace surfaces. Compatibility mirror when toolProviderId is set — global toolProvider.displayName is authoritative for vendor identity."
          },
          "legalName": {
            "type": "string",
            "maxLength": 512,
            "description": "Legal entity name for contractual and compliance display purposes."
          },
          "ownerOrgSourcedId": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional FK to the OneRoster organization when the publisher is a tenant org. Uses the composite (tenantId, sourcedId) cross-module FK shape.",
            "x-references": "oneroster:org.sourcedId",
            "x-onDelete": "restrict"
          },
          "contactEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Administrative contact email for the publisher. Not student-facing data."
          },
          "supportUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Publisher support page URL for administrators and end-users."
          },
          "privacyUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Publisher privacy policy URL displayed during consent and review flows."
          },
          "termsUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Publisher terms-of-service URL displayed during consent and review flows."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "suspended",
              "retired"
            ],
            "description": "Lifecycle status of the publisher registration. Draft publishers are not visible to application discovery.",
            "default": "draft"
          },
          "sandbox": {
            "type": "boolean",
            "description": "When true, the publisher and all its applications operate in sandbox isolation — writes do not affect production data.",
            "default": false
          }
        }
      },
      "UpdatePublisherRequest": {
        "type": "object",
        "description": "Update-Publisher request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "toolProviderId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Nullable FK to the global toolProvider. Set for vendor-linked publishers after backfill; null for purely tenant-local / non-vendor publisher rows.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Human-readable name of the publisher shown in administrative and marketplace surfaces. Compatibility mirror when toolProviderId is set — global toolProvider.displayName is authoritative for vendor identity."
          },
          "legalName": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Legal entity name for contractual and compliance display purposes."
          },
          "ownerOrgSourcedId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 256,
            "description": "Optional FK to the OneRoster organization when the publisher is a tenant org. Uses the composite (tenantId, sourcedId) cross-module FK shape.",
            "x-references": "oneroster:org.sourcedId",
            "x-onDelete": "restrict"
          },
          "contactEmail": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "maxLength": 320,
            "description": "Administrative contact email for the publisher. Not student-facing data."
          },
          "supportUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 2048,
            "description": "Publisher support page URL for administrators and end-users."
          },
          "privacyUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 2048,
            "description": "Publisher privacy policy URL displayed during consent and review flows."
          },
          "termsUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 2048,
            "description": "Publisher terms-of-service URL displayed during consent and review flows."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "suspended",
              "retired"
            ],
            "description": "Lifecycle status of the publisher registration. Draft publishers are not visible to application discovery.",
            "default": "draft"
          },
          "sandbox": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "When true, the publisher and all its applications operate in sandbox isolation — writes do not affect production data.",
            "default": false
          }
        }
      },
      "CreateRendererCapabilityRequest": {
        "type": "object",
        "description": "Create-RendererCapability request body (readOnly/server-managed fields excluded).",
        "required": [
          "rendererRef",
          "displayName",
          "acceptedContentKinds",
          "integrationProtocol",
          "integrationEndpoint",
          "lifecycleState"
        ],
        "additionalProperties": false,
        "properties": {
          "rendererRef": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Stable identifier for this renderer capability within the tenant, referenced by curriculum.courseComponent.rendererRef."
          },
          "applicationId": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional intra-module FK to the application that supplies this renderer. A renderer may or may not be provided by a registered application. Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Human-readable renderer name shown to admins and authoring tools for renderer selection and configuration."
          },
          "acceptedContentKinds": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "minItems": 1,
            "description": "Array of governed content-kind enum values this renderer can handle. Used by curriculum at write time to validate renderer/content-kind compatibility. Values are registry strings governed by the content module, not DB FKs, to keep the import graph acyclic."
          },
          "integrationProtocol": {
            "type": "string",
            "enum": [
              "alpha_embed",
              "lti_launch_ref",
              "external_link"
            ],
            "description": "How the renderer integrates with the platform delivery surface. alpha_embed uses the platform iframe embed protocol; lti_launch_ref stores an LTI launch reference; external_link opens a direct URL in a new context."
          },
          "integrationEndpoint": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Registered launch or render endpoint URL. The platform delivery surface calls this URL according to the integrationProtocol when rendering content that names this rendererRef."
          },
          "playgroundUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Optional URL for admin validation and author/test preview of the renderer outside production delivery."
          },
          "lifecycleState": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "deprecated",
              "retired"
            ],
            "description": "Lifecycle state of the renderer capability registration. Draft renderers are not available for curriculum delivery; deprecated renderers serve existing references but cannot be newly assigned; retired renderers are fully disabled.",
            "default": "draft"
          }
        }
      },
      "UpdateRendererCapabilityRequest": {
        "type": "object",
        "description": "Update-RendererCapability request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "applicationId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 256,
            "description": "Optional intra-module FK to the application that supplies this renderer. A renderer may or may not be provided by a registered application. Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Human-readable renderer name shown to admins and authoring tools for renderer selection and configuration."
          },
          "acceptedContentKinds": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "minItems": 1,
            "description": "Array of governed content-kind enum values this renderer can handle. Used by curriculum at write time to validate renderer/content-kind compatibility. Values are registry strings governed by the content module, not DB FKs, to keep the import graph acyclic."
          },
          "integrationProtocol": {
            "type": "string",
            "enum": [
              "alpha_embed",
              "lti_launch_ref",
              "external_link"
            ],
            "description": "How the renderer integrates with the platform delivery surface. alpha_embed uses the platform iframe embed protocol; lti_launch_ref stores an LTI launch reference; external_link opens a direct URL in a new context."
          },
          "integrationEndpoint": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Registered launch or render endpoint URL. The platform delivery surface calls this URL according to the integrationProtocol when rendering content that names this rendererRef."
          },
          "playgroundUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 2048,
            "description": "Optional URL for admin validation and author/test preview of the renderer outside production delivery."
          },
          "lifecycleState": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "deprecated",
              "retired"
            ],
            "description": "Lifecycle state of the renderer capability registration. Draft renderers are not available for curriculum delivery; deprecated renderers serve existing references but cannot be newly assigned; retired renderers are fully disabled.",
            "default": "draft"
          }
        }
      },
      "CreateToolProviderRequest": {
        "type": "object",
        "description": "Create-ToolProvider request body (readOnly/server-managed fields excluded).",
        "required": [
          "toolProviderId",
          "displayName",
          "status",
          "verifiedContactEmail",
          "ownershipPrincipal"
        ],
        "additionalProperties": false,
        "properties": {
          "toolProviderId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable global provider identifier. Client-supplied so seed/backfill migrations can pin deterministic ids."
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Human-readable vendor name shown in portal and catalog surfaces."
          },
          "legalName": {
            "type": "string",
            "maxLength": 512,
            "description": "Legal entity name for contractual and compliance display."
          },
          "verifiedContactEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Verified administrative contact email for the provider. Restricted metadata."
          },
          "supportUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Provider support URL."
          },
          "privacyUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Provider privacy policy URL."
          },
          "termsUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Provider terms-of-service URL."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "suspended",
              "retired"
            ],
            "description": "Provider lifecycle. Emergency suspension denies new credentials/launches/tokens via the installation eligibility rule.",
            "default": "draft"
          },
          "ownershipPrincipal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Stable ownership principal id (portal membership subject or operator id). Ownership transfer is operator-only."
          },
          "sandboxTenantId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional dedicated sandbox tenant id for this provider (filled by E3 sandbox provisioning)."
          }
        }
      },
      "UpdateToolProviderRequest": {
        "type": "object",
        "description": "Update-ToolProvider request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Human-readable vendor name shown in portal and catalog surfaces."
          },
          "legalName": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Legal entity name for contractual and compliance display."
          },
          "verifiedContactEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Verified administrative contact email for the provider. Restricted metadata."
          },
          "supportUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 2048,
            "description": "Provider support URL."
          },
          "privacyUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 2048,
            "description": "Provider privacy policy URL."
          },
          "termsUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 2048,
            "description": "Provider terms-of-service URL."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "suspended",
              "retired"
            ],
            "description": "Provider lifecycle. Emergency suspension denies new credentials/launches/tokens via the installation eligibility rule.",
            "default": "draft"
          },
          "ownershipPrincipal": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Stable ownership principal id (portal membership subject or operator id). Ownership transfer is operator-only."
          },
          "sandboxTenantId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Optional dedicated sandbox tenant id for this provider (filled by E3 sandbox provisioning)."
          }
        }
      },
      "CreateToolRegistrationRequest": {
        "type": "object",
        "description": "Create-ToolRegistration request body (readOnly/server-managed fields excluded).",
        "required": [
          "toolRegistrationId",
          "toolProviderId",
          "name",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "toolRegistrationId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable global registration identifier. Client-supplied for deterministic seed/backfill."
          },
          "toolProviderId": {
            "type": "string",
            "format": "uuid",
            "description": "Owning global toolProvider.",
            "x-references": "toolProvider.id",
            "x-onDelete": "restrict"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Canonical registration name (global catalog authority for vendor installations)."
          },
          "displayName": {
            "type": "string",
            "maxLength": 512,
            "description": "Human-readable display name. Authority for vendor_installation display; local application.displayName is a deprecated mirror."
          },
          "attribution": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string",
                "maxLength": 256
              },
              "logoUri": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "homepageUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "privacyUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "termsUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "category": {
                "type": "string",
                "maxLength": 256
              }
            },
            "description": "Display attribution metadata (label, logo, URLs, category). Authority for vendor_installation; local application.attribution is a deprecated mirror."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "suspended",
              "retired"
            ],
            "description": "Registration lifecycle. Suspension feeds the shared installation eligibility rule.",
            "default": "draft"
          }
        }
      },
      "UpdateToolRegistrationRequest": {
        "type": "object",
        "description": "Update-ToolRegistration request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "Canonical registration name (global catalog authority for vendor installations)."
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Human-readable display name. Authority for vendor_installation display; local application.displayName is a deprecated mirror."
          },
          "attribution": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "label": {
                "type": "string",
                "maxLength": 256
              },
              "logoUri": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "homepageUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "privacyUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "termsUrl": {
                "type": "string",
                "format": "uri",
                "maxLength": 2048
              },
              "category": {
                "type": "string",
                "maxLength": 256
              }
            },
            "description": "Display attribution metadata (label, logo, URLs, category). Authority for vendor_installation; local application.attribution is a deprecated mirror."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "suspended",
              "retired"
            ],
            "description": "Registration lifecycle. Suspension feeds the shared installation eligibility rule.",
            "default": "draft"
          }
        }
      },
      "CreateToolRegistrationRevisionRequest": {
        "type": "object",
        "description": "Create-ToolRegistrationRevision request body (readOnly/server-managed fields excluded).",
        "required": [
          "toolRegistrationRevisionId",
          "toolRegistrationId",
          "revisionNumber",
          "status",
          "oidcInitiationUrl",
          "redirectUris",
          "jwksUrl",
          "targetLinkUris",
          "requestedScopeCeiling"
        ],
        "additionalProperties": false,
        "properties": {
          "toolRegistrationRevisionId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable revision identifier. Client-supplied for deterministic seed/backfill."
          },
          "toolRegistrationId": {
            "type": "string",
            "format": "uuid",
            "description": "Parent global toolRegistration.",
            "x-references": "toolRegistration.id",
            "x-onDelete": "restrict"
          },
          "revisionNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonic revision number within the registration."
          },
          "status": {
            "type": "string",
            "enum": [
              "published",
              "retired",
              "suspended"
            ],
            "description": "Revision lifecycle. Emergency suspended denies use via the shared eligibility rule.",
            "default": "published"
          },
          "oidcInitiationUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "OIDC login initiation URL for this revision."
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "minItems": 1,
            "description": "Exact redirect-URI set for this revision."
          },
          "jwksUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "Tool JWKS URL for this revision."
          },
          "targetLinkUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "minItems": 1,
            "description": "Approved target-link URI set (default + exact variants). Used later by deferred LTI resource links."
          },
          "requestedScopeCeiling": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Maximum scopes this revision may request. Issuance intersects with application.approvedScopes."
          },
          "configSchema": {
            "type": "object",
            "description": "Optional JSON Schema / config document describing vendor config for this revision.",
            "additionalProperties": true
          }
        }
      },
      "CreateWebhookDeliveryReceiptRequest": {
        "type": "object",
        "description": "Create-WebhookDeliveryReceipt request body (readOnly/server-managed fields excluded).",
        "required": [
          "deliveryId",
          "endpointId",
          "applicationId",
          "eventType",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "deliveryId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Server-generated or deterministic delivery identifier for this delivery attempt sequence."
          },
          "endpointId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the webhook endpoint this delivery targets. Composite shape (tenantId, endpointId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "webhookEndpoint.endpointId",
            "x-onDelete": "restrict"
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Denormalized application identity from the endpoint for audit attribution and list filtering without joining through webhookEndpoint.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "eventId": {
            "type": "string",
            "maxLength": 256,
            "description": "Event identity — the unique identifier of the specific event instance being delivered."
          },
          "eventType": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Governed event type slug of the delivered event (e.g. results.lineItem.created). Matches the subscription vocabulary in webhookEndpoint.subscriptions."
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "delivered",
              "retrying",
              "failed",
              "exhausted"
            ],
            "description": "Delivery lifecycle status. Queued when created, delivered on 2xx, retrying on transient failure, failed on permanent failure, exhausted when retry policy limits are reached.",
            "default": "queued"
          },
          "attemptCount": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of delivery attempts made for this receipt. Incremented on each HTTP POST attempt to the callback URL.",
            "default": 0
          },
          "nextRetryAt": {
            "type": "string",
            "format": "date-time",
            "description": "Scheduled timestamp for the next retry attempt. Null when status is delivered, failed, or exhausted. Set by the retry policy backoff calculation."
          },
          "lastResponseStatus": {
            "type": "integer",
            "minimum": 100,
            "maximum": 599,
            "description": "Last HTTP status code received from the endpoint, if an attempt reached the callback URL. Null when no response was received (connection timeout, DNS failure)."
          },
          "lastErrorCode": {
            "type": "string",
            "maxLength": 256,
            "description": "Bounded diagnostic error code for the last failed attempt (e.g. connection_timeout, dns_failure, tls_error, http_5xx). Never the full response body or payload."
          },
          "payloadHash": {
            "type": "string",
            "maxLength": 128,
            "description": "Opaque integrity hash of the delivered payload for audit and reconciliation. Not a crypto design — just a diagnostic for verifying payload consistency across retries."
          }
        }
      },
      "CreateWebhookEndpointRequest": {
        "type": "object",
        "description": "Create-WebhookEndpoint request body (readOnly/server-managed fields excluded).",
        "required": [
          "endpointId",
          "applicationId",
          "callbackUrl",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "endpointId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Composite-natural key leg after tenantId. Stable identifier for this webhook endpoint within the tenant."
          },
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the application that owns this webhook subscription. Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "clientId": {
            "type": "string",
            "maxLength": 256,
            "description": "Optional intra-module FK to the auth client that owns this subscription. When present, deliveries are authenticated via this client's credentials. Composite shape (tenantId, clientId) — tenantId leg is implicit.",
            "x-references": "authClient.clientId",
            "x-onDelete": "restrict"
          },
          "callbackUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "HTTPS URL registered for signed POST delivery. Must be an absolute HTTPS URI in production. When clientId is present, must be one of the registered callback URLs on that auth client."
          },
          "subscriptions": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 256
            },
            "description": "Array of governed event type slugs this endpoint subscribes to. Uses platform-wide event slug vocabulary without FKing into every event-producing module."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_verification",
              "active",
              "paused",
              "failed",
              "retired"
            ],
            "description": "Lifecycle status of the webhook endpoint. Starts as pending_verification until a test delivery succeeds. Active endpoints receive signed deliveries. Paused endpoints are temporarily silenced. Failed endpoints have exceeded retry thresholds. Retired endpoints are permanently deactivated.",
            "default": "pending_verification"
          },
          "signingMaterialRef": {
            "type": "string",
            "maxLength": 512,
            "description": "Opaque auth-subsystem reference to the signing material used for delivery signatures (e.g. HMAC shared secret or asymmetric key handle). Write-only — never serialized on read responses. The auth seam owns issuing and rotation of the actual signing material.",
            "writeOnly": true
          },
          "grantedScopes": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Permission slugs required for deliveries to this endpoint. Each slug constrains what event data the endpoint may receive."
          },
          "retryPolicyRef": {
            "type": "string",
            "maxLength": 256,
            "description": "Policy key or reference for retry limits, backoff, timeout, and abandonment thresholds. May resolve to a platform default, tenant policy, or endpoint-level inline config."
          },
          "lastVerifiedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Managed timestamp set when a verification or test delivery succeeds. Null until first successful verification."
          }
        }
      },
      "UpdateWebhookEndpointRequest": {
        "type": "object",
        "description": "Update-WebhookEndpoint request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "applicationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Intra-module FK to the application that owns this webhook subscription. Composite shape (tenantId, applicationId) — tenantId leg is implicit via row-level multiTenant.",
            "x-references": "application.applicationId",
            "x-onDelete": "restrict"
          },
          "clientId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 256,
            "description": "Optional intra-module FK to the auth client that owns this subscription. When present, deliveries are authenticated via this client's credentials. Composite shape (tenantId, clientId) — tenantId leg is implicit.",
            "x-references": "authClient.clientId",
            "x-onDelete": "restrict"
          },
          "callbackUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "HTTPS URL registered for signed POST delivery. Must be an absolute HTTPS URI in production. When clientId is present, must be one of the registered callback URLs on that auth client."
          },
          "subscriptions": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "maxLength": 256
            },
            "description": "Array of governed event type slugs this endpoint subscribes to. Uses platform-wide event slug vocabulary without FKing into every event-producing module."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_verification",
              "active",
              "paused",
              "failed",
              "retired"
            ],
            "description": "Lifecycle status of the webhook endpoint. Starts as pending_verification until a test delivery succeeds. Active endpoints receive signed deliveries. Paused endpoints are temporarily silenced. Failed endpoints have exceeded retry thresholds. Retired endpoints are permanently deactivated.",
            "default": "pending_verification"
          },
          "signingMaterialRef": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Opaque auth-subsystem reference to the signing material used for delivery signatures (e.g. HMAC shared secret or asymmetric key handle). Write-only — never serialized on read responses. The auth seam owns issuing and rotation of the actual signing material.",
            "writeOnly": true
          },
          "grantedScopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "maxLength": 128
            },
            "description": "Permission slugs required for deliveries to this endpoint. Each slug constrains what event data the endpoint may receive."
          },
          "retryPolicyRef": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 256,
            "description": "Policy key or reference for retry limits, backoff, timeout, and abandonment thresholds. May resolve to a platform default, tenant policy, or endpoint-level inline config."
          },
          "lastVerifiedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Managed timestamp set when a verification or test delivery succeeds. Null until first successful verification."
          }
        }
      },
      "Problem": {
        "type": "object",
        "description": "RFC 7807 problem details.",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI identifying the problem type."
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem."
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code."
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence."
          },
          "instance": {
            "type": "string",
            "format": "uri",
            "description": "A URI identifying this occurrence."
          }
        },
        "required": [
          "title",
          "status"
        ]
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "servers": [
    {
      "url": "https://alpha.platform4.alphaschool.dev"
    }
  ]
}
