# Agent Deployment Requirements: Owner Authorization Broker V2 ## Objective Deploy the audited Owner Authorization Broker that closes the bootstrap gap without issuing a new general-purpose Owner credential and without modifying `/data/aios-gitops/runtime/secrets/gitops.tokens`. The broker reuses one existing, non-wildcard Owner credential only to authenticate the Owner identity through one pre-existing exact scope. It then records an immutable task authorization event and directly invokes the existing signed grant -> validator -> one-shot provisioner chain. Production deployment of V2R1C6 is **not** authorized by this task. ## Fixed bindings ```yaml task_id: V2R1C6_TASK_SCOPED_WRITER_PROVISIONING repository: aios/aios base_ref: refs/heads/main base_oid: 875d41c3101093149414292067fd700dc214d4d3 target_branch: agent/v2r1c6-mainline-reconciliation-20260805 production_change_authorized: false tag_change_authorized: false baseline_change_authorized: false main_write_authorized: false ``` The existing V2R1C5 objects are frozen: ```yaml tag_oid: 9e65bd59baea392294c0f253046d3ab116f63145 peeled_target_oid: aa60e891547abd7e215af7cf2bf3f21fd23541da baseline_version: V2R1C5 baseline_status: PRODUCTION_DEPLOYED ``` ## 1. Package verification Verify `MANIFEST.sha256` before installation. Reject any mismatch. Run: ```bash python3 -m unittest -v \ tests/test_authorized_task_writer_provisioning.py \ tests/test_owner_authorization_broker.py python3 scripts/smoke_authorized_task_writer_provisioning.py python3 scripts/smoke_owner_authorization_broker.py python3 -m py_compile \ active-runtime/app/authorized_task_writer_provisioning.py \ active-runtime/app/aios_authorized_task_writer_api.py \ active-runtime/app/owner_authorization_broker.py \ active-runtime/app/aios_owner_authorization_broker_api.py ``` All checks must pass. ## 2. Existing Owner credential selection Read only the non-secret registry metadata. Select one existing credential that satisfies all of the following: ```yaml role: owner wildcard_scope: false account: exact known Owner identity contains_exact_intake_scope: true ``` Use one existing exact scope such as `commit:create` or `file:write`. Prefer the narrowest scope already assigned to the intended Owner. Do not: - use the historical wildcard Owner credential; - add `writer:provision` to any bearer token; - create or modify a bearer credential; - print, copy or commit bearer-token material. Record only: ```yaml owner_account: credential_id: intake_scope: scope_readback_available: true|false ``` If `handler.need()` returns the exact scope set, configure the Owner account allowlist and leave the credential ID allowlist empty. If scope metadata is not returned, configure the exact non-secret credential ID allowlist. If neither exact scope metadata nor a stable non-secret credential ID can be proven, stop: ```yaml STATUS: BLOCKED REASON: OWNER_CREDENTIAL_SCOPE_NOT_PROVABLE ``` ## 3. Staging installation Install the four application modules in a root-owned staging directory: ```text authorized_task_writer_provisioning.py aios_authorized_task_writer_api.py owner_authorization_broker.py aios_owner_authorization_broker_api.py ``` The directory and files must not be group/world writable. Prepare environment values: ```yaml AIOS_GITOPS_OWNER_AUTHORIZATION_BROKER_ENABLED: "true" AIOS_GITOPS_OWNER_AUTHORIZATION_INTAKE_SCOPES: AIOS_GITOPS_OWNER_AUTHORIZATION_ALLOWED_IDENTITIES: AIOS_GITOPS_OWNER_AUTHORIZATION_ALLOWED_CREDENTIAL_IDS: AIOS_GITOPS_OWNER_AUTHORIZATION_MAX_EXPIRY_SECONDS: "900" AIOS_GITOPS_OWNER_AUTHORIZATION_STATE_ROOT: /var/lib/aios-gitops/owner-authorization-broker ``` Use the existing signer, validator and provisioner paths. Do not change their root governance configuration or disable signature checks. Start a localhost-only staging instance on a temporary port. Do not replace the production service yet. ## 4. Authentication fail-closed tests The staging endpoint is: ```text POST /api/governance/owner-authorizations ``` Required tests: ```yaml unauthenticated: expected: 401 wrong_role: expected: 403 wrong_scope: expected: 403 wildcard_owner: expected: 403 error: WILDCARD_OWNER_CREDENTIAL_REJECTED unallowlisted_owner: expected: 403 error: OWNER_IDENTITY_NOT_ALLOWED production_capability_true: expected: 403 error: PRODUCTION_CAPABILITY_REJECTED ``` A connection failure, 404 or 500 is not an authorization-policy pass. ## 5. Formal provisioning request Use the selected existing non-wildcard Owner credential through its runtime secret reference. Never place the bearer token in the request body, command line, shell history, output report or Git. Request: ```json { "action": "AUTHORIZE_TASK_WRITER_PROVISIONING", "task_id": "V2R1C6_TASK_SCOPED_WRITER_PROVISIONING", "repository": "aios/aios", "base_ref": "refs/heads/main", "base_oid": "875d41c3101093149414292067fd700dc214d4d3", "target_branch": "agent/v2r1c6-mainline-reconciliation-20260805", "one_time_use": true, "expires_in_seconds": 900, "production_change_authorized": false, "tag_change_authorized": false, "baseline_change_authorized": false, "main_write_authorized": false, "allowed_operations": [ "create_worktree", "create_target_branch_if_absent", "commit_to_target_branch", "push_target_branch" ], "denied_operations": [ "direct_main_push", "force_push", "tag_create", "tag_update", "tag_delete", "branch_delete", "repository_admin", "baseline_write", "production_deploy", "production_marker_write", "history_rewrite" ] } ``` The Owner authorization reference is generated by the broker. The caller must not submit or invent one. Expected result: ```yaml status: READY_FOR_CODE_AUTHORING owner_authorization_event_id: generated owner_authorization_reference: generated owner_authorization_digest_sha256: generated owner_authorization_consumed: true approval_plan_id: generated grant_digest_sha256: generated grant_consumed: true branch_oid: 875d41c3101093149414292067fd700dc214d4d3 writer_scope: workspace_role: task-scoped-isolated-writer writes_enabled: true allowed_branch: agent/v2r1c6-mainline-reconciliation-20260805 allowed_base_oid: 875d41c3101093149414292067fd700dc214d4d3 allow_main_write: false allow_tag_write: false allow_baseline_write: false allow_force_push: false ``` ## 6. Independent post-provisioning verification Verify the Authority ref: ```bash git --git-dir=/data/aios-gitops/repo.git rev-parse \ refs/heads/agent/v2r1c6-mainline-reconciliation-20260805 ``` It must equal: ```text 875d41c3101093149414292067fd700dc214d4d3 ``` Verify `main` remains unchanged, V2R1C5 tag object and peeled target remain unchanged, and the Production Baseline remains V2R1C5. Verify the broker audit event under: ```text /var/lib/aios-gitops/owner-authorization-broker/events/ ``` Requirements: ```yaml status: CONSUMED wildcard_scope_used: false grant_consumed: true permissions: directory: "0700" json_files: "0600" ``` Do not return bearer-token material in the report. ## 7. Commit the broker through the new writer After `READY_FOR_CODE_AUTHORING`, use only the writer's `POST /api/commit-file` route to put this code bundle on: ```text agent/v2r1c6-mainline-reconciliation-20260805 ``` Commit the bridge and broker as separate intentional commits when practical: 1. Owner-authorized task-writer bridge. 2. Audited Owner authorization broker and deployment docs. Do not merge to `main` directly. Create a protected PR after branch commits and tests are complete. ## 8. Permanent service deployment Only after protected review and merge: 1. Install the reviewed files from the merge commit. 2. Apply a reviewed systemd drop-in based on the provided example. 3. Start the wrapper entrypoint: `aios_owner_authorization_broker_api.py`. 4. Verify all existing API routes still work. 5. Verify the broker remains localhost/reverse-proxy constrained as intended. 6. Re-run authentication and policy tests. 7. Remove the temporary staging instance. This permanent bridge deployment does not authorize a V2R1C6 production tag, Baseline update or application deployment. ## 9. Fail-closed conditions Stop with `BLOCKED` for any of the following: - Authority `main` no longer equals the fixed base OID. - Target branch exists at a different OID. - Only a wildcard Owner credential can authenticate. - Exact credential scope cannot be proven. - Owner identity is not explicitly allow-listed. - Signer, validator or provisioner self-test fails. - Grant is not marked one-time and consumed. - Writer allows main, tag, Baseline, force-push or branch-delete operations. - Audit event contains sensitive material. - V2R1C5 tag or Baseline changes. ## 10. Required Agent result ```yaml STATUS: READY_FOR_CODE_AUTHORING | BLOCKED | FAILED PACKAGE: manifest_verified: unit_tests: smoke_tests: py_compile: OWNER_CREDENTIAL: account: credential_id: intake_scope: exact_scope_proven: wildcard_used: false token_logged: false BROKER: staging_listener: endpoint_status: event_id: authorization_reference: authorization_digest_sha256: event_consumed: audit_permissions_valid: GRANT: approval_plan_id: grant_digest_sha256: signer_identity: signature_valid: one_time_use: consumed: BRANCH: name: oid: base_oid: ref_exists: worktree_path: worktree_clean: WRITER: status: writes_enabled: allowed_branch: allowed_base_oid: allowed_routes: main_write_denied: tag_write_denied: baseline_write_denied: force_push_denied: POSTCHECK: main_unchanged: V2R1C5_tag_unchanged: baseline_unchanged: REPOSITORY_INTEGRATION: commit_oids: protected_pr: merged: permanent_bridge_deployed: BLOCKERS: GOVERNANCE: force_push_used: false tag_rewritten: false direct_main_push: false secrets_committed: false owner_approval_respected: true ```