Configure who may request work, which contracts may execute, who reviews changes and how outcomes are retained. This guide covers the implemented 0.2.0-rc14 controls. Test them in a non-production installation before enabling consequential actions.
Documentation · Integrations · Environment walkthrough · Deployment · Security and evidence
Understand the boundaries
- Identity: a signed token establishes the caller, tenant and roles.
- Capability contract: an operator reviews the exact endpoint, operations, schemas, runtime and readiness findings before approval.
- Tenant policy: deterministic rules can deny, constrain or defer a request. Policy releases require preflight and approval by a different principal.
- Execution: an enrolled runtime performs authorized work using provider-scoped credentials.
- Evidence: receipts and correlated records distinguish success, denial, failure and uncertainty.
These are separate controls. A high trust score is not permission. Registering a tool is not approval. A policy proposal is not activation. A model recommendation is not proof of a real-world effect. Only requests routed through the governed path are covered.
1. Configure an identity provider
Create an API application/resource in your IdP with a dedicated audience for AOS. Issue access tokens for that audience; do not substitute a browser ID token. AOS’s generic OIDC verifier checks the issuer, audience, allowed asymmetric algorithm, signature, expiry and required claims against the configured JWKS URL.
The decoded payload must contain sub, iss, aud, iat, exp, your tenant claim and at least one recognized AOS role. This example shows claim shape, not a usable token:
{
"sub": "operator-subject",
"iss": "https://identity.example.com/",
"aud": "api://aos",
"iat": 1790000000,
"exp": 1790003600,
"tenant_id": "engineering",
"organization_id": "example-organization",
"roles": ["operator", "policy_admin"],
"principal_type": "user"
}
The timestamps are illustrative and must be current in a real IdP-issued token. Configure the control plane with your actual issuer metadata:
export AOS_OIDC_ISSUER='https://identity.example.com/'
export AOS_OIDC_AUDIENCE='api://aos'
export AOS_OIDC_JWKS_URL='https://identity.example.com/.well-known/jwks.json'
export AOS_OIDC_ALGORITHMS='["RS256"]'
export AOS_OIDC_TENANT_CLAIM='tenant_id'
export AOS_OIDC_ORGANIZATION_CLAIM='organization_id'
export AOS_OIDC_ROLES_CLAIM='roles'
export AOS_OIDC_PRINCIPAL_TYPE_CLAIM='principal_type'
Use the issuer’s published JWKS endpoint, not a guessed path. Claim settings identify exact top-level keys; nested group objects are not automatically mapped. Configure the IdP to emit AOS role names. Use different human subjects for author and reviewer, even when both have policy_admin.
| Provider | Setup to verify in the provider |
|---|---|
| Microsoft Entra ID | Register/expose the AOS API, assign app roles or mapped claims, request the correct audience and use the exact tenant-specific issuer/JWKS. An Entra tid is an identity-directory tenant; do not silently treat it as your AOS workspace tenant. |
| Okta | Use an authorization server for your API audience; add explicit tenant and AOS-role claims to access tokens. Raw Okta group names need provider-side mapping to recognized roles. |
| Auth0 | Register the AOS API identifier; add tenant/role claims through an Action. Namespaced custom keys can be configured directly, for example AOS_OIDC_TENANT_CLAIM='https://aos.example.com/tenant_id'. |
Provider references: Entra access tokens, Okta claims, Auth0 JWKS. The generic protocol has automated tests; a real organization’s application, claims and token lifecycle still require live qualification.
2. Assign narrow roles
| Work | Required role pattern |
|---|---|
| Request governed actions | requester |
| Manage and approve capability contracts | operator |
| Create, submit and activate tenant policy releases | policy_admin |
| Approve a tenant policy release | A different subject with policy_admin; reviewer alone does not grant this endpoint |
| Review action approvals | reviewer, subject to the action’s approval checks |
| Publish runtime identity and observations | Service account with runtime_publisher |
| Manage usage budgets | billing_admin or the endpoint’s permitted administrative role |
| Audit/compliance review | compliance_auditor, with any additional role required by the selected export endpoint |
| Platform-wide administration | Dedicated platform_admin or narrowly controlled admin, according to the endpoint |
Do not use a shared administrator token for ordinary work. For a runtime token, emit principal_type: "service_account", runtime_id and node_id matching its configured identity. A user token is not interchangeable with a runtime identity. Access is tenant-bound; a different X-AOS-Tenant-ID header cannot grant another tenant.
3. Connect through CLI and UI
Save the current access token to a private file through your organization’s normal sign-in process. AOS does not provide an interactive enterprise OAuth login/refresh command or automatic browser SSO in this release.
export AOS_URL='https://aos.example.com'
export AOS_TENANT_ID='engineering'
export AOS_TOKEN_FILE="$PWD/operator-token.txt"
chmod 600 "$AOS_TOKEN_FILE"
aos product request GET /v1/identity/me
aos product runtime nodes
Check the returned subject, tenant, organization and roles before changing anything. In the UI, open /console/, click Session, enter the same tenant and select the token file. Its contents are read locally into a masked field, then sent to the selected AOS server for API authentication. Clear the session on shared machines. Do not expose the local workstation portal to the internet.
An expired token must be replaced through your IdP. JWKS key rotation is supported; instant per-token revocation is not promised by offline JWT verification. Use short expiry, remove access at the IdP, and use AOS capability/account controls for immediate containment where applicable.
For action-level review, use a different subject with the reviewer role. The requester cannot
approve their own action; reviewer permission alone does not permit execution. See
Action approvals for UI/CLI steps and exact-request binding. Review records
contain the supplied inputs and context, so keep secrets and unrelated private data out of them.
4. Define policy rules
The deterministic rule surface includes minimum trust, denied capabilities, required security attributes, allowed adapter types and regions, maximum estimated cost, risk levels requiring approval, and audit requirements. These rules are not a general-purpose policy programming language. Empty allow-lists do not mean deny-all. Missing/unreviewed metadata is not a safe substitute for provider-side access control.
Start with the real capability names/IDs and metadata used in your installation. This example deliberately denies one named capability while requiring audit and approval for high/critical risk:
Save policy-draft.json:
{
"name": "engineering-actions",
"rules": {
"denied_capabilities": ["capacity-changes"],
"require_audit": true,
"approval_required_for_risk": ["high", "critical"]
},
"change_summary": "Hold capacity changes while preserving audited observation work"
}
UI: Open Policies → New policy. Choose a template, give the policy a name and summary, then edit Rules JSON. Review the actual JSON before submission; selecting a different template replaces those rules. Draft creation alone changes no active behavior.
CLI:
aos product --output policy-created.json request POST /v1/policy-releases --file policy-draft.json
Read data.id from policy-created.json and replace POLICY_UUID below. Keep one file per response; exports will not overwrite evidence.
aos product request POST /v1/policy-releases/POLICY_UUID/submit
5. Run preflight and independent review
Save preflight.json with representative inputs and the real inventory. A passing preflight means the policy is internally eligible for activation; it does not prove your test dataset covers every production request.
{
"dataset_name": "engineering-acceptance",
"dataset_version": "1",
"samples": [
{"sample_id":"observe","input":{"capability_name":"capacity-observations","adapter_type":"http","trust_level":0.8,"risk_level":"low","audit_enabled":true}},
{"sample_id":"change-held","input":{"capability_name":"capacity-changes","adapter_type":"http","trust_level":0.8,"risk_level":"low","audit_enabled":true}},
{"sample_id":"missing-audit","input":{"capability_name":"capacity-observations","adapter_type":"http","trust_level":0.8,"risk_level":"low","audit_enabled":false}}
],
"inventory": {"capabilities":["capacity-observations","capacity-changes"],"adapter_types":["http"]},
"shadow": true
}
aos product --output preflight-result.json request POST /v1/policy-releases/POLICY_UUID/preflight --file preflight.json
Inspect sample decisions: observe should allow; held capability and missing audit should deny. Review warnings, violations, dataset digest and activation_ready. Add expired authority, cross-tenant, over-budget and provider-failure cases in the appropriate integration acceptance tests; these are not all expressed by this small policy dataset.
Save policy-decision.json containing {"approve":true,"reason":"Reviewed scope and preflight outcomes"}. Switch to a different reviewer’s current token file, whose subject has policy_admin:
export AOS_TOKEN_FILE="$PWD/reviewer-token.txt"
aos product request POST /v1/policy-releases/POLICY_UUID/decision --file policy-decision.json
aos product request POST /v1/policy-releases/POLICY_UUID/activate
Approval by the author must fail with HTTP 409. Activation requires an approved release and passing preflight. The policy table provides the equivalent Submit, Preflight, Approve and Activate controls according to role/status. Use the Session dialog to change identity; a role label on a screen is not identity proof.
Re-run actual allowed and denied tool requests after activation. Inspect receipts and ensure denied requests did not reach the provider. An approved policy is not a guarantee that every request will be allowed: contract activation, identity, entitlements, runtime controls and other obligations still apply.
6. Recover, revoke and retain
For an active policy, the authorized policy administrator can use Rollback with a reason. CLI equivalent, with a saved rollback.json such as {"reason":"Restore previously reviewed behavior"}:
aos product request POST /v1/policy-releases/POLICY_UUID/rollback --file rollback.json
Rollback requires a suitable prior release; it does not undo provider effects. An emergency hold is a new reviewed policy or capability revocation, not an edit to historical audit evidence. Revoke an affected capability, rotate exposed provider credentials and reconcile in-flight work before reopening.
Use Audit and Usage to inspect outcomes and cost estimates. Export correlated evidence privately; configured signed snapshots require operator keys and verification outside the viewer. Set backup, retention, deletion and incident procedures for your deployment. The Security guide explains which evidence claims a signature can and cannot support.
Qualification before production
Verify valid, expired and wrong-audience tokens; unknown roles; cross-tenant denial; separate author/reviewer identities; runtime subject binding; contract drift; provider credential rotation; preflight rejection; policy rollback; revoked access; resource reconciliation; independently retained evidence; and database recovery. The local walkthrough exercises selected controls, while live IdP/vendor and operational qualification remain deployment responsibilities.