4.0 KiB
Owner Authorization → Task Writer Provisioning Bridge
Purpose
This change closes the control-plane gap where an authenticated Owner can
approve a task in the API, but the runtime cannot automatically produce the
machine-verifiable, signed, one-time grant required by
aios-task-writer-provisioner.
The bridge adds one high-risk endpoint:
POST /api/task-writer/provision-authorized
It does not add a general branch endpoint to the hardened writer. Branch and
worktree creation remain the responsibility of the existing root-governed
one-shot provisioner. Source commits continue through the isolated writer's
existing POST /api/commit-file route.
Trust boundary
The API must authenticate the caller as role=owner and require the
writer:provision scope. The request contains an auditable Owner authorization
reference; it never contains a private key, token or signature.
The bridge:
- Validates an exact repository, base ref, base OID and target branch.
- Rejects all production, tag, baseline and direct-main capabilities.
- Generates a canonical approval plan and short-lived grant request.
- Calls the root-owned signer adapter.
- Calls the independent grant validator.
- Calls the one-shot task writer provisioner.
- Verifies the resulting branch, writer scope and negative policy tests.
- Stores a redacted, fsynced idempotency receipt.
The bridge never executes git update-ref, git branch, git push, a tag
operation, a baseline mutation or a deployment command directly.
Required runtime configuration
AIOS_GITOPS_REPOSITORY_IDENTITY=aios/aios
AIOS_GITOPS_AUTHORITY_GIT_DIR=/data/aios-gitops/repo.git
AIOS_GITOPS_AUTHORIZED_WRITER_STATE_ROOT=/var/lib/aios-gitops/authorized-writer-bridge
AIOS_GITOPS_GRANT_SIGNER_ADAPTER=/usr/local/libexec/aios-grant-signer-adapter
AIOS_GITOPS_GRANT_VALIDATOR=/usr/local/libexec/aios-grant-validator
AIOS_GITOPS_TASK_WRITER_PROVISIONER=/usr/local/libexec/aios-task-writer-provisioner
AIOS_GITOPS_OWNER_PROVISION_SCOPE=writer:provision
AIOS_GITOPS_GOVERNED_USE_SUDO=true
AIOS_GITOPS_SUDO_PATH=/usr/bin/sudo
When the API service is non-root, AIOS_GITOPS_GOVERNED_USE_SUDO=true
uses the fixed /usr/bin/sudo -n -- <governed executable> form. Sudoers must
allow only the three exact executables and must not allow a shell, arbitrary
environment preservation or arbitrary command paths.
The three governed executables must be absolute, regular, executable, non-symlink files and must not be group/world writable. Each must expose:
--help
--self-test
--grant-dir
--result-json
The signer result must bind approval_plan_id, grant_id,
grant_digest_sha256, signing_key_identity and proof that a signature is
present. The validator must independently attest the exact repository,
base/target bindings, signature, lifetime, operation lists and one-time-use
property. The provisioner must return READY_FOR_CODE_AUTHORING, consume the
grant, create the exact branch at the exact base OID, start a writer bound only
to POST /api/commit-file, and report successful negative policy tests.
Deployment model
Run aios_authorized_task_writer_api.py as the ChatGPT Actions API entrypoint.
It delegates all existing routes to aios_chatgpt_actions_api and intercepts
only the new provisioning endpoint.
Do not enable this endpoint until:
- the Owner scope is present in the API authorization registry;
- the signer adapter uses a runtime secret reference;
- the validator and provisioner pass their self-tests;
- the state directory is root-owned and mode
0700; - the negative tests show main, other branches, tags, baseline, force push and branch deletion are denied.
Failure behavior
Every mismatch fails closed. A changed main OID, existing conflicting branch,
expired or untrusted signature, missing negative test, writer scope expansion,
or unconsumed grant returns an error and leaves production state untouched.
Idempotent retries return the existing redacted receipt. A retry with a different task, repository, branch, base or Owner authorization reference is rejected.