auth: records carry an account identity; set-identity and import set it, replace keeps it #406
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 }}) | |
| # A FORK PR CANNOT RUN THIS JOB, AND UNTIL 2026-08-31 IT FAILED ON EVERY ONE. | |
| # | |
| # The token step below needs `secrets.CK_CI_APP_PRIVATE_KEY`, and GitHub withholds | |
| # secrets from workflows triggered by a pull request from a fork -- correctly, since | |
| # the workflow runs the PR's own code. So the token cannot be minted, the private | |
| # sibling checkouts fail, and cargo dies at manifest-load before a single test runs. | |
| # That is inherent to private path-dependencies plus fork isolation, not a | |
| # misconfiguration: no variable or permission setting fixes it. | |
| # | |
| # Measured: 11 of 11 fork-PR runs failed this way, across every contributor branch | |
| # this repo has ever received. Two harms, and the second is the one that matters: | |
| # a contributor sees red on everything they file and cannot tell whether it is | |
| # their code, and A GENUINE CI FAILURE ON A FORK PR WAS INDISTINGUISHABLE FROM THIS | |
| # SYSTEMIC ONE. An alarm that always fires is not an alarm. | |
| # | |
| # `pull_request_target` is the tempting fix and is REFUSED: it runs with secrets in | |
| # scope while checking out untrusted code, which turns a red badge into a | |
| # private-repo read token an attacker can exfiltrate. Skipping is honest; the | |
| # fork-safe job below runs what can be run without the siblings. | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| 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 | |
| # WHAT A FORK PR CAN ACTUALLY BE TOLD, given that the job above cannot run for it. | |
| # | |
| # THE NAME IS THE CONTRACT. It says "no build, no tests" because a green check on a | |
| # PR reads as "the suite passed", and a green that means less than it looks is worse | |
| # than the red it replaces -- the contributor stops looking, and so do I. Everything | |
| # here is a source scan; nothing compiles, nothing runs the vault. | |
| # | |
| # These four are the entire fork-safe set, and that is a measured claim rather than a | |
| # convenient one: every other gate arm either shells to cargo (which loads the | |
| # workspace manifest, which path-deps the private siblings, which a fork cannot check | |
| # out) or reads ../subconscious directly, as the inbound-contract check does. Verified | |
| # by reading each script for sibling references and cargo invocations -- 0 and 0 for | |
| # all four. | |
| # | |
| # They are not token checks. Between them they catch a design doc whose NOT-BUILT | |
| # claim the code contradicts, a threshold constant with no boundary test, an endpoint | |
| # constant that drifted from its manifest, and a Windows-breaking path comparison -- | |
| # every one of which has fired here in the last fortnight. | |
| fork-safe: | |
| name: Fork-safe checks (no build, no tests) | |
| if: >- | |
| github.event_name == 'pull_request' && | |
| github.event.pull_request.head.repo.full_name != github.repository | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout claustrum | |
| uses: actions/checkout@v5 | |
| - name: Source scans that need no build | |
| run: | | |
| python3 scripts/check-doc-status.py | |
| python3 scripts/check-path-rendering.py | |
| python3 scripts/threshold-controls.py | |
| python3 scripts/endpoint-hosts.py | |
| - name: State what this job did NOT check | |
| run: | | |
| echo "Source scans only. This job did NOT build, ran no test, and did not" | |
| echo "exercise the vault. The full suite needs private sibling repositories" | |
| echo "that a fork PR cannot check out, so a maintainer runs scripts/gate.sh" | |
| echo "on the merge candidate before it lands. Green here is necessary and" | |
| echo "nowhere near sufficient." |