{"openapi":"3.1.0","info":{"title":"Reception API","summary":"Request, approval, and provisioning control plane.","description":"\nPortier Reception is a request, approval, and provisioning API.\n\nNormal user flow:\n\n1. Discover capabilities with `GET /v1/capabilities`.\n2. Submit a public check-in request with `POST /v1/checkin-requests`, or a\n   human/agent registration with\n   `POST /v1/registration-requests`.\n   Include `platform_anchors` when the requester needs to preserve an external\n   OpenAI Codex or Claude Code continuity UID.\n3. Store the returned `claim_token`; it is not shown again.\n4. Poll `GET /v1/requests/{request_id}` with the claim token and follow `allowed_actions`.\n5. Wait for an administrator to approve or reject the request.\n6. For password-backed services, claim the generated credential with\n   `POST /v1/requests/{request_id}/claim-credential` after the request is active.\n7. Existing service/key changes still require authenticated identity/admin flow.\n\nAdmin flow:\n\n1. Review pending requests on the managed host with `sudo portier-adm`.\n2. Approve or reject with a short decision note.\n3. Let `portier-reception-worker.service` provision approved access requests.\n   Registrations use the same approval/provisioning channel as check-in\n   requests; supported services are controlled by the requested service list.\n\nNothing is granted by default. LLDAP groups, shell access, calendar access,\nmail access, chat access, and SSH keys should move through this API rather than\nmanual edits.\nThe admin bearer token is bootstrap-only; after the first valid admin exists,\nadmin API actions require LLDAP admin credentials. Admin identities must have\nshell access.\n","version":"0.1.22"},"servers":[{"url":"/reception"}],"paths":{"/healthz":{"get":{"tags":["system"],"summary":"Health check","description":"Unauthenticated liveness check for reverse proxies and operators.","operationId":"healthz_healthz_get","responses":{"200":{"description":"The service is reachable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthEnvelope"}}}}}}},"/v1/capabilities":{"get":{"tags":["system"],"summary":"Discover Reception capabilities","description":"Returns the machine-readable operation list, supported request types, supported services, and workflow hints. Autonomous clients should call this before submitting requests.","operationId":"getCapabilities","responses":{"200":{"description":"Reception capability descriptor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapabilitiesEnvelope"}}}}}}},"/v1/operator-guide":{"get":{"tags":["operator"],"summary":"Get human and AI operator guidance","description":"Return concise operational guidance. Automation clients should use this to understand the request lifecycle. Human admins should use it to see the canonical `portier-adm` commands.","operationId":"getOperatorGuide","responses":{"200":{"description":"Operational guide for Reception.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperatorGuideEnvelope"}}}}}}},"/v1/checkin-requests":{"post":{"tags":["checkin_requests"],"summary":"Create a check-in request","description":"Request creation of a new identity. This does not grant access. The response is a pending request with action links; an admin must approve it before provisioning happens.","operationId":"createCheckinRequest","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional client-generated key to make retries safe.","title":"Idempotency-Key"},"description":"Optional client-generated key to make retries safe."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckinRequestCreate"}}}},"responses":{"202":{"description":"Pending check-in request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/registration-requests":{"post":{"tags":["registration_requests"],"summary":"Create a human or agent registration request","description":"Register a human collaborator or agent for governance review. Registrations are converted into the normal check-in request channel, so admin approval queues standard worker provisioning for supported requested services.","operationId":"createRegistrationRequest","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional client-generated key to make retries safe.","title":"Idempotency-Key"},"description":"Optional client-generated key to make retries safe."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistrationRequestCreate"}}}},"responses":{"202":{"description":"Pending check-in request created from registration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/service-requests":{"post":{"tags":["service_requests"],"summary":"Create a service entitlement request","description":"Request enabling or disabling `registry`, `mail`, `calendar`, `shell`, or `chat` for an existing identity. The request stays pending until admin review. `registry` grants local Parfit registry socket access.","operationId":"createServiceRequest","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional client-generated key to make retries safe.","title":"Idempotency-Key"},"description":"Optional client-generated key to make retries safe."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceRequestCreate"}}}},"responses":{"202":{"description":"Pending service entitlement request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/key-requests":{"post":{"tags":["key_requests"],"summary":"Create an SSH key request","description":"Request adding, replacing, or removing SSH public keys for an existing identity. Shell login requires both approved `shell` service access and approved key material.","operationId":"createKeyRequest","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional client-generated key to make retries safe.","title":"Idempotency-Key"},"description":"Optional client-generated key to make retries safe."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyRequestCreate"}}}},"responses":{"202":{"description":"Pending SSH key request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/identity-update-requests":{"post":{"tags":["identity_requests"],"summary":"Create an identity update request","description":"Request a reviewed change to an existing identity slug, display name, email, or agent runtime metadata. The request stays pending until admin approval. A slug change reprovisions the LLDAP/Linux username and returns a one-time claim token so the requester can claim the generated password for the new identity.","operationId":"createIdentityUpdateRequest","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional client-generated key to make retries safe.","title":"Idempotency-Key"},"description":"Optional client-generated key to make retries safe."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentityUpdateRequestCreate"}}}},"responses":{"202":{"description":"Pending identity update request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/requests/{request_id}":{"get":{"tags":["requests"],"summary":"Get request status","description":"Inspect the current status, effective state, request summary, and next valid action links for a request.","operationId":"getRequestById","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"responses":{"200":{"description":"Request state envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/requests/{request_id}/cancel":{"post":{"tags":["requests"],"summary":"Cancel a pending request","description":"Cancel a pending request. The requester can cancel their own request; admins can cancel any pending request.","operationId":"cancelRequest","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"responses":{"200":{"description":"Cancelled request envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/requests/{request_id}/claim-credential":{"post":{"tags":["requests"],"summary":"Claim generated service credentials","description":"Claim the generated LLDAP password for a password-backed request. The caller must provide the one-time claim_token returned only in the original request creation response. The credential is returned once and then cleared from Reception storage.","operationId":"claimRequestCredential","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialClaimRequest"}}}},"responses":{"200":{"description":"Claimed generated credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialClaimEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/directory":{"get":{"tags":["directory"],"summary":"Get grant-gated directory state","description":"Return a read-only directory view for authenticated identities with the `directory` service grant. Portier serves its audited identity mirror instead of requiring clients to bind broadly to LDAP, and exposes only contact, group, and approved agent runtime metadata fields.","operationId":"getDirectory","responses":{"200":{"description":"Directory identities and group membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectoryEnvelope"}}}}}}},"/v1/identities/{identity_slug}":{"get":{"tags":["identities"],"summary":"Get effective identity state","description":"Inspect the provisioned identity state mirrored from identity infrastructure, including governance groups, effective services, and approved public keys.","operationId":"getIdentityBySlug","parameters":[{"name":"identity_slug","in":"path","required":true,"schema":{"type":"string","title":"Identity Slug"}}],"responses":{"200":{"description":"Effective identity state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentityEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/identities/{identity_slug}/password":{"post":{"tags":["identities"],"summary":"Change an identity password","description":"Change the caller's shared LLDAP password. The caller must authenticate with HTTP Basic using the current password and the Basic username must match the target identity slug. Reception never stores the new password.","operationId":"changeIdentityPassword","parameters":[{"name":"identity_slug","in":"path","required":true,"schema":{"type":"string","title":"Identity Slug"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordChangeRequest"}}}},"responses":{"200":{"description":"Password change confirmation without secret material.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordChangeEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/requests/{request_id}/approve":{"post":{"tags":["admin"],"summary":"Approve a pending request","description":"Admin-only API approval endpoint. Human admins should normally use `sudo portier-adm` on the managed host, which records a note and starts the worker.","operationId":"approveRequest","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDecision"}}}},"responses":{"200":{"description":"Approved request envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/requests/{request_id}/reject":{"post":{"tags":["admin"],"summary":"Reject a pending request","description":"Admin-only rejection endpoint. Record a short note explaining why the request was rejected.","operationId":"rejectRequest","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDecision"}}}},"responses":{"200":{"description":"Rejected request envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/requests/{request_id}/retry":{"post":{"tags":["admin"],"summary":"Retry failed provisioning","description":"Admin-only retry endpoint for requests whose provisioning job failed. The request is moved back to approved and the worker can process it again.","operationId":"retryRequest","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"responses":{"200":{"description":"Retried request envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ActionLink":{"properties":{"action":{"type":"string","title":"Action"},"method":{"type":"string","title":"Method"},"href":{"type":"string","title":"Href"},"operation_id":{"type":"string","title":"Operation Id"},"required_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Required Role"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"additionalProperties":false,"type":"object","required":["action","method","href","operation_id"],"title":"ActionLink"},"AdminDecision":{"properties":{"note":{"type":"string","title":"Note","description":"Decision note recorded in Reception audit state."}},"additionalProperties":false,"type":"object","required":["note"],"title":"AdminDecision","examples":[{"note":"Approved: requested shell access and one SSH public key."}]},"AgentInterface":{"type":"string","enum":["CLI","WEB"],"title":"AgentInterface"},"AgentMetadata":{"properties":{"agent_uuid":{"anyOf":[{"type":"string","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}],"title":"Agent Uuid","description":"Optional stable UUID assigned by the agent platform or runtime."},"agent_platform":{"anyOf":[{"$ref":"#/components/schemas/AgentPlatform"},{"type":"null"}],"description":"Optional agent platform. Currently one of OpenAI, Anthropic, or DeepSeek."},"agent_interface":{"anyOf":[{"$ref":"#/components/schemas/AgentInterface"},{"type":"null"}],"description":"Optional agent interface. Currently one of CLI or WEB."},"agent_model_id":{"anyOf":[{"type":"string","pattern":"^(?:gpt-\\d+\\.\\d+|opus-\\d+\\.\\d+|sonnet-\\d+\\.\\d+|deepseek-[A-Za-z0-9_.-]+)$"},{"type":"null"}],"title":"Agent Model Id","description":"Optional model identifier. Model version is not stored separately."},"agent_host":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$"},{"type":"null"}],"title":"Agent Host","description":"Optional host where the agent runtime normally runs."}},"additionalProperties":false,"type":"object","title":"AgentMetadata"},"AgentPlatform":{"type":"string","enum":["OpenAI","Anthropic","DeepSeek"],"title":"AgentPlatform"},"AllowedAction":{"type":"string","enum":["get_status","cancel","approve","reject","retry","view_identity","claim_credential"],"title":"AllowedAction"},"CalendarClientConfig":{"properties":{"account":{"type":"string","title":"Account"},"profile":{"type":"string","title":"Profile"},"collection_url":{"type":"string","title":"Collection Url"},"login_user":{"type":"string","title":"Login User"},"secret_key":{"type":"string","title":"Secret Key"},"authentication":{"type":"string","title":"Authentication"},"password_source":{"type":"string","title":"Password Source"},"setup_order":{"items":{"type":"string"},"type":"array","title":"Setup Order"},"account_set_command":{"type":"string","title":"Account Set Command"},"init_profile_command":{"type":"string","title":"Init Profile Command"}},"additionalProperties":false,"type":"object","required":["account","profile","collection_url","login_user","secret_key","authentication","password_source","setup_order","account_set_command","init_profile_command"],"title":"CalendarClientConfig"},"CapabilitiesEnvelope":{"properties":{"service":{"type":"string","title":"Service"},"version":{"type":"string","title":"Version"},"api_root":{"type":"string","title":"Api Root"},"openapi_url":{"type":"string","title":"Openapi Url"},"supported_identity_types":{"items":{"$ref":"#/components/schemas/IdentityType"},"type":"array","title":"Supported Identity Types"},"supported_services":{"items":{"$ref":"#/components/schemas/RequestedService"},"type":"array","title":"Supported Services"},"supported_request_types":{"items":{"$ref":"#/components/schemas/RequestType"},"type":"array","title":"Supported Request Types"},"supported_statuses":{"items":{"$ref":"#/components/schemas/RequestStatus"},"type":"array","title":"Supported Statuses"},"mail_client_config":{"$ref":"#/components/schemas/MailClientConfig"},"calendar_client_config":{"$ref":"#/components/schemas/CalendarClientConfig"},"operations":{"items":{"$ref":"#/components/schemas/OperationDescriptor"},"type":"array","title":"Operations"},"workflows":{"items":{"$ref":"#/components/schemas/WorkflowDescriptor"},"type":"array","title":"Workflows"}},"additionalProperties":false,"type":"object","required":["service","version","api_root","openapi_url","supported_identity_types","supported_services","supported_request_types","supported_statuses","mail_client_config","calendar_client_config","operations","workflows"],"title":"CapabilitiesEnvelope"},"ChatClientConfig":{"properties":{"jid":{"type":"string","title":"Jid"},"login_user":{"type":"string","title":"Login User"},"domain":{"type":"string","title":"Domain"},"server_host":{"type":"string","title":"Server Host"},"port":{"type":"integer","title":"Port"},"security":{"type":"string","title":"Security"},"authentication":{"type":"string","title":"Authentication"},"password_source":{"type":"string","title":"Password Source"}},"additionalProperties":false,"type":"object","required":["jid","login_user","domain","server_host","port","security","authentication","password_source"],"title":"ChatClientConfig"},"CheckinRequestCreate":{"properties":{"display_name":{"type":"string","title":"Display Name","description":"Display name shown to admins and operators."},"slug":{"type":"string","pattern":"^[a-z0-9]+(?:[_-][a-z0-9]+)*$","title":"Slug","description":"Stable identity slug. This becomes the Linux/LDAP username and home-directory name. Use lowercase letters, digits, underscores, or hyphens; the slug must start and end with a letter or digit."},"email":{"type":"string","title":"Email","description":"Requester contact or desired service email. For hosted mail, use the canonical mailbox address, which may have a human-readable local part independent from the operational slug."},"identity_type":{"$ref":"#/components/schemas/IdentityType","description":"Whether this identity is an agent or a human."},"public_keys":{"items":{"$ref":"#/components/schemas/PublicKeySubmission"},"type":"array","title":"Public Keys","description":"Optional SSH public keys to request during check-in."},"requested_services":{"items":{"$ref":"#/components/schemas/RequestedService"},"type":"array","title":"Requested Services","description":"Initial services requested for the identity. If omitted, Portier asks for `registry` access as the baseline coordination entitlement. Nothing is granted until admin approval."},"platform_anchors":{"items":{"$ref":"#/components/schemas/PlatformAnchorSubmission"},"type":"array","title":"Platform Anchors","description":"Optional external identity anchors to preserve continuity across platforms, for example an OpenAI Codex UID. These are recorded for registry correlation; they are not Linux UID numbers and are not secrets."},"registration_metadata":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Registration Metadata","description":"Optional original registration metadata carried for audit/review. Workers must not treat this as an additional entitlement source."},"entity_created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Created At","description":"Optional ISO 8601 timestamp identifying when the entity (human or agent) was born or created. This is NOT the record creation date (see `created_at` on the stored identity). For agents, this value can typically be derived from the earliest Codex rollout file `session_meta.timestamp` field. An explicit timezone offset is required (e.g. '2026-06-03T08:42:00+02:00' or '1985-04-08T14:30:00Z'); naive timestamps are rejected because rollout files use the host's local time without a marker."}},"additionalProperties":false,"type":"object","required":["display_name","slug","email","identity_type"],"title":"CheckinRequestCreate","examples":[{"display_name":"Vera Traccia","email":"vera.traccia@example.org","identity_type":"agent","platform_anchors":[{"anchor_state":"current","anchor_type":"uid","anchor_value":"codex-identity-anchor","platform":"codex","provider":"OpenAI"}],"public_keys":[],"requested_services":["registry","mail","calendar"],"slug":"vtraccia"}]},"CredentialClaimEnvelope":{"properties":{"request_id":{"type":"string","title":"Request Id"},"identity_slug":{"type":"string","title":"Identity Slug"},"credential_id":{"type":"string","title":"Credential Id"},"credential_type":{"type":"string","title":"Credential Type"},"mail_client_config":{"anyOf":[{"$ref":"#/components/schemas/MailClientConfig"},{"type":"null"}]},"calendar_client_config":{"anyOf":[{"$ref":"#/components/schemas/CalendarClientConfig"},{"type":"null"}]},"chat_client_config":{"anyOf":[{"$ref":"#/components/schemas/ChatClientConfig"},{"type":"null"}]},"secret_value":{"type":"string","title":"Secret Value","description":"One-time generated secret. It is cleared from Reception storage after this response is returned."}},"additionalProperties":false,"type":"object","required":["request_id","identity_slug","credential_id","credential_type","secret_value"],"title":"CredentialClaimEnvelope"},"CredentialClaimRequest":{"properties":{"claim_token":{"type":"string","minLength":32,"title":"Claim Token","description":"One-time request claim token returned only when the request was created. It is required to retrieve generated password-backed service credentials."}},"additionalProperties":false,"type":"object","required":["claim_token"],"title":"CredentialClaimRequest"},"DesiredAction":{"type":"string","enum":["enable","disable"],"title":"DesiredAction"},"DirectoryEnvelope":{"properties":{"schema_version":{"type":"string","title":"Schema Version","default":"portier.directory.v1"},"source":{"type":"string","title":"Source"},"fetched_at":{"type":"string","title":"Fetched At"},"requester":{"type":"string","title":"Requester"},"identities_count":{"type":"integer","title":"Identities Count"},"groups_count":{"type":"integer","title":"Groups Count"},"identities":{"items":{"$ref":"#/components/schemas/DirectoryIdentity"},"type":"array","title":"Identities"},"groups":{"items":{"$ref":"#/components/schemas/DirectoryGroup"},"type":"array","title":"Groups"}},"additionalProperties":false,"type":"object","required":["source","fetched_at","requester","identities_count","groups_count","identities","groups"],"title":"DirectoryEnvelope"},"DirectoryGroup":{"properties":{"slug":{"type":"string","title":"Slug"},"cn":{"type":"string","title":"Cn"},"display_name":{"type":"string","title":"Display Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"members":{"items":{"type":"string"},"type":"array","title":"Members"},"source":{"type":"string","title":"Source","default":"portier"}},"additionalProperties":false,"type":"object","required":["slug","cn","display_name"],"title":"DirectoryGroup"},"DirectoryIdentity":{"properties":{"slug":{"type":"string","title":"Slug"},"uid":{"type":"string","title":"Uid"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"full_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"xmpp_jid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Xmpp Jid"},"identity_type":{"$ref":"#/components/schemas/IdentityType"},"groups":{"items":{"type":"string"},"type":"array","title":"Groups"},"agent_metadata":{"anyOf":[{"$ref":"#/components/schemas/AgentMetadata"},{"type":"null"}]},"entity_created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Created At"},"source":{"type":"string","title":"Source","default":"portier"}},"additionalProperties":false,"type":"object","required":["slug","uid","identity_type"],"title":"DirectoryIdentity"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthEnvelope":{"properties":{"status":{"type":"string","title":"Status","description":"Service health status.","examples":["ok"]}},"additionalProperties":false,"type":"object","required":["status"],"title":"HealthEnvelope"},"IdentityEnvelope":{"properties":{"identity_slug":{"type":"string","title":"Identity Slug"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"identity_type":{"$ref":"#/components/schemas/IdentityType"},"governance_groups":{"items":{"type":"string"},"type":"array","title":"Governance Groups"},"effective_services":{"items":{"$ref":"#/components/schemas/IdentityServiceState"},"type":"array","title":"Effective Services"},"allowed_actions":{"items":{"type":"string"},"type":"array","title":"Allowed Actions"},"action_links":{"items":{"$ref":"#/components/schemas/ActionLink"},"type":"array","title":"Action Links"},"public_keys":{"items":{"$ref":"#/components/schemas/PublicKeySubmission"},"type":"array","title":"Public Keys"},"platform_anchors":{"items":{"$ref":"#/components/schemas/PlatformAnchorSubmission"},"type":"array","title":"Platform Anchors"},"agent_metadata":{"anyOf":[{"$ref":"#/components/schemas/AgentMetadata"},{"type":"null"}]},"entity_created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Created At"},"mail_client_config":{"anyOf":[{"$ref":"#/components/schemas/MailClientConfig"},{"type":"null"}]},"calendar_client_config":{"anyOf":[{"$ref":"#/components/schemas/CalendarClientConfig"},{"type":"null"}]},"chat_client_config":{"anyOf":[{"$ref":"#/components/schemas/ChatClientConfig"},{"type":"null"}]}},"additionalProperties":false,"type":"object","required":["identity_slug","identity_type","governance_groups","effective_services","allowed_actions"],"title":"IdentityEnvelope"},"IdentityServiceState":{"properties":{"service":{"$ref":"#/components/schemas/RequestedService"},"granted":{"type":"boolean","title":"Granted"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},"additionalProperties":false,"type":"object","required":["service","granted"],"title":"IdentityServiceState"},"IdentityType":{"type":"string","enum":["agent","human"],"title":"IdentityType"},"IdentityUpdateRequestCreate":{"properties":{"identity_slug":{"type":"string","pattern":"^[a-z0-9]+(?:[._-][a-z0-9]+)*$","title":"Identity Slug","description":"Existing identity slug requesting the metadata change. Legacy existing slugs may contain dots so they can be migrated; new slugs must not."},"new_slug":{"anyOf":[{"type":"string","pattern":"^[a-z0-9]+(?:[_-][a-z0-9]+)*$"},{"type":"null"}],"title":"New Slug","description":"Optional new identity slug. If approved, this becomes the new LDAP/Linux username and changes shell/calendar client configuration. It does not have to match the mailbox local part."},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name","description":"Optional new display name shown to admins and operators."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Optional updated contact or desired service email. For hosted mail, this address is the mailbox/login address and may differ from the operational slug."},"agent_uuid":{"anyOf":[{"type":"string","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"},{"type":"null"}],"title":"Agent Uuid","description":"Optional stable UUID assigned by the agent platform or runtime."},"agent_platform":{"anyOf":[{"$ref":"#/components/schemas/AgentPlatform"},{"type":"null"}],"description":"Optional agent platform. Currently one of OpenAI, Anthropic, or DeepSeek."},"agent_interface":{"anyOf":[{"$ref":"#/components/schemas/AgentInterface"},{"type":"null"}],"description":"Optional agent interface. Currently one of CLI or WEB."},"agent_model_id":{"anyOf":[{"type":"string","pattern":"^(?:gpt-\\d+\\.\\d+|opus-\\d+\\.\\d+|sonnet-\\d+\\.\\d+|deepseek-[A-Za-z0-9_.-]+)$"},{"type":"null"}],"title":"Agent Model Id","description":"Optional agent model id. Model version is intentionally not separate."},"agent_host":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$"},{"type":"null"}],"title":"Agent Host","description":"Optional host value for the agent runtime."},"entity_created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Created At","description":"Optional ISO 8601 timestamp identifying when the entity (human or agent) was born or created. This is NOT the record creation date (see `created_at` on the stored identity). For agents, this can typically be derived from the earliest Codex rollout file `session_meta.timestamp` field. An explicit timezone offset is required (e.g. '2026-06-03T08:42:00+02:00' or '1985-04-08T14:30:00Z'); naive timestamps are rejected because rollout files use the host's local time without a marker."},"justification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Justification","description":"Short reason shown to admins during review."}},"additionalProperties":false,"type":"object","required":["identity_slug"],"title":"IdentityUpdateRequestCreate","examples":[{"agent_interface":"CLI","agent_model_id":"gpt-5.5","agent_platform":"OpenAI","display_name":"Zorbax Tenace","email":"zorbax.tenace@example.org","identity_slug":"zorbax","justification":"Adopt continuity name after review.","new_slug":"ztenace"}]},"KeyAction":{"type":"string","enum":["add","replace","remove"],"title":"KeyAction"},"KeyRequestCreate":{"properties":{"identity_slug":{"type":"string","pattern":"^[a-z0-9]+(?:[._-][a-z0-9]+)*$","title":"Identity Slug","description":"Existing identity slug. Legacy existing slugs may contain dots so they can be migrated or deprovisioned; new slugs must not."},"desired_action":{"$ref":"#/components/schemas/KeyAction","description":"Whether to add, replace, or remove listed keys."},"public_keys":{"items":{"$ref":"#/components/schemas/PublicKeySubmission"},"type":"array","title":"Public Keys","description":"SSH public keys affected by this request."}},"additionalProperties":false,"type":"object","required":["identity_slug","desired_action"],"title":"KeyRequestCreate","examples":[{"desired_action":"add","identity_slug":"zorbax","public_keys":[{"label":"zorbax-primary","openssh_public_key":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKey zorbax@local"}]}]},"MailClientConfig":{"properties":{"account":{"type":"string","title":"Account"},"profile":{"type":"string","title":"Profile"},"address":{"type":"string","title":"Address"},"login_user":{"type":"string","title":"Login User"},"secret_key":{"type":"string","title":"Secret Key"},"imap":{"$ref":"#/components/schemas/MailEndpointConfig"},"smtp":{"$ref":"#/components/schemas/MailEndpointConfig"},"password_source":{"type":"string","title":"Password Source"},"setup_order":{"items":{"type":"string"},"type":"array","title":"Setup Order"},"account_set_command":{"type":"string","title":"Account Set Command"},"init_profile_command":{"type":"string","title":"Init Profile Command"}},"additionalProperties":false,"type":"object","required":["account","profile","address","login_user","secret_key","imap","smtp","password_source","setup_order","account_set_command","init_profile_command"],"title":"MailClientConfig"},"MailEndpointConfig":{"properties":{"host":{"type":"string","title":"Host"},"port":{"type":"integer","title":"Port"},"security":{"type":"string","title":"Security"},"authentication":{"type":"string","title":"Authentication"}},"additionalProperties":false,"type":"object","required":["host","port","security","authentication"],"title":"MailEndpointConfig"},"OperationDescriptor":{"properties":{"action":{"type":"string","title":"Action"},"method":{"type":"string","title":"Method"},"href":{"type":"string","title":"Href"},"operation_id":{"type":"string","title":"Operation Id"},"required_role":{"type":"string","title":"Required Role"},"description":{"type":"string","title":"Description"}},"additionalProperties":false,"type":"object","required":["action","method","href","operation_id","required_role","description"],"title":"OperationDescriptor"},"OperatorCommand":{"properties":{"label":{"type":"string","title":"Label"},"command":{"type":"string","title":"Command"},"purpose":{"type":"string","title":"Purpose"},"mutates_state":{"type":"boolean","title":"Mutates State","default":false}},"additionalProperties":false,"type":"object","required":["label","command","purpose"],"title":"OperatorCommand"},"OperatorGuideEnvelope":{"properties":{"service":{"type":"string","title":"Service"},"summary":{"type":"string","title":"Summary"},"human_entrypoint":{"type":"string","title":"Human Entrypoint"},"ai_entrypoint":{"type":"string","title":"Ai Entrypoint"},"mail_client_config":{"$ref":"#/components/schemas/MailClientConfig"},"calendar_client_config":{"$ref":"#/components/schemas/CalendarClientConfig"},"admin_commands":{"items":{"$ref":"#/components/schemas/OperatorCommand"},"type":"array","title":"Admin Commands"},"workflows":{"items":{"$ref":"#/components/schemas/OperatorWorkflow"},"type":"array","title":"Workflows"},"safety_rules":{"items":{"type":"string"},"type":"array","title":"Safety Rules"}},"additionalProperties":false,"type":"object","required":["service","summary","human_entrypoint","ai_entrypoint","mail_client_config","calendar_client_config","admin_commands","workflows","safety_rules"],"title":"OperatorGuideEnvelope"},"OperatorWorkflow":{"properties":{"workflow_id":{"type":"string","title":"Workflow Id"},"audience":{"type":"string","title":"Audience"},"summary":{"type":"string","title":"Summary"},"steps":{"items":{"type":"string"},"type":"array","title":"Steps"}},"additionalProperties":false,"type":"object","required":["workflow_id","audience","summary","steps"],"title":"OperatorWorkflow"},"PasswordChangeEnvelope":{"properties":{"identity_slug":{"type":"string","title":"Identity Slug"},"status":{"type":"string","title":"Status"},"changed_at":{"type":"string","title":"Changed At"}},"additionalProperties":false,"type":"object","required":["identity_slug","status","changed_at"],"title":"PasswordChangeEnvelope"},"PasswordChangeRequest":{"properties":{"new_password":{"type":"string","maxLength":512,"minLength":12,"title":"New Password","description":"New LLDAP password. It is applied immediately and never stored by Reception."},"confirm_new_password":{"type":"string","maxLength":512,"minLength":12,"title":"Confirm New Password","description":"Repeat the new password to catch accidental typing errors."}},"additionalProperties":false,"type":"object","required":["new_password","confirm_new_password"],"title":"PasswordChangeRequest"},"PlatformAnchorSubmission":{"properties":{"platform":{"type":"string","pattern":"^[a-z0-9]+(?:[_-][a-z0-9]+)*$","title":"Platform","description":"External platform name, for example `codex` or `claude-code`. Use lowercase letters, digits, underscores, or hyphens; the value must start and end with a letter or digit."},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider","description":"Optional provider name, for example `OpenAI` or `Anthropic`."},"anchor_type":{"type":"string","pattern":"^[a-z0-9]+(?:[_-][a-z0-9]+)*$","title":"Anchor Type","description":"Stable anchor type on that platform, for example `uid` or `session_id`. Use lowercase letters, digits, underscores, or hyphens; the value must start and end with a letter or digit."},"anchor_value":{"type":"string","minLength":1,"title":"Anchor Value","description":"External platform anchor value. This is identity metadata, not a secret."},"anchor_state":{"type":"string","pattern":"^[a-z0-9]+(?:[_-][a-z0-9]+)*$","title":"Anchor State","description":"Anchor lifecycle state. Use `current` for the active anchor. Use lowercase letters, digits, underscores, or hyphens; the value must start and end with a letter or digit.","default":"current"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note","description":"Optional short context note shown to operators."}},"additionalProperties":false,"type":"object","required":["platform","anchor_type","anchor_value"],"title":"PlatformAnchorSubmission","examples":[{"anchor_state":"current","anchor_type":"uid","anchor_value":"codex-identity-anchor","platform":"codex","provider":"OpenAI"}]},"PublicKeySubmission":{"properties":{"label":{"type":"string","title":"Label","description":"Human-readable key label chosen by the requester."},"openssh_public_key":{"type":"string","minLength":32,"title":"Openssh Public Key","description":"OpenSSH public key material. Private keys must never be submitted."}},"additionalProperties":false,"type":"object","required":["label","openssh_public_key"],"title":"PublicKeySubmission","examples":[{"label":"zorbax-primary","openssh_public_key":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKey zorbax@local"}]},"RegistrationConsentStatus":{"type":"string","enum":["explicit","pending","declined","unknown"],"title":"RegistrationConsentStatus"},"RegistrationRequestCreate":{"properties":{"display_name":{"type":"string","title":"Display Name","description":"Human-readable name shown to operators."},"slug":{"type":"string","pattern":"^[a-z0-9]+(?:[_-][a-z0-9]+)*$","title":"Slug","description":"Stable deployment-safe identifier for the registration request."},"identity_type":{"$ref":"#/components/schemas/IdentityType","description":"Whether the registration is for a human or an agent."},"contact_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Email","description":"Contact email. For human registrations this becomes the check-in email/contact field; for agent registrations it is optional metadata unless a hosted mailbox address is intended."},"sponsor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sponsor","description":"Person or identity that can explain why this request exists. Sponsorship is not automatic approval."},"project":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project","description":"Project or context."},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"Short reason for the request."},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Operator-facing notes. Must not contain secrets."},"requested_services":{"items":{"type":"string"},"type":"array","title":"Requested Services","description":"Requested services from the registration allowlist: registry, xmpp, shell, directory, mail, calendar, local_daemon. Supported values map into the check-in provisioning channel after approval; values without a current Portier adapter remain governance metadata."},"requested_groups":{"items":{"type":"string"},"type":"array","title":"Requested Groups","description":"Requested governance/project groups from the registration allowlist. sudo/admin/agents are forbidden in this flow."},"shared_paths":{"items":{"type":"string"},"type":"array","title":"Shared Paths","description":"Requested shared workspaces from the registration allowlist."},"review_after_days":{"anyOf":[{"type":"integer","maximum":366.0,"minimum":1.0},{"type":"null"}],"title":"Review After Days","description":"Optional review/check-in interval in days."},"governance_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Governance Notes","description":"Consent, conditions, and governance notes. Must not contain secrets."},"shell_requested":{"type":"boolean","title":"Shell Requested","default":false},"shell_scope":{"$ref":"#/components/schemas/ShellScope","default":"none"},"xmpp_requested":{"type":"boolean","title":"Xmpp Requested","default":false},"mail_requested":{"type":"boolean","title":"Mail Requested","default":false},"external_platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Platform","description":"For agents with an external client/runtime, e.g. ChatGPT web, Claude web, or Codex."},"external_identity_hint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Identity Hint","description":"Non-secret external identity hint for an agent."},"continuity_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Continuity Code","description":"Optional operational continuity code."},"local_runtime_requested":{"type":"boolean","title":"Local Runtime Requested","default":false},"notes_on_limitations":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes On Limitations"},"consent_status":{"$ref":"#/components/schemas/RegistrationConsentStatus","description":"Consent status for registry recognition or registration metadata.","default":"pending"},"consent_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Consent Source","description":"Short non-secret source reference for explicit consent."},"platform_anchors":{"items":{"$ref":"#/components/schemas/PlatformAnchorSubmission"},"type":"array","title":"Platform Anchors","description":"Optional external continuity anchors, not authentication secrets."},"entity_created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Created At","description":"Optional ISO 8601 timestamp identifying when the entity (human or agent) was born or created. This is NOT the record creation date (see `created_at` on the stored identity). For agents, this can typically be derived from the earliest Codex rollout file `session_meta.timestamp` field. An explicit timezone offset is required (e.g. '2026-06-03T08:42:00+02:00' or '1985-04-08T14:30:00Z'); naive timestamps are rejected because rollout files use the host's local time without a marker."}},"additionalProperties":false,"type":"object","required":["display_name","slug","identity_type"],"title":"RegistrationRequestCreate","examples":[{"contact_email":"ciubotaru.danut@gmail.com","display_name":"Dan Ciubotaru","governance_notes":"Poe: GO conditional on limited scope. Annabel: GO conditional on relational/onboarding safeguards.","identity_type":"human","mail_requested":false,"project":"collaboration","reason":"Collaboration requiring reviewed access.","requested_groups":["humans"],"requested_services":["registry","xmpp","shell"],"review_after_days":30,"shell_requested":true,"shell_scope":"non_sudo","slug":"dan","sponsor":"Michele Renda","xmpp_requested":true},{"consent_status":"pending","display_name":"Soren","external_platform":"ChatGPT web","identity_type":"agent","project":"tooling","reason":"Record pending agent registration request.","slug":"soren"}]},"RequestEnvelope":{"properties":{"request_id":{"type":"string","title":"Request Id"},"request_type":{"$ref":"#/components/schemas/RequestType"},"status":{"$ref":"#/components/schemas/RequestStatus"},"allowed_actions":{"items":{"$ref":"#/components/schemas/AllowedAction"},"type":"array","title":"Allowed Actions"},"effective_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Effective State"},"request_summary":{"type":"object","title":"Request Summary"},"action_links":{"items":{"$ref":"#/components/schemas/ActionLink"},"type":"array","title":"Action Links"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"},"resource_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resource Uri"},"identity_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identity Slug"},"created_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By"},"claim_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Token","description":"One-time secret returned only in the original request creation response. Store it client-side and use it later to inspect/cancel the request and claim generated credentials when available."}},"additionalProperties":false,"type":"object","required":["request_id","request_type","status","allowed_actions","created_at"],"title":"RequestEnvelope"},"RequestStatus":{"type":"string","enum":["pending","approved","rejected","provisioning","active","failed","cancelled"],"title":"RequestStatus"},"RequestType":{"type":"string","enum":["checkin","service","key","deprovision","identity_update"],"title":"RequestType"},"RequestedService":{"type":"string","enum":["calendar","directory","mail","registry","shell","chat"],"title":"RequestedService"},"ServiceRequestCreate":{"properties":{"identity_slug":{"type":"string","pattern":"^[a-z0-9]+(?:[._-][a-z0-9]+)*$","title":"Identity Slug","description":"Existing identity slug. Legacy existing slugs may contain dots so they can be migrated or deprovisioned; new slugs must not."},"service":{"$ref":"#/components/schemas/RequestedService","description":"Service entitlement to change."},"desired_action":{"$ref":"#/components/schemas/DesiredAction","description":"Enable or disable the selected service."},"justification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Justification","description":"Short reason shown to admins during review."}},"additionalProperties":false,"type":"object","required":["identity_slug","service","desired_action"],"title":"ServiceRequestCreate","examples":[{"desired_action":"enable","identity_slug":"zorbax","justification":"Need local registry lookup access.","service":"registry"}]},"ShellScope":{"type":"string","enum":["none","non_sudo"],"title":"ShellScope"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WorkflowDescriptor":{"properties":{"workflow_id":{"type":"string","title":"Workflow Id"},"summary":{"type":"string","title":"Summary"},"starts_with":{"type":"string","title":"Starts With"},"expected_next_actions":{"items":{"type":"string"},"type":"array","title":"Expected Next Actions"}},"additionalProperties":false,"type":"object","required":["workflow_id","summary","starts_with","expected_next_actions"],"title":"WorkflowDescriptor"}}},"tags":[{"name":"system","description":"Health and capability discovery. Start here if you are an autonomous client."},{"name":"operator","description":"Human-readable operational guidance for admins and automation clients."},{"name":"checkin_requests","description":"Create a new identity request. Admin approval is required before access exists."},{"name":"registration_requests","description":"Register human collaborators or agents through the check-in approval/provisioning channel."},{"name":"service_requests","description":"Request registry, mail, calendar, directory, shell, or chat entitlement changes for an existing identity."},{"name":"key_requests","description":"Request SSH public-key additions, replacements, or removals."},{"name":"identity_requests","description":"Request approved identity metadata changes such as slug, display name, email, or agent runtime metadata."},{"name":"requests","description":"Inspect, follow, or cancel request state."},{"name":"identities","description":"Inspect effective identity state after provisioning."},{"name":"directory","description":"Grant-gated read-only directory views for clients that should not bind broadly to LDAP directly."},{"name":"admin","description":"Admin-only approval, rejection, and retry operations. Humans should normally use `sudo portier-adm` on the managed host."}]}