82. Separate workflow-host allow-list from caller allow-list
Date: 2026-08-04
Status
Accepted
Builds on ADR 0078.
Context
Mint trust previously tangled two distinct allow-lists:
- Callers — which orgs/repos may request tokens (
ALLOWED_ORGS,PER_REPO_WIF_REPOS, and related enrollment paths). - Workflow hosts — which repos may appear in
job_workflow_refas the source of workflows that call the mint.
The coupling made it hard to allow a repo to obtain tokens without also treating it as a trusted place to host minting workflow code (and the reverse). For example, per-repo callers listed in PER_REPO_WIF_REPOS were automatically accepted as workflow hosts via ValidateWorkflowRef, which checked the caller's own repository as a valid workflow source.
Installs that vendor reusable workflows into a consumer repo (e.g. github setup --vendor) change job_workflow_ref to that consumer repo. Those workflows cannot mint unless the consumer is explicitly listed as a workflow host — which was previously only possible by adding it to PER_REPO_WIF_REPOS, conflating caller enrollment with workflow-host trust.
Decision
Separate controls
Introduce WORKFLOW_HOST_REPOS, a new environment variable listing repos whose workflows are trusted to call the mint in per-repo mode. This is independent of ALLOWED_ORGS and PER_REPO_WIF_REPOS.
Per-repo mode
Per-repo callers (those in PER_REPO_WIF_REPOS) have their job_workflow_ref validated against WORKFLOW_HOST_REPOS. The upstream repo (fullsend-ai/fullsend) is always accepted. When WORKFLOW_HOST_REPOS is not set, it defaults to fullsend-ai/fullsend only.
Per-org mode
Per-org callers (those whose repository_owner is in ALLOWED_ORGS) have their job_workflow_ref hard-wired to two sources:
- The caller's own org
.fullsendconfig repo ({org}/.fullsend) - The upstream
fullsend-ai/fullsendrepo
No separate allow-list is consulted. This matches the operational model where per-org installs rely on {org}/.fullsend as their workflow host.
Dual enrollment
When a caller is both an enrolled repo (PER_REPO_WIF_REPOS) and its org is an enrolled org (ALLOWED_ORGS), both workflow-ref validation modes apply. The workflow may come from:
- Per-repo sources: any repo in
WORKFLOW_HOST_REPOS(plus upstream) - Per-org sources:
{org}/.fullsendconfig repo (plus upstream)
The handler tries per-org validation first, then falls back to per-repo validation. If either succeeds, the workflow ref is accepted. Scope treatment uses per-org mode (the superset) — dual enrollment only expands the set of accepted workflow hosts.
Public mode
Public mode (PER_REPO_WIF_REPOS=*) uses the same per-repo validation path — WORKFLOW_HOST_REPOS and the ALLOWED_WORKFLOW_FILES basename gate both apply. The only difference between public and tight per-repo mode is caller enrollment: PER_REPO_WIF_REPOS=* means every repo is accepted as a caller without explicit listing.
Note: ADR 0059 dropped the basename gate for public mode ("Basename gate: that restriction was dropped"). This ADR supersedes that exception: public mode now applies
ALLOWED_WORKFLOW_FILESvia the shared per-repo validation path.
CLI and status surfaces
fullsend mint workflow-host add|remove|listmanages theWORKFLOW_HOST_REPOSenv var on the mint.fullsend mint statusdisplays the effective workflow-host allow-list.GET /v1/statusincludesworkflow_host_reposin the response.
Consequences
- Operators can grant a repo caller access (via
PER_REPO_WIF_REPOS) without implicitly trusting it as a workflow host. Workflow-host trust requires an explicitWORKFLOW_HOST_REPOSentry or the use of upstream workflows. - Vendored workflow installs (
--vendor) require a one-time admin action to add the vendored-workflow repo toWORKFLOW_HOST_REPOSbefore those workflows can mint tokens. - Existing per-repo callers that previously relied on hosting their own workflows (via the old
ValidateWorkflowReflogic that accepted the caller's own repo fromPER_REPO_WIF_REPOS) must either switch to upstream workflows or be added toWORKFLOW_HOST_REPOS. - Per-org callers see no behavior change — their workflow host validation was already restricted to
.fullsendand upstream. - The default
WORKFLOW_HOST_REPOSvalue (fullsend-ai/fullsend) matches the previous behavior for callers using upstream workflows.
Related ADRs
| Topic | ADR |
|---|---|
| Simplified mint authorization policy | 0078 |
| Public mint mode (basename gate exception superseded above) | 0059 |
