Skip to content
Merged
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
49 changes: 30 additions & 19 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
# CrustCore code owners.
#
# Contract files (CLAUDE.md §7.3, ROADMAP.md §20.2) are the trust boundary:
# changes are serialized and require maintainer review. Listing them here makes
# that review a required, automated gate rather than a convention.
# Contract files and trust-boundary implementations are serialized and require
# maintainer review. Branch protection must require code-owner approval for this
# file to become an enforced server-side gate.

# Default owner for everything.
* @RNT56
* @RNT56

# Contract files — never edit in parallel; maintainer review required.
/CLAUDE.md @RNT56
/AGENTS.md @RNT56
/INVARIANTS.md @RNT56
/THREAT_MODEL.md @RNT56
/SECURITY.md @RNT56
/Cargo.toml @RNT56
/Cargo.lock @RNT56
/docs/policy.md @RNT56
/docs/secrets.md @RNT56
/docs/sandbox.md @RNT56
/docs/backend-contract.md @RNT56
/crates/crustcore-kernel/src/event.rs @RNT56
/crates/crustcore-kernel/src/action.rs @RNT56
# Repository contracts and release/security metadata.
/CLAUDE.md @RNT56
/AGENTS.md @RNT56
/INVARIANTS.md @RNT56
/THREAT_MODEL.md @RNT56
/SECURITY.md @RNT56
/Cargo.toml @RNT56
/Cargo.lock @RNT56
/.github/workflows/ @RNT56

# Public trust contracts.
/docs/policy.md @RNT56
/docs/secrets.md @RNT56
/docs/sandbox.md @RNT56
/docs/backend-contract.md @RNT56

# Code-level trust boundaries.
/crates/crustcore-kernel/src/event.rs @RNT56
/crates/crustcore-kernel/src/action.rs @RNT56
/crates/crustcore-kernel/src/state.rs @RNT56
/crates/crustcore-policy/src/decision.rs @RNT56
/crates/crustcore-secrets/src/lib.rs @RNT56
/crates/crustcore-policy/src/caps.rs @RNT56
/crates/crustcore-backend/src/lib.rs @RNT56
/crates/crustcore-backend/src/integrate.rs @RNT56
/crates/crustcore-secrets/ @RNT56
/crates/crustcore-zeroize/ @RNT56
/crates/crustcore-sandbox/ @RNT56
16 changes: 16 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: 2
updates:
- package-ecosystem: cargo
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
groups:
rust-security-and-maintenance:
patterns:
- "*"
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
29 changes: 22 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: CI

on:
push:
branches: ["**"]
branches: ["main"]
pull_request:

# Cancel superseded runs on the same ref.
Expand All @@ -14,6 +14,21 @@ env:
CARGO_TERM_COLOR: always

jobs:
security-audit:
name: dependency audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cargo
key: audit-${{ hashFiles('Cargo.lock') }}
- name: Install cargo-audit
run: cargo install cargo-audit --locked
- name: Reject vulnerable locked dependencies
run: cargo audit --deny warnings

verify:
name: verify (${{ matrix.os }})
runs-on: ${{ matrix.os }}
Expand All @@ -24,10 +39,10 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
components: rustfmt, clippy

Expand All @@ -49,7 +64,7 @@ jobs:
&& echo "bwrap functional" || echo "bwrap present but not functional (tests will gate-only)"

- name: Cache cargo registry and target
uses: actions/cache@v4
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.cargo/registry
Expand Down Expand Up @@ -87,9 +102,9 @@ jobs:
name: nano size gate (<800kB)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: actions/cache@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.cargo/registry
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ jobs:
- { os: ubuntu-latest, target: x86_64-linux } # the flagship size target
- { os: macos-latest, target: aarch64-macos }
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable

- name: Build the release artifacts
shell: bash
Expand Down Expand Up @@ -69,7 +69,7 @@ jobs:
fi
cat "SHA256SUMS-${{ matrix.target }}.txt"

- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dist-${{ matrix.target }}
path: dist/*
Expand All @@ -81,9 +81,9 @@ jobs:
if: startsWith(github.ref, 'refs/tags/') # only on a tag, never on a manual dry-run
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # for the release-notes file
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- uses: actions/download-artifact@v4
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: dist
merge-multiple: true
Expand Down
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,23 @@ agent/PR/role/size/invariant audit trail.

### Fixed

- **End-to-end trust-boundary hardening.** macOS Seatbelt now denies host reads and
writes by default, uses a private per-run temp directory, and binds every sandbox
capability to the exact profile it authorizes. Capability fields are sealed behind
policy-issued constructors; task creation refuses missing or partially unlimited
budgets (including finite daemon token ceilings); verifier attestations are
non-cloneable; concurrent daemon tasks receive unique durable ids and worktrees.
- **Durable verifier evidence.** `crustcore run` and live daemon tasks now persist
owner-only atomic event logs, embed the authenticated receipt in the matching
`ToolCallCompleted` frame, verify the receipt-to-log join before completion, and use
an owner-only persistent receipt key. `crustcore inspect` authenticates and joins
persisted receipts instead of checking only frame hashes.
- **Verified draft-PR execution.** The live daemon now validates repo/ref configuration,
commits and verifies the exact candidate, persists its authenticated evidence before
integration, pushes through an owner-only ephemeral credential-helper lease, and opens
a real draft PR through the GitHub REST adapter. No-op workers are refused even when
they claim completion, and native mode refuses coding goals it cannot implement.

- **Final-polish audit (multi-agent) — fixed 5 union-merge + hygiene defects.** A
comprehensive end-to-end audit (6 finder dimensions; every finding adversarially
verified to reject churn) surfaced, and this fixes: a missing untrusted-input bound on
Expand All @@ -392,6 +409,18 @@ agent/PR/role/size/invariant audit trail.

### Changed

- **Supply-chain baseline hardened.** GitHub App RS256 signing moved from the
RustCrypto `rsa` crate with its unpatched timing advisory to `jsonwebtoken` backed
by AWS-LC. Sidecar secret values use `zeroize`; nano secret bytes and receipt MAC
keys use the tiny audited first-party `crustcore-zeroize` primitive, preserving
the zero-third-party nano graph. CI runs
`cargo audit --deny warnings`; workflow actions are immutable-SHA pinned at their
maintained Node 24 majors; Dependabot
and CODEOWNERS cover dependencies, workflows, contracts, secrets, and sandbox code.
Feature branches validate once through `pull_request`; `push` CI is reserved for
`main`, eliminating duplicate PR-branch runs without weakening post-merge coverage.
The minimum supported Rust version is now 1.88.

- **Consolidated the duplicated security primitives into `crustcore-types::hash`.** The
constant-time 32-byte compare (`ct_eq`) and the hex decoders (`hex_val`, `hex32_decode`)
were copy-pasted across `crustcore-receipts`, `crustcore-daemon` (webhook + Slack), and
Expand All @@ -411,6 +440,7 @@ agent/PR/role/size/invariant audit trail.

| Date | Phase/Task | Change | PR / Branch | Agent / Role | Nano Δ | Invariants |
| --- | --- | --- | --- | --- | --- | --- |
| 2026-07-12 | end-to-end-hardening | Sandbox/capability/budget seals; non-cloneable verifier evidence; durable event-log + receipt join; real confined verified-patch-to-draft-PR path; unique daemon task ids; AWS-LC JWT migration; supply-chain policy | `codex/end-to-end-hardening` | Codex (Supervisor/Implementer) | +16.5 KiB local macOS nano (444.6 KiB total, 55.6%) | Enforces 1-3, 6-14, 18-20; completion now requires persisted joined evidence |
| 2026-06-28 | v0.6/E.1 | Cockpit view core: `build_cockpit` composes TaskDetail/EvidenceSummary(refs-only)/ApprovalForm(op-hash-bound) from the read-model, bounded; renders evidence, mints nothing. Completes Phase E + all of v0.6 | `claude/v06-e1-cockpit` | Claude (Implementer) | 0 kB (crustcore-dev) | Enforces 2, 5, 11, 13, 14; read-model only, op-bound approvals, no minting |
| 2026-06-28 | v0.6/E.3 | `slack::SlackAllowlist` + `normalize_message` mirroring Telegram (same RuntimeEvent stream + gates, deny-all empty) + redacted `render_to_slack`; live API `#[ignore]`d | `claude/v06-e3-slack` | Claude (Implementer) | 0 kB (daemon-only) | Enforces 1-5, 7, 8, 11, 15, 16; opt-in, redacted, same dispatch as Telegram |
| 2026-06-28 | v0.6/F.1 | `snapshot_all`/`adopt_from_snapshot` cross-process recovery: stable ids, re-leased under new owner, Pending-resume-from-log, carried-usage re-charge, over-budget→terminal. Completes Phase F | `claude/v06-f1-recovery` | Claude (Implementer) | 0 kB (daemon-only) | Enforces 11, 12, 13; recovery restores supervision, never completion |
Expand Down
Loading
Loading