v12 release audit follow-up
Status: 12.0.0-rc.1 is published and independently installable; the stable
12.0.0 candidate follows that release lineage with bounded post-RC fixes and
is in exact-SHA closeout. This document neither publishes nor authorizes
stable by itself. Its exact candidate must repeat the mandatory local, hosted,
packaging, consumer, ownership and attestation gates before the owner approves
the tag.
Each hosted result remains evidence for its recorded commit, not every future
tree; crates.io availability requires the registry receipt.
Baseline and method
The audited code candidate is a6b3bc8a on main, including the
second-computer report in CLIFIX.md, fail-closed SQLite schema
validation for automatic migration generation, and the corrected mutation
inventory. All 22 applicable push workflows passed on that SHA. The immutable
RC tag is v12.0.0-rc.1 at
2b19567e8d184ad3ceeebae812de71b06d32e484. Stable preparation synchronizes
package versions, public documentation, site copy and release evidence. It also
contains bounded post-RC correctness/hardening changes to CSRF composition,
session-cookie handling, generated registration/billing/container contracts and
Studio’s browser assets. These are not a new product feature, but they do change
runtime behavior and therefore require fresh evidence. The immutable tag commit
must pass the complete stable release workflow rather than inheriting a pass by
description.
Review covers every published crate. IoT receives only a light triage under the owner’s explicit v12 exception. Each deep review traces public inputs through validation, state and side effects, compares documented behavior, and adds negative regressions for reproduced defects. Existing tests alone do not close a finding. Regressions are run before and after corrections when feasible.
This is repository-owned code review and testing, not an independent security assessment, provider certification, or a claim that every line or deployment configuration has been exhaustively analyzed. Tests are serialized on the memory-limited local machine. The final local workspace gate completed after the correction batch.
Evidence-bound repository grade
The authoritative scoring method remains the
quality scorecard; this audit does not create a second,
more flattering grading system. Under that policy, the reviewed implementation
supports a maximum local aggregate of 94/A when all conditioning gates are
green. Each of the 15 active non-IoT crates has an A ceiling, while
rullst-iot retains the owner-approved 83/B exception because physical
device and boot-chain evidence is outside the v12 campaign.
That is an evidence-bounded engineering grade, not a security certification, feature-completeness percentage, independent audit result, or release authorization. A candidate earns the recorded grade only when its exact SHA passes the applicable scorecard constraints. The RC met those conditions only after its automatic and manual gates, packaging checks, documentation review, and explicit GO decision completed. That evidence remains bounded to the RC and does not authorize the future stable release. The exact stable candidate earns the grade only after its conditioning gates pass.
Coverage ledger
| Crate / surface | Review scope | Current status |
|---|---|---|
rullst-orm | Projection identifiers, empty-set predicates, tenant/global scopes, transactions, policy mutations, nested queries and search | Reproduced isolation/transaction defects corrected; focused default/strict-SQLite/Redis regressions and the final all-feature workspace gate are green; live external-backend matrices remain release evidence |
rullst-orm-macros | Generated SQL bindings, parser diagnostics, portable identifiers and scope generation | Corrected generated contracts; 43 unit tests, one smoke test and 24 compile-fail cases green |
rullst-core | HTTP security composition, CSRF, lifecycle and development state ownership | CSRF/security composition 21 tests green; four reload tests and actual Node client behavior tests green |
cargo-rullst | Remote CLI handoff, public profile accuracy, supervised restart, generated contracts | Supervisor, dashboard, command-behavior, public-profile and materialized blueprint gates are green; snapshot launch retries bounded transient Linux executable-busy races; automatic SQLite migration generation now rejects unsafe database-owned identifiers before writing Rust source |
rullst-auth | JWT expiry/revocation, encrypted sessions, role guards, passkey/SQLite cancellation | Corrections green: 60 library tests and five durable JWT integrations |
rullst-security | WebSocket origin enforcement, middleware readiness, bounded redaction, crypto/input policies | 159 library tests and two Tower tests green; final rate-limit run passed 11 tests including two added afterward (161 library cases now) |
rullst-connect | OIDC claims/nonce, refresh semantics, callback state and token lifetimes | Corrections green: 204 library tests with Axum-session and SQLite features |
rullst-capital | Provider side effects, pricing, charge binding, authenticated payload schema and signature protocols | 99 library plus 22 integration tests green with Actix; one later Actix duplicate-header regression also green |
rullst-nexus | Admin transport/origin/authorization and tenant/audit boundaries | Corrections green: 50 library plus 11 integration tests, including real SQLite tenant/audit cases; the default coverage pass now includes those cases and its shared-pool race was removed, with 10 consecutive parallel integration runs green |
rullst-studio | Local operator boundary, handoff layout/telemetry changes, dynamic HTML | Static boundary review found no additional reproduced defect; 48 library tests, integrations and the final workspace gate are green |
rullst-macros | Escaping/raw HTML, generated handler/runtime contracts | Static trust-context review completed; no new reproduced defect; final all-feature workspace tests and doctests are green |
rullst-ai | Provider/mock separation, redirect handling, response limits and tool-policy boundaries | 102 library tests green, including real local HTTP regressions for all five native transports |
rullst-mail | Provider side effects, transport limits, attachments/headers, suppression and delivery evidence | 98 library tests green with SQLite, including actual HTTP and cancelled-write regressions |
rullst-messaging | Publication/lease/retry/idempotency, local durability and outbox composition | Cancellation defect corrected; focused SQLite evidence and final all-feature workspace coverage, including the optional ORM outbox relay, are green |
rullst | Facade feature wiring, composed subsystem and tutorial contracts | Static facade/feature review; existing verified-TLS composition retained; final composed all-feature workspace tests and doctests are green |
rullst-iot | Manifest/public capability honesty only; no hardware or deep audit | Light review complete; README/manifest agree on helper/simulator/transport boundaries; approved scope exception |
Counts above describe separate focused runs and overlap; do not sum them into an
invented coverage metric. In addition, the complete workspace test suite passed
with all features, and workspace Clippy passed with all targets, all features
and -D warnings.
Reproduced defects and correction boundaries
| Area | Observed failure | Correction and remaining boundary |
|---|---|---|
| ORM projections | Safe-looking select/pluck accepted SQL expressions | Validate safe projection identifiers; deliberate raw SQL remains a caller-owned escape hatch |
| ORM membership and scopes | Empty IN matched all rows; OR escaped tenant/global/soft-delete constraints | Empty sets are false predicates; group mandatory scopes separately and preserve nested query errors |
| ORM search | Local and external Scout paths bypassed model scopes; empty external results could select ID zero | Start from the scoped query, reject missing context before provider calls and bind provider IDs through empty-aware membership |
| ORM transactions | pluck, streaming/eager paths or mutation callbacks could bypass/wait on an already borrowed transaction | Use the managed executor; release query locks before callbacks/eager work where supported; unsupported mutation-callback reentry returns a typed validation error instead of hanging |
| ORM mutations/macros | Bulk delete bypassed model policy; keyset iteration could escape its cursor; unsupported identifiers reached malformed generated code | Reject unauthorized bulk mutation, group keyset predicates, propagate errors and emit compile diagnostics for unsupported identifiers/scopes |
| Durable local stores | Cancellation during manual BEGIN left uncommitted state in a pooled connection | SQLx RAII transactions in Auth JWT/passkey, Mail suppression and Messaging; cancellation racing dispatched commit still requires reconciliation |
| Authentication | Expired revoked JWT could become accepted during skew allowance | Enforce hard expiry independently of permitted clock skew; no distributed revocation claim |
| OAuth/OIDC | Missing claims, nonce downgrade, refresh-token confusion, empty callback state and invalid lifetimes | Strict provider-specific validation and checked positive bounded lifetimes; real accounts and distributed one-shot callback storage still need external evidence |
| Security middleware | HTTP/2 CONNECT bypassed WebSocket origin policy; cloned Tower services lost acquired readiness | Apply the origin guard to the extended method and call the ready service instance |
| Abuse controls/logs | Reset zero-limit admission, counter overflow, concurrent capacity escape and redaction suffix leakage | Checked bounded admission, atomic capacity/reclamation and bounded fail-closed redaction; controls remain process-local |
| Core CSRF | Empty proofs accepted; valid split Cookie fields rejected; duplicate proofs ambiguous | Nonempty bounded unique tokens, multi-field cookie parsing and exact supported form media type; unsigned double-submit is not a session-signed CSRF scheme |
| Production CSRF composition | An application router with an explicit CSRF layer was wrapped by the Server production baseline, so a first GET emitted two different cookies and the rendered form echoed only one; browsers retained the other and valid submissions failed with 403 | A private request marker makes nested framework/application CSRF composition idempotent while preserving validation at the outer boundary; the exact two-layer regression requires one matching cookie and a successful matching POST. Applications still own HTTPS, session authentication and exact exemptions |
| Examples Omni/HTML/COEP report | A generated Tauri package used colliding Windows MSVC PDB target names; html! rejected source comments; the deployed LMS needed reviewed cross-origin media behavior | Give the Omni library a distinct rullst_omni_lib target and compile-test the emitted entrypoint; strip bounded source comments in the macro parser; retain require-corp by default while exposing a closed, validated Core COEP application setting. Cross-origin media still requires matching CSP, server headers and deployed-browser evidence |
| Nexus operator access | An absolute HTTPS URI impersonated verified TLS; local Host/Origin boundary incomplete | Require the private verified-transport capability and validate local browser Host/Origin; deployment proxies must supply the correct trusted adapter |
| Capital live operations | Fabricated portals/no-op mutations, four hardcoded prices and undocumented mock aliases | Explicit unsupported errors for unimplemented live behavior; deterministic mocks only through documented mock credentials; consult the crate’s provider-method matrix |
| Capital receipts/webhooks | Incomplete authenticated payloads inferred active/paid; charge identity insufficiently bound; Polar/MP body-only signatures did not represent their protocols | Validate required event/status/charge bindings; bounded Polar header-based Standard Webhooks verification; incompatible legacy live signature paths fail closed, including MP until its full provider verification is implemented |
| AI/Mail transports | Redirects forwarded private request content; AI JSON unbounded; suppression cancellation leaked state | Pooled redirect-disabled clients, connection/request budgets, bounded native AI responses and SQLx rollback ownership; native custom endpoints remain trusted operator configuration |
| Public DLL reload | Windows LMS loaded an independent ORM/runtime state and unsafe cross-runtime workarounds were proposed | Remove public DLL generation and use directly linked supervised restart; retained legacy loader is experimental and not a stable Rust ABI |
| Automatic migration generation | SQLite table and column names reached a metadata query and generated Rust comments/strings without validation | Reuse the strict bounded database-identifier policy, bind the SQLite metadata lookup and reject the complete schema before generating any file; regressions cover newline-bearing table and column identifiers |
| Release coverage | The earlier final-main LLVM artifact reported 78,962/87,941 lines (89.7897%) while the upload job itself stayed green; default Nexus SQLite/audit paths were omitted | Nexus is now included in the merged default-profile pass and exact 90% whole-repository and framework-library floors run before upload. PR #183’s hosted artifact reported 79,349/87,941 lines (90.2298%) overall and 59,767/66,004 (90.5506%) across 435 governed framework-library files; the frozen release SHA must repeat this gate |
| Fuzz campaign | Earlier hosted runs found complete-tree rendering in unsupported-union and missing-ID model diagnostics. On 36411ea1, 39 of 40 targets completed their full 5.5-hour campaigns; fuzz_parser alone found a third valid derive tree where unconditional Field::span() validation exceeded the ten-second per-input limit | Anchor model, relation, field and unsupported-type diagnostics to bounded identifiers instead of rendering complete syntax trees; retain all three discovered shapes in the parser corpus. The latest exact ASan reproducer improved from a repeatable 12.1-second timeout to about 30 milliseconds locally; a fresh five-minute local campaign completed 1,740,804 executions without a finding, and all 43 macro unit tests plus 24 compile-fail cases are green. Hosted diagnostic run 34495340300 then completed 1,541,970 executions in 301 seconds on corrected code commit 40c1b083, with no finding. The subsequent complete 40-target campaign passed on 7697fb8a in run 34642351302; its evidence is carried only across the bounded final delta described below |
The parser correction also passed the exact local workspace gates:
cargo test --workspace --all-features and
cargo clippy --workspace --all-features -- -D warnings. This is local
evidence only and does not replace the hosted final-candidate matrix.
The adversarial regressions use local databases, mock keys, signed synthetic tokens and loopback HTTP servers—not real credentials or real payment requests. Provider capability corrections are observable behavior changes: callers must handle explicit errors where previous code returned misleading success.
AI-assisted security review evidence
A read-only Codex Security deep scan inspected representative repository
surfaces and preserved a partial, not exhaustive, report after reaching its
configured budget. It reported no Critical or High finding and independently
validated one Low-severity, Medium-confidence generated-source injection path
in make:migration:auto. The finding required control of a selected SQLite
schema, explicit generator invocation and a later insufficiently reviewed build,
but its possible impact justified correction before the RC.
The follow-up working-tree scan reviewed both changed production files but reached its smaller budget during threat-model construction, before final validation. It produced no report and is deliberately not counted as a pass. The release evidence for the correction is therefore the source trace, the two crafted-SQLite regressions, the complete all-feature workspace tests, strict workspace Clippy and the forthcoming hosted candidate gates. This AI-assisted review is neither an independent audit nor a claim of complete repository coverage.
Website, README and first-run documentation
The organization root website and the framework Pages site were different
deployments. The old organization site still described main as v5 and dev
as v12, and its privacy page asserted unverified worldwide legal compliance.
Both entry points now have prepared matching source, with separate deployment
receipts still required. The RC copy presented v12.0.0-rc.1 as an explicit
evaluation candidate and marked v5 end-of-life. Stable preparation presents
12.0.0 as the supported v12 line while retaining application-specific
security and deployment limits.
The landing uses local CSS/JavaScript/images, finite reduced-motion-aware animation, thirteen owner-supplied social links and a concrete privacy notice. No analytics, social embeds or browser storage were added. Benchmark templates replace remote fonts with system fonts and pin Chart.js with integrity metadata; the remaining jsDelivr request is disclosed. The README preserves the top and bottom dedication, workflow dashboard, genuine coverage/Scorecard badges and evidence boundaries. It corrects the obsolete frontend-profile advertisement.
The beginner learning page links existing authoritative tutorials instead of creating another competing API reference. Initial guides clarify matching CLI installation, optional persistence, first-build time, actual generator paths and how to verify a visible result.
Verified locally for the stable-promotion worktree: mdbook build docs,
python3 .github/validate-site.py, node --check docs/site.js, and
node .github/site-browser-smoke.mjs. The Chromium test passed desktop,
390/320-pixel layouts, keyboard/mobile menu behavior, clipboard success/denial,
privacy disclosure, reduced motion, no-JavaScript navigation and no external
landing requests or browser storage. The RC organization-site export previously
passed the same smoke suite with --organization-site; the stable copy still
requires its separate deployment receipt. This is not a WCAG or cross-browser
certification.
Development reload decision
The public v12 development loop uses supervised process restart. Both
cargo rullst dev and cargo rullst dash enable it automatically; plain
cargo run remains ordinary execution. The wizard no longer asks for a DLL
profile, and the legacy scaffold flag fails with migration guidance.
A successful build precedes stopping the existing child. Compilation errors leave that child serving. Each process runs an owned executable snapshot, so a Windows executable lock does not prevent the next Cargo build. The browser refreshes through a same-origin generation probe after a new server responds. State in memory resets; this does not promise zero-downtime deployment.
The tutorial explains the contract. The v13 decision is evidence-driven: compare measured reload time, failure recovery, process cleanup, memory and state ownership across databases and operating systems before considering a different architecture.
RC receipt and remaining stable publication work
- Approved code candidate
a6b3bc8apassed all 22 applicable automatic push workflows. Codecov reported 91.49% repository coverage and 100% patch coverage; the separately enforced framework-library component also passed 90%. - The dependency, code-scanning and secret-scanning APIs each reported zero open alerts after the hosted candidate completed.
- Sixteen exact
12.0.0-rc.1archives passed metadata/topological preflight, content audit and Cargo package verification. An extracted consumer compiled, the packaged CLI installed and reported the correct version, and all six installed-CLI blueprints generated and compiled without monorepo paths. - The complete 40-target hosted fuzz campaign passed on parent
7697fb8ain run34642351302. It remains historical RC evidence. The stable delta now includes Core/Auth and generated-application runtime changes, so the stable candidate must repeat the applicable fuzz campaign instead of carrying that result forward as exact-SHA evidence. - The full mutation campaign is complete. The originating run
34688592153left six of eighty shards incomplete; exact-SHA recovery run34738841341completed eleven of twelve halves before GitHub twice shut down the runner at the same resource-intensive ORM mutant. Finalization run34761010296split only that remaining half again, bounded its internal test timeout and passed both fragments, the aggregate and the evidence boundary. The verified content-addressed artifact reports 14,391/14,391 candidates classified across 87 complete artifacts: 8,705 caught, 3,553 missed, 76 timed out and 2,057 unviable, for a conservative caught percentage of 70.57%. Its source is1ffdf0a72577d1a974b4e87e2bf207f4a3580243; inventory SHA-256 is986d5cc1de71f7c8afbae7823a8fca53304b84f8e81b8f9e2d1fd3949c15ef80. Mutation remains informational: full classification is valid sensitivity evidence, while surviving and timed-out mutants remain explicit follow-up findings rather than being mislabeled as caught. - The owner supplied explicit GO for
v12.0.0-rc.1on September 12, 2026 after reviewing the package graph and topological plan. The stable closeout commit synchronizes versions/documentation, hardens release/assurance workflows and contains the explicitly listed post-RC fixes. Its exact SHA must pass the applicable hosted checks; then the protected tag workflow must recheck name ownership, reproduce the archives, publish in order, verify registry checksums/indexing and emit provenance. The 94/A score is supporting evidence, not a security certification or authorization for stable12.0.0.
RC publication receipt and stable promotion
- Tag
v12.0.0-rc.1resolves to2b19567e8d184ad3ceeebae812de71b06d32e484. The release workflow’s verify and publish jobs succeeded on that SHA. All sixteen packages were published in topological order, indexed with the verified archive checksums and exposed through docs.rs; the owner also completed a separate-machine CLI smoke test. - The GitHub release is marked as a prerelease and contains all sixteen crate archives, checksum files, Cargo metadata/lockfile, Cargo Audit JSON, CycloneDX 1.5 SBOM, bounded security evidence, advisory policy, ownership evidence and tag context. GitHub’s SHA-pinned build-provenance attestation verified for the archives and evidence bundle.
- The overall historical run is red only because the additional reusable SLSA
generator failed during environment detection: its transitive
[email protected]reference violated this repository’s full-SHA Action policy. It never generated or uploaded provenance. It is not counted as release evidence, and no SLSA level is claimed. Stable preparation removes that redundant external job while retaining the successful SHA-pinned GitHub attestation already produced inside the verified job. - All package names are now registered. Trusted Publishing is configured by the owner for the sixteen packages, the temporary bootstrap secret was removed, and the exposed bootstrap token was revoked. Stable publication must use the short-lived OIDC credential; the bootstrap path should remain inactive.
- Stable
12.0.0promotes the audited RC lineage plus the declared post-RC corrections: idempotent nested CSRF composition, stricter session-cookie parsing/logout, transactional generated LMS registration, POST/CSRF billing mutations, hardened generated containers, self-contained Studio assets, collision-free Omni targets, source-comment parsing and explicit validated COEP application policy. The remaining delta is version/documentation/SBOM reconciliation, changelog-derived release notes and removal of the incompatible redundant SLSA job. Every runtime correction requires renewed evidence and must remain visible before GO.
Residual limitations for the next reviewer
- HTML escaping does not make
RawHtml, custom escaping implementations, JavaScript contexts or URL policies safe automatically. RPC parameters are untrusted inputs, not identity assertions. - Some direct session/passkey helpers depend on caller input-size bounds even when HTTP middleware limits requests. Cookie isolation matters for the unsigned double-submit scheme. Local rate controls are not distributed limits.
- OIDC fixtures do not establish live-account acceptance, JWKS stampede resistance or multi-host atomic callback consumption.
- NFS-e remains preparation/offline evidence, not official fiscal authorization. Payment fixtures do not homologate providers or fully model every event schema.
- SQLite cancellation tests prove rollback ownership before commit; they cannot make cancellation during a dispatched commit into exactly-once knowledge.
- Some older route smoke tests accept unavailable-database responses and prove route presence only. Real SQLite behavioral tests are identified separately.
- IoT received only the agreed manifest/README review. No physical devices, browser WebAuthn ceremony, store signing, live provider or deployment proxy certification was performed.
Evidence handling
Confirmed security defects remain local until corrections and regression evidence are ready for a coordinated commit. Findings are classified by impact, not by whether the previous scorecard happened to be green. Provider behavior that cannot be completed within the current v12 contract must fail explicitly and be documented as unsupported; mock success is not live-provider evidence.
Repeatable focused verification receipts
These focused commands and the final local preflight succeeded during the
September 5–6 correction batch. The September 8 PR #183 tree, merged as
adb83c8b, independently repeated cargo test --workspace --all-features,
strict all-feature workspace Clippy, formatting and diff checks successfully:
CARGO_BUILD_JOBS=1 cargo test -p cargo-rullst --lib -- --test-threads=1
CARGO_BUILD_JOBS=1 cargo test -p rullst-core --lib server::dev_reload -- --test-threads=1
node rullst-core/src/server/dev_reload/client_tests.cjs
CARGO_BUILD_JOBS=1 cargo test -p rullst-nexus --lib --tests -- --test-threads=1
CARGO_BUILD_JOBS=1 cargo test -p rullst-security --lib rate_limit::tests -- --test-threads=1
CARGO_BUILD_JOBS=1 cargo test -p rullst-ai --lib
CARGO_BUILD_JOBS=1 cargo test -p rullst-mail --features sqlite --lib
CARGO_BUILD_JOBS=1 cargo test -p rullst-connect --features axum-session,sqlite --lib
CARGO_BUILD_JOBS=1 cargo test -p rullst-capital --features actix --lib --tests
CARGO_BUILD_JOBS=1 cargo test -p rullst-capital --features actix --lib middleware_rejects_duplicate_standard_webhook_headers
CARGO_BUILD_JOBS=1 cargo test -p rullst-messaging --features sqlite -- --test-threads=1 --quiet
CARGO_BUILD_JOBS=1 cargo clippy -p cargo-rullst -p rullst-core --lib -- -D warnings
CARGO_BUILD_JOBS=1 cargo clippy --workspace --all-targets --keep-going -- -D warnings
CARGO_BUILD_JOBS=1 cargo test --workspace --all-features
CARGO_BUILD_JOBS=1 cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo fmt --all -- --check
git diff --check
bash .github/check-historical-roadmap-ledger.sh
bash .github/check-crate-architecture.sh
ORM default/strict-SQLite/Redis and macro compile-fail results are recorded in the coverage ledger. Live-service backend verification remains distinct from the passing all-feature compile, lint and local workspace gates.