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:provisionto 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:
- Owner-authorized task-writer bridge.
- 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:
- Install the reviewed files from the merge commit.
- Apply a reviewed systemd drop-in based on the provided example.
- Start the wrapper entrypoint:
aios_owner_authorization_broker_api.py. - Verify all existing API routes still work.
- Verify the broker remains localhost/reverse-proxy constrained as intended.
- Re-run authentication and policy tests.
- 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
mainno 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