{"openapi":"3.1.0","info":{"title":"Dictiva API","version":"1.0.0","description":"Programmatic access to governance data — statements, assemblies, glossary, controls, regulations, and more.\n\n## Authentication\nAuthenticate via API key (Bearer token) or browser session cookie.\n\n## Versioning\nAll public API endpoints are available under `/api/v1/`. For example: `GET /api/v1/statements`.\nUnversioned paths (`/api/statements`) continue to work as aliases.\nInternal routes (`/api/auth/*`, `/api/health/*`) are not versioned.\n\n## Rate Limiting\nAPI key-authenticated requests are rate-limited per key using a fixed-window counter (60-second window):\n\n| Plan Tier | Requests per Minute |\n|-----------|-------------------|\n| Community (free) | 5 |\n| Professional | 20 |\n| Business | 100 |\n| Enterprise | 500 |\n\nRate limit headers are included in every API key-authenticated response:\n- `X-RateLimit-Limit` — maximum requests allowed per window\n- `X-RateLimit-Remaining` — requests remaining in the current window\n- `X-RateLimit-Reset` — Unix timestamp (seconds) when the window resets\n- `X-RateLimit-Window` — window duration in seconds (60)\n\nWhen the limit is exceeded, the API returns `429 Too Many Requests` with a `Retry-After` header.\nSession-based (browser) requests are exempt from rate limiting.\n\n## MCP Agent Access\nAgent endpoints under `/agent/*` require the `mcp_access` entitlement, available on Business and Enterprise plans.\nRequests without the required entitlement receive a `403 Forbidden` response with `reason: \"mcp_access_required\"`.\nMCP requests are metered separately from standard API requests.\n\n---\n\n*Patent Pending.*","contact":{"name":"Dictiva","url":"https://dictiva.com"}},"servers":[{"url":"{baseUrl}/api/v1","description":"Versioned API (recommended)","variables":{"baseUrl":{"default":"http://localhost:3100","description":"Base URL of the Dictiva instance"}}},{"url":"{baseUrl}/api","description":"Unversioned API (alias)","variables":{"baseUrl":{"default":"http://localhost:3100","description":"Base URL of the Dictiva instance"}}}],"security":[{"bearerAuth":[]},{"cookieAuth":[]}],"tags":[{"name":"Statements","description":"Governance statements — CRUD, search, lifecycle transitions"},{"name":"Policies & Standards","description":"Policy assemblies — collections of pinned statement versions"},{"name":"Actions","description":"Task inbox — action items for review, acknowledgement, etc."},{"name":"Glossary","description":"Tenant glossary — terms, relationships, external links"},{"name":"Library","description":"Unified content library — statements, glossary, regulations"},{"name":"Regulations","description":"Regulation registry — requirements, mappings, annotations"},{"name":"Settings","description":"Tenant settings — API keys, tags, members, domains"},{"name":"Auth","description":"Authentication — sign-in method resolution, SSO routing"},{"name":"Health","description":"Health checks — liveness, readiness, service status"},{"name":"Billing","description":"Billing — checkout, portal, usage, credit packs"},{"name":"Agent","description":"Agent API — machine-readable governance bundles, ontology, and policy search for AI agents"},{"name":"Platform Admin","description":"Platform admin endpoints — tenant management, plan overrides, credit adjustments, trial extensions"},{"name":"Releases","description":"Release version management — changelog, version tracking, auto-generation"},{"name":"Invitation Requests","description":"Early access — public invitation request submission"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication. Pass your key as `Authorization: Bearer dv_live_...`. Keys are created in Settings → API Keys. Each key is scoped to specific read permissions (e.g. `statement:read`, `glossary:read`)."},"cookieAuth":{"type":"apiKey","in":"cookie","name":"better-auth.session_token","description":"Browser session cookie (set automatically on login)."}},"schemas":{"ValidationError":{"type":"object","properties":{"error":{"type":"string","example":"Validation failed"},"details":{"type":"array","items":{"type":"object","properties":{"path":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}},"message":{"type":"string"},"code":{"type":"string"}},"required":["path","message","code"]}}},"required":["error","details"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"string","example":"Not found"}},"required":["error"]},"RateLimitError":{"type":"object","properties":{"error":{"type":"string","example":"Rate limit exceeded"},"retryAfter":{"type":"integer","example":42,"description":"Seconds until the rate limit window resets"}},"required":["error"]},"McpAccessDenied":{"type":"object","properties":{"error":{"type":"string","example":"MCP access requires Business or Enterprise plan"},"reason":{"type":"string","enum":["mcp_access_required"],"example":"mcp_access_required"},"upgradeUrl":{"type":"string","format":"uri","example":"https://dictiva.com/settings?tab=billing","description":"URL where the tenant admin can upgrade their plan"}},"required":["error","reason"]},"PaginationParams":{"type":"object","properties":{"page":{"type":"integer","minimum":1,"default":1,"example":1},"per_page":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20}}},"PaginationMeta":{"type":"object","properties":{"page":{"type":"integer","example":1},"perPage":{"type":"integer","example":20},"total":{"type":"integer","example":142},"totalPages":{"type":"integer","example":8}},"required":["page","perPage","total","totalPages"]},"FacetCount":{"type":"object","properties":{"field":{"type":"string","example":"lifecycle_state"},"counts":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","example":"effective"},"count":{"type":"integer","example":23}},"required":["value","count"]}}},"required":["field","counts"]},"PolicyCommitmentAttestation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"agentIdentityId":{"type":"string","format":"uuid"},"subjectDid":{"type":"string","pattern":"^did:[a-z0-9]+:/i","example":"did:web:dictiva.com:agents:code-reviewer","description":"W3C Decentralized Identifier."},"statementId":{"type":"string","format":"uuid"},"statementVersion":{"type":"integer"},"statementHash":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","example":"sha256:b8a1d2c3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1"},"commitmentTier":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"},"targetTier":{"type":["string","null"],"enum":["T1","T2","T3","T4","T5","T6",null],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"},"scope":{"$ref":"#/components/schemas/PcaScope"},"chainOfAuthority":{"$ref":"#/components/schemas/PcaChainOfAuthority"},"credential":{"type":"object","additionalProperties":{},"description":"Full signed W3C VC, verbatim."},"issuedAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"revalidationInterval":{"type":"string","pattern":"^P","example":"P90D"},"lastRevalidatedAt":{"type":["string","null"],"format":"date-time"},"signatureAlgorithm":{"type":"string","enum":["ed25519","hmac_sha256"]},"statusListUrl":{"type":["string","null"],"format":"uri"},"statusListIndex":{"type":["integer","null"]},"revokedAt":{"type":["string","null"],"format":"date-time"},"revokedReason":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","tenantId","agentIdentityId","subjectDid","statementId","statementVersion","statementHash","commitmentTier","targetTier","scope","chainOfAuthority","credential","issuedAt","expiresAt","revalidationInterval","lastRevalidatedAt","signatureAlgorithm","statusListUrl","statusListIndex","revokedAt","revokedReason","createdAt","updatedAt"]},"PcaScope":{"type":["object","null"],"properties":{"tenants":{"type":"array","items":{"type":"string"}},"entityTypes":{"type":"array","items":{"type":"string"}},"actionClasses":{"type":"array","items":{"type":"string"}},"refusalRules":{"type":"array","items":{"type":"object","additionalProperties":{}}}}},"PcaChainOfAuthority":{"type":["object","null"],"properties":{"assemblyId":{"type":"string","format":"uuid"},"issuedBy":{"type":"string","pattern":"^did:[a-z0-9]+:/i","example":"did:web:dictiva.com:agents:code-reviewer","description":"W3C Decentralized Identifier."},"approvedBy":{"type":"array","items":{"type":"string","pattern":"^did:[a-z0-9]+:/i","example":"did:web:dictiva.com:agents:code-reviewer","description":"W3C Decentralized Identifier."}}},"required":["issuedBy"]},"IssueAttestationRequest":{"type":"object","properties":{"subjectDid":{"type":"string","pattern":"^did:[a-z0-9]+:/i","example":"did:web:dictiva.com:agents:code-reviewer","description":"W3C Decentralized Identifier."},"statementId":{"type":"string","format":"uuid","description":"UUID of the governance statement in this tenant's `statements` table. Callers typically resolve this via `search_statements` / `GET /api/agent/statements` before issuing.","example":"550e8400-e29b-41d4-a716-446655440000"},"statementRef":{"type":"object","properties":{"uri":{"type":"string","format":"uri"},"version":{"type":"integer","minimum":1},"hash":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","example":"sha256:b8a1d2c3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1"}},"required":["uri","version","hash"],"description":"Reference to the statement being committed to, with canonical hash for verifier re-computation. The issuer validates `hash` against the current canonical body of `statementId` at `version` — mismatches fail with 422 `statement_hash_mismatch`."},"commitmentTier":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"},"targetTier":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"},"scope":{"$ref":"#/components/schemas/PcaScope"},"evidence":{"type":"array","items":{"$ref":"#/components/schemas/PcaEvidence"}},"chainOfAuthority":{"$ref":"#/components/schemas/PcaChainOfAuthority"},"revalidationInterval":{"type":"string","pattern":"^P","example":"P90D"}},"required":["subjectDid","statementId","statementRef","commitmentTier","evidence","chainOfAuthority"]},"PcaEvidence":{"type":"object","properties":{"evidenceKind":{"type":"string","description":"Evidence kind per PCA spec §5 registry. Unknown kinds are accepted per spec (extensible registry).","example":"adr"},"reference":{"type":"string","description":"URI, path, or git commit-SHA reference to the evidence artifact.","example":"https://github.com/dictiva/dictiva/blob/main/docs/decisions/040-policy-commitment-attestation.md"},"description":{"type":"string"},"digest":{"type":"object","properties":{"sha256":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","example":"sha256:b8a1d2c3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1"}},"required":["sha256"],"description":"Content digest of the referenced artifact."},"statementJson":{"type":"object","additionalProperties":{},"description":"Optional in-toto Statement envelope verbatim. Preserved for verifier inspection."}},"required":["evidenceKind","reference"]},"VerifyAttestationRequest":{"type":"object","properties":{"credential":{"type":"object","additionalProperties":{},"description":"A signed W3C VC of type PolicyCommitmentCredential to verify."}},"required":["credential"]},"RevokeAttestationRequest":{"type":"object","properties":{"reason":{"type":"string","minLength":3,"maxLength":500,"description":"Human-readable revocation reason (audit trail). Typed into VC Status List 2021 metadata when enabled."}},"required":["reason"]},"VerificationResult":{"type":"object","properties":{"verified":{"type":"boolean"},"effectiveTier":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"},"errors":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"evidenceIndex":{"type":"integer"}},"required":["code","message"]}}},"required":["verified"]},"CommitmentTier":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"},"CoverageMatrixStatement":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayId":{"type":"string","example":"STMT-AI-001"},"title":{"type":"string"},"lifecycleState":{"type":"string","enum":["draft","in_review","approved","effective","retired","archived"]},"domainId":{"type":["string","null"],"format":"uuid"},"currentVersion":{"type":["integer","null"]}},"required":["id","displayId","title","lifecycleState","domainId","currentVersion"]},"CoverageMatrixAgent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"did":{"type":"string","pattern":"^did:[a-z0-9]+:/i","example":"did:web:dictiva.com:agents:code-reviewer","description":"W3C Decentralized Identifier."},"displayName":{"type":"string"},"iconKey":{"type":"string"},"lifecycle":{"type":"string"}},"required":["id","did","displayName","iconKey","lifecycle"]},"CoverageMatrixCell":{"type":"object","properties":{"statementId":{"type":"string","format":"uuid"},"agentIdentityId":{"type":"string","format":"uuid"},"maxTier":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"},"latestExpiresAt":{"type":"string","description":"ISO 8601 timestamp of the latest expiry across the cell's commitments."},"hasRevoked":{"type":"boolean","description":"True if any commitment in this cell is revoked."},"hasExpired":{"type":"boolean","description":"True if any commitment in this cell has expired."},"commitmentCount":{"type":"integer","minimum":1}},"required":["statementId","agentIdentityId","maxTier","latestExpiresAt","hasRevoked","hasExpired","commitmentCount"]},"CoverageMatrixResponse":{"type":"object","properties":{"statements":{"type":"array","items":{"$ref":"#/components/schemas/CoverageMatrixStatement"}},"agents":{"type":"array","items":{"$ref":"#/components/schemas/CoverageMatrixAgent"}},"cells":{"type":"array","items":{"$ref":"#/components/schemas/CoverageMatrixCell"},"description":"Sparse — only populated (statement × agent) pairs are returned. The UI fills empty cells visually."},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]}},"required":["statements","agents","cells","pagination"]},"GapStatement":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayId":{"type":"string","example":"STMT-AI-001"},"title":{"type":"string"},"lifecycleState":{"type":"string","enum":["draft","in_review","approved","effective","retired","archived"]},"domainId":{"type":["string","null"],"format":"uuid"},"maxTier":{"type":["string","null"],"enum":["T1","T2","T3","T4","T5","T6",null],"description":"Populated for `belowTarget` rows; null for `untouched` and `stale`.","example":"T4"},"attestingAgentCount":{"type":"integer","minimum":0,"description":"Distinct agents with at least one live commitment on this statement. Always 0 for `untouched`."},"attestedVersion":{"type":["integer","null"],"description":"Populated for `stale` rows: oldest attested statement version among this statement's commitments."},"currentVersion":{"type":["integer","null"],"description":"Statement's current version number (the version the canonical body now reflects)."}},"required":["id","displayId","title","lifecycleState","domainId","maxTier","attestingAgentCount","attestedVersion","currentVersion"]},"GapReportResponse":{"type":"object","properties":{"untouched":{"type":"array","items":{"$ref":"#/components/schemas/GapStatement"},"description":"Statements with zero live commitments (no agent has attested at any tier)."},"belowTarget":{"type":"array","items":{"$ref":"#/components/schemas/GapStatement"},"description":"Statements where MAX(commitment_tier) across all agents is below `target_tier`."},"stale":{"type":"array","items":{"$ref":"#/components/schemas/GapStatement"},"description":"Statements with at least one commitment against an older version (statement edited since attestation)."},"summary":{"type":"object","properties":{"totalStatements":{"type":"integer"},"untouchedCount":{"type":"integer"},"belowTargetCount":{"type":"integer"},"staleCount":{"type":"integer"},"targetTier":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"}},"required":["totalStatements","untouchedCount","belowTargetCount","staleCount","targetTier"]},"truncated":{"type":"object","properties":{"untouched":{"type":"boolean"},"belowTarget":{"type":"boolean"},"stale":{"type":"boolean"}},"required":["untouched","belowTarget","stale"]}},"required":["untouched","belowTarget","stale","summary","truncated"]},"ExpiringCommitment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"statementId":{"type":"string","format":"uuid"},"statementDisplayId":{"type":"string","example":"STMT-AI-001"},"statementTitle":{"type":"string"},"agentIdentityId":{"type":"string","format":"uuid"},"agentDid":{"type":"string","pattern":"^did:[a-z0-9]+:/i","example":"did:web:dictiva.com:agents:code-reviewer","description":"W3C Decentralized Identifier."},"agentDisplayName":{"type":"string"},"commitmentTier":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"},"issuedAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"daysUntilExpiry":{"type":"integer","minimum":0,"description":"Whole days from now until the credential expires."},"lastRevalidatedAt":{"type":["string","null"],"format":"date-time"},"revalidationInterval":{"type":"string","description":"ISO 8601 duration (e.g., 'P90D').","example":"P90D"}},"required":["id","statementId","statementDisplayId","statementTitle","agentIdentityId","agentDid","agentDisplayName","commitmentTier","issuedAt","expiresAt","daysUntilExpiry","lastRevalidatedAt","revalidationInterval"]},"ExpirationCalendarResponse":{"type":"object","properties":{"commitments":{"type":"array","items":{"$ref":"#/components/schemas/ExpiringCommitment"},"description":"Chronological list (ascending by `expiresAt`)."},"summary":{"type":"object","properties":{"totalExpiringInWindow":{"type":"integer"},"byTier":{"type":"object","properties":{"T1":{"type":"integer"},"T2":{"type":"integer"},"T3":{"type":"integer"},"T4":{"type":"integer"},"T5":{"type":"integer"},"T6":{"type":"integer"}},"required":["T1","T2","T3","T4","T5","T6"]},"earliestExpiry":{"type":["string","null"]},"latestExpiry":{"type":["string","null"]},"windowDays":{"type":"integer"}},"required":["totalExpiringInWindow","byTier","earliestExpiry","latestExpiry","windowDays"]},"truncated":{"type":"boolean","description":"True when more commitments exist beyond the page limit."}},"required":["commitments","summary","truncated"]},"InvitationRequestBody":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":255,"description":"Full name"},"email":{"type":"string","maxLength":255,"format":"email","description":"Corporate email address"},"company":{"type":"string","minLength":2,"maxLength":255,"description":"Company or organization name"},"jobTitle":{"type":"string","maxLength":255,"description":"Job title or role"},"useCases":{"type":"string","maxLength":2000,"description":"Use cases, interest, or details about your governance needs"},"isUrgent":{"type":"boolean","default":false,"description":"Whether you need an expedited response"},"urgencyExplanation":{"type":"string","maxLength":2000,"description":"Required if isUrgent is true — explain the urgency (min 20 chars)"}},"required":["name","email","company"]},"InvitationRequestResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Request ID"},"message":{"type":"string","description":"Confirmation message"}},"required":["id","message"]},"InvitationRequestError":{"type":"object","properties":{"error":{"type":"string","description":"Error message"}},"required":["error"]}},"parameters":{}},"paths":{"/api/statements":{"get":{"tags":["Statements"],"summary":"Search statements","description":"Full-text search via Typesense with Postgres ILIKE fallback. Supports filtering by domain, lifecycle, modality, type, risk tier, and adoption status. Returns faceted results.","parameters":[{"schema":{"type":"string","description":"Search query (default: *)","example":"data retention"},"required":false,"description":"Search query (default: *)","name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"per_page","in":"query"},{"schema":{"type":"string","description":"Filter by domain name"},"required":false,"description":"Filter by domain name","name":"domain","in":"query"},{"schema":{"type":"string","description":"Filter by lifecycle state","example":"effective"},"required":false,"description":"Filter by lifecycle state","name":"lifecycle","in":"query"},{"schema":{"type":"string","description":"Filter by modality","example":"must"},"required":false,"description":"Filter by modality","name":"modality","in":"query"},{"schema":{"type":"string","description":"Filter by statement type","example":"obligation"},"required":false,"description":"Filter by statement type","name":"type","in":"query"},{"schema":{"type":"string","description":"Filter by risk tier","example":"high"},"required":false,"description":"Filter by risk tier","name":"risk_tier","in":"query"},{"schema":{"type":"string","description":"Filter by adoption status: adopted, diverged, native"},"required":false,"description":"Filter by adoption status: adopted, diverged, native","name":"adoption","in":"query"},{"schema":{"type":"string","description":"Sort order (default: updated_at:desc)","example":"updated_at:desc"},"required":false,"description":"Sort order (default: updated_at:desc)","name":"sort","in":"query"}],"responses":{"200":{"description":"Search results with facets and pagination metadata","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"document":{"type":"object","additionalProperties":{}},"highlights":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["document"]}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]},"facets":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"counts":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"count":{"type":"integer"}},"required":["value","count"]}}},"required":["field","counts"]}}},"required":["data","meta","facets"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Statements"],"summary":"Create a statement","description":"Create a new governance statement in draft lifecycle state.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"body":{"type":"string","minLength":1,"maxLength":10000},"modality":{"type":"string","enum":["must","should","may"]},"statementType":{"type":"string","enum":["obligation","prohibition","permission","responsibility"]},"domainId":{"type":"string","format":"uuid"},"riskTier":{"type":"string","enum":["low","medium","high","critical"]},"maturityLevel":{"type":"string","enum":["foundational","intermediate","advanced","exemplary"]},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100}},"annotations":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["rationale","justification","example","note","guidance"]},"content":{"type":"string","minLength":1}},"required":["type","content"]}},"effectiveAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"}]},"reviewAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"}]},"sunsetAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"}]}},"required":["title","body","modality","statementType"]}}}},"responses":{"201":{"description":"Statement created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/statements/{id}":{"get":{"tags":["Statements"],"summary":"Get a statement","description":"Retrieve a single statement by ID, including current version, domain, annotations, and relationships.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Statement detail","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"patch":{"tags":["Statements"],"summary":"Update a statement","description":"Partially update a statement. Creates a new version when title or body changes.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"displayId":{"type":"string","minLength":1,"maxLength":50},"title":{"type":"string","minLength":1,"maxLength":500},"body":{"type":"string","minLength":1,"maxLength":10000},"modality":{"type":"string","enum":["must","should","may"]},"statementType":{"type":"string","enum":["obligation","prohibition","permission","responsibility"]},"riskTier":{"type":["string","null"],"enum":["low","medium","high","critical",null]},"maturityLevel":{"type":["string","null"],"enum":["foundational","intermediate","advanced","exemplary",null]},"lifecycleState":{"type":"string","enum":["draft","in_review","approved","effective","retired","archived"]},"domainId":{"type":["string","null"],"format":"uuid"},"annotations":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["rationale","justification","example","note","guidance"]},"content":{"type":"string","minLength":1}},"required":["type","content"]}},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100}},"effectiveAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}]},"reviewAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}]},"sunsetAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}]},"appliesTo":{"type":"string","enum":["human","agent","both"]},"actorScope":{"type":["array","null"],"items":{"type":"string","enum":["employee","reviewer","service-account","agent","agent-workflow","external-tool"]}},"enforcementMode":{"type":"string","enum":["informational","human_review_required","machine_readable","machine_enforceable"]},"agentGuidance":{"type":["object","null"],"properties":{"allowedActions":{"type":"array","items":{"type":"string"}},"prohibitedActions":{"type":"array","items":{"type":"string"}},"requiredContext":{"type":"array","items":{"type":"string"}},"requiredApprovals":{"type":"array","items":{"type":"string"}},"evidenceRequirements":{"type":"array","items":{"type":"string"}},"escalationRules":{"type":"array","items":{"type":"string"}},"failureMode":{"type":"string"}}}}}}}},"responses":{"200":{"description":"Statement updated"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"delete":{"tags":["Statements"],"summary":"Delete a statement","description":"Soft-delete a statement (sets deleted_at timestamp).","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Statement deleted"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/statements/{id}/transitions":{"post":{"tags":["Statements"],"summary":"Transition lifecycle state","description":"Move a statement through its lifecycle (submit, approve, reject, activate, retire, reinstate, archive). Validates allowed transitions.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["submit","approve","reject","activate","retire","reinstate","archive"]},"comment":{"type":"string","maxLength":2000}},"required":["action"]}}}},"responses":{"200":{"description":"Transition applied"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/statements/{id}/history":{"get":{"tags":["Statements"],"summary":"Get governance event history","description":"Paginated governance events for a statement. Filterable by action type (comma-separated). Returns standardized { data, meta } envelope.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"example":50},"required":false,"name":"per_page","in":"query"},{"schema":{"type":"string","description":"Comma-separated action filter","example":"approved,submitted"},"required":false,"description":"Comma-separated action filter","name":"action","in":"query"}],"responses":{"200":{"description":"Paginated governance events","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"action":{"type":"string"},"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid"},"actorName":{"type":"string"},"summary":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","action","entityType","entityId","actorName","summary","createdAt"],"additionalProperties":{}}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]}},"required":["data","meta"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/statements/{id}/relationships":{"get":{"tags":["Statements"],"summary":"List statement relationships","description":"Get all relationships (parent, child, related) for a statement.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Statement relationships","content":{"application/json":{"schema":{"type":"object","properties":{"relationships":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["relationships"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/statements/{id}/mappings":{"get":{"tags":["Statements"],"summary":"List control mappings","description":"Get all control framework mappings for a statement.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Control mappings","content":{"application/json":{"schema":{"type":"object","properties":{"mappings":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["mappings"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/statements/{id}/comprehension-points":{"get":{"tags":["Statements","Comprehension"],"summary":"List comprehension points","description":"Get atomic comprehension points for a statement's current version. Points are AI-generated (source: ai) or manually created (source: manual). Each point is a testable assertion used in the comprehension verification engine.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Comprehension points for the current version","content":{"application/json":{"schema":{"type":"object","properties":{"points":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sortOrder":{"type":"number"},"pointText":{"type":"string"},"questionText":{"type":"string"},"questionType":{"type":"string","enum":["true_false","multiple_choice"]},"correctAnswer":{"type":"string"},"distractors":{"type":"array","items":{"type":"string"}},"source":{"type":"string","enum":["ai","manual"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","sortOrder","pointText","questionText","questionType","correctAnswer","distractors","source","createdAt"]}},"total":{"type":"number"}},"required":["points","total"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Statements","Comprehension"],"summary":"Regenerate comprehension points","description":"Re-run AI decomposition to generate new comprehension points for the statement's current version. Replaces existing AI-generated points but preserves manually created ones. Requires statement:edit permission.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Points regenerated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"statementTitle":{"type":"string"},"pointsGenerated":{"type":"number"},"manualPointsPreserved":{"type":"number"}},"required":["success","statementTitle","pointsGenerated","manualPointsPreserved"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/assemblies":{"get":{"tags":["Policies & Standards"],"summary":"List assemblies","description":"List all assemblies for the current tenant with pagination and optional search.","parameters":[{"schema":{"type":"string","description":"Search query"},"required":false,"description":"Search query","name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Paginated assembly list","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":{}}},"total":{"type":"number"},"page":{"type":"number"},"perPage":{"type":"number"}},"required":["items","total","page","perPage"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Policies & Standards"],"summary":"Create an assembly","description":"Create a new policy assembly (policy, standard, procedure, or guideline).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":5000},"assemblyType":{"type":"string","enum":["policy","standard","procedure","guideline"]},"domainId":{"type":"string","format":"uuid"}},"required":["title","assemblyType"]}}}},"responses":{"201":{"description":"Assembly created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/assemblies/{id}":{"get":{"tags":["Policies & Standards"],"summary":"Get an assembly","description":"Retrieve an assembly by ID with its items (pinned statement versions).","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Assembly detail with items","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"patch":{"tags":["Policies & Standards"],"summary":"Update an assembly","description":"Partially update an assembly's title, description, domain, or state.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"displayId":{"type":"string","minLength":1,"maxLength":50},"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":5000},"footerContent":{"type":["object","null"],"properties":{"content":{"type":"string","maxLength":5000},"format":{"type":"string","enum":["markdown"],"default":"markdown"}},"required":["content"]},"assemblyType":{"type":"string","enum":["policy","standard","procedure","guideline"]},"domainId":{"type":["string","null"],"format":"uuid"},"assemblyState":{"type":"string","enum":["draft","under_review","published","superseded","archived"]},"approvedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}]},"publishedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}]},"effectiveAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}]},"reviewAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}]},"sunsetAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}]},"renewalPeriodMonths":{"type":["integer","null"],"minimum":1,"maximum":120}}}}}},"responses":{"200":{"description":"Assembly updated"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"delete":{"tags":["Policies & Standards"],"summary":"Delete an assembly","description":"Soft-delete an assembly.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Assembly deleted"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/assemblies/{id}/items":{"post":{"tags":["Policies & Standards"],"summary":"Add item to assembly","description":"Pin a specific statement version to the assembly.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"statementVersionId":{"type":"string","format":"uuid"},"sortOrder":{"type":"integer","minimum":0}},"required":["statementVersionId"]}}}},"responses":{"201":{"description":"Item added to assembly"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/assemblies/{id}/publish":{"post":{"tags":["Policies & Standards"],"summary":"Publish an assembly","description":"Transition an assembly to the published state, creating a manifest snapshot.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Assembly published"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/assemblies/{id}/export":{"get":{"tags":["Policies & Standards"],"summary":"Export assembly as PDF","description":"Generate and download a PDF export of the assembly with all included statements.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"PDF document","content":{"application/pdf":{"schema":{"type":"string"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/actions":{"get":{"tags":["Actions"],"summary":"List action items","description":"List action items for the current user with optional filtering by status, type, and priority.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"per_page","in":"query"},{"schema":{"type":"string","description":"Filter by status: pending, in_progress, completed, dismissed, snoozed"},"required":false,"description":"Filter by status: pending, in_progress, completed, dismissed, snoozed","name":"status","in":"query"},{"schema":{"type":"string","description":"Filter by action type"},"required":false,"description":"Filter by action type","name":"type","in":"query"},{"schema":{"type":"string","description":"Filter by priority: low, normal, high, urgent"},"required":false,"description":"Filter by priority: low, normal, high, urgent","name":"priority","in":"query"}],"responses":{"200":{"description":"Paginated action items","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":{}}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]}},"required":["data","meta"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Actions"],"summary":"Create an action item","description":"Create a new action item assigned to a user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"actionType":{"type":"string","enum":["review_statement","review_assembly","comprehension_check","acknowledgement_request","exception_decision","exception_expiring","attestation_pending","attestation_followup","draft_stale","divergence_available","evidence_gap","system_alert","profile_completion","tag_automation"]},"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":2000},"sourceType":{"type":"string","enum":["statement","assembly","exception","attestation_campaign","comprehension_session","acknowledgement_request","system","domain_tag"]},"sourceId":{"type":"string","format":"uuid"},"priority":{"type":"string","enum":["low","normal","high","urgent"],"default":"normal"},"dueDate":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"}]}},"required":["userId","actionType","title","sourceType"]}}}},"responses":{"201":{"description":"Action item created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/actions/{id}":{"get":{"tags":["Actions"],"summary":"Get an action item","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Action item detail","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"patch":{"tags":["Actions"],"summary":"Update an action item","description":"Update status, priority, or snooze an action item.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","in_progress","completed","dismissed","snoozed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"snoozedUntil":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"}]}}}}}},"responses":{"200":{"description":"Action item updated"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"delete":{"tags":["Actions"],"summary":"Delete an action item","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Action item deleted"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/actions/bulk":{"post":{"tags":["Actions"],"summary":"Bulk update action items","description":"Complete, dismiss, or snooze multiple action items at once (max 100).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100},"action":{"type":"string","enum":["complete","dismiss","snooze"]},"snoozedUntil":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"}]}},"required":["ids","action"]}}}},"responses":{"200":{"description":"Bulk update result","content":{"application/json":{"schema":{"type":"object","properties":{"updated":{"type":"number"}},"required":["updated"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/actions/count":{"get":{"tags":["Actions"],"summary":"Count action items","description":"Get counts of action items grouped by status for the current user.","responses":{"200":{"description":"Action item counts by status","content":{"application/json":{"schema":{"type":"object","properties":{"pending":{"type":"number"},"in_progress":{"type":"number"},"total":{"type":"number"}},"required":["pending","in_progress","total"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/glossaries":{"get":{"tags":["Glossary"],"summary":"List glossaries","description":"List all glossaries accessible to the current tenant (tenant-owned + adopted library glossaries).","responses":{"200":{"description":"Glossary list","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["items"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/glossaries/{id}":{"get":{"tags":["Glossary"],"summary":"Get a glossary","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Glossary detail with term count","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/glossaries/{id}/terms":{"get":{"tags":["Glossary"],"summary":"List glossary terms","description":"List all terms in a glossary with pagination and optional search.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Search query"},"required":false,"description":"Search query","name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Paginated term list","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":{}}},"total":{"type":"number"},"page":{"type":"number"},"perPage":{"type":"number"}},"required":["items","total","page","perPage"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Glossary"],"summary":"Create a glossary term","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"term":{"type":"string","minLength":1,"maxLength":500},"definition":{"type":"string","minLength":1,"maxLength":10000},"abbreviation":{"type":"string","maxLength":50},"context":{"type":"string","maxLength":2000}},"required":["term","definition"]}}}},"responses":{"201":{"description":"Term created"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/glossaries/{id}/terms/{termId}":{"get":{"tags":["Glossary"],"summary":"Get a glossary term","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"termId","in":"path"}],"responses":{"200":{"description":"Term detail with relationships and external links","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"patch":{"tags":["Glossary"],"summary":"Update a glossary term","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"termId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"term":{"type":"string","minLength":1,"maxLength":500},"definition":{"type":"string","minLength":1,"maxLength":10000},"abbreviation":{"type":["string","null"],"maxLength":50},"context":{"type":["string","null"],"maxLength":2000}}}}}},"responses":{"200":{"description":"Term updated"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"delete":{"tags":["Glossary"],"summary":"Delete a glossary term","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"termId","in":"path"}],"responses":{"200":{"description":"Term deleted"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/glossaries/{id}/terms/{termId}/relationships":{"get":{"tags":["Glossary"],"summary":"List term relationships","description":"Get all relationships (broader, narrower, synonym, related, variant) for a term.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"termId","in":"path"}],"responses":{"200":{"description":"Term relationships","content":{"application/json":{"schema":{"type":"object","properties":{"relationships":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["relationships"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Glossary"],"summary":"Create term relationship","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"termId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"targetTermId":{"type":"string","format":"uuid"},"relationshipType":{"type":"string","enum":["broader","narrower","synonym","related","variant"]},"description":{"type":"string","maxLength":500},"displayOrder":{"type":"integer","minimum":0,"maximum":999,"default":0}},"required":["targetTermId","relationshipType"]}}}},"responses":{"201":{"description":"Relationship created"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/glossaries/{id}/terms/{termId}/external-links":{"get":{"tags":["Glossary"],"summary":"List external links for a term","description":"Get all external links (URLs to authoritative sources like Collibra, articles, videos).","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"termId","in":"path"}],"responses":{"200":{"description":"External links","content":{"application/json":{"schema":{"type":"object","properties":{"links":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["links"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Glossary"],"summary":"Add external link to a term","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"termId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":2000}},"required":["url","title"]}}}},"responses":{"201":{"description":"External link added"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/library":{"get":{"tags":["Library"],"summary":"Search the content library","description":"Unified search across library statements, glossary terms, and regulations. Supports tab-based filtering (statements, glossary, regulations).","parameters":[{"schema":{"type":"string","description":"Search query (default: *)"},"required":false,"description":"Search query (default: *)","name":"q","in":"query"},{"schema":{"type":"string","description":"Filter by tab: statements, glossary, regulations"},"required":false,"description":"Filter by tab: statements, glossary, regulations","name":"tab","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"per_page","in":"query"},{"schema":{"type":"string","description":"Filter by domain"},"required":false,"description":"Filter by domain","name":"domain","in":"query"}],"responses":{"200":{"description":"Library search results with facets and pagination metadata","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"document":{"type":"object","additionalProperties":{}},"highlights":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["document"]}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]},"facets":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"counts":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"count":{"type":"integer"}},"required":["value","count"]}}},"required":["field","counts"]}}},"required":["data","meta","facets"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/library/statements/{id}":{"get":{"tags":["Library"],"summary":"Get a library statement","description":"Retrieve a single library statement with its current version, domain, and metadata.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Library statement detail","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/library/statements/{id}/term-links":{"get":{"tags":["Library"],"summary":"Get term links for a library statement","description":"Retrieve glossary terms linked to a specific library statement version.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Linked glossary terms","content":{"application/json":{"schema":{"type":"object","properties":{"termLinks":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["termLinks"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/library/glossary":{"get":{"tags":["Library"],"summary":"Browse library glossary","description":"Browse the shared governance glossary with search and pagination.","parameters":[{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Library glossary terms with pagination metadata","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":{}}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]}},"required":["data","meta"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/library/glossary/{id}":{"get":{"tags":["Library"],"summary":"Get a library glossary term","description":"Retrieve a single library glossary term with relationships, external links, and statement links.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Library glossary term detail","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/regulations":{"get":{"tags":["Regulations"],"security":[],"summary":"List regulations","description":"List all regulations in the registry with optional filtering by region, category, and sector.","parameters":[{"schema":{"type":"string","description":"Search query"},"required":false,"description":"Search query","name":"q","in":"query"},{"schema":{"type":"string","description":"Filter by region","example":"EU"},"required":false,"description":"Filter by region","name":"region","in":"query"},{"schema":{"type":"string","description":"Filter by category"},"required":false,"description":"Filter by category","name":"category","in":"query"},{"schema":{"type":"string","description":"Filter by sector (general, financial_services, healthcare, education, public)"},"required":false,"description":"Filter by sector (general, financial_services, healthcare, education, public)","name":"sector","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"example":20},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Regulation list","content":{"application/json":{"schema":{"type":"object","properties":{"regulations":{"type":"array","items":{"type":"object","additionalProperties":{}}},"found":{"type":"number"},"facets":{"type":"array","items":{"type":"object","additionalProperties":{}}},"families":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"memberSlugs":{"type":"array","items":{"type":"string"}},"region":{"type":"string"}},"required":["id","label","memberSlugs","region"]}}},"required":["regulations","found","facets","families"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/regulations/{slug}":{"get":{"tags":["Regulations"],"security":[],"summary":"Get a regulation","description":"Retrieve a regulation by slug with its requirements and metadata.","parameters":[{"schema":{"type":"string","description":"Regulation slug","example":"gdpr"},"required":true,"description":"Regulation slug","name":"slug","in":"path"}],"responses":{"200":{"description":"Regulation detail with requirements","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string"}},"required":["slug"],"additionalProperties":{}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/regulations/{slug}/annotations":{"get":{"tags":["Regulations"],"summary":"List regulation annotations","description":"Get all annotations (rationale, guidance, examples) for a regulation.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"Regulation annotations","content":{"application/json":{"schema":{"type":"object","properties":{"annotations":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["annotations"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Regulations"],"summary":"Add a regulation annotation","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"annotationType":{"type":"string","enum":["rationale","justification","example","note","guidance"]},"content":{"type":"string","minLength":1,"maxLength":10000}},"required":["annotationType","content"]}}}},"responses":{"201":{"description":"Annotation created"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/regulations/{slug}/requirements/adopt":{"post":{"tags":["Regulations"],"summary":"Adopt regulation requirements","description":"Adopt selected regulation requirements as tenant statements, optionally assigning to a domain.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"requirementIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1},"targetDomainId":{"type":"string","format":"uuid"}},"required":["requirementIds"]}}}},"responses":{"201":{"description":"Requirements adopted as statements","content":{"application/json":{"schema":{"type":"object","properties":{"adopted":{"type":"number"},"statementIds":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["adopted","statementIds"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/regulations/{slug}/requirements/{reqId}/mappings":{"get":{"tags":["Regulations"],"summary":"List requirement mappings","description":"Get all statement mappings for a specific regulation requirement.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"reqId","in":"path"}],"responses":{"200":{"description":"Requirement-to-statement mappings","content":{"application/json":{"schema":{"type":"object","properties":{"mappings":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["mappings"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Regulations"],"summary":"Create requirement mapping","description":"Map a library statement to a regulation requirement.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"reqId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"libraryStatementId":{"type":"string","format":"uuid"},"mappingType":{"type":"string","enum":["satisfies","partially_satisfies","implements","addresses"]},"notes":{"type":["string","null"],"maxLength":2000}},"required":["libraryStatementId","mappingType"]}}}},"responses":{"201":{"description":"Mapping created"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/settings/api-keys":{"get":{"tags":["Settings"],"summary":"List API keys","description":"List all API keys for the current tenant. Only key prefixes are returned (hashes are never exposed).","responses":{"200":{"description":"API key list","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"keyPrefix":{"type":"string","example":"dv_live_AbCdEf"},"scopes":{"type":"array","items":{"type":"string"}},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","name","description","keyPrefix","scopes","lastUsedAt","expiresAt","revokedAt","createdAt"]}}},"required":["keys"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Settings"],"summary":"Create an API key","description":"Generate a new API key. The full key is returned **only once** in the response — store it securely. Subsequent reads only show the prefix.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":1000},"scopes":{"type":"array","items":{"type":"string","enum":["statement:read","assembly:read","glossary:read","control:read","exception:read","attestation:read","library:browse","action:read","report:read","regulation:read"]},"minItems":1},"expiresAt":{"type":"string","format":"date-time"}},"required":["name","scopes"]}}}},"responses":{"201":{"description":"API key created — full key returned only once","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"key":{"type":"string","description":"Full API key — store securely, shown only once","example":"dv_live_AbCdEfGhIjKlMnOpQrStUvWxYz0123456789abc"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"expiresAt":{"type":["string","null"],"format":"date-time"}},"required":["id","key","name","scopes","expiresAt"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"patch":{"tags":["Settings"],"summary":"Update an API key","description":"Update an API key's name, description, or scopes.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":["string","null"],"maxLength":1000},"scopes":{"type":"array","items":{"type":"string","enum":["statement:read","assembly:read","glossary:read","control:read","exception:read","attestation:read","library:browse","action:read","report:read","regulation:read"]},"minItems":1}},"required":["id"]}}}},"responses":{"200":{"description":"API key updated"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"delete":{"tags":["Settings"],"summary":"Revoke an API key","description":"Permanently revoke an API key. This cannot be undone.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"]}}}},"responses":{"200":{"description":"API key revoked"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/settings/tags":{"get":{"tags":["Settings"],"summary":"List governed tags","description":"List all governed tags for the current tenant, with their rules and usage counts.","responses":{"200":{"description":"Tag list","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["items"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"post":{"tags":["Settings"],"summary":"Create a governed tag","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"domainId":{"type":"string","format":"uuid"},"tag":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":2000},"lifecycle":{"type":"string","enum":["active","deprecated","retired"],"default":"active"},"color":{"type":"string","maxLength":50},"scope":{"type":"string","enum":["tenant","domain","assembly"],"default":"tenant"},"ownerId":{"type":"string","format":"uuid"}},"required":["domainId","tag"]}}}},"responses":{"201":{"description":"Tag created"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/settings/tags/{id}":{"patch":{"tags":["Settings"],"summary":"Update a governed tag","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tag":{"type":"string","minLength":1,"maxLength":100},"description":{"type":["string","null"],"maxLength":2000},"lifecycle":{"type":"string","enum":["active","deprecated","retired"]},"color":{"type":["string","null"],"maxLength":50},"scope":{"type":"string","enum":["tenant","domain","assembly"]},"ownerId":{"type":["string","null"],"format":"uuid"}}}}}},"responses":{"200":{"description":"Tag updated"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}},"delete":{"tags":["Settings"],"summary":"Delete a governed tag","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tag deleted"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/settings/admin/activity":{"get":{"tags":["Settings"],"summary":"List admin activity","description":"Paginated governance event audit log. Filterable by entity type, action, and actor.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"example":50},"required":false,"name":"per_page","in":"query"},{"schema":{"type":"string","description":"Filter by entity type","example":"statement"},"required":false,"description":"Filter by entity type","name":"entityType","in":"query"},{"schema":{"type":"string","description":"Filter by action","example":"approved"},"required":false,"description":"Filter by action","name":"action","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Filter by actor user ID"},"required":false,"description":"Filter by actor user ID","name":"actorId","in":"query"}],"responses":{"200":{"description":"Paginated governance events","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"actorName":{"type":"string"},"action":{"type":"string"},"entityType":{"type":"string"},"summary":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","actorName","action","entityType","summary","createdAt"],"additionalProperties":{}}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]}},"required":["data","meta"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/settings/members":{"get":{"tags":["Settings"],"summary":"List tenant members","description":"List all users who are members of the current tenant.","responses":{"200":{"description":"Member list","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["items"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/settings/domains":{"get":{"tags":["Settings"],"summary":"List governance domains","description":"List all governance domains configured for the tenant.","responses":{"200":{"description":"Domain list","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["items"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/auth/resolve-method":{"post":{"tags":["Auth"],"summary":"Resolve sign-in method","description":"Determine the authentication method for a given email address. Returns `credential` for magic link sign-in, or `sso` with provider details for domains with verified SSO configuration. This is a pre-authentication endpoint — no session or API key required.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"alice@acme.com"}},"required":["email"]}}}},"responses":{"200":{"description":"Authentication method resolved","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"method":{"type":"string","enum":["credential"]}},"required":["method"]},{"type":"object","properties":{"method":{"type":"string","enum":["sso"]},"providerId":{"type":"string","example":"sso_abc123"},"tenantName":{"type":"string","example":"Acme Corp"}},"required":["method","providerId","tenantName"]}]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}},"/api/health":{"get":{"tags":["Health"],"summary":"Overall health check","description":"Returns aggregate health status of all backend services (Postgres, Typesense, Redis, schema).","security":[],"responses":{"200":{"description":"All services healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded"]},"timestamp":{"type":"string"},"version":{"type":"string"},"services":{"type":"object","properties":{"webapp":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","unhealthy"]},"latency_ms":{"type":"integer"}},"required":["status","latency_ms"]},"postgres":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","unhealthy"]},"latency_ms":{"type":"integer"}},"required":["status","latency_ms"]},"typesense":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","unhealthy"]},"latency_ms":{"type":"integer"}},"required":["status","latency_ms"]},"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","unhealthy"]},"latency_ms":{"type":"integer"}},"required":["status","latency_ms"]},"redis":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","unhealthy"]},"latency_ms":{"type":"integer"}},"required":["status","latency_ms"]}},"required":["webapp","postgres","typesense","schema","redis"]}},"required":["status","timestamp","version","services"]}}}},"503":{"description":"One or more services unhealthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded"]},"timestamp":{"type":"string"},"version":{"type":"string"},"services":{"type":"object","additionalProperties":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","unhealthy"]},"latency_ms":{"type":"integer"}},"required":["status","latency_ms"]}}},"required":["status","timestamp","version","services"]}}}}}}},"/api/health/live":{"get":{"tags":["Health"],"summary":"Liveness probe","description":"Simple liveness check — always returns 200 if the process is running. Used by orchestrators (Kubernetes, Docker).","security":[],"responses":{"200":{"description":"Process alive","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]}},"required":["status"]}}}}}}},"/api/health/redis":{"get":{"tags":["Health"],"summary":"Redis health check","security":[],"responses":{"200":{"description":"Redis connected","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy"]},"latency_ms":{"type":"integer"}},"required":["status","latency_ms"]}}}},"503":{"description":"Redis unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["unhealthy"]},"error":{"type":"string"}},"required":["status","error"]}}}}}}},"/api/health/typesense":{"get":{"tags":["Health"],"summary":"Typesense health check","security":[],"responses":{"200":{"description":"Typesense connected","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy"]},"latency_ms":{"type":"integer"}},"required":["status","latency_ms"]}}}},"503":{"description":"Typesense unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["unhealthy"]},"error":{"type":"string"}},"required":["status","error"]}}}}}}},"/api/billing/checkout":{"post":{"tags":["Billing"],"summary":"Create Stripe Checkout session for plan upgrade","description":"Creates a Stripe Checkout session for upgrading to Professional or Business. Promotion codes enabled. Returns a redirect URL to the Stripe-hosted checkout page.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"planTier":{"type":"string","enum":["professional","business"]},"billingInterval":{"type":"string","enum":["monthly","annual"]}},"required":["planTier","billingInterval"]}}}},"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/billing/portal":{"post":{"tags":["Billing"],"summary":"Create Stripe Customer Portal session","description":"Creates a Customer Portal session for managing subscription, payment methods, invoice history, and cancellation. Requires an active Stripe customer.","responses":{"200":{"description":"Portal session created","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}}}},"400":{"description":"No billing account found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/billing/usage":{"get":{"tags":["Billing"],"summary":"Get tenant billing state","description":"Returns the full billing state: current plan, subscription status, usage metrics for the current period, remaining credits, plan limits, and the complete entitlement map.","responses":{"200":{"description":"Billing state","content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"tier":{"type":"string","enum":["community","professional","business","enterprise"]},"monthlyPriceCents":{"type":["number","null"]},"annualPriceCents":{"type":["number","null"]}},"required":["id","name","slug","tier","monthlyPriceCents","annualPriceCents"]},"subscription":{"type":["object","null"],"properties":{"status":{"type":"string"},"billingInterval":{"type":"string","enum":["monthly","annual"]},"currentPeriodStart":{"type":["string","null"],"format":"date-time"},"currentPeriodEnd":{"type":["string","null"],"format":"date-time"},"cancelAt":{"type":["string","null"],"format":"date-time"}},"required":["status","billingInterval","currentPeriodStart","currentPeriodEnd","cancelAt"]},"usage":{"type":"object","properties":{"aiCreditsUsed":{"type":"number"},"purchasedCreditsUsed":{"type":"number"},"statementsCreated":{"type":"number"},"assembliesCreated":{"type":"number"},"usersActive":{"type":"number"},"apiRequests":{"type":"number"},"periodStart":{"type":"string"}},"required":["aiCreditsUsed","purchasedCreditsUsed","statementsCreated","assembliesCreated","usersActive","apiRequests","periodStart"]},"credits":{"type":"object","properties":{"monthly":{"type":"number"},"purchased":{"type":"number"},"total":{"type":"number"}},"required":["monthly","purchased","total"]},"limits":{"type":"object","properties":{"maxUsers":{"type":["number","null"]},"maxAssemblies":{"type":["number","null"]},"maxStatements":{"type":["number","null"]},"maxGlossaryTerms":{"type":["number","null"]},"maxFrameworks":{"type":["number","null"]},"monthlyAiCredits":{"type":["number","null"]}},"required":["maxUsers","maxAssemblies","maxStatements","maxGlossaryTerms","maxFrameworks","monthlyAiCredits"]},"entitlements":{"type":"object","additionalProperties":{"type":"object","properties":{"allowed":{"type":"boolean"},"reason":{"type":"string"},"limit":{"type":["number","null"]},"current":{"type":"number"},"upgradeTarget":{"type":"string"}},"required":["allowed"]}}},"required":["plan","subscription","usage","credits","limits","entitlements"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/billing/credits":{"post":{"tags":["Billing"],"summary":"Create Stripe Checkout session for credit pack purchase","description":"Creates a one-time payment Checkout session for purchasing an AI credit pack. Packs: Starter (500 credits / $9), Growth (1,000 / $15), Scale (5,000 / $59). Credits are added to the tenant balance after successful payment via webhook.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"pack":{"type":"string","enum":["starter","growth","scale"]}},"required":["pack"]}}}},"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]}}}},"400":{"description":"Invalid pack","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/billing/api-usage":{"get":{"tags":["Billing"],"summary":"Get API and MCP usage metrics for the current billing period","description":"Returns API and MCP request counts for the current period, daily breakdown over the last 30 days, rate limit utilization, and top endpoints. Used by the usage dashboard in Settings > Billing.","responses":{"200":{"description":"API usage metrics","content":{"application/json":{"schema":{"type":"object","properties":{"period":{"type":"object","properties":{"start":{"type":"string","example":"2026-03-01"},"end":{"type":"string","example":"2026-03-31"}},"required":["start","end"]},"apiRequests":{"type":"integer","example":142},"mcpRequests":{"type":"integer","example":38},"rateLimit":{"type":"object","properties":{"tier":{"type":"string","enum":["community","professional","business","enterprise"]},"requestsPerMinute":{"type":"integer","example":20},"utilizationPercent":{"type":"number","example":12.5}},"required":["tier","requestsPerMinute","utilizationPercent"]},"daily":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","example":"2026-03-25"},"apiRequests":{"type":"integer"},"mcpRequests":{"type":"integer"}},"required":["date","apiRequests","mcpRequests"]}}},"required":["period","apiRequests","mcpRequests","rateLimit","daily"]}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/agent/bundles/{assemblyId}":{"get":{"tags":["Agent"],"summary":"Get compiled assembly bundle","description":"Compiles an assembly into a machine-readable governance bundle with statements, glossary, agent guidance, and a signed content manifest.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Assembly UUID"},"required":true,"description":"Assembly UUID","name":"assemblyId","in":"path"},{"schema":{"type":"string","enum":["json","json-ld"],"description":"Output format","example":"json"},"required":false,"description":"Output format","name":"format","in":"query"},{"schema":{"type":"string","enum":["human","agent","both"],"description":"Filter statements by actor applicability"},"required":false,"description":"Filter statements by actor applicability","name":"actor","in":"query"}],"responses":{"200":{"description":"Compiled governance bundle","content":{"application/json":{"schema":{"type":"object","properties":{"bundleVersion":{"type":"string"},"format":{"type":"string","enum":["json","json-ld"]},"compiledAt":{"type":"string"},"assembly":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayId":{"type":"string"},"title":{"type":"string"},"assemblyType":{"type":"string"},"assemblyState":{"type":"string"}},"required":["id","displayId","title","assemblyType","assemblyState"],"additionalProperties":{}},"statements":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayId":{"type":"string"},"title":{"type":["string","null"]},"body":{"type":["string","null"]},"modality":{"type":["string","null"]},"statementType":{"type":["string","null"]},"lifecycleState":{"type":"string"},"appliesTo":{"type":"string"},"actorScope":{"type":["array","null"],"items":{"type":"string"}},"enforcementMode":{"type":["string","null"]},"domain":{"type":["string","null"]},"agentGuidance":{"type":["object","null"],"properties":{"allowedActions":{"type":["array","null"],"items":{"type":"string"}},"prohibitedActions":{"type":["array","null"],"items":{"type":"string"}},"requiredContext":{"type":["array","null"],"items":{"type":"string"}},"requiredApprovals":{},"evidenceRequirements":{"type":["array","null"],"items":{"type":"string"}},"escalationRules":{"type":["object","null"],"additionalProperties":{}},"failureMode":{"type":["object","null"],"additionalProperties":{}}},"required":["allowedActions","prohibitedActions","requiredContext","evidenceRequirements","escalationRules","failureMode"]},"updatedAt":{"type":"string"}},"required":["id","displayId","title","body","modality","statementType","lifecycleState","appliesTo","actorScope","enforcementMode","domain","agentGuidance","updatedAt"],"additionalProperties":{}}},"glossary":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"term":{"type":"string"}},"required":["id","term"],"additionalProperties":{}}},"manifest":{"type":"object","properties":{"statementCount":{"type":"integer"},"glossaryTermCount":{"type":"integer"},"contentHash":{"type":"string"},"algorithm":{"type":"string","enum":["sha256"]}},"required":["statementCount","glossaryTermCount","contentHash","algorithm"]}},"required":["bundleVersion","format","compiledAt","assembly","statements","glossary","manifest"],"additionalProperties":{}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"404":{"description":"Assembly not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Assembly not found"}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/agent/statements":{"get":{"tags":["Agent"],"summary":"Search statements by governance dimension","description":"Returns statements filtered by actor applicability, enforcement mode, domain, and actor scope. Includes structured agent guidance fields.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["human","agent","both"],"description":"Filter by actor applicability"},"required":false,"description":"Filter by actor applicability","name":"applies_to","in":"query"},{"schema":{"type":"string","enum":["informational","human_review_required","machine_readable","machine_enforceable"],"description":"Filter by enforcement mode"},"required":false,"description":"Filter by enforcement mode","name":"enforcement_mode","in":"query"},{"schema":{"type":"string","description":"Comma-separated actor scopes (e.g. agent,agent-workflow)"},"required":false,"description":"Comma-separated actor scopes (e.g. agent,agent-workflow)","name":"actor_scope","in":"query"},{"schema":{"type":"string","description":"Filter by governance domain name"},"required":false,"description":"Filter by governance domain name","name":"domain","in":"query"},{"schema":{"type":"string","description":"Text search"},"required":false,"description":"Text search","name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Paginated list of statements with agent guidance","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayId":{"type":"string"},"title":{"type":["string","null"]},"body":{"type":["string","null"]},"modality":{"type":["string","null"]},"statementType":{"type":["string","null"]},"lifecycleState":{"type":"string"},"appliesTo":{"type":"string"},"actorScope":{"type":["array","null"],"items":{"type":"string"}},"enforcementMode":{"type":["string","null"]},"domain":{"type":["string","null"]},"agentGuidance":{"type":["object","null"],"properties":{"allowedActions":{"type":["array","null"],"items":{"type":"string"}},"prohibitedActions":{"type":["array","null"],"items":{"type":"string"}},"requiredContext":{"type":["array","null"],"items":{"type":"string"}},"requiredApprovals":{},"evidenceRequirements":{"type":["array","null"],"items":{"type":"string"}},"escalationRules":{"type":["object","null"],"additionalProperties":{}},"failureMode":{"type":["object","null"],"additionalProperties":{}}},"required":["allowedActions","prohibitedActions","requiredContext","evidenceRequirements","escalationRules","failureMode"]},"updatedAt":{"type":"string"}},"required":["id","displayId","title","body","modality","statementType","lifecycleState","appliesTo","actorScope","enforcementMode","domain","agentGuidance","updatedAt"]}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]}},"required":["data","meta"]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/agent/statements/{idOrDisplayId}":{"get":{"tags":["Agent"],"summary":"Resolve a single statement (issuance-ready bundle)","description":"Returns one statement by UUID or displayId, including the canonical hash + currentVersion + uri an issuer needs to call POST /api/agent/attestations. Use this to resolve a statementRef in a `dictiva attest` issuance flow without computing the canonical hash client-side.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Statement UUID (e.g. 550e8400-...) or displayId (e.g. AAG-014).","example":"AAG-014"},"required":true,"description":"Statement UUID (e.g. 550e8400-...) or displayId (e.g. AAG-014).","name":"idOrDisplayId","in":"path"}],"responses":{"200":{"description":"Statement resolved with canonical hash + version","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayId":{"type":"string"},"title":{"type":["string","null"]},"body":{"type":["string","null"]},"modality":{"type":["string","null"]},"statementType":{"type":["string","null"]},"lifecycleState":{"type":"string"},"appliesTo":{"type":"string"},"actorScope":{"type":["array","null"],"items":{"type":"string"}},"enforcementMode":{"type":["string","null"]},"domain":{"type":["string","null"]},"agentGuidance":{"type":["object","null"],"properties":{"allowedActions":{"type":["array","null"],"items":{"type":"string"}},"prohibitedActions":{"type":["array","null"],"items":{"type":"string"}},"requiredContext":{"type":["array","null"],"items":{"type":"string"}},"requiredApprovals":{},"evidenceRequirements":{"type":["array","null"],"items":{"type":"string"}},"escalationRules":{"type":["object","null"],"additionalProperties":{}},"failureMode":{"type":["object","null"],"additionalProperties":{}}},"required":["allowedActions","prohibitedActions","requiredContext","evidenceRequirements","escalationRules","failureMode"]},"updatedAt":{"type":"string"},"currentVersion":{"type":"integer","minimum":1},"canonicalHash":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","description":"JCS-canonical SHA-256 of the body at currentVersion"},"uri":{"type":"string","format":"uri","description":"Canonical https URL for inclusion in statementRef.uri"}},"required":["id","displayId","title","body","modality","statementType","lifecycleState","appliesTo","actorScope","enforcementMode","domain","agentGuidance","updatedAt","currentVersion","canonicalHash","uri"]}},"required":["data"]}}}},"400":{"description":"Missing or empty identifier"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"404":{"description":"Statement not found in this tenant"},"422":{"description":"Statement has no versions to attest against"},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/agent/glossary":{"get":{"tags":["Agent"],"summary":"Search glossary terms with ontology metadata","description":"Returns glossary terms with machine keys, aliases, term types, and ontology relationships. Filtered by actor applicability and term type.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["human","agent","both"],"description":"Filter by actor applicability"},"required":false,"description":"Filter by actor applicability","name":"applies_to","in":"query"},{"schema":{"type":"string","enum":["concept","role","action","constraint","metric"],"description":"Filter by term type"},"required":false,"description":"Filter by term type","name":"term_type","in":"query"},{"schema":{"type":"string","description":"Text search"},"required":false,"description":"Text search","name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Paginated list of glossary terms with ontology metadata","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"term":{"type":"string"},"definition":{"type":["string","null"]},"status":{"type":["string","null"]},"machineKey":{"type":["string","null"]},"aliases":{"type":["array","null"],"items":{"type":"string"}},"termType":{"type":["string","null"]},"appliesTo":{"type":"string"},"actorScope":{"type":["array","null"],"items":{"type":"string"}},"broaderTermId":{"type":["string","null"],"format":"uuid"},"glossary":{"type":"string"},"relationships":{"type":"array","items":{"type":"object","properties":{"targetTermId":{"type":"string","format":"uuid"},"relationshipType":{"type":"string"}},"required":["targetTermId","relationshipType"]}},"updatedAt":{"type":"string"}},"required":["id","term","definition","status","machineKey","aliases","termType","appliesTo","actorScope","broaderTermId","glossary","relationships","updatedAt"]}},"meta":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","perPage","total","totalPages"]}},"required":["data","meta"]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/agent/ontology":{"get":{"tags":["Agent"],"summary":"Export glossary as ontology graph","description":"Returns the full glossary as a typed ontology graph with hierarchical and associative relationships between terms.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["json","json-ld"],"description":"Output format","example":"json"},"required":false,"description":"Output format","name":"format","in":"query"},{"schema":{"type":"string","enum":["human","agent","both"],"description":"Filter by actor applicability"},"required":false,"description":"Filter by actor applicability","name":"applies_to","in":"query"}],"responses":{"200":{"description":"Ontology graph with terms and relationships","content":{"application/json":{"schema":{"type":"object","properties":{"ontologyVersion":{"type":"string"},"compiledAt":{"type":"string"},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]},"terms":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"term":{"type":"string"},"definition":{"type":["string","null"]},"machineKey":{"type":["string","null"]},"aliases":{"type":["array","null"],"items":{"type":"string"}},"termType":{"type":["string","null"]},"appliesTo":{"type":"string"},"actorScope":{"type":["array","null"],"items":{"type":"string"}},"broaderTermId":{"type":["string","null"],"format":"uuid"}},"required":["id","term","definition","machineKey","aliases","termType","appliesTo","actorScope","broaderTermId"]}},"relationships":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string","format":"uuid"},"target":{"type":"string","format":"uuid"},"type":{"type":"string"},"description":{"type":["string","null"]}},"required":["source","target","type","description"]}},"stats":{"type":"object","properties":{"termCount":{"type":"integer"},"relationshipCount":{"type":"integer"},"termTypes":{"type":"object","additionalProperties":{"type":"integer"}},"actorApplicability":{"type":"object","additionalProperties":{"type":"integer"}}},"required":["termCount","relationshipCount","termTypes","actorApplicability"]}},"required":["ontologyVersion","compiledAt","tenant","terms","relationships","stats"],"additionalProperties":{}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/agent/skills/attestation-drafts":{"post":{"tags":["Agent"],"summary":"Register skill `attests:` frontmatter as workbench drafts","description":"Ingests skills carrying `attests:` YAML frontmatter into the workbench drafts inbox. Idempotent against (skillPath, contentHash). Same drafts table + finalize/reject flow as the GitHub-webhook ingestion path.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"skills":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1},"path":{"type":"string","minLength":1},"frontmatter":{"type":"object","additionalProperties":{}},"contentHash":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$"}},"required":["name","path","frontmatter"]},"minItems":1,"maxItems":100}},"required":["skills"]}}}},"responses":{"200":{"description":"Drafts ingested (or returned as deduped)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"drafts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"skillName":{"type":"string"},"skillPath":{"type":"string"},"statementRef":{"type":"string"},"tier":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"]},"status":{"type":"string","enum":["pending_review"]},"deduped":{"type":"boolean"}},"required":["id","skillName","skillPath","statementRef","tier","status","deduped"]}},"ingested":{"type":"integer","minimum":0},"skipped":{"type":"integer","minimum":0}},"required":["drafts","ingested","skipped"]}},"required":["data"]}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/mcp":{"post":{"summary":"MCP governance server (Streamable HTTP)","description":"Model Context Protocol endpoint over Streamable HTTP, stateless JSON mode. Accepts JSON-RPC 2.0 requests (initialize, tools/list, tools/call, resources/list, resources/read, prompts/list, prompts/get). Same 6 tools as the stdio transport, gated by the same API-key auth and Business+ entitlement. Pairs with scripts/mcp-governance-server.ts for local stdio use.","tags":["Agent"],"security":[{"bearerAuth":[]}],"requestBody":{"description":"JSON-RPC 2.0 request per MCP Streamable HTTP spec","content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"anyOf":[{"type":"string"},{"type":"number"}]},"method":{"type":"string","description":"MCP method name (initialize, tools/list, tools/call, etc.)","example":"tools/list"},"params":{"type":"object","additionalProperties":{}}},"required":["jsonrpc","method"],"additionalProperties":{}}}}},"responses":{"200":{"description":"JSON-RPC 2.0 response or SSE stream","content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"anyOf":[{"type":"string"},{"type":"number"}]},"result":{"type":"object","additionalProperties":{}},"error":{"type":"object","properties":{"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"]}},"required":["jsonrpc","id"]}}}},"401":{"description":"Missing or invalid API key"},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/agent/attestations":{"post":{"tags":["Policy Commitment Attestation"],"summary":"Issue a Policy Commitment Attestation credential","description":"Issues a signed W3C Verifiable Credential of type `PolicyCommitmentCredential`\nbinding the given agent DID to the referenced statement at the declared\nmaturity tier.\n\n**Status:** contract-first — returns 501 Not Implemented until Epic B\n#2302 wires the DigitalBazaar-backed issuer. The request body is\nvalidated today; malformed payloads return 400.\n\n**Spec:** https://policycommitment.dictiva.com/SPEC.md","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueAttestationRequest"}}}},"responses":{"201":{"description":"Attestation issued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyCommitmentAttestation"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"501":{"description":"Not yet implemented — contract-first stub. See Epic B #2302."}}},"get":{"tags":["Policy Commitment Attestation"],"summary":"List issued attestations","parameters":[{"schema":{"type":"string"},"required":false,"name":"subject_did","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"statement_id","in":"query"},{"schema":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Commitment Maturity Ladder tier, per PCA spec §4.","example":"T4"},"required":false,"description":"Commitment Maturity Ladder tier, per PCA spec §4.","name":"tier","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Default: false."},"required":false,"description":"Default: false.","name":"include_revoked","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Paginated list of attestations.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PolicyCommitmentAttestation"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"perPage":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"501":{"description":"Not yet implemented — contract-first stub. See Epic B #2302."}}}},"/api/agent/attestations/{id}":{"get":{"tags":["Policy Commitment Attestation"],"summary":"Retrieve a specific attestation","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Attestation UUID."}],"responses":{"200":{"description":"Attestation row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyCommitmentAttestation"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Not yet implemented — contract-first stub. See Epic B #2302."}}}},"/api/agent/attestations/{id}/revoke":{"post":{"tags":["Policy Commitment Attestation"],"summary":"Revoke a previously-issued attestation","description":"Flips the VC Status List 2021 bit for the referenced credential and\nwrites `revokedAt` / `revokedReason` to the database. Revocation is\naudit-trail: the row is never deleted.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeAttestationRequest"}}}},"responses":{"200":{"description":"Attestation revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyCommitmentAttestation"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Not yet implemented — contract-first stub. See Epic B #2302."}}}},"/api/agent/attestations/verify":{"post":{"tags":["Policy Commitment Attestation"],"summary":"Stateless verification of a PCA credential","description":"Accepts an already-signed W3C VC of type `PolicyCommitmentCredential`\nand returns a `VerificationResult` without persisting anything. Useful\nfor third-party verifiers that want to cross-check a VC against the\npublished PCA spec.\n\n**Stub behavior:** partial tier-floor validation is live today (the\nlibrary `src/lib/attestation/tiers.ts` runs against the commitment\npayload shape). Cryptographic verification via the DigitalBazaar suite\nis pending Epic B #2302.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyAttestationRequest"}}}},"responses":{"200":{"description":"Verification result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationResult"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — MCP agent access requires Business or Enterprise plan. Upgrade to enable agent endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAccessDenied"}}}},"501":{"description":"Full verification not yet implemented. See Epic B #2302."}}}},"/api/governance/attestations/coverage-matrix":{"get":{"tags":["Policy Commitment Attestation"],"summary":"Statement × agent coverage matrix","description":"Returns the (statement × agent) → max-attested-tier matrix for the\nauthenticated tenant.\n\nPagination is on **statements** (rows), not cells. Cells are returned\n**sparsely** — only populated pairs are present; empty cells render\nvisually as gaps. Default page size 50 statements; cap 200.\n\nCell aggregation respects `include_revoked` (default false). `maxTier`\nis computed in Postgres via `MAX(commitment_tier)`, which leverages\nenum declaration order (T1 < T2 < ... < T6).\n\nThis is the demo path behind the *\"Governance your agents can follow\"*\ntagline: rows tell you which statements exist, columns tell you which\nagents committed, cell color tells you the maturity tier.","parameters":[{"schema":{"type":"string","format":"uuid","description":"Filter statements by domain UUID."},"required":false,"description":"Filter statements by domain UUID.","name":"domain_id","in":"query"},{"schema":{"type":"string","enum":["draft","in_review","approved","effective","retired","archived"],"description":"Filter statements by lifecycle state (e.g., 'effective' to hide drafts).","example":"effective"},"required":false,"description":"Filter statements by lifecycle state (e.g., 'effective' to hide drafts).","name":"lifecycle_state","in":"query"},{"schema":{"type":"string","pattern":"^did:[a-z0-9]+:/i","example":"did:web:dictiva.com:agents:code-reviewer","description":"Limit columns to a single agent (e.g., for an agent profile view)."},"required":false,"description":"Limit columns to a single agent (e.g., for an agent profile view).","name":"subject_did","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Include revoked credentials in cell aggregation. Default false."},"required":false,"description":"Include revoked credentials in cell aggregation. Default false.","name":"include_revoked","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1,"example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"per_page","in":"query"}],"responses":{"200":{"description":"Coverage matrix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoverageMatrixResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/governance/attestations/gap-report":{"get":{"tags":["Policy Commitment Attestation"],"summary":"Coverage gaps grouped by category","description":"Returns three categories of statement-level coverage gaps for the\nauthenticated tenant:\n\n* **untouched** — statements with zero live commitments\n* **belowTarget** — statements where MAX(commitment_tier) across all\n  agents is below `target_tier` (default T4)\n* **stale** — statements with at least one commitment against an older\n  version (statement was edited after attestation)\n\nEach group is independently capped via `limit_per_group` (default\n100, max 200). When a group overflows, its `truncated` flag is set —\nthe UI can show \"first N of M\" without follow-up pagination.\n\nThis endpoint answers the policy-author question *\"which of my\nstatements aren't covered well enough?\"* The per-agent counterpart\n(\"which statements is agent X behind on?\") is M2 / Epic G work.","parameters":[{"schema":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"default":"T4","description":"Threshold tier for the `belowTarget` group. Statements where MAX(tier) < target_tier are flagged. Default T4.","example":"T4"},"required":false,"description":"Threshold tier for the `belowTarget` group. Statements where MAX(tier) < target_tier are flagged. Default T4.","name":"target_tier","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Filter statements by domain UUID."},"required":false,"description":"Filter statements by domain UUID.","name":"domain_id","in":"query"},{"schema":{"type":"string","enum":["draft","in_review","approved","effective","retired","archived"],"description":"Filter statements by lifecycle state (e.g., 'effective' to hide drafts).","example":"effective"},"required":false,"description":"Filter statements by lifecycle state (e.g., 'effective' to hide drafts).","name":"lifecycle_state","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":100,"description":"Cap on rows returned per group (untouched, belowTarget, stale). When exceeded, the corresponding `truncated` flag is set.","example":100},"required":false,"description":"Cap on rows returned per group (untouched, belowTarget, stale). When exceeded, the corresponding `truncated` flag is set.","name":"limit_per_group","in":"query"}],"responses":{"200":{"description":"Gap report grouped by category.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GapReportResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/governance/attestations/expiration-calendar":{"get":{"tags":["Policy Commitment Attestation"],"summary":"Credentials expiring in the next N days","description":"Returns a flat, chronologically-ordered list of credentials whose\n`expiresAt` falls within `window_days` days from now (default 30).\nDrives the workbench revalidation queue at\n`/workbench/attestations/expiring`.\n\nThe response is intentionally flat — the UI does its own grouping\n(by week, by tier, by agent) without round-trips. The summary block\nreturns a tier-bucket histogram + earliest/latest expiry computed\nacross the FULL in-window set, so it stays accurate even when the\npage is truncated.\n\nAlready-expired credentials are excluded — they're handled by the\nBullMQ revalidation worker via `needs_revalidation` governance\nevents. Mixing them into the calendar would conflate \"what's coming\nup?\" with \"what failed?\".\n\nTier filter (`min_tier`) compares in enum-space:\n`commitment_tier >= $min::commitment_tier`.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":365,"default":30,"description":"Lookahead window in days. Default 30; common values 30 / 60 / 90.","example":30},"required":false,"description":"Lookahead window in days. Default 30; common values 30 / 60 / 90.","name":"window_days","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Filter to commitments on statements in a specific domain."},"required":false,"description":"Filter to commitments on statements in a specific domain.","name":"domain_id","in":"query"},{"schema":{"type":"string","pattern":"^did:[a-z0-9]+:/i","example":"did:web:dictiva.com:agents:code-reviewer","description":"Filter to commitments by a single agent (e.g., for an agent profile view)."},"required":false,"description":"Filter to commitments by a single agent (e.g., for an agent profile view).","name":"subject_did","in":"query"},{"schema":{"type":"string","enum":["T1","T2","T3","T4","T5","T6"],"description":"Filter to commitments at or above this tier (e.g., `T4` to surface only high-stakes credentials).","example":"T4"},"required":false,"description":"Filter to commitments at or above this tier (e.g., `T4` to surface only high-stakes credentials).","name":"min_tier","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Include revoked credentials. Default false."},"required":false,"description":"Include revoked credentials. Default false.","name":"include_revoked","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":200,"example":200},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Expiration calendar.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpirationCalendarResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"Unauthorized — missing or invalid API key / session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden — insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded — too many requests for this API key. Check `Retry-After` header.","headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed per window (varies by plan tier)","schema":{"type":"integer","example":20}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current 60-second window","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate limit window resets","schema":{"type":"integer","example":1742342460}},"X-RateLimit-Window":{"description":"Window duration in seconds","schema":{"type":"integer","example":60}},"Retry-After":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}}}}}},"/api/platform/tenants/{id}/billing":{"get":{"tags":["Platform Admin"],"summary":"Get tenant billing overview","description":"Returns the full billing state for a tenant: plan, subscription, usage metrics, recent billing events, credit transactions, and all available plans for override. Platform admin only.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tenant billing overview","content":{"application/json":{"schema":{"type":"object","properties":{"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"purchasedCredits":{"type":["number","null"]},"subscriptionStatus":{"type":["string","null"]},"stripeCustomerId":{"type":["string","null"]}},"required":["id","name","slug","purchasedCredits","subscriptionStatus","stripeCustomerId"]},"plan":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"tier":{"type":"string"},"monthlyAiCredits":{"type":["number","null"]}},"required":["id","name","slug","tier","monthlyAiCredits"]},"allPlans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"tier":{"type":"string"}},"required":["id","name","slug","tier"]}},"subscription":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"billingInterval":{"type":"string","enum":["monthly","annual"]},"currentPeriodStart":{"type":["string","null"],"format":"date-time"},"currentPeriodEnd":{"type":["string","null"],"format":"date-time"},"cancelAt":{"type":["string","null"],"format":"date-time"},"canceledAt":{"type":["string","null"],"format":"date-time"},"stripeSubscriptionId":{"type":["string","null"]}},"required":["id","status","billingInterval","currentPeriodStart","currentPeriodEnd","cancelAt","canceledAt","stripeSubscriptionId"]},"usage":{"type":["object","null"],"properties":{"aiCreditsUsed":{"type":"number"},"purchasedCreditsUsed":{"type":"number"},"statementsCreated":{"type":"number"},"assembliesCreated":{"type":"number"},"usersActive":{"type":"number"},"apiRequests":{"type":"number"},"periodStart":{"type":"string"},"periodEnd":{"type":"string"}},"required":["aiCreditsUsed","purchasedCreditsUsed","statementsCreated","assembliesCreated","usersActive","apiRequests","periodStart","periodEnd"]},"billingEvents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"action":{"type":"string"},"summary":{"type":["string","null"]},"actorName":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","action","summary","actorName","createdAt"]}},"creditTransactions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"amount":{"type":"number"},"balanceAfter":{"type":"number"},"description":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","type","amount","balanceAfter","description","createdAt"]}}},"required":["tenant","plan","allPlans","subscription","usage","billingEvents","creditTransactions"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Not a platform admin","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/platform/tenants/{id}/plan-override":{"post":{"tags":["Platform Admin"],"summary":"Override tenant plan","description":"Directly set a tenant's plan without Stripe subscription change. Used for partner/enterprise grants. Sets subscriptionStatus to active. Platform admin only.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"planId":{"type":"string","format":"uuid"},"reason":{"type":"string","minLength":1,"maxLength":500}},"required":["planId","reason"]}}}},"responses":{"200":{"description":"Plan overridden","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"fromPlan":{"type":"string"},"toPlan":{"type":"string"}},"required":["ok","fromPlan","toPlan"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Not a platform admin","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Tenant or plan not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/platform/tenants/{id}/credit-adjustment":{"post":{"tags":["Platform Admin"],"summary":"Adjust tenant credits","description":"Add or remove purchased credits from a tenant's balance (bonus, refund, or adjustment). Atomic transaction: balance update + ledger entry. Balance cannot go below zero. Platform admin only.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"type":"integer","description":"Credits to add (positive) or remove (negative)"},"type":{"type":"string","enum":["bonus","refund","adjustment"]},"description":{"type":"string","minLength":1,"maxLength":500}},"required":["amount","type","description"]}}}},"responses":{"200":{"description":"Credits adjusted","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"previousBalance":{"type":"number"},"newBalance":{"type":"number"},"transactionId":{"type":"string","format":"uuid"}},"required":["ok","previousBalance","newBalance","transactionId"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Not a platform admin","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/releases":{"get":{"tags":["Releases"],"summary":"List releases","description":"Returns all releases. Platform admins see drafts and silent releases; non-admins see only published, non-silent entries.","responses":{"200":{"description":"List of releases","content":{"application/json":{"schema":{"type":"object","properties":{"releases":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"string"},"title":{"type":"string"},"internalBody":{"type":["string","null"]},"customerBody":{"type":["string","null"]},"linkedIssues":{"type":["array","null"],"items":{"type":"object","properties":{"number":{"type":"number"},"title":{"type":"string"},"url":{"type":"string"}},"required":["number","title","url"]}},"visibility":{"type":"string","enum":["customer","internal","silent"]},"deployedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","version","title","internalBody","customerBody","linkedIssues","visibility","deployedAt","publishedAt","createdAt","updatedAt"]}}},"required":["releases"]}}}},"401":{"description":"Unauthorized"}}},"post":{"tags":["Releases"],"summary":"Create release","description":"Creates a new release entry. Platform admin only. Version must be unique and follow YYYY.MM.DD[.N] format.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"string"},"title":{"type":"string"},"internalBody":{"type":"string"},"customerBody":{"type":"string"},"linkedIssues":{"type":"array","items":{"type":"object","properties":{"number":{"type":"number"},"title":{"type":"string"},"url":{"type":"string"}},"required":["number","title","url"]}},"visibility":{"type":"string","enum":["customer","internal","silent"]},"deployedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":["string","null"],"format":"date-time"}},"required":["version","title","deployedAt"]}}}},"responses":{"201":{"description":"Release created","content":{"application/json":{"schema":{"type":"object","properties":{"release":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"string"},"title":{"type":"string"},"internalBody":{"type":["string","null"]},"customerBody":{"type":["string","null"]},"linkedIssues":{"type":["array","null"],"items":{"type":"object","properties":{"number":{"type":"number"},"title":{"type":"string"},"url":{"type":"string"}},"required":["number","title","url"]}},"visibility":{"type":"string","enum":["customer","internal","silent"]},"deployedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","version","title","internalBody","customerBody","linkedIssues","visibility","deployedAt","publishedAt","createdAt","updatedAt"]}},"required":["release"]}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — platform admin required"},"409":{"description":"Version already exists"}}}},"/api/releases/latest":{"get":{"tags":["Releases"],"summary":"Latest release version","description":"Returns the most recent release version and deploy timestamp. Public endpoint (no auth required). Used by client-side hot swap polling. Cached for 60 seconds.","security":[],"responses":{"200":{"description":"Latest release","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":["string","null"]},"deployedAt":{"type":["string","null"],"format":"date-time"}},"required":["version","deployedAt"]}}}}}}},"/api/releases/{version}":{"get":{"tags":["Releases"],"summary":"Get release by version","description":"Returns a single release. Non-admins only see published, non-silent releases.","parameters":[{"schema":{"type":"string"},"required":true,"name":"version","in":"path"}],"responses":{"200":{"description":"Release detail","content":{"application/json":{"schema":{"type":"object","properties":{"release":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"string"},"title":{"type":"string"},"internalBody":{"type":["string","null"]},"customerBody":{"type":["string","null"]},"linkedIssues":{"type":["array","null"],"items":{"type":"object","properties":{"number":{"type":"number"},"title":{"type":"string"},"url":{"type":"string"}},"required":["number","title","url"]}},"visibility":{"type":"string","enum":["customer","internal","silent"]},"deployedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","version","title","internalBody","customerBody","linkedIssues","visibility","deployedAt","publishedAt","createdAt","updatedAt"]}},"required":["release"]}}}},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}}},"patch":{"tags":["Releases"],"summary":"Update release","description":"Updates an existing release. Platform admin only. Set publishedAt to make visible on changelog, null to unpublish.","parameters":[{"schema":{"type":"string"},"required":true,"name":"version","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"internalBody":{"type":["string","null"]},"customerBody":{"type":["string","null"]},"linkedIssues":{"type":["array","null"],"items":{"type":"object","properties":{"number":{"type":"number"},"title":{"type":"string"},"url":{"type":"string"}},"required":["number","title","url"]}},"visibility":{"type":"string","enum":["customer","internal","silent"]},"deployedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":["string","null"],"format":"date-time"}}}}}},"responses":{"200":{"description":"Release updated","content":{"application/json":{"schema":{"type":"object","properties":{"release":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"string"},"title":{"type":"string"},"internalBody":{"type":["string","null"]},"customerBody":{"type":["string","null"]},"linkedIssues":{"type":["array","null"],"items":{"type":"object","properties":{"number":{"type":"number"},"title":{"type":"string"},"url":{"type":"string"}},"required":["number","title","url"]}},"visibility":{"type":"string","enum":["customer","internal","silent"]},"deployedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","version","title","internalBody","customerBody","linkedIssues","visibility","deployedAt","publishedAt","createdAt","updatedAt"]}},"required":["release"]}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — platform admin required"},"404":{"description":"Not found"}}}},"/api/releases/generate":{"post":{"tags":["Releases"],"summary":"Auto-generate release notes","description":"Generates a draft release entry from merged commits since the last release. Groups by conventional commit prefix. Platform admin only.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"sinceVersion":{"type":"string"}}}}}},"responses":{"201":{"description":"Draft release generated","content":{"application/json":{"schema":{"type":"object","properties":{"release":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"string"},"title":{"type":"string"},"internalBody":{"type":["string","null"]},"customerBody":{"type":["string","null"]},"linkedIssues":{"type":["array","null"],"items":{"type":"object","properties":{"number":{"type":"number"},"title":{"type":"string"},"url":{"type":"string"}},"required":["number","title","url"]}},"visibility":{"type":"string","enum":["customer","internal","silent"]},"deployedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","version","title","internalBody","customerBody","linkedIssues","visibility","deployedAt","publishedAt","createdAt","updatedAt"]},"generated":{"type":"boolean","enum":[true]}},"required":["release","generated"]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — platform admin required"}}}},"/api/invitation-requests":{"post":{"tags":["Invitation Requests"],"summary":"Submit an invitation request","description":"Public endpoint for requesting early access to Dictiva. Requires a corporate email (free email providers are rejected). Sends a notification to the Dictiva team for review.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationRequestBody"}}}},"responses":{"201":{"description":"Invitation request submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationRequestResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationRequestError"}}}},"409":{"description":"Duplicate request — email already submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationRequestError"}}}},"422":{"description":"Corporate email required — free email providers rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationRequestError"}}}}}}}},"webhooks":{}}