Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
949 changes: 949 additions & 0 deletions .github/scripts/audit_workflow_trust.py

Large diffs are not rendered by default.

421 changes: 421 additions & 0 deletions .github/scripts/test_audit_workflow_trust.py

Large diffs are not rendered by default.

116 changes: 116 additions & 0 deletions .github/workflow-trust-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"schema": 1,
"rules": {
"cargo_locked_subcommands": [
"bench",
"build",
"check",
"clippy",
"doc",
"metadata",
"run",
"test"
],
"require_container_digest": true,
"require_checkout_credentials_disabled": true,
"require_external_uses_full_sha": true
Comment on lines +14 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Trust rules lack rationale 📘 Rule violation ▣ Testability

The three public boolean trust rules are published only as configuration keys, without a rationale
field or corresponding documentation explaining why each rule exists. Their positive and
counterexample tests do not satisfy the checklist's separate rationale requirement.
Agent Prompt
## Issue description
The public workflow trust policy defines three boolean rules without documenting the rationale for each rule.

## Issue Context
Preserve the current machine-readable values and audit behavior. Add an explicit rationale field supported by the policy format, or a clearly linked documentation section that explains why digest-bound containers, credentialless checkout, and full-SHA external references are required.

## Fix Focus Areas
- .github/workflow-trust-policy.json[14-16]
- specs/015-af-01-trusted-development-baseline/stack-a-inventory.md[96-106]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

},
"rationales": {
"cargo_locked_subcommands": "Lockfile-consuming Cargo commands must use the checked-in Cargo.lock rather than silently resolving a different dependency graph during assurance execution.",
"require_container_digest": "Job and service containers on proof-relevant workflows must resolve to an immutable image generation so a mutable tag cannot silently change the execution environment.",
"require_checkout_credentials_disabled": "Checkout must not persist the GitHub token into repository Git configuration because later steps do not require ambient repository write credentials.",
"require_external_uses_full_sha": "External Actions and reusable workflows must be bound to an immutable 40-hex commit so mutable tags or branches cannot change executed code without a repository diff."
},
"workflows": {
".github/workflows/cf06-oracle.yml": {
"jobs": {
"oracle-changed-profile": {
"permissions": {
"contents": "read"
},
"runner": "ubuntu-24.04",
"timeout_minutes": 25
},
"oracle-proof": {
"permissions": {},
"runner": "ubuntu-24.04",
"timeout_minutes": 5
},
"oracle-self-smoke": {
"permissions": {
"contents": "read"
},
"runner": "ubuntu-24.04",
"timeout_minutes": 20
}
}
},
".github/workflows/cf11-multi-version-proof.yml": {
"jobs": {
"real-package-graph": {
"permissions": {
"contents": "read"
},
"runner": "ubuntu-24.04",
"timeout_minutes": 20
}
}
},
".github/workflows/cf11g-context-proof.yml": {
"jobs": {
"deterministic-context-cli": {
"permissions": {
"contents": "read"
},
"runner": "ubuntu-24.04",
"timeout_minutes": 15
}
}
},
".github/workflows/cf12-impact-proof.yml": {
"jobs": {
"deterministic-impact-cli": {
"permissions": {
"contents": "read"
},
"runner": "ubuntu-24.04",
"timeout_minutes": 15
}
}
},
".github/workflows/cf13-quality-gate-proof.yml": {
"jobs": {
"deterministic-quality-gate": {
"permissions": {
"contents": "read"
},
"runner": "ubuntu-24.04",
"timeout_minutes": 15
}
}
},
".github/workflows/ci.yml": {
"jobs": {
"rust": {
"permissions": {
"contents": "read"
},
"runner": "ubuntu-24.04",
"timeout_minutes": 30
}
}
},
".github/workflows/registry-download-smoke.yml": {
"jobs": {
"registry-download": {
"permissions": {
"contents": "read"
},
"runner": "ubuntu-24.04",
"timeout_minutes": 15
}
}
}
},
"exceptions": []
}
12 changes: 8 additions & 4 deletions .github/workflows/cf06-oracle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ permissions:
jobs:
oracle-self-smoke:
name: oracle-self-smoke
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 / Node 24
with:
Expand Down Expand Up @@ -94,7 +95,8 @@ jobs:

