Architecture
How a label becomes a sandboxed turn, and what is allowed to decide.
A label on a pull request does not run code on the pull request branch. The hosted path is a webhook, a queue, and one sandboxed turn.
GitHub App autofeat-axc
|
v
POST /webhook
Cloud Run service autofeat-web
project axc-autofeat, region us-central1
|
v
Pub/Sub topic autofeat-work
|
v
worker pulls subscription autofeat-work-pull
|
v
rootless Docker executor (UID 60531 via sudo)
|
v
egress gateway (SNI allowlist, enforce)
|
v
check run autofeat/<action>
sticky comment <!-- autofeat:state -->
git ref heads/autofeat-state/pr-<N>The public receiver is https://autofeat-web-774341561528.us-central1.run.app. The path is POST /webhook. A path named /webhooks/github is not served.
The worker is a NixOS host. The executor image is rootless Docker. The controller process is UID 1000. The agent process is UID 60531. Egress is enforced outside this repository's Python. The live host list is the nixos module key egress.allowedHosts.
Three control layers
Each layer can only narrow what the layer above already allows.
- Policy file.
.autofeat/config.ymlon the default branch is the ceiling.autofeat exec --configis ignored. The decision snapshot carriespolicy_sha, the default-branch commit that was judged. - Labels.
autofeat:goadmits a turn.autofeat:stopandautofeat:pauserefuse first. Removing a label does not resume a stopped or paused run. See Labels. - Signed directive. A directive in a comment is untrusted input. It is clamped to policy. The portal cannot forge the HMAC. See Security.
Allowlist
The receiver answers HTTP 200 and does not enqueue work unless both the installation and the repository are allowlisted, and pause_all is false. Log reasons: ignored_installation, ignored_repository, ignored_paused. Stored repository names are lower case. See Admin API.
What one turn writes
| Write | Name |
|---|---|
| Check run | autofeat/<action>, for example autofeat/review |
| Sticky comment | marker <!-- autofeat:state --> |
| Journal | git ref heads/autofeat-state/pr-<N> |
A dry run still writes those three. It does not push, review, merge, or add autofeat:ready. The ready label is added only when dry run is off and merge mode is stop_before_merge. See Merge modes.
Policy mode
policy.mode: review_only (the default) allows review, gate, merge, and halt. It forbids plan, implement, and test. policy.mode: full can allow write actions. Doctor warns when full is combined with dry_run: false.
Review uses method delegate. Gate, merge, and halt use method native. Method flow is refused. Native review is refused. See Agents and models.