Skip to content

Fix differential fuzzer: dead import always skipped it, then fix what… #208

Fix differential fuzzer: dead import always skipped it, then fix what…

Fix differential fuzzer: dead import always skipped it, then fix what… #208

Workflow file for this run

name: CI
on:
push:
branches: [main, master, feat/**, docs/**, infra/**, release/**]
pull_request:
branches: [main, master]
workflow_dispatch:
permissions:
contents: read
# The Python suite validates the pure-Python reference implementation in a single
# type system. The Rust TCB is validated by the rust-check + TCB-tests jobs.
env:
AUTHGATE_BACKEND: python
AUTHGATE_ADMIN_TOKEN: ci-admin-token
jobs:
rust-check:
name: Rust — clippy + tests
runs-on: ubuntu-24.04
defaults:
run:
working-directory: authgate-kernel
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Cargo cache
uses: Swatinem/rust-cache@9bdad043e88c75890e36ad3bbc8d27f0090dd609
with:
workspaces: authgate-kernel
- name: TCB LOC guard — engine.rs must stay under 300 lines
run: |
loc=$(wc -l < src/engine.rs)
echo "engine.rs: ${loc} lines"
if [ "$loc" -gt 300 ]; then
echo "ERROR: engine.rs exceeds 300 LOC (TCB inflation). Current: ${loc}"
echo "If this is a legitimate TCB change, update the limit with justification."
exit 1
fi
- name: TCB API guard — engine.rs must export exactly one public function
run: |
pub_fns=$(grep -c '^pub fn ' src/engine.rs || true)
echo "engine.rs public functions: ${pub_fns}"
if [ "$pub_fns" -gt 1 ]; then
echo "ERROR: engine.rs has ${pub_fns} public functions (must be 1: verify)."
echo "New public API in engine.rs expands the TCB surface. Move to a separate module."
exit 1
fi
- name: TCB import guard — engine.rs may only import from capability and wire
run: |
bad_imports=$(grep '^use crate::' src/engine.rs | grep -v 'crate::capability\|crate::wire' || true)
if [ -n "$bad_imports" ]; then
echo "ERROR: engine.rs imports from outside capability/wire:"
echo "$bad_imports"
echo "TCB must not depend on modules outside its defined boundary."
exit 1
fi
- name: TCB purity check — no randomness/network/filesystem in engine.rs
run: |
if grep -E 'OsRng|rand_core|TcpStream|UdpSocket|File::open|fs::read|fs::write|std::net' src/engine.rs; then
echo "ERROR: engine.rs contains I/O or randomness (TCB violation)"
exit 1
fi
- name: TCB v2 full-path LOC ceiling — semantic-contamination guard
run: |
# Per the architect's discipline rule: every LOC inside the TCB v2 path
# must justify its existence. The hard ceiling forces scope-creep visibility.
# If this fails, the PR must either: remove LOC, OR justify the increase
# and update the ceiling here with sign-off.
ENGINE=$(wc -l < src/tcb/engine.rs)
DAG=$(wc -l < src/tcb/dag.rs)
CG=$(wc -l < src/tcb/call_gate.rs)
SEQ=$(wc -l < src/tcb/sequence.rs)
TYPES=$(wc -l < src/tcb/types.rs)
TOTAL=$((ENGINE + DAG + CG + SEQ + TYPES))
CEILING=1500
echo "TCB v2 LOC breakdown:"
echo " engine.rs : $ENGINE"
echo " dag.rs : $DAG"
echo " call_gate.rs : $CG"
echo " sequence.rs : $SEQ"
echo " types.rs : $TYPES"
echo " TOTAL : $TOTAL (ceiling: $CEILING)"
if [ "$TOTAL" -gt "$CEILING" ]; then
echo ""
echo "ERROR: TCB v2 total exceeds $CEILING LOC."
echo ""
echo "Per TCB_DISCIPLINE.md:"
echo " Rule 1: anything removable without breaking invariants belongs OUTSIDE TCB"
echo " Rule 2: no semantic concept enters TCB"
echo " Rule 3: every new TCB line needs a test, proof, or invariant"
echo ""
echo "Either shrink the TCB or update the ceiling in .github/workflows/ci.yml"
echo "with a written justification of what attack the new code prevents."
exit 1
fi
# Individual file caps — engine.rs is most sacred
if [ "$ENGINE" -gt 500 ]; then
echo "ERROR: engine.rs ${ENGINE} > 500 LOC (hard cap)"
exit 1
fi
if [ "$CG" -gt 500 ]; then
echo "ERROR: call_gate.rs ${CG} > 500 LOC"
exit 1
fi
- name: TCB v2 purity — no I/O, network, randomness, or semantic terms
run: |
# Per discipline rule 2: forbidden semantic concepts must never appear
# inside the TCB. These would be semantic contamination.
FORBIDDEN_TERMS='manipulation_score|coercion|sovereignty_metric|constitutional|recursive_governance|persuasion_score|ethics|alignment_score|trustworthiness'
BAD=$(grep -rE "$FORBIDDEN_TERMS" src/tcb/ || true)
if [ -n "$BAD" ]; then
echo "ERROR: forbidden semantic terms found inside TCB v2:"
echo "$BAD"
echo ""
echo "These concepts are heuristics. They belong in extensions/, not in the TCB."
echo "See TCB_DISCIPLINE.md rule 2: 'no semantic concept enters TCB'."
exit 1
fi
# No I/O in TCB
IO=$(grep -rE 'std::fs::|TcpStream|UdpSocket|std::net::|reqwest|hyper' src/tcb/ || true)
if [ -n "$IO" ]; then
echo "ERROR: I/O found inside TCB v2:"
echo "$IO"
exit 1
fi
- name: TCB algebra guard — capability.rs must stay finite and self-contained
run: |
cap_loc=$(wc -l < src/capability.rs)
echo "capability.rs: ${cap_loc} lines"
if [ "$cap_loc" -gt 200 ]; then
echo "ERROR: capability.rs exceeds 200 LOC (hard ceiling). Capability algebra must stay finite."
echo "Ceiling raised from 150→200 in v2 to accommodate the expanded AI/agent capability taxonomy"
echo "and CapabilityRisk enum. If you need more than 200 LOC, you are adding policy logic."
echo "That belongs outside the TCB."
exit 1
fi
if grep -E '^use crate::' src/capability.rs; then
echo "ERROR: capability.rs imports from the project (use crate:: found)."
echo "capability.rs must be self-contained — zero project dependencies."
exit 1
fi
if grep -E '^pub struct |^struct ' src/capability.rs; then
echo "ERROR: capability.rs contains struct definitions."
echo "Only enums are permitted. Structs carry state and open extension points."
exit 1
fi
- name: Clippy — zero-panic policy
run: |
cargo clippy --all-targets -- \
-D warnings \
-D clippy::unwrap_used \
-D clippy::expect_used \
-D clippy::indexing_slicing \
-D clippy::panic
- name: Build (locked)
run: cargo build --release --locked
python-test:
name: Python — lint + tests
runs-on: ubuntu-24.04
needs: rust-check
strategy:
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build Rust kernel
working-directory: authgate-kernel
run: pip install .
- name: Install Python dependencies
run: pip install -e ".[dev]"
- name: Lint (ruff)
run: ruff check src tests
- name: Type check (mypy)
run: mypy src --ignore-missing-imports
- name: Test with coverage gate
run: pytest --cov=authgate --cov-report=term-missing --cov-fail-under=85
supply-chain:
name: Supply chain — cargo-deny + audit
runs-on: ubuntu-24.04
defaults:
run:
working-directory: authgate-kernel
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: cargo-deny
uses: EmbarkStudios/cargo-deny-action@v2
with:
manifest-path: authgate-kernel/Cargo.toml
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: cargo audit
run: |
cargo install cargo-audit --locked
# Ignore list mirrors authgate-kernel/deny.toml. RUSTSEC-2025-0020 and
# RUSTSEC-2026-0177 (pyo3 new_closure — not called by this crate, see
# deny.toml) are direct-dep non-issues; the rest are transitive through
# wasmtime 25 (optional `sandbox` feature only).
cargo audit \
--ignore RUSTSEC-2025-0020 --ignore RUSTSEC-2026-0177 \
--ignore RUSTSEC-2024-0436 --ignore RUSTSEC-2025-0046 --ignore RUSTSEC-2025-0057 \
--ignore RUSTSEC-2025-0118 --ignore RUSTSEC-2026-0020 --ignore RUSTSEC-2026-0021 \
--ignore RUSTSEC-2026-0085 --ignore RUSTSEC-2026-0086 --ignore RUSTSEC-2026-0087 \
--ignore RUSTSEC-2026-0088 --ignore RUSTSEC-2026-0089 --ignore RUSTSEC-2026-0091 \
--ignore RUSTSEC-2026-0092 --ignore RUSTSEC-2026-0093 --ignore RUSTSEC-2026-0094 \
--ignore RUSTSEC-2026-0095 --ignore RUSTSEC-2026-0096 \
--ignore RUSTSEC-2026-0204 --ignore RUSTSEC-2026-0222
api-smoke:
name: API smoke test
runs-on: ubuntu-24.04
needs: python-test
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build and install
working-directory: authgate-kernel
run: pip install .
- run: pip install -e ".[dev]"
- name: Smoke test API
run: pytest tests/test_api.py -v
cli-smoke:
name: CLI — pip install + authgate-cli --help
runs-on: ubuntu-24.04
needs: rust-check
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Fresh venv install (matches README Quick Start)
run: |
python -m venv /tmp/ag-cli-venv
/tmp/ag-cli-venv/bin/pip install -U pip
/tmp/ag-cli-venv/bin/pip install ./authgate-kernel
/tmp/ag-cli-venv/bin/pip install .
/tmp/ag-cli-venv/bin/authgate-cli --help
/tmp/ag-cli-venv/bin/authgate-cli verify --help
performance-gate:
name: Performance regression gate
runs-on: ubuntu-24.04
needs: python-test
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -e ".[dev]"
- name: Run benchmarks with performance gate
run: |
python benchmarks/comprehensive_bench.py --gate
echo "All performance targets met"
adversarial-simulation:
name: Adversarial simulation (231 scenarios, 0 violations)
runs-on: ubuntu-24.04
needs: python-test
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -e ".[dev]"
- name: Run simulation engine
run: |
cd attack_harness
python simulation/run_simulation.py
echo "Simulation passed: 0 violations"
red-team-tests:
name: Red team adversarial tests
runs-on: ubuntu-24.04
needs: python-test
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -e ".[dev]"
- name: Run red team tests
run: pytest tests/test_adversarial_redteam.py tests/test_epoch_revocation.py tests/test_api_redteam_boundary.py -v
docker-smoke:
name: Docker image build + /readyz smoke
runs-on: ubuntu-24.04
needs: api-smoke
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Build image
run: docker build -t authgate:ci .
- name: Smoke container
run: |
docker run -d --name ag \
-e AUTHGATE_ADMIN_TOKEN=ci-smoke-token \
-e AUTHGATE_AUDIT_PATH=/data/audit.jsonl \
-p 8000:8000 authgate:ci
for i in $(seq 1 30); do
curl -sf http://localhost:8000/readyz && break || sleep 1
done
curl -sf http://localhost:8000/readyz
curl -sf http://localhost:8000/healthz
curl -sf -X POST http://localhost:8000/verify \
-H 'content-type: application/json' \
-d '{"action_id":"ci","actor":{"name":"ghost","kind":"MACHINE"},"bypasses_verifier":true}' \
| grep -q '"permitted":false'
docker rm -f ag