AUR-018 — Fixar contratos SCM e CI seguros
Documento histórico do board. Pode descrever componentes removidos; para uso atual, consulte o guia do produto.
Behavior
This card fixes, as data, the capability and trust-boundary matrix that any future GitHub, Gitea, or GitLab adapter must respect. It does not implement a client, a webhook receiver, or a CI pipeline. Two roles are distinguished everywhere in the matrix:
- analyzer — reads a change, including one whose head may be hostile (a fork or an external branch not owned by a maintainer). It is presented only a read-only credential, on every forge, with no exception.
- publisher — writes a result back (a comment, check, status, or release). It always runs in a context decoupled from the hostile-head checkout the analyzer used, and only there may it hold a write-scoped credential.
Contract
.board/research/scm-ci.mdis the dated, versioned research: one row per vendor source actually consulted, and a matrix table naming the analyzer and publisher credential, scope, and trust boundary for GitHub, Gitea, and GitLab.standards/scm/capabilities.yamlis the machine-readable form of that matrix:forges.<name>.analyzer,forges.<name>.publisher, and the cross-forgerule.hostile_head_read_onlyinvariant. A future adapter card reads this file; it does not re-derive scopes from prose.tests/acceptance/AUR-018.sh::AC-001is the sole executable gate for this card: it requires.board/research/scm-ci.mdto exist, be non-empty, and contain, case-insensitively,GitHub,Gitea,GitLab,analyzer,publisher, andleast privilege. Absence of any one term is theinvalidvector and exits non-zero before any effect outsidepaths.tests/integration/AUR-018_test.go(TestAUR018Boundary) is the structural lint, discoverable bygo test ./tests/integration/...: it parsesstandards/scm/capabilities.yaml, requires all three forges to declare both roles, requiresallow_write_on_hostile_head: falseeverywhere, cross-checks that every forge named incapabilities.yamlalso appears in the matrix table ofscm-ci.md(so the machine-readable limits and the human-readable research can never diverge), and requires every source cited inscm-ci.mdto name an allowlisted vendor-docs domain together with a version or an access date — the same shapeMUT-002targets.
Limits
standards/scm/capabilities.yaml'slimits.max_token_scopes_per_role: 3bounds how many scope entries an adapter may request per role per forge.limits.allowed_analyzer_ci_events/forbidden_analyzer_ci_eventsbound which CI trigger the analyzer role may run under; GitHub'spull_request_targetandworkflow_runare explicitly forbidden for the analyzer because GitHub's own docs describe them as privileged even when triggered from a public fork.- No role in any forge entry may set
allow_write_on_hostile_head: true;MUT-001proves the acceptance path rejects that change.
Example (no secret involved)
$ ./.board/bin/oci-run --profile bootstrap-readonly-v1 --card AUR-018
{"card":"AUR-018","scenario":"AC-001","result":"pass"}
$ echo $?
0
Removing any one of the six required terms from
.board/research/scm-ci.md (for example replacing least privilege with a
paraphrase) reproduces the invalid vector:
$ sed 's/least privilege/least-priv only/' .board/research/scm-ci.md > /tmp/scm-ci-mut.md
$ f=/tmp/scm-ci-mut.md bash -c 'grep -Fiq "least privilege" "$f"'; echo $?
1
Diagnostic procedure
- Run the accept command above and capture
exit_codeandstdout_sha256from theoci-runJSON envelope. - If
exit_code != 0,stderrnames the missing term (AUR-018/AC-001: SCM/CI baseline absentwhen the file itself is missing or empty, or a bare non-zero exit from the term loop otherwise) — check.board/research/scm-ci.mdfor the six required terms first. - Run
go test ./tests/integration/...to check the structural lint independently of the shell gate; a failure there names which forge, role, or source row is missing or malformed instandards/scm/capabilities.yamlor.board/research/scm-ci.md. - Confirm no output at any step contains
AURUM_SECRET_CANARY.