Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
faa0423
feat(audit): Ed25519-signed checkpoints over the chain head (ADR-015)
claude Oct 1, 2026
0c642a9
ci: surface clippy failures as check annotations
claude Oct 1, 2026
924e67a
ci: strip colour codes before annotating clippy output
claude Oct 1, 2026
05522dc
feat(exec): Landlock sandbox, no_new_privs, and a hardened executor i…
claude Oct 1, 2026
b6c97ec
feat(exec): per-capability Landlock confinement; fix log_vacuum path …
claude Oct 1, 2026
7a4656d
feat(exec): enforce network denial with seccomp; scrub child environment
claude Oct 1, 2026
fdc999e
feat(llm): provider-native tool use for Anthropic (ADR-017)
claude Oct 2, 2026
1e858d4
feat(llm): native tool use for OpenAI and Ollama (ADR-017)
claude Oct 2, 2026
eae64bc
feat(policy): policy files with tighten and replace modes (ADR-018)
claude Oct 2, 2026
ee14a91
fix(mcp): lock the plan store; an approved plan could be executed twice
claude Oct 2, 2026
1d0cc2d
feat(runner): one plan executor for run, tui and execute (ADR-019)
claude Oct 2, 2026
6a36fbe
feat(llm): retries, per-attempt deadlines and session budgets (ADR-020)
claude Oct 2, 2026
63e660d
feat(observability): metrics from the audit stream, LLM token metrics…
claude Oct 2, 2026
dc64c37
fix(fleet): policy, approval and audit on the fleet path; close two i…
claude Oct 2, 2026
d6a8b22
test(fleet): serialise tests that write and exec a fake ssh; annotate…
claude Oct 2, 2026
87d7b93
test(llm): make span tests deterministic
claude Oct 2, 2026
e6cc670
feat(tui): Gate tab for plans proposed over MCP; fix goal-field input
claude Oct 2, 2026
82dc895
Supply chain: cargo-deny, pinned actions, SBOM and provenance; fix 4 …
claude Oct 2, 2026
0a906e7
Property tests and protocol fuzzing; close resource-guard bypasses
claude Oct 2, 2026
42adf57
Release wrap-up for 0.2.0: docs brought in line with the code
claude Oct 2, 2026
3915977
gate r1: vacuum boundary normalised at the enforcement point; seccomp…
marcuspat Oct 4, 2026
bcfe5ae
gate r2: relative paths rejected at the boundary; Unrestricted fails …
marcuspat Oct 4, 2026
35a2cc3
gate r3 follow-up: seccomp test invariants corrected (no 4th gate run…
marcuspat Oct 4, 2026
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
76 changes: 67 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,98 @@ on:
pull_request:
branches: ["main"]

# Least privilege: nothing here writes to the repository.
permissions:
contents: read

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
RUST_TOOLCHAIN: "1.97.0"

jobs:
test:
name: Build & Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
# Pinned, not `stable`: a new stable release adds clippy lints, and
# `-D warnings` then fails CI for code nobody touched (1.99 did this via
# `double_must_use` in async-trait's expansion). Bump deliberately —
# the procedure is in docs/SUPPLY_CHAIN.md.
- name: Install Rust ${{ env.RUST_TOOLCHAIN }}
uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
components: clippy, rustfmt

- name: Cache cargo registry & build
uses: actions/cache@v4
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
key: ${{ runner.os }}-cargo-${{ env.RUST_TOOLCHAIN }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-${{ env.RUST_TOOLCHAIN }}-

- name: cargo fmt
run: cargo fmt --all -- --check

# `--locked`: CI builds exactly what Cargo.lock says, and fails if the
# lockfile is stale instead of silently resolving something newer.
- name: cargo check
run: cargo check --workspace --all-targets
run: cargo check --workspace --all-targets --locked

- name: cargo test
run: cargo test --workspace
shell: bash
run: |
set -o pipefail
cargo test --workspace 2>&1 | tee test.log

# Name the failing tests in check annotations, so a red run can be
# diagnosed from the checks API.
- name: Annotate test failures
if: failure()
shell: bash
run: |
if [ -f test.log ]; then
sed -E 's/\x1B\[[0-9;]*[A-Za-z]//g' test.log \
| grep -E '^test .* \.\.\. FAILED$|panicked at ' | head -9 \
| while IFS= read -r line; do echo "::error::${line}"; done || true
fi

- name: cargo clippy
run: cargo clippy --workspace --all-targets -- -D warnings
shell: bash
run: |
set -o pipefail
cargo clippy --workspace --all-targets --message-format=short -- -D warnings 2>&1 | tee clippy.log

# Surface lint failures as check annotations, so they are readable from
# the checks API without downloading the job log.
- name: Annotate clippy failures
if: failure()
shell: bash
run: |
echo "::notice::$(rustc --version)"
if [ -f clippy.log ]; then
sed -E 's/\x1B\[[0-9;]*[A-Za-z]//g' clippy.log \
| grep -E '(error|warning)(\[[A-Za-z0-9_:]+\])?:' \
| grep -v 'could not compile' | head -9 \
| while IFS= read -r line; do echo "::error::${line}"; done || true
fi

supply-chain:
name: Supply chain (cargo-deny)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

# Advisories (the RustSec database `cargo audit` reads), licences,
# banned/wildcard dependencies and crate sources. Configured in deny.toml.
- name: cargo deny check
uses: EmbarkStudios/cargo-deny-action@3c6349835b2b7b196a839186cb8b78e02f7b5f25 # v2.1.1
with:
command: check
arguments: --all-features
62 changes: 46 additions & 16 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,45 @@ permissions:
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
RUST_TOOLCHAIN: "1.97.0" # keep in step with ci.yml
CYCLONEDX_VERSION: "0.5.9"

jobs:
verify:
name: Verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.inputs.tag || github.ref }}

- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Install Rust ${{ env.RUST_TOOLCHAIN }}
uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
with:
components: clippy
toolchain: ${{ env.RUST_TOOLCHAIN }}
components: clippy, rustfmt

- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2

- name: cargo clippy
run: cargo clippy --workspace --all-targets -- -D warnings
run: cargo clippy --workspace --all-targets --locked -- -D warnings

- name: cargo test
run: cargo test --workspace
run: cargo test --workspace --locked

- name: cargo audit
uses: rustsec/audit-check@v2
uses: rustsec/audit-check@69366f33c96575abad1ee0dba8212993eecbe998 # v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}

binaries:
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}
needs: verify
permissions:
contents: read
id-token: write # sign the provenance attestation (Sigstore, keyless)
attestations: write # store it against the repository
strategy:
fail-fast: false
matrix:
Expand All @@ -61,16 +68,19 @@ jobs:
- target: x86_64-apple-darwin
os: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.inputs.tag || github.ref }}

- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
# The same pinned compiler that CI tested with, not whatever `stable`
# happens to be on release day.
- name: Install Rust ${{ env.RUST_TOOLCHAIN }}
uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
targets: ${{ matrix.target }}

- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with:
key: ${{ matrix.target }}

Expand All @@ -90,8 +100,28 @@ jobs:
cd dist
shasum -a 256 "sentinel-${{ matrix.target }}" > "sentinel-${{ matrix.target }}.sha256"

# CycloneDX SBOM of exactly the dependency set compiled into this
# target's binary, published next to it.
- name: Generate SBOM
shell: bash
run: |
set -euo pipefail
cargo install cargo-cyclonedx --locked --version "${CYCLONEDX_VERSION}"
cargo cyclonedx --manifest-path sentinel-tui/Cargo.toml --format json \
--describe binaries --target "${{ matrix.target }}" --target-in-filename
cp "sentinel-tui/sentinel_bin_${{ matrix.target }}.cdx.json" \
"dist/sentinel-${{ matrix.target }}.cdx.json"

# SLSA build provenance: binds the binary's digest to this workflow run
# and commit. Verify with
# gh attestation verify sentinel-<target> --repo marcuspat/Sentinel
- name: Attest build provenance
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0
with:
subject-path: dist/sentinel-${{ matrix.target }}

- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: sentinel-${{ matrix.target }}
path: dist/
Expand All @@ -103,12 +133,12 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
ref: ${{ github.event.inputs.tag || github.ref }}

- name: Download artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
path: artifacts
merge-multiple: true
Expand All @@ -134,7 +164,7 @@ jobs:
fi

- name: Create release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
tag_name: ${{ github.event.inputs.tag || github.ref_name }}
name: Sentinel ${{ github.event.inputs.tag || github.ref_name }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target/
.claude/
*.cdx.json
Loading
Loading