Rullst CI/CD and Verification Contract
This document describes what the repository’s automation currently executes. It is not evidence that a workflow has passed for a particular commit. A green claim must always point to the GitHub Actions run, commit SHA, logs, and produced artifacts.
Last source-level review: 2026-09-11.
Status language
| Status | Meaning |
|---|---|
| Blocking | A failing command fails that workflow run. Branch protection still determines whether the check is required for merging. |
| Automated evidence | The workflow runs automatically, but part of its result is external, uploaded, or deliberately non-blocking. |
| Informational | The workflow is explicitly advisory and must not be described as a release gate. A manual trigger alone does not make a strict candidate check informational. |
| Roadmap | The idea is preserved, but this repository does not yet provide reproducible evidence for it. |
The distinction matters: Kani, Miri, mutation testing, or a scanner can be very valuable without proving that the entire framework is panic-free, race-free, memory-safe, or compliant with a regulation.
Mainline execution model
The v12 dashboard and its automatic status badges are pinned to main. The
continuous workflows accept pushes to main and pull requests targeting it,
and expose workflow_dispatch where a safe rerun is useful. Superseded runs of
these workflows are cancelled per workflow and ref so rapid development does
not spend runner capacity proving an obsolete commit.
ci.yml deliberately treats the expensive operating-system matrix differently.
Format and Clippy continue to give feedback on draft pull requests. The complete
Linux/macOS/Windows test matrix, blocking line coverage, SemVer fan-out and
CodeQL analysis start for a pull request only when it is ready
for review, and it can always be requested manually. Each operating system
executes eight parallel shards: the non-CLI workspace, ordinary CLI targets,
the LMS contract, three public-profile groups and two generated-blueprint groups.
The basic/relational/polyglot and foundation/product partitions retain every original
case while bounding the longest Windows and macOS jobs. No test is omitted;
this changes wall-clock scheduling rather than the assertions being executed.
Hosted CI permits two nested compiler jobs for the otherwise serial generated
profile/blueprint builds; constrained local runs retain their one-job default.
Each CLI
shard fetches the locked registry inventory before its generated applications
prove that they compile without network access. After that
reviewed commit is merged, the automatic main push repeats Linux rather than
paying for the same macOS and Windows proof twice. A direct push to main
therefore has Linux evidence only until a maintainer explicitly runs ci.yml;
release candidates must use the manual full matrix when no successful ready-PR
run points to the exact candidate tree.
The SHA-bound quality scorecard is generated only by a ready pull request or a
manual full-matrix run. It is deliberately skipped on the Linux-only automatic
main run, because that execution cannot honestly award cross-platform
verification credit. Run ci.yml manually on a final main candidate to
produce the exact-SHA release scorecard. Manual diagnostic runs may select one
operating system and one test shard; those deliberately do not produce a
full-matrix scorecard and do not replace final-candidate evidence.
GitHub executes schedule events from the repository’s default branch, so
scheduled and continuous v12 evidence now share the active main source line.
Tag publication remains deliberately unavailable through a manual button.
Manual and periodic execution map
Every verification workflow except the PR-context-only ai-sentinel-pr.yml
and tag-only release.yml can now be started from Actions → select workflow
→ Run workflow. A manual run checks the selected branch’s current SHA; record
that SHA and the run URL before treating it as release evidence. The release
workflow intentionally has no button because its publication authority begins
only with an exact version tag.
The workflows below run only when requested manually:
| Workflow | Evidence | RC interpretation |
|---|---|---|
dast-zap.yml | OWASP ZAP baseline against a release blog showcase plus fresh generated REST API and complete LMS applications | REST/LMS warnings and failures block unless an exact rule ID is versioned as INFO with a local explanation in .zap/; those configs are passed explicitly to the pinned scanner and unlisted warnings remain live. The showcase is informational because it deliberately uses third-party presentation assets; reports and application logs are retained. This remains representative, not universal deployment coverage. |
fuzzing.yml | All 40 declared libFuzzer targets from the validated shared inventory | Required v12 RC evidence: release mode first validates the ten package lockfiles and compiles every declared target in ten package-level preflight jobs, then every target must finish without a crash for the 5.5-hour budget; target-specific corpora are restored and saved, while failure reproducers are retained. Dependency-lock drift fails preflight, campaign and corpus jobs. The proc-macro parser uses strict processes of at most 30 minutes sharing one corpus, which bounds sanitizer RSS without weakening the total budget. A strict five-minute single-target diagnostic accelerates correction feedback but is explicitly ineligible as RC evidence. This is bounded evidence, not proof for every input. |
kani.yml | Twenty named bounded formal harnesses in ten supported runtime/library packages | Required v12 RC evidence for the declared harnesses: every proof has an isolated strict matrix job. Rullst itself stays on stable Rust 1.98.1 with a Rust 1.96 MSRV; only the separately built Kani verifier uses its pinned nightly-2026-08-01 compiler (rustc 1.99.0-nightly) because the latest stable Kani bundle’s Rust 1.93 compiler cannot compile the framework. The proc-macro-only rullst-macros target remains unsupported by Kani and is covered by compile-pass/fail and generated-project evidence instead. |
miri.yml | Randomized-layout Miri execution over 15 named pure-Rust/default-feature scopes | Required v12 RC evidence for the declared scopes: every selected scope is strict. This nightly-only interpreter uses pinned nightly-2026-08-21 (rustc 1.100.0-nightly); it does not change the project’s stable toolchain or MSRV. Native FFI, OS syscall, network/provider, umbrella re-export, and example-application boundaries are excluded explicitly rather than emitted as tolerated errors. |
mutants.yml | A fail-fast reviewed inventory, eighty lossless shards over the measured 14,380-mutant workspace scope, their artifacts and a strict aggregate | Informational: a cheap all-feature --list --json preflight rejects inventory drift before runners start; every shard then uses that release surface, and aggregation requires every reviewed candidate to receive exactly one classification before reporting the conservative caught percentage. A targeted mode retests one validated production Rust file after a correction; it does not replace the complete campaign. Missed/time-out exit codes remain findings, while a broken baseline, incomplete artifact set, preflight/classification mismatch, invalid invocation or cargo-mutants internal failure fails the workflow. The 80-way split replaces an invalid 16-way attempt whose default-feature baseline omitted optional tests and whose slowest CLI/ORM jobs could not fit the 5h30 bound. “Pass” does not honestly mean every possible mutant was killed. |
These workflows are periodic and manually runnable:
| Cadence | Workflows | Mode |
|---|---|---|
| Daily | audit.yml, sanitizers.yml | Cargo Audit is blocking; TSan/ASan are blocking when executed. |
| Weekly | bench.yml, cargo-deny.yml, codeql.yml, corpus-sync.yml, coverage.yml, documentation.yml, pqc-compliance.yml, proptest.yml, scorecards.yml, security-audit.yml, trufflehog.yml, udeps.yml | The inventory below identifies which results are blocking, automated evidence, or informational. Corpus sync warms and minimizes the same 40 validated target corpora with bounded parallelism. |
All remaining test/build workflows run on the documented push, pull-request or path filters and also expose a manual rerun. For an RC checkpoint, first use the automatic mainline suite, then manually run the five manual-only workflows and any periodic/platform matrix whose latest successful run does not point to the same candidate SHA. Physical devices, store approval, live provider accounts, external security review and human release approval remain outside GitHub Actions.
Required local and release baseline
The contributor baseline from AGENTS.md is:
cargo test --workspace --all-features
cargo clippy --workspace --all-features -- -D warnings
cargo fmt --all
The main CI uses the stricter all-target Clippy form and checks formatting without modifying files:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-features
Rust CI disables Cargo incremental compilation and uses the pinned sccache
Action and binary to store content-addressed compiler outputs in GitHub Actions
cache. The current cc build dependency also honors the same Rust compiler
wrapper, so compatible bundled DuckDB C++ objects can be reused. Same-repository
pull requests can populate only their GitHub-isolated refs/pull/.../merge
cache scope, making a failed-job rerun useful without modifying the trusted
default-branch namespace. Fork pull requests remain read-only. Pushes and
explicit manual runs on main populate entries reusable by later pull
requests. Cache contents never substitute for a test result.
The tag-only verifier uses the same namespace strictly read-only, so it can
reuse an exact trusted compiler output but cannot alter the cache while
creating release artifacts; every release command and assertion still runs.
The setup action’s job-scoped Cargo archive is disabled in these compiler-cache
jobs, so neither the raw workspace target tree nor duplicate registry bundles
compete with compiler objects. CLI integration tests create and remove nested
Cargo targets, and archiving whole mutable trees previously produced false
missing-directory annotations, duplicated roughly 9.56 GiB across twenty
active main caches, and caused eviction churn at GitHub’s default 10 GiB
repository limit. Cargo may redownload registry sources on a fresh runner; this
small network cost is preferable to storing the same registry/target archive
under many job-specific keys. A first run on a new cache namespace is still a
cold build; evaluate acceleration using the reported cache hit ratio and a
later compatible run, never by weakening or omitting assertions.
The same content-addressed approach accelerates LLVM coverage, benchmark,
mutation/fuzz compilation and the scheduled release-mode regression suite. The
weekly corpus workflow warms the same fuzz compiler namespace used by the
manual campaign. Benchmarks remain
sequential on one runner so comparisons do not mix host variance. Coverage
deliberately remains one report job because splitting it without a reviewed
profile-data merge could change the repository percentage. Its second
default-feature pass is limited to ORM, Studio and the public facade: those are
the packages with default-SQLite tests excluded by the mutually exclusive
all-feature graph, so unrelated workspace tests are not repeated. The release-mode
workspace is safe to split because every shard
returns an ordinary test result, while the two source locations that actually
use proptest! still receive their configured 10,000-case runs. SemVer checks
fan out from the machine-readable release order and validate one published API
per job, so adding or removing a release package cannot silently drift from the
matrix.
The all-feature coverage pass uses pinned cargo-nextest to schedule the same
discovered unit and integration tests concurrently. It performs no retry and a
flaky retry could not be normalized into success. A repository profile fixes
four global slots and permits at most two integration tests that launch nested
generated-application Cargo builds, preventing compiler fan-out from trading
latency for memory or disk exhaustion. The exact per-test JUnit result and
duration record is retained for 30 days. This runner is a coverage scheduler,
not a replacement for Rust CI: the required multi-platform shards continue to
execute the complete inventory with ordinary cargo test, preserving both
traditional libtest process semantics and the materialized-project gates.
CodeQL also remains one analysis job. Its Cargo target cache is disabled so the extractor observes compilation for the exact SHA instead of inheriting a fresh artifact from another run; the analysis database itself is not interchangeable with ordinary test shards. Rust CodeQL’s faster buildless mode is intentionally not used because manual compilation gives the extractor the stronger generated code boundary needed by this release.
ci.yml also compiles and exercises each ORM strict database feature in
isolation (PostgreSQL, MySQL, and SQLite), exercises the runtime-only Core and
all 45 public umbrella features in isolated additive graphs with automatic
manifest-drift detection, runs the portable database matrix on Linux, and
tests the complete all-feature workspace in eight parallel shards on Linux,
macOS, and Windows. Feature-boundary rows and threat-model negative tests also
fan out into four deterministic strict shards each; their matrix job remains a
single blocking dependency for the quality scorecard. Each threat-model shard
primes the reviewed lockfile before its deliberately offline generated-project
checks, so it does not inherit a hidden source-cache dependency from another
job. The umbrella’s
cfg(doctest) aggregation reads all 52 public tutorial files directly, so that
same command discovers the versioned Rust blocks, compiles or executes complete
examples, and records explicitly contextual fragments as ignored instead of pretending
they are standalone programs. Its pinned live Redis job also proves that
scheduled Core jobs are not claimed early, that Core cache inspection returns
bounded metadata without values, plus ORM
cache hit/TTL/recovery, tenant/table invalidation, rollback preservation,
process-local post-commit observers and Scout commit ordering. A separate
SQLite outbox contract runs on all three operating systems and covers
atomicity, conflicting idempotency keys, claim races, lease expiry,
retry and dead-letter; the relational matrix repeats the core outbox lifecycle
against PostgreSQL, MySQL, MariaDB and strict SQLite. A dedicated job checks
the declared MSRV, Rust 1.96.0. The Linux provider matrix also runs the
feature-gated Scout adapter against a digest-pinned Meilisearch image; Algolia
and Elasticsearch use bounded local protocol fixtures because no hosted
provider account is part of CI. The same matrix runs typed, parameterized L2
and cosine queries against a digest-pinned PostgreSQL + pgvector image. It also
runs Nexus’s default Any/SQLite HTTP contract explicitly, because the global
all-feature graph intentionally selects a strict database profile and excludes
that materialized tenant/audit target. Coverage separately merges the default
workspace pass, so those routes contribute real executed-line evidence.
After a ready-PR or manual full-matrix Rust CI run finishes, an observational job emits a SHA-bound per-crate quality scorecard into the workflow summary and a 90-day artifact. The score combines versioned expert-audit ceilings with the actual gate results; a failed/skipped/cancelled gate can remove the dimensions it was meant to prove, while a green gate cannot inflate a crate beyond its audited ceiling. This is engineering-evidence reporting, not capability completion or certification. See the scorecard methodology.
Rows with no feature selected compile every package target. Feature-selected rows compile the isolated library graph; feature-enabled tests, examples, and benchmarks remain covered by the workspace and specialist jobs. This avoids pulling unrelated development dependencies into every boundary while retaining real integration coverage.
The tag-only packaged-distribution gate reads the complete feature set from the
extracted rullst package manifest and compiles that crates-only consumer with
defaults disabled and every public feature enabled. A partial hand-maintained
feature allowlist therefore cannot make a monorepo-only integration appear
release-ready.
Recommended main branch-protection profile
Require every job emitted by the following workflows before merging into
main: Rust CI, GitHub Actions Lint, Documentation, End-to-End Smoke Tests, Cargo Audit,
Security Audit, Cargo Deny, CodeQL, Test Coverage, Cargo Machete, SemVer Checks,
Spellcheck, Crate Architecture Policy, TruffleHog, Unsafe Policy, WebAssembly Matrix, Zero
Panics, no-std Build, IoT Integration, and PR Security Evidence.
Do not configure a path-filtered, scheduled, manual, deployment, or tag-only workflow as a universal required check: an intentionally skipped workflow may never create the check context. In particular, IoT Cryptography Containment is blocking when relevant paths change, and the Omni desktop, Android and iOS compile workflows are blocking only when the Omni generator boundary changes. Pages, benchmarks, fuzzing, sanitizers, Kani, Miri, mutation testing, udeps, ZAP, Scorecard, and release provenance belong to deeper evidence or release policy. GitHub repository rulesets remain the enforcement source; this document records the recommended profile and does not claim that the hosted setting is already enabled.
Phase 4 release-engineering status
Goal from gpt.md | Current status | Assessment |
|---|---|---|
| Trifecta with all features | Implemented | CI and tag release both run format, all-target/all-feature Clippy, and all-feature tests. |
| Strict DB features in isolation | Implemented in workflow | strict-postgres, strict-mysql, and strict-sqlite compile independently and each runs a backend-specific CRUD test with only the selected strict feature enabled. |
| Honest blocking/informational labels | Implemented | Unsafe and Wasm checks are blocking in continuous CI; the declared Kani, Miri and fuzzing scopes are strict v12 RC gates; mutation testing and udeps explicitly remain informational. |
| Cover every fuzz target | Implemented in workflow | .github/fuzz-targets.json is the shared inventory for the manual campaign and corpus maintenance. A blocking validator compares it with all ten fuzz manifests and their 40 source files. This records configuration, not a successful six-hour run. |
| Package all crates before publishing | Implemented in workflow | The tag-only release validates versions, packages all publishable workspace crates, hashes and attests the archives, then publishes in dependency order. |
| Unified evidence bundle per tag | Implemented in workflow | The tag-scoped bundle contains Cargo.lock, Cargo metadata, CycloneDX 1.5 SBOM, Cargo Audit JSON, deny.toml, bounded compliance evidence, governed advisory exceptions, commit/tag context, and checksums. The bundle and .crate archives are included in build-provenance attestation. |
| Align manifest, changelog, tag, registry, and notes | Partial | The release validates vMAJOR.MINOR.PATCH against publishable manifest versions. Changelog state and registry/release-note consistency are not automatically verified. Worth implementing before calling 12.0.0 released. |
Important evidence boundaries
Zero-panics and unsafe Rust
zero-panics.yml denies Clippy’s unwrap, expect, panic, todo, and unimplemented
lints for published runtime libraries, procedural-macro engines, CLI production
targets, generated runtime templates, and the Wasm Core path. Tests are excluded
where assertion panics are test semantics.
unsafe-policy.yml compiles production libraries and binaries with
-Dunsafe-code. The only reviewed file-level exceptions are the Radar OS probe
and dynamic-library loader, and the workflow fails if that allowlist changes.
This is an enforced boundary, not a claim that all dependencies contain no
unsafe Rust.
Coverage
coverage.yml runs LLVM coverage over workspace all-features and default
profiles plus the live database matrix, then uploads LCOV to Codecov using
GitHub OIDC rather than a long-lived upload secret. It also retains exact JSON
and text line summaries for 30 days so a passing upload cannot be confused
with the coverage percentage. The all-feature pass uses pinned cargo-nextest
only to run the same discovered tests concurrently, with zero retries, bounded
nested-Cargo concurrency and a retained JUnit execution record. Rust CI still
runs ordinary cargo test across Linux, macOS and Windows. The default-profile pass explicitly includes
ORM, Studio, Nexus and the umbrella facade so their real SQLite contracts are
not hidden by mutually exclusive all-feature database profiles. Before upload,
the workflow independently rejects an LLVM summary below 90% for either the
whole repository or the governed framework-library paths. codecov.yml also
requires at least 90%, with zero tolerance, for those views and changed lines;
failure to upload LCOV also fails the workflow. The report
filters examples, benchmarks, auxiliary test support, and separate test files.
CLI and proc-macro code therefore remains part of the blocking repository
aggregate and is additionally visible as informational components. Their
stronger semantic evidence still comes from materialized scaffolds and
compile-pass/compile-fail contracts. The README exposes both the public overall
badge and the separate framework_libraries badge rather than substituting the
higher component result for the repository total.
Formal, dynamic, and stress analysis
- Kani and Miri are manual research evidence scoped to the harnesses/packages
that actually execute. Rullst itself remains pinned to stable Rust 1.98.1
and keeps Rust 1.96 as its declared MSRV. Kani builds reviewed upstream
revision
8fcd6d90ed07b559e553ca8a92b95f2db69b2c78with the verifier’s own pinnednightly-2026-08-01compiler (rustc 1.99.0-nightly) into a bundle and installer, then treats proof failures in twenty isolated harness jobs across ten supported packages as real matrix failures. That revision intentionally predates acompare_bytescompiler crash reproduced with Kani’s firstrustc 1.100.0-nightlysnapshot. The workflow does not patch manifests, bypass MSRV data, or change Rullst’s stable toolchain. Kani cannot verify the proc-macro-onlyrullst-macrostarget. Miri, which only runs on nightly Rust, pinsnightly-2026-08-21(rustc 1.100.0-nightly) and strictly executes 15 named pure-Rust/default-feature scopes. Its matrix excludes nativering, AWS-LC, SQLite, OS-syscall and network/provider execution that Miri cannot interpret; native CI, integration tests and sanitizers remain the applicable evidence for those paths. Therullstumbrella re-export facade and Blog example add no separate interpreter scope. A selected-scope failure fails the run. The Kani Security harnesses prove pure production decisions such as Vault key-ID character policy, DLP buffer admission, ASCII-folded RASP matching, SRI asset limits and bounded Login Guard delay; the IoT matrix also proves the complete CoAP option-component classification. They do not claim that Kani verifieszeroize’s unsupported inline assembly, cryptographic implementations or the entire concurrent middleware implementations. - Mutation testing is manual, split into 80 lossless shards over the measured
14,380-mutant inventory, and intentionally informational while results are
uploaded. Before the expensive matrix starts, a fail-fast
--list --jsonpreflight verifies the exact unique candidate set; the final aggregate must match that reviewed list, not merely its count. The hosted command makes--all-featuresexplicit and.cargo/mutants.tomlapplies the same feature policy locally; the ignored legacy root configuration and its exclusions were not silently activated. Targeted mode accepts exactly one tracked production.rspath so a correction can be retested without restarting the complete workspace campaign. Exit statuses for missed and timed-out mutants remain findings; baseline, usage and internal failures do not get normalized into green jobs. The aggregate also fails closed when an artifact is absent, a shard is incomplete or the reviewed full inventory drifts; its conservative percentage never treats a timeout as caught. - Fuzzing and corpus maintenance pin
nightly-2026-08-21instead of following a moving nightly alias. This verifier-only toolchain does not change the framework’s stable Rust 1.98.1 toolchain or its Rust 1.96 MSRV. Before a release campaign starts, ten strict preflight jobs compile every target so a stale import or broken fuzz manifest fails in minutes rather than alongside hours of valid campaigns. A five-minute one-target diagnostic is correction feedback only; the evidence-boundary job refuses to call it release evidence. Each of the ten fuzz packages has a checked-in dependency lock; inventory validation requires it, and locked metadata plus a post-command drift check prevents preflight, campaign or corpus maintenance from silently resolving a different dependency graph. The parser campaign restarts its ASan process every 30 minutes while retaining one corpus and the full 5.5-hour target budget, preventing instrumentation RSS accumulation from masquerading as a parser crash. - Branch coverage,
cargo-udeps, TSan and ASan share the reviewednightly-2026-08-21analysis snapshot instead of following a moving nightly alias. The first two remain observational/informational; sanitizer failures remain blocking whenever their daily/manual matrix executes. cargo-udepsis weekly/manual and explicitly non-blocking.- TSan and ASan run daily/manual across twelve runtime/domain packages; Messaging runs its integration contract so its concurrent state is actually exercised rather than reporting a zero-test library pass. There is no MSan job in the current sanitizer workflow.
- The manual ZAP workflow materializes, release-builds and migrates a fresh
REST API and complete LMS through the real CLI. Both baselines fail on any
warning/failure, preserve INFO observations and use no ignored rules. The
release blog showcase is scanned separately but remains informational because
its documented presentation boundary deliberately uses a relaxed CSP and
third-party assets. Its rules retain those external-asset findings for review
and reduce only evidenced token/state signals or escaped showcase reflections
to INFO; they do not hide findings with
IGNORE. These three targets are representative evidence, not coverage of every blueprint, authenticated role, browser, proxy or deployment. - Property tests and benchmarks are scheduled/manual evidence. The property workflow preserves the complete all-feature release-mode regression suite in eight parallel shards and separately runs the ORM and Connect property contracts with 10,000 generated cases. The eight published benchmark groups, backed by nine Criterion binaries, emit non-blocking alerts at a 20% regression and feed the public benchmark hub; they are not a promise against every nanosecond-level regression.
Fuzzing and OSS-Fuzz
The manual fuzzing.yml matrix covers all 40 declared libFuzzer targets:
Core 12, ORM 5, Security 7, Connect 3, Mail 4, AI 3, IoT 3, Capital 1, Nexus 1,
and Studio 1. The checked-in .github/fuzz-targets.json is validated against
every */fuzz/Cargo.toml, corresponding lockfile and source file before either
the manual campaign or weekly corpus job can fan out. Release mode then compiles all targets in ten
package-level preflight jobs before starting any long campaign. Both jobs use
versioned per-target corpora and one content-addressed compiler-cache namespace;
campaign failures retain their exact reproducer, and the weekly job performs a
bounded warm-up before minimizing and uploading each actual corpus. A clean
run remains evidence only for its exact SHA, target, corpus, toolchain and time
budget. Diagnostic mode is limited to one exact inventory target for five
minutes and is never counted as the forty-target RC gate.
The oss-fuzz/projects/rullst directory is a local integration draft. It is not
proof of upstream acceptance, continuous ClusterFuzz execution, or coverage of
all 40 targets; its helper build must be completed and validated against the
official OSS-Fuzz repository before submission. The integration is worth
finishing, but a “100% first-pass acceptance” promise is not meaningful and
should not be made.
Supply chain and release provenance
All direct third-party GitHub Actions references in this repository’s workflow
files are pinned to full commit SHAs. A pinned composite action can still carry
its own transitive downloads or references, so blocking integrations must also
be reviewed for that behavior. RustSec exceptions are limited by deny.toml
and documented with owners, controls, and expiry dates in
docs/src/security-advisory-exceptions.md.
scorecards.yml runs the pinned OpenSSF Scorecard action on main pushes and
weekly, uploads SARIF to GitHub code scanning, and publishes OIDC-authenticated
results to the public Scorecard API so the README badge follows the latest
completed analysis. The numeric score is supply-chain evidence, not a security
certification.
release.yml is tag-only. It verifies source, validates the exact semantic tag
against every publishable crate, packages before the first publish, and creates
a tag-bound evidence bundle containing the lockfile, Cargo metadata, CycloneDX
1.5, Cargo Audit JSON, dependency policy, bounded compliance evidence, advisory
exceptions, commit context, and checksums. The .crate archives and evidence
receive a GitHub build-provenance attestation, while the official generic SLSA generator produces
release provenance. This does not by itself establish project-wide SLSA
Level 3 certification, Sigstore Cosign binary signing, or regulatory compliance.
workflow-lint.yml validates all workflow syntax, GitHub expressions, and
embedded shell with Actionlint 1.7.7. Its container is pinned to an immutable
linux/amd64 digest, just like third-party GitHub Actions are pinned to full
commit SHAs.
architecture.yml is repository-owned and deterministic. It rejects any
internal dependency edge or optionality change that is not reflected in the
reviewed crate-architecture-policy.json. The earlier TangleGuard integration
was removed because its composite action downloaded an unversioned latest
binary without a repository-pinned checksum, which was unsuitable for a
blocking supply-chain gate.
Workflow inventory (37 definitions)
Durations are intentionally omitted because runner load, cache state, and the dependency graph make static estimates unreliable.
| Workflow | Trigger | Mode | Actual scope |
|---|---|---|---|
ai-sentinel-pr.yml | pull requests | Automated evidence | Generates bounded CLI audit, compliance report, and CycloneDX SBOM artifacts; no certification claim. |
architecture.yml | main push and PR, manual | Blocking | Compares Cargo’s publishable non-dev internal dependency graph with the reviewed crate-architecture-policy.json; unreviewed normal/build edges, removals, or optionality changes fail, while test-only dev-dependencies do not masquerade as production coupling. |
audit.yml | main push and PR, daily, manual | Blocking | Cargo Audit over the production lock and all ten fuzz-package locks with one advisory-database fetch. The v12 candidate applies no advisory exceptions; future exceptions must pass the separate owner/expiry governance check. |
bench.yml | main push, weekly, manual | Automated evidence | Eight published groups backed by nine Criterion binaries, with non-blocking 20% regression alerts and gh-pages data consumed by the benchmark hub. Scheduled runs use the repository default branch. |
cargo-deny.yml | main push and PR, weekly, manual | Blocking | Advisory, license, ban, and source policy from deny.toml. |
ci.yml | main push and PR, manual | Blocking plus observational report | Format, all-target/all-feature Clippy, eight-shard multi-OS tests including Cargo-aware doctests sourced from all 52 tutorials, four-way feature/threat partitions, the SQLite transactional outbox contract and Messaging concurrency suite, relational/polyglot live matrices, isolated strict-DB/feature boundaries, MSRV, and a ready-PR/manual full-matrix SHA-bound per-crate quality scorecard artifact. A targeted manual OS/shard run is diagnostic and cannot emit the full scorecard. |
codeql.yml | main push and PR, weekly, manual | Blocking run | Rust CodeQL after an all-target/all-feature workspace check. |
corpus-sync.yml | weekly, manual | Informational | Validates the shared 40-target inventory and ten package lockfiles, restores each real target corpus, performs a bounded warm-up, minimizes it, uploads the result and warms the campaign’s content-addressed compiler cache; individual target failures are retained but tolerated, while dependency-lock drift remains a hard failure. |
coverage.yml | main push and PR, weekly, manual | Blocking plus observational job | LLVM LCOV generation with a pinned, zero-retry, bounded-concurrency nextest scheduler and retained JUnit inventory; a focused default-SQLite pass for ORM/Studio/Nexus/the facade; exact local 90% floors; and blocking OIDC-authenticated Codecov upload. Scheduled/manual branch instrumentation is non-blocking and uses the pinned verifier-only nightly. |
dast-zap.yml | manual | Blocking generated targets plus informational showcase | Pins the ZAP image by digest, scans fresh release/migrated REST API and complete LMS surfaces as blocking gates, scans the CDN-backed blog showcase informationally, and uploads separate reports plus application logs. |
documentation.yml | main push and PR, weekly, manual | Blocking plus informational external scan | Builds the mdBook; validates landing/benchmark templates, project identity, the README workflow count, local assets, pinned external chart scripts and all requested social links. Real Chromium checks desktop/390px/320px layout, keyboard/mobile navigation, clipboard success/denial, privacy disclosure, reduced motion, no-JS navigation, and absence of external landing requests/browser storage. This is a bounded browser contract, not WCAG certification. Also validates the 190-claim historical roadmap denominator and repository-local links. Scheduled/manual runs preserve an informational external-link report. |
e2e-smoke.yml | main push and PR, manual | Blocking | Boots the release Blog application and checks HTTP, headers, CSRF form flow, SQLite persistence, and the persisted page parsed by real headless Chromium. |
fuzzing.yml | manual | Blocking v12 RC campaign or diagnostic | Release mode validates ten package lockfiles and compiles all targets in ten package preflights before forty 5.5-hour libFuzzer jobs, with per-target corpus caching and failure reproducers. Lock drift is always rejected. The parser restarts its ASan process at most every 30 minutes while preserving the budget. Single-target diagnostic mode runs for five minutes and the evidence boundary marks it ineligible for release. |
iot-integration.yml | main push and PR, manual | Blocking | Host IoT tests, signed OTA invariants, and one Cortex-M no-std build; no hardware claim. |
kani.yml | manual | Blocking v12 RC scope; bounded evidence | Builds an immutable reviewed Kani snapshot with the verifier-only nightly-2026-08-01 compiler, while Rullst stays on stable Rust 1.98.1 with a Rust 1.96 MSRV. It verifies twenty named bounded harnesses in isolated jobs across ten supported packages. Proof failures fail their matrix jobs; the proc-macro-only crate remains outside Kani’s supported targets. |
machete.yml | main push and PR, manual | Blocking | Unused dependency scan with configured exceptions. |
miri.yml | manual | Blocking v12 RC scope; bounded evidence | Pinned nightly-only Miri executes 15 named pure-Rust/default-feature scopes with randomized layouts without changing Rullst’s stable toolchain or MSRV. Native FFI/syscall/network paths, the umbrella re-export facade, and the Blog example are explicit boundaries; selected-scope failures fail the workflow. |
mutants.yml | manual | Informational | A fail-fast exact-inventory preflight followed by eighty lossless pinned cargo-mutants 27.1.0 shards over the measured 14,380-mutant all-feature workspace scope, or one validated production-file diagnostic, with uploaded results, compiler caching and a strict completeness aggregate bound to the preflight list. Findings stay informational, but baseline/tool/invocation failures, missing artifacts, incomplete classification and reviewed-inventory drift fail the run. |
no_std-build.yml | main push and PR, manual | Blocking | Builds rullst-iot for three bare-metal targets; this is compile evidence, not hardware execution. |
omni-android.yml | relevant main changes and PRs, manual | Blocking when triggered | Generates a fresh deterministic Omni shell, initializes Android and compiles an unsigned aarch64 debug APK. It does not test a physical device, Play testing, signing, privacy declarations or store acceptance. |
omni-desktop.yml | relevant main changes and PRs, manual | Blocking when triggered | Generates a fresh deterministic HTTPS-backed shell and checks its Tauri crate on Linux, macOS and Windows. It does not build/sign every installer or exercise a GUI/WebView session. |
omni-ios.yml | relevant main changes, manual | Blocking | Generates a fresh deterministic Omni iOS shell on macOS and compiles it for the runner’s simulator architecture. It does not test a physical device, signing, privacy declarations, TestFlight or App Store acceptance. |
pages.yml | main push, manual | Deploy | Validates and deploys the unreleased v12 landing page, local visual assets, mdBook and benchmark hub/dashboards to GitHub Pages while preserving history data fetched from gh-pages. |
pqc-compliance.yml | relevant main changes, weekly, manual | Blocking | Signed OTA and Vault tests, RustSec audit, and simulator-boundary checks; explicitly no PQC/HSM certification. |
proptest.yml | weekly, manual | Blocking run | Eight parallel release-mode workspace shards plus dedicated ORM and Connect property contracts with configured case counts. |
release.yml | exact-looking version tags | Release | Tag validation, full verification, package-all, evidence bundle, checksums, attestations, dependency-order publish, and release provenance. |
sanitizers.yml | daily, manual | Blocking run | TSan and ASan library matrices on pinned nightly-2026-08-21; this verifier toolchain does not change Rullst’s stable compiler or MSRV. |
scorecards.yml | main push, weekly, manual | Automated evidence | OpenSSF Scorecard analysis and SARIF/artifact upload; not SLSA certification. |
security-audit.yml | main push and PR, weekly, manual | Blocking | Cross-checks active advisory IDs and expiry metadata across the ledger, Cargo Deny, and scanner workflows, then independently reruns Cargo Audit. |
semver.yml | main push and PR, manual | Blocking | Fans out one job per machine-readable release-order entry and compares each supported, already-published library API with its exact latest non-yanked crates.io baseline. Never-published packages and proc-macro/binary API surfaces unsupported by cargo-semver-checks are reported explicitly. |
spellcheck.yml | main push and PR, manual | Blocking | Repository typo scan. |
trufflehog.yml | main push and PR, weekly, manual | Blocking | Verified-secret scan over the configured Git history range. |
udeps.yml | weekly, manual | Informational | cargo-udeps signal on pinned nightly-2026-08-21; command failures are tolerated. |
unsafe-policy.yml | main push and PR, manual | Blocking | Denies new production unsafe code and validates the reviewed exception allowlist. |
wasm-matrix.yml | main push and PR, manual | Blocking | Compiles Core, the public rullst facade and macros for wasm32-unknown-unknown and wasm32-wasip1. |
workflow-lint.yml | main push and PR, manual | Blocking | Validates the shared fuzz inventory, then Actionlint checks workflow syntax, GitHub expressions and embedded shell using an immutable container digest. |
zero-panics.yml | main push and PR, manual | Blocking | Panic-family Clippy lints plus generated-code regression checks for published runtime targets. |
Preserved next-generation roadmap
These ideas remain valuable, but are not current guarantees:
| Idea | Status and recommendation |
|---|---|
| Loom and Shuttle concurrency exploration | Not implemented — worth implementing for the small shared-state primitives that have explicit concurrency invariants. Do not apply them indiscriminately to the whole workspace. |
cargo-vet dependency review | Not implemented — worth implementing once review ownership and audit criteria are defined; an empty policy file would add ceremony without assurance. |
cargo-careful and zero-allocation assertions | Not implemented — worth targeted experiments. Allocation claims need stable benchmarks and explicit hot paths before becoming gates. |
| PGO and BOLT | Not implemented — defer until production profiles exist. Fixed throughput-gain percentages must not be promised in advance. |
Chaos testing with fail-rs | Not implemented — worth implementing around queues, database retries, and provider timeouts after deterministic failure contracts exist. |
| AFL.rs/honggfuzz differential fuzzing | Not implemented — valuable after the 40 libFuzzer targets have healthy corpora and triage ownership. |
| Sigstore Cosign signing | Not implemented. Consider it for separately distributed binaries/containers; current .crate provenance and checksums should remain the immediate priority. |
| Absolute “100% pure Rustls” mandate | Not established and not recommended as a marketing absolute. Enforce an audited TLS dependency policy based on supported platforms and threat model instead. |
| Complete upstream OSS-Fuzz integration | Partial draft — worth finishing. Validate every intended target with helper.py build_fuzzers and check_build, then submit upstream; do not imply acceptance before merge. |
The goal of this roadmap is stronger, reproducible evidence—not a larger number of badges or absolute claims that no finite test suite can establish.