oracle-changed-profile:
name: oracle-changed-profile
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 25
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 / Node 24
with:
Expand Down Expand Up @@ -277,7 +279,9 @@ jobs:
needs:
- oracle-self-smoke
- oracle-changed-profile
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions: {}
steps:
- name: Enforce all CF-06 oracle validation suites
env:
Expand All @@ -286,4 +290,4 @@ jobs:
run: |
set -euo pipefail
test "$SELF_SMOKE_RESULT" = success
test "$CHANGED_PROFILE_RESULT" = success
test "$CHANGED_PROFILE_RESULT" = success
15 changes: 11 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ permissions:

jobs:
rust:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.97.1
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 / Node 24
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@032958afbdc797a9164d3bc0b56325c1308924a5 # 1.97.1
with:
components: rustfmt, clippy
- name: AF-01 workflow trust audit tests
run: python3 .github/scripts/test_audit_workflow_trust.py
- name: AF-01 repository workflow trust audit
run: python3 .github/scripts/audit_workflow_trust.py
- name: Format
run: cargo fmt --all -- --check
- name: Clippy
Expand Down Expand Up @@ -143,4 +150,4 @@ jobs:
assert report["decision"]["passed"] is True
assert report["decision"]["blocking_findings"] == 0
assert report["compatibility"]["findings"] == []
PY
PY
4 changes: 2 additions & 2 deletions .github/workflows/registry-download-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ permissions:

jobs:
registry-download:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 / node24
Expand Down Expand Up @@ -112,4 +112,4 @@ jobs:
fi
echo "VSAC fallback resolve/verify failed on attempt ${attempt}; retrying" >&2
sleep $((attempt * 5))
done
done
110 changes: 110 additions & 0 deletions specs/015-af-01-trusted-development-baseline/stack-a-inventory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# AF-01 Stack A Workflow Trust Inventory

Status: IMPLEMENTATION_EVIDENCE / T010

Canonical inventory base:

```text
main: eeecb0bc03c7040bb18b70bce8b69d618384f783
tree: d5abe932f1436a9612f45bf130ba29aadbc5a133
AF-01 planning: CANONICAL
```

This inventory records the tracked GitHub workflow/action authority that AF-01 Stack A must make machine-checkable. It is not a substitute for the repository-owned discovery audit: the audit must discover future workflow and Action metadata files automatically.

## Tracked workflow files

1. `.github/workflows/ci.yml`
2. `.github/workflows/cf06-oracle.yml`
3. `.github/workflows/cf11-multi-version-proof.yml`
4. `.github/workflows/cf11g-context-proof.yml`
5. `.github/workflows/cf12-impact-proof.yml`
6. `.github/workflows/cf13-quality-gate-proof.yml`
7. `.github/workflows/registry-download-smoke.yml`

## Tracked Action metadata

- `action.yml`

No `action.yaml` metadata file is present at the inventory base. AF-01 discovery still treats both `action.yml` and `action.yaml` at any tracked path as authoritative scan inputs.

## Job authority inventory

| Workflow | Job | Current effective permission | Current runner | Current container | Current timeout | Stack A disposition |
|---|---|---|---|---|---|---|
| `ci.yml` | `rust` | `contents: read` | `ubuntu-latest` | none | none | pin runner/actions, disable checkout credentials, add timeout |
| `cf06-oracle.yml` | `oracle-self-smoke` | `contents: read` | `ubuntu-latest` | none | none | fixed runner, explicit job permission, timeout |
| `cf06-oracle.yml` | `oracle-changed-profile` | `contents: read` | `ubuntu-latest` | none | none | fixed runner, explicit job permission, timeout |
| `cf06-oracle.yml` | `oracle-proof` | inherited `contents: read` | `ubuntu-latest` | none | none | reduce to no repository permission, fixed runner, timeout |
| `cf11-multi-version-proof.yml` | `real-package-graph` | `contents: read` | `ubuntu-24.04` | Rust digest pinned | 20m | retain |
| `cf11g-context-proof.yml` | `deterministic-context-cli` | `contents: read` | `ubuntu-24.04` | Rust digest pinned | 15m | retain |
| `cf12-impact-proof.yml` | `deterministic-impact-cli` | `contents: read` | `ubuntu-24.04` | Rust digest pinned | 15m | retain |
| `cf13-quality-gate-proof.yml` | `deterministic-quality-gate` | `contents: read` | `ubuntu-24.04` | Rust digest pinned | 15m | retain |
| `registry-download-smoke.yml` | `registry-download` | `contents: read` | `ubuntu-latest` | none | 15m | fixed runner |

