Files
aios/AGENT_OWNER_AUTHORIZATION_BROKER_DEPLOYMENT.md
T

9.9 KiB

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

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:

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:

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:

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:

owner_account: <non-secret account>
credential_id: <non-secret ID, when available>
intake_scope: <one exact existing 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:

STATUS: BLOCKED
REASON: OWNER_CREDENTIAL_SCOPE_NOT_PROVABLE

3. Staging installation

Install the four application modules in a root-owned staging directory:

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:

AIOS_GITOPS_OWNER_AUTHORIZATION_BROKER_ENABLED: "true"
AIOS_GITOPS_OWNER_AUTHORIZATION_INTAKE_SCOPES: <one exact existing scope>
AIOS_GITOPS_OWNER_AUTHORIZATION_ALLOWED_IDENTITIES: <exact owner account>
AIOS_GITOPS_OWNER_AUTHORIZATION_ALLOWED_CREDENTIAL_IDS: <exact ID or empty>
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:

POST /api/governance/owner-authorizations

Required tests:

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:

{
  "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:

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:

git --git-dir=/data/aios-gitops/repo.git rev-parse \
  refs/heads/agent/v2r1c6-mainline-reconciliation-20260805

It must equal:

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:

/var/lib/aios-gitops/owner-authorization-broker/events/

Requirements:

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:

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

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