All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Commit messages follow the Angular convention defined in ADR-0024.
-
TmpFile capture mode for subprocess.spawn (ADR-0054 revision 2) — persists stdout/stderr to
.substrate-subprocess-stream-<job_id>.<stream>via atomic rename of.tmp.<uuid7>transit file; coexists with live notifications/progress channel. -
subprocess.tmp_rootTOML config key (defaults to firstpolicy.rootsentry) — controls the directory where TmpFile capture-mode stream transit and final files reside (ADR-0017 revision 2). -
SubprocessResult.stdout_tmp_path/stderr_tmp_pathOption<PathBuf>fields — absolute paths to persisted final stream files; set only whencapture_kind = "tmp_file"and the job terminates withSucceeded. -
#SubprocessResultCUE definition added todocs/arch/schemas/subprocess.cueformalising the terminal output shape including tmp path fields. -
subprocess bounded context (ADR-0052 supersedes ADR-0044) with tools
subprocess.spawn,subprocess.list,subprocess.cancel,subprocess.result, andsubprocess.signalbehind Cargo featuresubprocess(default-OFF); includes CUE schema, Rego invariants, 12 Gherkin features, domain README, and Structurizr DSL container entry. -
ADR-0050: system resource monitoring (
sys.mem,sys.cpu). -
ADR-0051: per-process resource stats (
proc.stats,proc.top). -
ADR-0053: process lifecycle cascade contract (
setsid+PR_SET_PDEATHSIGon Linux + macOS watchdog pipe for orphan prevention). -
ADR-0054: subprocess stdout/stderr stream multiplex via
notifications/progresschunked payload (StreamChunkvalue object). -
ADR-0055: orphan reaper on startup removes stale
.tmp.<uuid7>files older thanstartup.orphan_reap_age_secs.
- ADR-0044 status superseded by ADR-0052; the no-subprocess invariant is narrowed rather than removed.
no_subprocess.regopolicy scope narrowed:crates/substrate-subprocess/is whitelisted fortokio::process::Command; all other crates retain the unconditional prohibition; the forbidden high-level crate list (subprocess,duct,xshell,cmd_lib,shell-words) remains global.- tokio workspace dependency gains the
processfeature when thesubprocessCargo feature is enabled. substrate-mcp-servergains the optionalsubprocessCargo feature that activates the substrate-subprocess adapter registration.
- Subprocess stream transit files created with mode
0600(owner read/write only) — prevents subprocess output leakage to other users on shared hosts (ADR-0033 revision 2, ADR-0054 revision 2). - Layer 5 (subprocess sandbox) added to the security model (ADR-0004
amendment):
setsidprocess group isolation, unconditional stripping ofLD_PRELOAD/DYLD_INSERT_LIBRARIES/LD_LIBRARY_PATH/DYLD_LIBRARY_PATH,PR_SET_PDEATHSIG(SIGTERM)on Linux, and macOS watchdog pipe. - STRIDE expansion for subprocess BC (ADR-0029 amendment) covering new threat identifiers: S-NEW-3 (binary allowlist bypass), T-NEW-6 (env injection via LD_PRELOAD), R-NEW-1 (deny audit trail for spawned binaries), I-NEW-2 (stdout/stderr capture integrity), D-NEW-3/D-NEW-4/D-NEW-5 (subprocess resource exhaustion, quota, and cascade-kill denial paths), E-NEW-1 (privilege escalation via binary allowlist misconfiguration), E-NEW-2 (container escape via unconstrained subprocess).
0.1.0 — 2026-05-23
First public release. Spec-as-source-of-truth phase complete; across 276 Gherkin scenarios, 72 pass, 54 skip (no step definition yet), and 150 fail — all tracked as follow-up work. The release was iterated through a full parallel-subagent audit (code quality, security, architecture, QA, documentation) before the tag landed at its final commit.
Architecture spec (docs/arch/)
- 49 MADR 4.0 ADRs covering: bounded contexts, crate stack + async zones, security model, error taxonomy, MCP protocol negotiation, async job control-plane, filesystem index, capability adapter factory, SIMD runtime dispatch, no-subprocess policy, local-deploy + codesign, Mermaid spec diagrams (mandatory), MCP Tasks primitive adoption.
- 64 Gherkin features across 7 bounded contexts plus cross-cutting concerns (job lifecycle, SIMD fallback, capability negotiation, startup contract, internal-error correlation).
- 11 CUE schemas with
// DDD role:headers covering policy config, error catalog, hints grammar, index config, jobs, MCP tool spec, runtime config, security policy, shared kernel, SIMD capability, tool card. - 6 Rego policies including
hexagonal_layering,no_subprocess,commit_conventions. - Structurizr DSL with C4 context + container views (now reflecting the two platform-shim crates).
- TLA+ formal model for the job registry (
JobRegistry.tla). - 41 Mermaid diagrams across ADRs and domain READMEs (ADR-0047).
Workspace (crates/)
- Cargo workspace layout per ADR-0022 with hexagonal layering enforced
via Rego policy:
substrate-domain(pure ports + value objects),substrate-policy(allowlist + path jail),substrate-config(figment-based TOML loader), seven adapter crates per bounded context, two platform-shim crates (substrate-signal-sys,substrate-fs-index-macos-sys), andsubstrate-mcp-servercomposition root. - Rust 2024 edition, MSRV
1.85, toolchain pinned to1.95viarust-toolchain.toml. - rmcp 1.7 with
["server", "transport-io", "macros"]features (no networked transports). - Tokio 1.4x multi-thread runtime; no
netfeature unless theoutbound-netCargo feature is opted in.
Bounded contexts and tools
filesystem-query:fs.read,fs.read_dir,fs.find,fs.stat,fs.hash, with platform-native stat tiers (LinuxStatx,MacosGetattrlist).filesystem-mutation:fs.mkdir,fs.write,fs.copy,fs.rename,fs.remove,fs.set_permissions,fs.symlink,fs.touch, with transactional write pattern (<target>.tmp.<uuid7>+ atomic rename).process:proc.list,proc.tree,proc.signal— Linux start-time via/proc/uptime+CLK_TCK; macOS viasysctl. PID allowlist blocks{0, 1, 2}(init / kernel threads) regardless of caller.system-info:sys.info,sys.uptime,sys.df,sys.uname,sys.hostname,sys.load_average.text-processing:text.search,text.count_lines,text.head,text.tailwith SIMD-accelerated literal search (Teddy when available).archive:archive.tar.create,archive.tar.extract,archive.zip.create,archive.zip.extract,archive.gzip.compress,archive.gzip.decompress,archive.hash.- Asynchronous job control-plane (
job.list,job.result,job.cancel,job.status) for Bucket C long-running operations, with idempotency-key dedup and TTL-based result GC.
Security
- Allowlist (TOML, default-deny) → path jail via
strict-path+openat2(RESOLVE_BENEATH | NO_SYMLINKS)on Linux,O_NOFOLLOW_ANYon macOS. - Real Linux
openat2capability probe; the post-call canonical path is retrieved via/proc/self/fd/<fd>readlink (not lexically reconstructed) so audit trails carry the kernel-resolved path.SYS_OPENAT2syscall constants gated per architecture (x86_64 / aarch64 / s390x / riscv). - Dry-run mandatory for mutations; elicitation form-mode required for
every destructive op:
fs.remove,fs.rename(gate added),fs.set_permissions(mask covers world-writable + setuid + setgid),proc.signal SIGKILL/SIGTERM/SIGSTOP, archive create/extract. - proc.signal gate order is dry-run → elicitation → PID allowlist → existence → delivery (per ADR-0035).
- Signal safety:
SIGPIPEignored at startup via dedicatedsubstrate-signal-syscrate; blake3 mmap feature disabled to avoid SIGBUS on concurrent truncation. - Cancellation:
CancellationToken+tokio::select! biasedwith work as the first arm. - Transactional writes with
statvfspreflight disk-space guard. deny.tomlconfigured withvulnerability = "deny",unmaintained = "warn", and yanked-crate denial;.gitignoreexcludes.env*files.
Errors and audit
- 13 base error codes plus 6 kernel-induced and 7 startup codes; stable
SUBSTRATE_<UPPER_SNAKE>form. - Every error envelope carries
code,message_en_us,recovery_hint(≤150chars), andcorrelation_id(UUIDv7, generated at dispatcher entry and threaded through every error returned by the request). - Audit-event taxonomy: structured JSON emitted to
stderronly;stdoutremains the JSON-RPC channel (ADR-0005). - Startup-error correlation IDs use
Uuid::new_v7, not a deterministic XOR construction.
Tooling
spec validateframework wired (CUE, Conftest/Rego, Vale, Structurizr, MADR lint, Mermaid lint, OpenAPI lint, TLC for the TLA+ model).- GitHub Actions CI workflow (
.github/workflows/ci.yml) coveringcargo build / fmt / clippy / nextestand the spec full lane. mise.tomlpinning Rust + the tool versions used by the spec framework.
Testing
- Cucumber test harness in
crates/substrate-mcp-server/tests/cucumber.rswith 311+ step definitions matching 64 Gherkin features. - Workspace unit suite: 278 tests passing.
- Property tests via
proptestfor system-info, text, archive, filesystem-mutation invariants.
Community and metadata
CONTRIBUTING.md,CODE_OF_CONDUCT.md(Contributor Covenant 2.1 by reference),SECURITY.md,CHANGELOG.md,LICENSE(dual-license aggregator), and.github/templates (issue forms, PR template, Dependabot config). GitHub community-profile health: 100%.Cargo.tomlworkspace metadata,LICENSE-MIT,LICENSE-APACHEidentity normalized toFabricio Archanjo <farchanjo@gmail.com>.- Repository links point at
github.com/farchanjo/substrate.
- 150 of 276 Gherkin scenarios are currently failing — mostly fixture bodies for newly-implemented step defs, OS-specific edges, and async cancellation timing. The skip count fell from 148 to 54 in the audit pass, surfacing real failure modes that were previously hidden.
- macOS notarization pipeline (ADR-0045) is documented but not yet automated end-to-end.
- TLC model coverage is partial; only the job-registry invariants are checked.
scanner/linux.rscarries aTODO(perf)thread::sleep(100ms)on cold-start delta-CPU sampling. The intended fix (startupLazyLockbaseline) is deferred to avoid race-introduction risk.