## External Action / reusable-workflow references

Immutable references already used by current proof workflows:

```text
actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961
dtolnay/rust-toolchain@032958afbdc797a9164d3bc0b56325c1308924a5
actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
```

Current `ci.yml` is the outlier:

```text
actions/checkout@v4
dtolnay/rust-toolchain@1.97.1
```

`action.yml` is a local composite Action and contains no external `uses:` reference at this base.

## Checkout credential inventory

Every current checkout in the proof/oracle/registry workflows sets:

```yaml
persist-credentials: false
```

`ci.yml` does not and must be reconciled.

## Container identity inventory

Current containerized proof jobs use digest-bound Rust images. No service containers are present at this base. AF-01 policy applies the digest rule to every future job or service container that appears; a mutable tag is never accepted merely because it is new or non-proof-labeled.

## Cargo lockfile-consuming command inventory

Current workflow commands that build/check/test/run against the Rust dependency graph already use `--locked` in the proof/oracle/registry workflows and in the relevant `ci.yml` clippy/test/run invocations. `cargo fmt` and `cargo --version` are not lockfile-consuming commands and are outside this rule.

AF-01 audit treats at least these cargo subcommands as lockfile-consuming when present in workflow shell commands:

```text
bench
build
check
clippy
doc
metadata
run
test
```

## Machine-checkable target after T014/T015

- every discovered workflow has an exact policy entry for every discovered job;
- effective workflow/job permissions equal the policy declaration, with no unresolved GitHub default authority;
- all current runners become `ubuntu-24.04`;
- every job has an explicit bounded `timeout-minutes`;
- all external `uses:` references are full 40-hex commit SHAs;
- all checkout steps persist no credentials;
- every job/service container reference, if present, is digest-bound with `sha256`;
- all lockfile-consuming cargo invocations use `--locked`;
- every tracked `action.yml` and `action.yaml` is scanned for external `uses:` references.

## Scope boundary

Stack A changes development-assurance configuration only. It does not change commandF product semantics, CF-06 production oracle identity, the CF-10 frozen corpus, report schemas, or runtime authority.
16 changes: 8 additions & 8 deletions specs/015-af-01-trusted-development-baseline/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ Status: PLANNING_CANDIDATE
- [x] **T002** Audit current repository assurance gaps: unprotected `main`; mixed mutable/immutable workflow references; missing cargo-deny/cargo-audit/zizmor/Scorecard; no fuzz/mutation/coverage/portability/release assurance program; stale README capability surface.
- [x] **T003** Research current primary guidance for GitHub Actions full-SHA pinning, SLSA v1.2, Sigstore bundles, Rust fuzzing/mutation/coverage/security tooling, and HL7 FHIR release status.
- [x] **T004** Add `docs/COMMAND_F_ASSURANCE_PROGRAM_2026-08-26.md` and AF-01 Spec Kit planning package; preserve CF-14/15/16 identities.
- [ ] **T005** Planning gate: exact final planning head passes all path-applicable CI, independent CodeRabbit/Qodo review truth is recorded without invented PASS, zero unresolved substantive planning findings remain, and planning PR is merged to canonical `main`.
- [x] **T005** Planning gate: exact final planning head passes all path-applicable CI, independent CodeRabbit/Qodo review truth is recorded without invented PASS, zero unresolved substantive planning findings remain, and planning PR is merged to canonical `main`.

## Phase 1 / Stack A — workflow trust audit and baseline hardening

Depends on T005.

