100 lines
4.0 KiB
Markdown
100 lines
4.0 KiB
Markdown
# 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:
|
|
|
|
1. Validates an exact repository, base ref, base OID and target branch.
|
|
2. Rejects all production, tag, baseline and direct-main capabilities.
|
|
3. Generates a canonical approval plan and short-lived grant request.
|
|
4. Calls the root-owned signer adapter.
|
|
5. Calls the independent grant validator.
|
|
6. Calls the one-shot task writer provisioner.
|
|
7. Verifies the resulting branch, writer scope and negative policy tests.
|
|
8. 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
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
--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.
|