Skip to content
10 changes: 6 additions & 4 deletions docs/evidence/g01-broker.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ Runner-group and private repository inspection require an installation/user auth
0. Validate private inputs and the supported native controller build; reserve, write and sync the exact non-secret controller snapshot when applicable. Acquire the fixed account ledger, pin resources/controller state, consume this phase slot durably, and check compatible existing controller inventory. For controller mode, run the credential-free canonical local-state preparation and validate its exact receipt before any authenticated request. These local checks precede every API call.
1. Verify App, owner and organization installation with the App JWT.
2. Flush a non-secret token issuance intent.
3. Flush the non-secret read-token intent, then request an installation token with repository access restricted to `repository_ids: [exact_canary_id]` and exactly `organization_self_hosted_runners: read` plus `metadata: read`. The organization-only scope requests only `organization_self_hosted_runners: read` and no repository IDs.
4. Validate the returned read-token scope and expiry, then use it to verify the exact private non-fork repository (for repository scope), the named nondefault/noninherited runner group, public repositories explicitly disallowed, selected-only visibility, exact workflow restriction and the one selected repository. A failed check stops before any write token is requested. This first preflight is read-only.
5. After read-only preflight succeeds, repeat the final reusable-callee workflow GET. Only then request the management installation token with the exact existing write scope. Validate its returned permission/repository scope and repeat provider-state preflight with that token. Then repeat the same workflow GET immediately before handoff. A mismatch at either later check refuses child handoff, but any already-issued token may remain valid until expiry.
3. Flush the non-secret read-token intent, then immediately before dispatching the installation-token POST, sync `read_token_lifecycle_started` to the fixed account admission ledger. If that sync cannot be established, do not send the request. When a v3 attempt exits before this boundary, sync `read_token_request_not_dispatched`; this preserves later recovery without claiming a request happened. Request a token restricted to `repository_ids: [exact_canary_id]` and exactly `organization_self_hosted_runners: read` plus `metadata: read`. The organization-only scope requests only `organization_self_hosted_runners: read` and no repository IDs. If the response exposes a syntactically valid token but fails typed decoding, expiry or exact-scope validation, do not use it for provider reads; make one self-revocation attempt under the already-durable lifecycle intent. If the returned read token equals the caller workflow-verification token, record the collision and stop before provider-state preflight or DELETE, leaving the lifecycle unresolved.
4. Validate the accepted read-token scope and expiry, then use it to verify the exact private non-fork repository (for repository scope), the named nondefault/noninherited runner group, public repositories explicitly disallowed, selected-only visibility, exact workflow restriction and the one selected repository. After this preflight attempt, durably record a revocation intent and revoke the broker-issued read token with `DELETE /installation/token`. Only `204` with an empty response confirms revocation. An unsuccessful or ambiguous result is best-effort recorded and stops before the final workflow check or any write token request. This first provider preflight is read-only; token revocation is a separate credential effect.
5. After the read token is confirmed revoked and the read-only preflight succeeded, repeat the final reusable-callee workflow GET. Only then request the management installation token with the exact existing write scope. Validate its returned permission/repository scope and repeat provider-state preflight with that token. Then repeat the same workflow GET immediately before handoff. A mismatch at either later check refuses child handoff, but the management token may remain valid until expiry.
6. Only after both provider-state checks and the final workflow check, hand credentials to the exact reviewed controller child. No authentication-discovery route is supported.

Repository restriction does **not** cryptographically restrict the organization-level self-hosted-runners permission to one runner group. The broker and reviewed controller enforce the selected canary policy, under the trusted-controller assumption. This boundary assumes a trusted controller UID and host administrators; file modes and a stdin pipe do not isolate either. The read-only preflight token is issued by the existing App; no separate user or organization credential is requested. The broker never adds Actions permission to the G02 App or mints the separate workflow authority.

A failed/ambiguous token request, failed policy check, expired credential, uncertain handoff or error leaves the intent and stops. There is no automatic retry, token refresh, token replacement or automatic revocation. Either issued token may remain valid until GitHub expires it even if no handoff occurs. A future operator approval must include both potential issuances, not just the eventual read/phase. The maximum remaining operation lifetime is ten minutes, approval expiry, or one minute before the management installation-token expiry, whichever occurs first.
A failed/ambiguous token request, failed policy check, expired credential, uncertain handoff or error leaves the intent and stops. This account-wide start is written before the POST can be dispatched, so a lost success response remains an unresolved lifecycle even when no token candidate is available to revoke. The v3 reusable-callee route makes one self-revocation attempt for each usable read-token candidate, including a token rejected for expiry or scope, and does not run provider preflight for rejected issuance. The per-attempt journal records `read_only_token_revocation_started` before DELETE. A caller-token collision records `read_only_token_revocation_skipped` and stops without a provider request, leaving the account intent pending. After a successful DELETE and a durable per-attempt `read_only_token_revoked` record, the broker syncs `read_token_lifecycle_confirmed` to the account ledger. If the per-attempt success record or the account confirmation cannot be synced, a best-effort `read_only_token_revocation_uncertain` record is attempted and the unmatched lifecycle intent blocks every later phase, including `inspect` and `cleanup`, before another authenticated request, management-token issuance or child handoff. An incomplete legacy reusable-callee claim without lifecycle or no-dispatch evidence also fails closed because its earlier POST outcome cannot be reconstructed. Correctly paired historical `read_token_revocation_started` / `read_token_revocation_confirmed` records remain accepted as completed history. The next open re-syncs the ledger before interpreting a visible confirmation. There is no automatic retry or token refresh/replacement. An uncertain revocation may leave the read token valid until expiry. A management token issued before a later failure may also remain valid until expiry; it is not automatically revoked. A future operator approval must include both potential issuances and the read-token revocation effect, not just the eventual read/phase. The maximum remaining operation lifetime is ten minutes, approval expiry, or one minute before the management installation-token expiry, whichever occurs first.

The self-revocation request uses the [GitHub App installation-token revocation endpoint](https://docs.github.com/en/rest/apps/installations#revoke-an-installation-access-token), which accepts an installation access token and requires no additional permissions. This API contract is official documentation; fixture evidence does not prove live GitHub behavior for the selected installation.

## Historical discovery is an authentication effect

Expand Down
Loading