# Lifecycle service authority 5 management API operations. - [POST /v1/projects/{project_id}/lifecycle-service-grants](/docs/api/operations/propose_v1_projects__project_id__lifecycle_service_grants_post): Propose - [GET /v1/projects/{project_id}/lifecycle-service-grants](/docs/api/operations/listing_v1_projects__project_id__lifecycle_service_grants_get): Listing - [POST /v1/projects/{project_id}/lifecycle-service-grants/{grant_id}/approve](/docs/api/operations/approve_v1_projects__project_id__lifecycle_service_grants__grant_id__approve_post): Approve - [POST /v1/projects/{project_id}/lifecycle-service-grants/{grant_id}/revoke](/docs/api/operations/revoke_v1_projects__project_id__lifecycle_service_grants__grant_id__revoke_post): Revoke - [GET /v1/projects/{project_id}/lifecycle-service-grants/{grant_id}](/docs/api/operations/detail_v1_projects__project_id__lifecycle_service_grants__grant_id__get): Detail ## POST /v1/projects/{project_id}/lifecycle-service-grants Propose Propose 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; LifecycleServiceProposal | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `reason` | | string | Yes | Validation: min length 8; max length 500 | | `issuer` | | string | Yes | Validation: min length 1; max length 2048 | | `subject` | | string | Yes | Validation: min length 1; max length 255 | ### Responses #### 201 Successful Response | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | | string | Yes | | | `project_id` | | string | Yes | | | `issuer` | | string | Yes | | | `subject` | | string | Yes | | | `capability` | | lifecycle-consumer | Yes | | | `status` | | pending_review \| effective \| revoked | Yes | | | `active` | | boolean | Yes | | | `version` | | integer | Yes | Validation: minimum 1; maximum 3 | | `proposal_digest` | | string | Yes | Validation: pattern ^[a-f0-9]{64}$ | | `proposer` | | string | Yes | | | `approver` | | string \| null | Yes | | | `proposal_audit_id` | | string | Yes | | | `approval_audit_id` | | string \| null | Yes | | | `revocation_audit_id` | | string \| null | Yes | | | `created_at` | | string · date-time | Yes | | | `approved_at` | | string \| null | Yes | | | `revoked_at` | | string \| null | Yes | | #### 422 Validation Error | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `detail` | | ValidationError[] | No | | ### 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/lifecycle-service-grants' \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'idempotency-key: REPLACE_WITH_IDEMPOTENCY_KEY' \ -H 'Content-Type: application/json' \ --data '{ "reason": "REPLACE_WITH_REASON", "issuer": "REPLACE_WITH_ISSUER", "subject": "REPLACE_WITH_SUBJECT" }' ``` #### TypeScript (Node.js/server-side) ```typescript const response = await fetch('https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/lifecycle-service-grants', { method: 'POST', headers: { Authorization: `Bearer ${process.env.TAIFA_MANAGEMENT_TOKEN}`, 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "reason": "REPLACE_WITH_REASON", "issuer": "REPLACE_WITH_ISSUER", "subject": "REPLACE_WITH_SUBJECT" }) }); 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/lifecycle-service-grants', headers={'Authorization': 'Bearer ' + os.environ['TAIFA_MANAGEMENT_TOKEN'], 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY'}, json=json.loads('{"reason":"REPLACE_WITH_REASON","issuer":"REPLACE_WITH_ISSUER","subject":"REPLACE_WITH_SUBJECT"}') ) response.raise_for_status() ``` ### Response example No response example in the current specification. [Request and response examples](/docs/api/operations/propose_v1_projects__project_id__lifecycle_service_grants_post) ## GET /v1/projects/{project_id}/lifecycle-service-grants Listing Listing 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 | | | `limit` | query | string | No | Validation: pattern ^(?:[1-9]\|[1-9][0-9]\|100)$ | | `after_id` | query | string · uuid \| null | No | | ### Request body This operation has no request body. ### Responses #### 200 Successful Response | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `[].id` | | string | Yes | | | `[].project_id` | | string | Yes | | | `[].issuer` | | string | Yes | | | `[].subject` | | string | Yes | | | `[].capability` | | lifecycle-consumer | Yes | | | `[].status` | | pending_review \| effective \| revoked | Yes | | | `[].active` | | boolean | Yes | | | `[].version` | | integer | Yes | Validation: minimum 1; maximum 3 | | `[].proposal_digest` | | string | Yes | Validation: pattern ^[a-f0-9]{64}$ | | `[].proposer` | | string | Yes | | | `[].approver` | | string \| null | Yes | | | `[].proposal_audit_id` | | string | Yes | | | `[].approval_audit_id` | | string \| null | Yes | | | `[].revocation_audit_id` | | string \| null | Yes | | | `[].created_at` | | string · date-time | Yes | | | `[].approved_at` | | string \| null | Yes | | | `[].revoked_at` | | string \| null | Yes | | #### 422 Validation Error | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `detail` | | ValidationError[] | No | | ### Request examples Illustrative only. Replace placeholders and keep management tokens on the server. #### cURL ```sh curl -X GET 'https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/lifecycle-service-grants' \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' ``` #### TypeScript (Node.js/server-side) ```typescript const response = await fetch('https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/lifecycle-service-grants', { method: 'GET', headers: { Authorization: `Bearer ${process.env.TAIFA_MANAGEMENT_TOKEN}` } }); const result = await response.json(); ``` #### Python ```python import os import requests response = requests.request( 'GET', 'https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/lifecycle-service-grants', headers={'Authorization': 'Bearer ' + os.environ['TAIFA_MANAGEMENT_TOKEN']} ) response.raise_for_status() ``` ### Response example No response example in the current specification. [Request and response examples](/docs/api/operations/listing_v1_projects__project_id__lifecycle_service_grants_get) ## POST /v1/projects/{project_id}/lifecycle-service-grants/{grant_id}/approve Approve Approve 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 | | | `grant_id` | path | string | Yes | | | `idempotency-key` | header | string | Yes | | ### Request body #### application/json Required; LifecycleServiceApproval | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `reason` | | string | Yes | Validation: min length 8; max length 500 | | `expected_version` | | integer | Yes | Validation: minimum 1 | | `proposal_digest` | | string | Yes | Validation: pattern ^[a-f0-9]{64}$ | ### Responses #### 200 Successful Response | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | | string | Yes | | | `project_id` | | string | Yes | | | `issuer` | | string | Yes | | | `subject` | | string | Yes | | | `capability` | | lifecycle-consumer | Yes | | | `status` | | pending_review \| effective \| revoked | Yes | | | `active` | | boolean | Yes | | | `version` | | integer | Yes | Validation: minimum 1; maximum 3 | | `proposal_digest` | | string | Yes | Validation: pattern ^[a-f0-9]{64}$ | | `proposer` | | string | Yes | | | `approver` | | string \| null | Yes | | | `proposal_audit_id` | | string | Yes | | | `approval_audit_id` | | string \| null | Yes | | | `revocation_audit_id` | | string \| null | Yes | | | `created_at` | | string · date-time | Yes | | | `approved_at` | | string \| null | Yes | | | `revoked_at` | | string \| null | Yes | | #### 422 Validation Error | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `detail` | | ValidationError[] | No | | ### 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/lifecycle-service-grants/REPLACE_WITH_GRANT_ID/approve' \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'idempotency-key: REPLACE_WITH_IDEMPOTENCY_KEY' \ -H 'Content-Type: application/json' \ --data '{ "reason": "REPLACE_WITH_REASON", "expected_version": 0, "proposal_digest": "REPLACE_WITH_PROPOSAL_DIGEST" }' ``` #### TypeScript (Node.js/server-side) ```typescript const response = await fetch('https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/lifecycle-service-grants/REPLACE_WITH_GRANT_ID/approve', { method: 'POST', headers: { Authorization: `Bearer ${process.env.TAIFA_MANAGEMENT_TOKEN}`, 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "reason": "REPLACE_WITH_REASON", "expected_version": 0, "proposal_digest": "REPLACE_WITH_PROPOSAL_DIGEST" }) }); 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/lifecycle-service-grants/REPLACE_WITH_GRANT_ID/approve', headers={'Authorization': 'Bearer ' + os.environ['TAIFA_MANAGEMENT_TOKEN'], 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY'}, json=json.loads('{"reason":"REPLACE_WITH_REASON","expected_version":0,"proposal_digest":"REPLACE_WITH_PROPOSAL_DIGEST"}') ) response.raise_for_status() ``` ### Response example No response example in the current specification. [Request and response examples](/docs/api/operations/approve_v1_projects__project_id__lifecycle_service_grants__grant_id__approve_post) ## POST /v1/projects/{project_id}/lifecycle-service-grants/{grant_id}/revoke Revoke Revoke 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 | | | `grant_id` | path | string | Yes | | | `idempotency-key` | header | string | Yes | | ### Request body #### application/json Required; LifecycleServiceRevocation | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `reason` | | string | Yes | Validation: min length 8; max length 500 | | `expected_version` | | integer | Yes | Validation: minimum 1 | ### Responses #### 200 Successful Response | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | | string | Yes | | | `project_id` | | string | Yes | | | `issuer` | | string | Yes | | | `subject` | | string | Yes | | | `capability` | | lifecycle-consumer | Yes | | | `status` | | pending_review \| effective \| revoked | Yes | | | `active` | | boolean | Yes | | | `version` | | integer | Yes | Validation: minimum 1; maximum 3 | | `proposal_digest` | | string | Yes | Validation: pattern ^[a-f0-9]{64}$ | | `proposer` | | string | Yes | | | `approver` | | string \| null | Yes | | | `proposal_audit_id` | | string | Yes | | | `approval_audit_id` | | string \| null | Yes | | | `revocation_audit_id` | | string \| null | Yes | | | `created_at` | | string · date-time | Yes | | | `approved_at` | | string \| null | Yes | | | `revoked_at` | | string \| null | Yes | | #### 422 Validation Error | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `detail` | | ValidationError[] | No | | ### 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/lifecycle-service-grants/REPLACE_WITH_GRANT_ID/revoke' \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'idempotency-key: REPLACE_WITH_IDEMPOTENCY_KEY' \ -H 'Content-Type: application/json' \ --data '{ "reason": "REPLACE_WITH_REASON", "expected_version": 0 }' ``` #### TypeScript (Node.js/server-side) ```typescript const response = await fetch('https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/lifecycle-service-grants/REPLACE_WITH_GRANT_ID/revoke', { method: 'POST', headers: { Authorization: `Bearer ${process.env.TAIFA_MANAGEMENT_TOKEN}`, 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "reason": "REPLACE_WITH_REASON", "expected_version": 0 }) }); 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/lifecycle-service-grants/REPLACE_WITH_GRANT_ID/revoke', headers={'Authorization': 'Bearer ' + os.environ['TAIFA_MANAGEMENT_TOKEN'], 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY'}, json=json.loads('{"reason":"REPLACE_WITH_REASON","expected_version":0}') ) response.raise_for_status() ``` ### Response example No response example in the current specification. [Request and response examples](/docs/api/operations/revoke_v1_projects__project_id__lifecycle_service_grants__grant_id__revoke_post) ## GET /v1/projects/{project_id}/lifecycle-service-grants/{grant_id} Detail Detail 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 | | | `grant_id` | path | string | Yes | | ### Request body This operation has no request body. ### Responses #### 200 Successful Response | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | | string | Yes | | | `project_id` | | string | Yes | | | `issuer` | | string | Yes | | | `subject` | | string | Yes | | | `capability` | | lifecycle-consumer | Yes | | | `status` | | pending_review \| effective \| revoked | Yes | | | `active` | | boolean | Yes | | | `version` | | integer | Yes | Validation: minimum 1; maximum 3 | | `proposal_digest` | | string | Yes | Validation: pattern ^[a-f0-9]{64}$ | | `proposer` | | string | Yes | | | `approver` | | string \| null | Yes | | | `proposal_audit_id` | | string | Yes | | | `approval_audit_id` | | string \| null | Yes | | | `revocation_audit_id` | | string \| null | Yes | | | `created_at` | | string · date-time | Yes | | | `approved_at` | | string \| null | Yes | | | `revoked_at` | | string \| null | Yes | | #### 422 Validation Error | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `detail` | | ValidationError[] | No | | ### Request examples Illustrative only. Replace placeholders and keep management tokens on the server. #### cURL ```sh curl -X GET 'https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/lifecycle-service-grants/REPLACE_WITH_GRANT_ID' \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' ``` #### TypeScript (Node.js/server-side) ```typescript const response = await fetch('https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/lifecycle-service-grants/REPLACE_WITH_GRANT_ID', { method: 'GET', headers: { Authorization: `Bearer ${process.env.TAIFA_MANAGEMENT_TOKEN}` } }); const result = await response.json(); ``` #### Python ```python import os import requests response = requests.request( 'GET', 'https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/lifecycle-service-grants/REPLACE_WITH_GRANT_ID', headers={'Authorization': 'Bearer ' + os.environ['TAIFA_MANAGEMENT_TOKEN']} ) response.raise_for_status() ``` ### Response example No response example in the current specification. [Request and response examples](/docs/api/operations/detail_v1_projects__project_id__lifecycle_service_grants__grant_id__get)