# Propose an immutable permission catalog POST /v1/projects/{project_id}/permission-catalogs Current project owner proposes a versioned catalog. A separate current platform project approver must approve it. Idempotency-Key replays the exact actor and body. Authentication: bearer access token with audience `taifa-management`. Endpoint roles and eligibility are reviewed separately from the OpenAPI bearer scheme. No operation-specific scopes are declared in the OpenAPI document. Bearer authentication and endpoint authorization requirements still apply. ## Parameters | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `project_id` | path | string | Yes | | | `idempotency-key` | header | string | Yes | | ## Request body ### application/json Required; CatalogProposal | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `reason` | | string | Yes | Validation: min length 8; max length 500 | | `permissions` | | Permission[] | Yes | Validation: min items 1; max items 32 | ## Responses ### 201 Successful Response | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | | string | Yes | | | `project_id` | | string | Yes | | | `revision` | | integer | Yes | | | `permissions` | | Permission[] | Yes | | | `digest` | | string | Yes | | | `status` | | pending_review \| approved \| superseded \| revoked | Yes | | | `proposer` | | string | Yes | | | `approver` | | string \| null | Yes | | | `created_at` | | string | Yes | | | `expires_at` | | string | Yes | | | `actions` | | (approve \| revoke)[] | Yes | | | `revocations` | | RevocationRead[] | No | | ### 403 Current project authority or independent review required No fields declared in the current specification. ### 409 Current exact proposal, catalog, version or idempotency conflict No fields declared in the current specification. ### 413 Exact JSON request exceeds 64 KiB No fields declared in the current specification. ### 422 Invalid exact reviewed policy or registration No fields declared in the current specification. ### 503 Configured owned issuer authority unavailable No fields declared in the current specification. ## Request examples Illustrative only. Replace placeholders and keep management tokens on the server. ### cURL ```sh curl -X POST 'https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/permission-catalogs' \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'idempotency-key: REPLACE_WITH_IDEMPOTENCY_KEY' \ -H 'Content-Type: application/json' \ --data '{ "permissions": [ { "description": "Read assigned case records", "id": "case.read" } ], "reason": "Define reviewed case access permissions" }' ``` ### TypeScript (Node.js/server-side) ```typescript const response = await fetch('https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/permission-catalogs', { method: 'POST', headers: { Authorization: `Bearer ${process.env.TAIFA_MANAGEMENT_TOKEN}`, 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "permissions": [ { "description": "Read assigned case records", "id": "case.read" } ], "reason": "Define reviewed case access permissions" }) }); const result = await response.json(); ``` ### Python ```python import os import json import requests response = requests.request( 'POST', 'https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/permission-catalogs', headers={'Authorization': 'Bearer ' + os.environ['TAIFA_MANAGEMENT_TOKEN'], 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY'}, json=json.loads('{"permissions":[{"description":"Read assigned case records","id":"case.read"}],"reason":"Define reviewed case access permissions"}') ) response.raise_for_status() ``` ## Response example No response example in the current specification.