{
  "schema": "aaes/capability-pack/1",
  "provider": "okta",
  "version": "1.0.0",
  "description": "Read Okta users, groups, and group members; add or remove group members and deactivate users. Membership can grant application access, and deactivation can destroy data in assigned applications.",
  "notes": "The endpoint host 'okta-org.invalid' is a reserved non-production placeholder (an RFC 2606 reserved TLD): substitute the customer's own Okta org host (or configured custom domain) before enabling, in the endpoints, the resource locators and the egress allowlist — the allowlist matches exactly, so all three must be substituted together, and substitution is a required deployment step. Every endpoint here is on the customer org host, not a shared Okta SaaS host, so the allowlist moves with the tenant.\n\nThis pack registers only endpoints the public Okta Management API documents (verified against the official OpenAPI spec that builds Okta's management SDKs): listing users, listing groups, listing a group's member users, adding and removing a user in a group, and the user lifecycle deactivate operation.\n\nDocumented exclusions: single-user and single-group reads (GET /api/v1/users/{id} and GET /api/v1/groups/{groupId}; the user and group reads here are collection reads only), user creation and profile update (POST /api/v1/users, POST/PUT /api/v1/users/{id}), permanent user deletion (DELETE /api/v1/users/{id} — Okta documents it as unrecoverable and it is the truly irreversible off-boarding step), suspend/unsuspend, session clearing and password operations, group creation and group-rule management, and application assignment APIs.\n\nApproval classification: identity changes are extensive. Lifecycle deactivation is registered as delete at the minimum R3 tier: Okta documents deactivation as a destructive operation — the user is deprovisioned from all assigned applications, which may destroy their data such as email or files, and Okta states the action cannot be recovered; the directory account can later be reactivated, but reactivation does not restore deprovisioned application data, so this pack makes no general-reversibility claim, and delete is one of the designated actions requiring human approval.\n\nGroup membership assignment is declared update and share at the minimum R3 tier because membership can grant application access, roles and policies downstream — assigning membership is access-granting — and an R2 variant would require an enforced, reviewed restriction to groups that grant nothing, which this pack does not register.\n\nMembership removal is declared delete at the minimum R3 tier: the operation deletes the membership relationship itself, and where the group granted access the removal revokes it; re-adding the user later is a new assignment, not an undo of this call.\n\nThe floors are lower bounds, not risk assessments. The pack registers an SSWS API token because it is the auth scheme every Okta org supports, but SSWS tokens are long-lived, carry the permissions of the creating admin, and are not scoped; OAuth 2.0 service-app authentication with scoped tokens (okta.users.read, okta.groups.read, okta.users.manage, okta.groups.manage — the minimum per capability) is the better-hygiene path and the deployment should prefer it where available.\n\nAAES has not been certified by Okta; the endpoints here are configuration to review and test; the vendor has not endorsed it.",
  "credential": {
    "secret_ref_id": "secret-ref-okta-ssws-token",
    "custody": "customer_vault",
    "inject": "header",
    "inject_name": "Authorization",
    "note": "An Okta SSWS API token for the customer's own org, held in the client's own secret manager. The stored material must be the complete Authorization header value: the scheme 'SSWS', one separating space, then the token — 'SSWS <token>'. customer_vault is the only generally-supported production custody model here — identity_federation and customer_broker are refused at startup and inline is lab-only.\n\nSSWS tokens are long-lived, unscoped, and inherit the full permissions of the admin who created them (tracking that admin's privilege changes): create the token from a dedicated least-privilege admin service account.\n\nOkta expires a token after 30 days without use — the 30-day window refreshes with each API call — and deprovisions the token if the creating admin is deactivated; tokens can also be revoked in the Admin Console at any time, and an expired or revoked value fails closed. Renewal ownership sits with an external deployment process: the executor injects the stored value verbatim and performs no token lifecycle itself.\n\nPrefer OAuth 2.0 service-app authentication with scoped access tokens where the deployment supports it; review token rotation and the creating admin's role before enabling.\n\nExecutor hygiene: the value must live only in executor memory for the lifetime of a call, must never be written to logs, traces or diagnostics, and must not appear in crash dumps; a deployment that cannot meet that bar must not enable the pack."
  },
  "capabilities": [
    {
      "capability_id": "okta.users.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "okta-org.invalid"
      ],
      "endpoint": "https://okta-org.invalid/api/v1/users",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-okta-ssws-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "okta-org-users",
      "description": "List users in the org: names, emails, logins, phones and status, which are personal data. The registered path covers the collection read only — single-user reads (GET /api/v1/users/{id}) are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "okta.groups.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "okta-org.invalid"
      ],
      "endpoint": "https://okta-org.invalid/api/v1/groups",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-okta-ssws-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "okta-org-groups",
      "description": "List groups in the org: names and descriptions, which reveal org structure. The registered path covers the collection read only — single-group reads (GET /api/v1/groups/{groupId}) are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "okta.groups.members.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "okta-org.invalid"
      ],
      "endpoint": "https://okta-org.invalid/api/v1/groups/GROUP_ID/users",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-okta-ssws-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "okta-org-users",
      "description": "List the member users of one group; the response is user profiles, which are personal data.\n\nGROUP_ID is a placeholder the deployment binds to a concrete group before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "okta.groups.members.add",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "okta-org.invalid"
      ],
      "endpoint": "https://okta-org.invalid/api/v1/groups/GROUP_ID/users/USER_ID",
      "method": "PUT",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-okta-ssws-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "update",
        "share"
      ],
      "resource_id": "okta-org-users",
      "description": "Add a user to a group. Group membership can grant application access, roles and policies downstream, so the capability declares update and share at the minimum R3 tier — assigning membership is access-granting, and share is one of the designated actions requiring human approval. Okta permits direct membership changes only on groups of the OKTA_GROUP type.\n\nGROUP_ID and USER_ID are placeholders the deployment binds to concrete ids before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "okta.groups.members.remove",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "okta-org.invalid"
      ],
      "endpoint": "https://okta-org.invalid/api/v1/groups/GROUP_ID/users/USER_ID",
      "method": "DELETE",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-okta-ssws-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "delete"
      ],
      "resource_id": "okta-org-users",
      "description": "Remove a user from a group: the HTTP DELETE deletes the membership relationship itself, so the declared action is delete at the minimum R3 tier. Where the group granted access, the removal revokes it; re-adding the user later is a new assignment, not an undo of this call. Okta permits direct membership changes only on groups of the OKTA_GROUP type.\n\nGROUP_ID and USER_ID are placeholders the deployment binds to concrete ids before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "okta.users.lifecycle.deactivate",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "okta-org.invalid"
      ],
      "endpoint": "https://okta-org.invalid/api/v1/users/USER_ID/lifecycle/deactivate",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-okta-ssws-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "delete"
      ],
      "resource_id": "okta-org-users",
      "description": "Deactivate a user. Okta documents deactivation as a destructive operation: the user is deprovisioned from all assigned applications, which may destroy their data such as email or files, and Okta states the action cannot be recovered. The directory account can later be reactivated, but reactivation does not restore deprovisioned application data, so this pack claims no general reversibility.\n\nThe user's transitioningToStatus property reports DEPROVISIONED while the deprovision is in progress, and a caller may request asynchronous processing with the Prefer: respond-async header per the documented request mode; completion timing is therefore not an unconditional guarantee of this registration.\n\nRegistered as delete at the minimum R3 tier — delete is one of the designated actions requiring human approval.\n\nOn supported AAES-mediated execution paths, irreversible actions require approval by an authorized person; this does not prevent calls through bypass or observation-only paths. Permanent user deletion (DELETE /api/v1/users/{id}, which Okta documents as unrecoverable) is deliberately not registered. USER_ID is a placeholder the deployment binds to a concrete user before enabling.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "okta-org-users",
      "kind": "api",
      "locator": "https://okta-org.invalid/api/v1/users",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "okta-org-groups",
      "kind": "api",
      "locator": "https://okta-org.invalid/api/v1/groups",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-10-22",
    "sources": [
      "https://developer.okta.com/docs/reference/core-okta-api/ (retrieved 2026-09-21)",
      "https://developer.okta.com/docs/api/openapi/okta-management/management/tag/User/ (retrieved 2026-09-21)",
      "https://developer.okta.com/docs/api/openapi/okta-management/management/tag/Group/ (retrieved 2026-09-21)",
      "https://developer.okta.com/docs/api/openapi/okta-management/management/tag/UserLifecycle/ (retrieved 2026-09-21)",
      "https://github.com/okta/okta-management-openapi-spec/blob/master/dist/current/management-minimal.yaml (retrieved 2026-09-21)",
      "https://developer.okta.com/docs/guides/create-an-api-token/main/ (retrieved 2026-09-21)"
    ],
    "reviewer_id": "owner-delegated"
  }
}
