Skip to content

Merge pull request #14 from iceteaSA/feat/provenance-declare-known-fi… #312

Merge pull request #14 from iceteaSA/feat/provenance-declare-known-fi…

Merge pull request #14 from iceteaSA/feat/provenance-declare-known-fi… #312

Workflow file for this run

name: CI
on:
push:
branches: [master]
pull_request:
workflow_call:
# Manual trigger, so a commit whose push webhook was missed (GitHub occasionally
# drops one) can be re-run without an empty commit: `gh workflow run CI`.
workflow_dispatch:
# DAILY, TO CATCH SIBLING DRIFT THAT NO PUSH OF OURS WOULD REVEAL.
#
# The subconscious and commons checkouts below carry no `ref:`, so they take each
# repo's DEFAULT BRANCH -- this pipeline floats on their tip by design, which is
# what makes it able to see an upstream break at all. But push/PR triggers only
# fire on OUR commits, so a breaking change upstream stays invisible here until we
# happen to push, which may be days.
#
# Measured 2026-08-16: subc-protocol made two manifest fields required at 15:19;
# our last CI run was the previous night, so the break sat undetected on this side
# while a peer who builds claustrum in THEIR pipeline hit it first. For a
# credential vault the bad version of that story is discovering it during an
# emergency deploy, when the pressure is highest and the diagnosis budget lowest.
#
# 2 minutes a day converts "whenever we next push" into "within 24 hours".
schedule:
- cron: "17 6 * * *"
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
jobs:
# Linux + Windows matrix. Windows is the load-bearing leg (the cfg(windows)
# master-key/operator-path branches and any path handling can't be exercised on
# local macOS/Linux). macOS is intentionally not in CI: it is the dev platform
# (continuously tested locally) and is where the keychain path is developed.
#
# Runners are GitHub-hosted. They were Blacksmith while this repo was private:
# the org is on the free plan, where GitHub blocks private-repo Actions jobs at
# the zero spending limit, and third-party runners do not consume the included
# minutes. Public repos get GitHub-hosted minutes for free, so the workaround
# retired with the repo's visibility on 2026-08-27.
#
# macOS is still absent, and the earlier note here ("re-add macOS if public")
# oversimplified. Two facts pull in opposite directions: the keychain path is
# macOS-only and has NO CI coverage at all, which is a real gap; but the macOS
# leg has never run green here, and coupling an unproven leg to a visibility
# flip risks reddening CI at the worst possible moment. It goes in as its own
# change, proven on its own, rather than riding this one.
test:
name: Test (${{ matrix.os }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu
runner: ubuntu-latest
- os: windows
runner: windows-latest
defaults:
run:
working-directory: claustrum
steps:
- name: Checkout claustrum
uses: actions/checkout@v5
with:
path: claustrum
# This repo path-deps the private cortexkit/subconscious (subc wire) and
# cortexkit/commons (storage libs) siblings. The default GITHUB_TOKEN is
# scoped to this repo only, so mint a short-lived token from the org-installed
# cortexkit-ci GitHub App (Contents: read) to check both out. Cargo loads the
# whole workspace manifest (incl. the sibling path-deps) before resolving any
# package, so both must be present or the build fails at manifest-load.
- name: Mint cross-repo read token
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ vars.CK_CI_APP_CLIENT_ID }}
private-key: ${{ secrets.CK_CI_APP_PRIVATE_KEY }}
owner: cortexkit
repositories: subconscious,commons
- name: Checkout subconscious
uses: actions/checkout@v5
with:
repository: cortexkit/subconscious
path: subconscious
token: ${{ steps.app-token.outputs.token }}
- name: Checkout commons
uses: actions/checkout@v5
with:
repository: cortexkit/commons
path: commons
token: ${{ steps.app-token.outputs.token }}
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
# The real-daemon e2e rig spawns the subc daemon (exe `ck-subc`; the PACKAGE
# is still subc-core) as a subprocess. Build it from the sibling checkout so
# the rig finds it under ../subconscious/target/debug.
- name: Build subc binaries (real-daemon e2e)
working-directory: subconscious
run: cargo build -p subc-core --bins
# Compare the wire facts this repo transcribes against the document that owns
# them. Runs here rather than as a test because it reads a sibling checkout,
# which `cargo test` has no business depending on -- and because a drift is a
# contract question for a human rather than a failing assertion to fix locally.
- name: Inbound contract check
# Pinned to bash because this job also runs on Windows, where the default
# shell is pwsh and the script would not execute at all. Pinning runs it on
# both legs; restricting it to one leg with an `if` would mean the check
# silently stops running the day that leg is renamed or removed, which is
# the failure mode this script exists to catch in a different form.
shell: bash
run: ./scripts/check-inbound-contracts.sh ../subconscious/docs/specs/push-sealed-payload.md
# Pins the HOST every provider endpoint constant reaches. A population check
# rather than a unit test: a per-constant assertion cannot fail when a NEW
# endpoint appears, and comparing a constant to itself proves nothing about the
# value. A wrong host receives a live refresh token and the failure looks like
# an ordinary dead login, so it is worth failing the build over.
# Pinned to bash on both legs for the same reason as the contract check above.
- name: Endpoint hosts
shell: bash
run: python3 scripts/endpoint-hosts.py
- name: Path rendering
# The scripts compare paths against posix literals in manifests. str(Path)
# renders backslashes on Windows, which has broken this build twice --
# both times in a script whose author had just fixed the other one.
shell: bash
run: python3 scripts/check-path-rendering.py
- name: Design doc status claims
run: python3 scripts/check-doc-status.py
- name: Threshold boundary controls
# Bash-pinned to match its siblings. NOTE the path rendering is handled in
# the script via as_posix(), not by this pin: the separator comes from
# Python, so the shell choice does not affect it.
shell: bash
run: python3 scripts/threshold-controls.py
- name: Format check
# SCOPED TO THIS REPO'S OWN CRATES. `--all` reaches through the sibling path
# dependencies and checks sources owned by other repos, so a peer's
# unformatted Rust would fail THIS build for code no commit here can fix.
# Their formatting is their CI's job. Members are DERIVED rather than typed,
# so adding a crate cannot silently drop it from the check, and an empty
# derivation refuses rather than passing vacuously.
shell: bash
run: |
set -euo pipefail
pkgs=$(cargo metadata --no-deps --format-version 1 \
| python3 -c 'import json,sys; print(" ".join("-p "+p["name"] for p in json.load(sys.stdin)["packages"]))')
test -n "$pkgs" || { echo "empty format scope; refusing" >&2; exit 1; }
echo "format scope: $pkgs"
# shellcheck disable=SC2086
cargo fmt $pkgs -- --check
- name: Clippy
run: cargo clippy --locked --workspace --all-targets -- -D warnings
# Lint the feature-gated code (the kill-9 pre-commit seam, the rotation and login
# crash-cut helpers, and the rename-ceremony one-shots) too, so it is held to the
# same -D warnings bar even though it is compiled out of the default build.
# Without this the gated binaries would rot unnoticed until the next rename, which
# is the worst moment to discover they no longer compile.
- name: Clippy (conformance seams)
run: cargo clippy --locked --workspace --all-targets --features kill9-test-seam,rotate-test-seam,login-test-seam,migration-tools -- -D warnings
- name: Test
run: cargo test --locked --workspace --all-targets
# Run the security-conformance suite with both crash-safety seams enabled: the
# real-SIGKILL mid-refresh test and the master-key-rotation crash-cut test (both
# ship-gate requirements). They are Unix-only (rely on SIGKILL + kernel
# lease-lock release) and compile to nothing on Windows, so the step is harmless
# there.
- name: Security-conformance suite (crash-safety seams)
run: cargo test --locked --workspace --all-targets --features kill9-test-seam,rotate-test-seam,login-test-seam
# Run the #[ignore]'d real-daemon e2e (incl. the on-the-wire malicious-client
# harness) under a real supervised subc-core. This is the ONLY layer that
# catches cross-component contract bugs (e.g. a CLI/daemon lease-namespace
# split, a broken descriptor/launch-nonce wiring) — a class that already bit
# us and that no in-proc test can surface. CRED_REQUIRE_DAEMON=1 is the
# anti-masking guard: a missing/unbuildable sibling subc-core FAILS the job
# rather than silently skipping, so this gate can never zero-out green.
# Ubuntu-only: it spawns the daemon + binds loopback ports (the well-trodden
# path mirrored from the llm-runner rig); the Windows leg covers the
# cfg(windows) branches via the regular suite above.
- name: Real-daemon e2e (ship gate, no silent skip)
if: matrix.os == 'ubuntu'
env:
CRED_REQUIRE_DAEMON: "1"
run: cargo test --locked -p credentials-module --test real_daemon_e2e -- --ignored --test-threads=1
# Assert the api-key validation bypass is absent from a REAL release binary. It
# is #[ignore]'d because it builds the release profile, so without this step it
# would never run and the guarantee would be nominal. Ubuntu-only: the property
# is about the source gate, which is platform-independent, and the release build
# is the expensive part.
- name: Release-artifact assertions (ship gate)
if: matrix.os == 'ubuntu'
run: cargo test --locked -p credentials-module --test cli_admin validation_bypass_is_absent -- --ignored