- [ ] **T010** Inventory every tracked `.github/workflows/*.yml|*.yaml`, every tracked Action metadata file named `action.yml` or `action.yaml` at any repository depth, every external `uses:` reference, runner label, workflow/job permission, checkout credential setting, job/service container image identity, and cargo lockfile-consuming command on canonical planning main.
- [ ] **T011** Define a minimal checked-in AF-01 workflow-trust policy format that makes allowed workflow/job permissions and proof-container identity modes machine-checkable, including any narrowly scoped exception schema with reason/revisit condition.
- [ ] **T012** Implement repository-owned deterministic workflow-trust audit with complete workflow plus `action.yml`/`action.yaml` discovery, local-action allowance, full-40-hex external action/reusable-workflow requirement, checkout credential check, effective workflow/job permission normalization plus allowlist enforcement, proof-critical job/service container digest enforcement, and proof-runner policy.
- [ ] **T013** Add positive and counterexample tests for T012, including mutable external `uses:` in `action.yaml`, tag/branch/short-SHA rejection, missing `persist-credentials: false`, overbroad permission rejection, unresolved inherited/default permission rejection, proof-critical mutable job/service container rejection, new-workflow/action-metadata coverage, malformed input fail-closed behavior, and deterministic repeat output.
- [ ] **T014** Harden `.github/workflows/ci.yml` to full-SHA external Actions, credentialless checkout, explicit machine-checkable least permissions, fixed supported runner label, bounded timeout, and preserved existing semantic/test steps.
- [ ] **T015** Reconcile every other existing workflow and repository Action metadata file to the AF-01 baseline, including permission declarations and proof-critical container digest identity, without changing its product/oracle/proof semantics or path-filter authority except where later universal required-check aggregation is explicitly introduced.
- [ ] **T016** Add a regression that discovers both `action.yml` and `action.yaml` anywhere in the tracked tree and fails if a future workflow, Action metadata file, permission grant, external Action ref, checkout credential setting, or proof-critical container identity escapes AF-01 trust auditing.
- [x] **T010** Inventory every tracked `.github/workflows/*.yml|*.yaml`, every tracked Action metadata file named `action.yml` or `action.yaml` at any repository depth, every external `uses:` reference, runner label, workflow/job permission, checkout credential setting, job/service container image identity, and cargo lockfile-consuming command on canonical planning main.
- [x] **T011** Define a minimal checked-in AF-01 workflow-trust policy format that makes allowed workflow/job permissions and proof-container identity modes machine-checkable, including any narrowly scoped exception schema with reason/revisit condition.
- [x] **T012** Implement repository-owned deterministic workflow-trust audit with complete workflow plus `action.yml`/`action.yaml` discovery, local-action allowance, full-40-hex external action/reusable-workflow requirement, checkout credential check, effective workflow/job permission normalization plus allowlist enforcement, proof-critical job/service container digest enforcement, and proof-runner policy.
- [x] **T013** Add positive and counterexample tests for T012, including mutable external `uses:` in `action.yaml`, tag/branch/short-SHA rejection, missing `persist-credentials: false`, overbroad permission rejection, unresolved inherited/default permission rejection, proof-critical mutable job/service container rejection, new-workflow/action-metadata coverage, malformed input fail-closed behavior, and deterministic repeat output.
- [x] **T014** Harden `.github/workflows/ci.yml` to full-SHA external Actions, credentialless checkout, explicit machine-checkable least permissions, fixed supported runner label, bounded timeout, and preserved existing semantic/test steps.
- [x] **T015** Reconcile every other existing workflow and repository Action metadata file to the AF-01 baseline, including permission declarations and proof-critical container digest identity, without changing its product/oracle/proof semantics or path-filter authority except where later universal required-check aggregation is explicitly introduced.
- [x] **T016** Add a regression that discovers both `action.yml` and `action.yaml` anywhere in the tracked tree and fails if a future workflow, Action metadata file, permission grant, external Action ref, checkout credential setting, or proof-critical container identity escapes AF-01 trust auditing.
- [ ] **T017** Run mandatory workspace gates and every path-applicable existing proof/oracle workflow on the exact Stack A head.
- [ ] **T018** Request CodeRabbit and Qodo on exact Stack A head; disposition every substantive returned finding and require zero unresolved material review threads.
- [ ] **T019** Merge Stack A only from its exact qualified head and record canonical merge/main/tree.
Expand Down
Loading