Integration Documentation: Architecture, API, Tutorials
July 31, 2026 ยท View on GitHub
This document consolidates the integration-facing documentation for Asupersync: architecture overview, API reference orientation, and practical tutorials. It is written for developers integrating the runtime or the RaptorQ stack into other systems (including fastapi_rust).
Quick Start (minimal)
use asupersync::{Cx, Outcome};
use asupersync::proc_macros::scope;
use asupersync::runtime::RuntimeBuilder;
fn main() -> Result<(), asupersync::Error> {
let rt = RuntimeBuilder::current_thread().build()?;
rt.block_on(async {
// Structured concurrency: a scope closes to quiescence.
let cx = Cx::for_request();
scope!(cx, {
cx.trace("worker running");
Outcome::ok(())
});
});
Ok(())
}
Notes:
- The
scope!macro is available in default builds; if you disable default features, re-enableproc-macros. Cx::for_request()is convenient for integration testing and request-style entry points.- Production code should receive
Cxfrom runtime-managed tasks when available. - Use
CxandScopefor all effects: no ambient authority. - A region closes to quiescence: all children complete and all finalizers run.
- Cancellation is a protocol (request -> drain -> finalize), not a silent drop.
Tokio Migration Playbook
Use the native Asupersync modules first when your stack fits the built-in
runtime, HTTP, web, gRPC, or database surfaces. Reach for
asupersync-tokio-compat only at the boundary where a dependency is hard-wired
to Tokio or hyper runtime traits.
Migration Readiness Planner
Before changing a brownfield project, run the read-only planner so the migration starts from an inventory, proof-pack, semantic map, and operator phase plan rather than from hand-maintained notes.
python3 scripts/migration_readiness_planner.py --list
python3 scripts/migration_readiness_planner.py --dry-run --scenario tokio-http-service
python3 scripts/migration_readiness_planner.py --execute --output-root "${TMPDIR:-/tmp}/asupersync_migration_planner_e2e"
python3 scripts/migration_readiness_planner.py --project-root /path/to/rust/project --output-root target/migration-readiness
The planner never mutates the scanned project. For a real project, read these report fields first:
summary.final_verdict:ready,needs_quarantine, orblockedproof_pack.proof_commands: remote-required cargo-tree checks such asdefault-production-tokio-tree,metrics-production-tokio-tree, andfuzz-tokio-quarantine-treesemantic_map.recommendations: Cx threading, region ownership, cancellation checkpoints, and capability narrowing workoperator_report.phase_plan: six ordered phases that map inventory rows back to the migration playbookoperator_report.residual_risks: rows that still need manual design review
Migration Recipe Compiler
Use docs/migration_recipe_compiler.md when planner findings need to become an
agent-readable implementation checklist. The checked contract at
artifacts/migration_recipe_compiler_v1.json maps Tokio, hyper, tonic, axum,
tower, and reqwest concepts to native Asupersync modules, proof lanes, compat
boundary policy, and no-destructive-edit rules. It is not an auto-porting
codemod; unresolved findings stay as owner beads or residual-risk rows.
Fixture recipes:
| Project shape | Planner scenario | Expected report path |
|---|---|---|
| Already native Asupersync crate | native-clean | summary.final_verdict=ready, native proof commands, no residual risk rows |
| Tokio HTTP service using axum/hyper/tower markers | tokio-http-service | needs_quarantine, semantic recommendations for region ownership, cancellation, and capability narrowing |
| Mixed native code with an explicit compat boundary | mixed-compat-boundary | needs_quarantine, compat rows mapped to compat_boundary_ok guidance |
| Malformed Cargo manifest | malformed-workspace | blocked, fail-closed manifest parse and inventory report reasons |
| Optional Tokio edge or transitive lockfile path | feature-gated-tokio-edge | quarantine rows plus proof commands that separate default, metrics, and fuzz graphs |
| Ambient env/fs authority plus alternate runtime | blocked-ambient-authority-service | blocked, hard-blocker classification and manual design risk rows |
| Parseable project with no runtime evidence | zero-evidence-empty | blocked, zero-runtime-surface and zero-semantic-recommendation reasons |
Use these fixtures as deterministic examples only. Real migration signoff still
comes from running --project-root against the target project and keeping the
no-Tokio production graph checks green for the core crate.
Compat crate feature gates and the entrypoints they expose:
| Feature | Use when | Entry points |
|---|---|---|
hyper-bridge | hyper, hyper-util, reqwest, tonic, or any client/server path that wants hyper runtime traits | hyper_bridge::AsupersyncExecutor, hyper_bridge::AsupersyncTimer |
tokio-io | A crate needs Tokio AsyncRead / AsyncWrite or hyper runtime I/O traits | io::TokioIo<T>, io::AsupersyncIo<T> |
tower-bridge | You need to run tower middleware inside Asupersync or expose an Asupersync service to tower | tower_bridge::FromTower<S>, tower_bridge::IntoTower<S> |
full | You need all three bridge families together | all of the above |
Rules of thumb:
- Prefer native
src/web/andsrc/grpc/when you control the application surface. The compat crate is for interoperability, not for replacing Asupersync'sCx-first model. - Keep
Cxexplicit across every boundary. The compat layer is designed so the call site still owns region lifetime, cancellation, and capability narrowing. - Treat adapters as edge infrastructure. Do not add Tokio dependencies to the
core
asupersynccrate or to examples that are meant to show the native runtime surface.
hyper, reqwest, tonic, and hyper-based clients
When a client or server stack expects hyper runtime traits, wire three pieces: an executor, a timer, and a compatible I/O wrapper.
use asupersync_tokio_compat::hyper_bridge::{AsupersyncExecutor, AsupersyncTimer};
use asupersync_tokio_compat::io::TokioIo;
let executor = AsupersyncExecutor::with_spawn_fn(|future| {
// Route adapter-spawned work into the owning region.
let _ = future;
});
let timer = AsupersyncTimer::new();
let asupersync_stream = /* asupersync::net::TcpStream or TLS stream */;
let io = TokioIo::new(asupersync_stream);
let builder = hyper::server::conn::http1::Builder::new().timer(timer);
let _ = (executor, io, builder);
Use this pattern for libraries that sit on hyper's runtime traits, including
reqwest-style client transport, tonic's hyper transport path, and direct
hyper connection builders.
tower and axum-style middleware stacks
Use FromTower<S> when you want to keep a tower middleware/service stack but
call it from Asupersync code with an explicit &Cx. Use IntoTower<S> when an
Asupersync service must be presented as a tower::Service.
use asupersync_tokio_compat::tower_bridge::FromTower;
let tower_service = tower::ServiceBuilder::new()
.service(my_tower_service);
let bridge = FromTower::new(tower_service);
let response = bridge.call(&cx, request).await?;
This is the right bridge for tower, tower-http, and middleware-heavy
stacks. If you are migrating an axum application, prefer moving handlers and
request state to Asupersync's native web surface over time, and keep the tower
bridge only for the layers you cannot retire immediately.
Tokio runtime-context and I/O shims
Some libraries do not need a full hyper bridge; they only need Tokio task context or Tokio I/O traits. For those cases, use the narrower runtime and I/O adapters.
use asupersync_tokio_compat::runtime::with_tokio_context;
let result = with_tokio_context(&cx, || async {
tokio_locked_client.call().await
}).await;
with_tokio_context and AsupersyncRuntime::new(&cx).enter(...) keep Cx
installed while the wrapped code runs, and the I/O adapters let you translate
streams in either direction:
TokioIo<T>: Asupersync stream -> Tokio/hyper traitsAsupersyncIo<T>: Tokio stream -> Asupersync traits
Use the narrowest bridge that satisfies the dependency. If a library only needs I/O trait compatibility, do not also bring in the hyper or tower bridges.
Suggested migration order
- Replace top-level
tokio::spawn, timers, and channels with native Asupersync equivalents in your application code. - Keep third-party Tokio-locked crates behind the compat boundary, not spread through the core of the application.
- Migrate HTTP/web/gRPC surfaces to native Asupersync modules when practical, leaving only truly external crates on the compat path.
- Re-run the no-Tokio production graph checks on the core crate once the boundary is in place:
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo tree -e normal -p asupersync -i tokio
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo tree -e normal -p asupersync --features metrics -i tokio
These commands should still print warning: nothing to print. The compat crate
is an opt-in satellite, not part of the default production graph.
Wave2 Capability Smoke Recipes
These recipes are the public entry points for the promoted Wave2 capability
evidence lanes. They are intentionally small: each row names the capability, the
host context, the proof command, and the evidence artifact to inspect after the
command. Cargo-backed checks must run through rch exec; broker or browser
lanes must emit deterministic skip rows when their host prerequisites are not
available.
| Capability | Host context | Smoke command | Evidence |
|---|---|---|---|
| Remote transport lifecycle | remote worker | bash scripts/run_remote_transport_lifecycle_evidence.sh --output-root ${TMPDIR:-/tmp}/wave2_remote_transport_examples | artifacts/wave2/remote_transport_lifecycle_evidence.json |
| gRPC deadline + health conformance | native deterministic conformance | bash scripts/run_grpc_deadline_health_conformance_evidence.sh --output-root ${TMPDIR:-/tmp}/wave2_grpc_examples | artifacts/wave2/conformance_grpc_deadline_health_evidence.json |
| Actor mailbox + trace-event conformance | native deterministic conformance | bash scripts/run_actor_trace_conformance_evidence.sh --output-root ${TMPDIR:-/tmp}/wave2_actor_trace_examples | artifacts/wave2/conformance_actor_mailbox_trace_event_evidence.json |
| Massive-swarm capacity envelope | operator profile / large-host planning | bash scripts/run_massive_swarm_capacity_envelope.sh --output-root ${TMPDIR:-/tmp}/wave2_capacity_examples | artifacts/wave2/massive_swarm_capacity_envelope_evidence.json |
| Operator swarm profile diagnostics | operator diagnostics | bash scripts/run_operator_swarm_profile_diagnostics.sh --output-root ${TMPDIR:-/tmp}/wave2_operator_examples | artifacts/wave2/operator_swarm_profile_diagnostics_evidence.json |
Recipe rules:
- Keep
Cxflow, region ownership, cancellation/drain/finalize, and no-ambient-runtime boundaries visible in any Rust example promoted from these recipes. - Do not convert evidence artifacts into decorative demos; a row is public only when the command and artifact form a reproducible adoption path.
- Do not add Tokio, hyper, axum, reqwest, async-std, or smol dependencies to core runtime examples.
- If a capability is platform, broker, or formal-tooling gated, keep a stable
unsupported_reason, fallback target, owner bead, and deterministic log row instead of silently skipping it.
The inventory and fail-closed contract for these recipes live in
artifacts/wave2/capability_examples_smoke_recipes_evidence.json and
tests/wave2_capability_examples_contract.rs.
Wave2 Support-Matrix Reconciliation
The Wave2 docs support matrix is downstream of machine-checkable source
evidence, not tracker status. The canonical registry is
artifacts/wave2_capability_evidence_registry_v1.json; public docs reconcile
against that registry plus the lane-specific artifacts before a support class is
promoted.
Public support-class vocabulary used by the docs matrix:
| Support class | Meaning |
|---|---|
shipped | Source, artifact, and command proof support the public claim without a feature-gate caveat |
feature-gated | Shipped only when the named Cargo feature or host gate is enabled |
preview | Public but explicitly not a stable blanket support promise |
lab/virtual-backed | Proven through deterministic lab or virtual runtime evidence |
substrate-only | Internal or lower-level substrate exists, but no public runtime lane is promoted |
broker/coordinator-only | Host can coordinate bounded work but must not own a direct Browser Edition runtime |
deferred | Tracked and intentionally not promoted yet |
unsupported | The platform or runtime contract rules out the claim |
platform-scoped | Support depends on an explicit OS, browser, or host prerequisite |
Reconciliation proof lives in
artifacts/wave2/docs_support_matrix_reconciliation_evidence.json,
scripts/run_wave2_docs_support_matrix_reconciliation.sh, and
tests/wave2_docs_support_matrix_reconciliation_contract.rs. The proof checks
README, Browser Edition docs, integration docs, formal proof posture, QPACK
support posture, conformance evidence, capability examples, and the Wave2
registry together so promoted rows have public markers and non-promoted rows
keep an explicit fallback, owner, residual risk, or unsupported reason.
The Wave2 signoff proof pack is represented by
artifacts/wave2/wave2_signoff_proof_pack_evidence.json and closes the
capability-completion proof-pack marker for promoted registry rows.
Effect-Safe Context Wrappers
Framework integrations should wrap Cx to provide least-privilege access.
HTTP (RequestRegion)
use asupersync::cx::cap::CapSet;
use asupersync::web::request_region::RequestContext;
use asupersync::web::Response;
type RequestCaps = CapSet<true, true, false, false, false>;
async fn handler(ctx: &RequestContext<'_>) -> Response {
let cx = ctx.cx_narrow::<RequestCaps>();
cx.checkpoint()?;
// spawn/time allowed; IO/remote not exposed
cx.trace("request handled");
Response::default()
}
For fully read-only handlers, use ctx.cx_readonly() to remove all gated APIs.
gRPC (CallContextWithCx)
use asupersync::cx::cap::CapSet;
use asupersync::grpc::{CallContext, CallContextWithCx};
type GrpcCaps = CapSet<true, true, false, false, false>;
fn handle(call: &CallContext, cx: &asupersync::Cx) {
let ctx = call.with_cx(cx);
let cx = ctx.cx_narrow::<GrpcCaps>();
cx.trace("handling request");
}
Use CallContext::with_cx(&cx) to construct the wrapper.
These wrappers are zero-cost type-level restrictions; they do not alter runtime behavior, but they remove access to gated APIs at compile time.
Architecture Overview
Conceptual flow
User Future
-> Scope / Region
-> Scheduler
-> Cancellation + Obligations
-> Trace / Lab Runtime
Core invariants (recap)
- Structured concurrency: every task is owned by exactly one region.
- Region close implies quiescence: no live children, all finalizers done.
- Cancellation is a protocol: request -> drain -> finalize (idempotent).
- Losers are drained after races.
- No obligation leaks: permits/acks/leases must resolve.
- No ambient authority: effects flow through
Cxand explicit capabilities.
Obligation leak escalation policy
Obligation leaks are always marked as leaked, traced, and counted in metrics. The escalation policy controls what happens after detection:
- Lab runtime (default):
LabConfig::panic_on_leak(true)maps toObligationLeakResponse::Panicโ fail fast so tests surface leaks deterministically. - Production runtime (default):
RuntimeConfig.obligation_leak_response = Logโ log the leak, emit trace + metrics, and continue (recovery by resolving the leak record so regions can quiesce). - Recovery-only mode:
ObligationLeakResponse::Silentโ keep trace + metrics, suppress error logs for noisy environments.
Override via RuntimeBuilder::obligation_leak_response(...) or
LabConfig::panic_on_leak(false) when you need to adjust strictness.
Module map (Phase 0/1)
cx/: capability context andScopeAPI (entry point for effects)runtime/: scheduler and runtime state (RuntimeBuilder,Runtime)cancel/: cancellation protocol and propagationobligation/: linear obligations (permits/acks/leases)combinator/: join/race/timeout combinatorslab/: deterministic runtime, oracles, trace capturetrace/+record/: trace events and runtime recordstypes/: identifiers, outcomes, budgets, policies, timechannel/,stream/,sync/: cancel-correct primitivestransport/: symbol transport traits and helpersencoding/,decoding/,raptorq/: RaptorQ pipelinessecurity/,observability/: auth and structured tracing
Protocol stack overview
- HTTP/1.1:
src/http/h1/(codec + client/server helpers)- Tests:
tests/http_verification.rs, fuzz targetsfuzz_http1_request/fuzz_http1_response
- Tests:
- HTTP/2:
src/http/h2/(frames, HPACK, streams, connection)- Tests:
tests/http_verification.rs, fuzz targetsfuzz_http2_frame/fuzz_hpack_decode
- Tests:
- gRPC:
src/grpc/(framing, client/server, interceptors)- Tests:
tests/grpc_verification.rs
- Tests:
- WebSocket:
src/net/websocket/(handshake, frames, client/server)- Conformance tests:
tests/conformance/mod.rswireswebsocket_extension_negotiation_rfc6455and the directory-backedwebsocket_rfc6455suite for framing, masking, control-frame, close, error-handling, extension, and fragmentation coverage. - Runtime/e2e tests:
tests/e2e_websocket.rsandtests/e2e/websocket/
- Conformance tests:
- HTTP/3:
src/http/h3_native.rs(native frame/settings/control-stream and QPACK field-section primitives)- Default support is default static-only QPACK.
- The opt-in dynamic QPACK field-section/table support is exposed through
H3QpackMode::DynamicTableAllowedandQpackContext. - The opt-in dynamic QPACK instruction-stream state machine is exposed
through
QpackInstructionStreamState: callers register remote QPACK encoder/decoder unidirectional streams explicitly, feed instruction bytes outside HTTP/3 frame parsing, and use the bounded blocked-stream scheduler tied toSETTINGS_QPACK_BLOCKED_STREAMS. - QPACK string literals support Huffman encode/decode through the shared HPACK Huffman implementation.
- QPACK encoder/decoder unidirectional stream types still reject HTTP/3 frame mapping; instruction processing is available only through the explicit QPACK instruction-stream API. This is not a claim of h3/quinn drop-in parity, default dynamic QPACK, or full QUIC deployment parity.
- Support matrix:
artifacts/http3_qpack_support_matrix_v1.json
- Web framework:
src/web/(router, extractors, middleware, request-region wrappers, static files, sessions/cookies, security helpers, and SSE response formatting)- The current wave2 proof lane is
tests/e2e_web.rs, including route/path extraction, middleware short-circuiting, panic recovery plus security headers, bounded SSE batch response formatting, and request-region panic isolation. Ssecurrently serializes a finite list of events into one boundedtext/event-streambody. It is useful for small finite event responses, but it is not long-lived streaming SSE and does not yet model client disconnect or producer backpressure through a request-region-owned stream.- True streaming SSE is tracked by
asupersync-o74l7u.1. Until that bead is implemented and proven, docs and support matrices must distinguish finite bounded SSE batch responses from request-region-owned streaming SSE.
- The current wave2 proof lane is
Testing reference
See TESTING.md for test categories, logging conventions, conformance suite usage,
and fuzzing instructions.
wasm32 Guardrails
Browser-targeted compilation is explicitly gated to prevent accidental partial builds with semantic holes:
target_arch = "wasm32"requires exactly one canonical browser profile:wasm-browser-minimalwasm-browser-devwasm-browser-prodwasm-browser-deterministic
- The following features are compile-time rejected on wasm32:
cliio-uringtlstls-native-rootstls-webpki-rootssqlitepostgresmysqlkafka
Profile composition rules:
wasm-browser-minimal=wasm-runtimeonly (ABI/contract validation lane)wasm-browser-dev=wasm-runtime + browser-iowasm-browser-prod=wasm-runtime + browser-iowasm-browser-deterministic=wasm-runtime + deterministic-mode + browser-tracenative-runtimeis forbidden on wasm32 browser builds
Policy and deterministic dependency-audit profiles are documented in
docs/wasm_dependency_audit_policy.md.
Optimization-variant policy (dev/canary/release) is defined in
.github/wasm_optimization_policy.json and validated by
scripts/check_wasm_optimization_policy.py, which emits
artifacts/wasm_optimization_pipeline_summary.json for downstream perf/reliability
gates.
WASM Workspace Slicing Matrix (WASM-02 / asupersync-umelq.3.4)
This matrix is the canonical slicing contract for browser compilation closure. It defines what stays in the wasm browser core path vs what remains optional or native-only.
| Slice | Browser status | Surface |
|---|---|---|
| Semantic core (required) | always-on in browser profiles | types, record, cx, cancel, obligation, combinator, runtime scheduler/cancellation core, trace core schema |
| Browser capability/runtime adapters | on for browser profiles that include I/O | runtime::reactor::browser, browser-facing I/O/time seams, wasm ABI boundary types |
| Deterministic diagnostics overlay | only in deterministic profile | browser-trace, deterministic replay-oriented trace hooks and artifact surfaces |
| Feature-gated optional adapters | off by default in browser profiles | proc-macros, metrics, tracing-integration, tower, trace-compression, config-file, lock-metrics |
| Native-only deferred slice | excluded from wasm32 builds | fs, grpc, messaging, process, server, signal, plus tls/database/kafka feature families |
Extraction and optionalization rules:
- If a module requires native OS primitives (
libc,nix, sockets, process/signal), it must stay behindcfg(not(target_arch = "wasm32")). - Browser profiles must compile without enabling any deferred native surface.
- New browser-path code must route effects through explicit capability seams; no ambient host access.
- Changes to this matrix must be reflected in
Cargo.tomlfeature closure and insrc/lib.rscompile-time guardrails.
Deterministic validation bundle for this matrix:
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_wasm_docs cargo check --target wasm32-unknown-unknown \
--no-default-features --features wasm-browser-minimal
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_wasm_docs cargo check --target wasm32-unknown-unknown \
--no-default-features --features wasm-browser-dev
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_wasm_docs cargo check --target wasm32-unknown-unknown \
--no-default-features --features wasm-browser-deterministic
Expected outcomes:
- each profile compiles in isolation,
- selecting multiple canonical profiles fails at compile time,
- native-only modules remain excluded from wasm32 closure.
Browser Edition Documentation IA (WASM-15 / asupersync-umelq.16.1)
This section is the canonical information architecture and navigation contract
for Browser Edition docs. Downstream docs beads (16.2, 16.3, 16.4, 16.5)
should extend this structure instead of inventing parallel navigation trees.
Primary user journeys:
- First-use onboarding: install -> run a minimal browser workflow -> verify deterministic behavior.
- Framework adoption: integrate into React/Next flows without breaking ownership/cancellation semantics.
- Incident response: capture trace -> replay deterministically -> map findings to mitigation.
- Security/perf hardening: verify authority boundaries, redaction posture, and budget thresholds.
Navigation top-level (required):
| Lane | Reader intent | Required doc surfaces | Exit criteria |
|---|---|---|---|
Concepts | Understand guarantees and constraints before coding | Browser semantic contract, invariants, capability model, deferred-surface register | Reader can explain what is in-scope vs deferred and why |
Quickstart | Get working minimal app fast | Install/profile selection, minimal code path, deterministic smoke validation | Reader can run one successful browser flow and verify expected output |
API + Profiles | Choose correct runtime/profile/capability envelope | Feature profile matrix, capability wrappers, ABI/ownership boundaries | Reader can select a profile and avoid forbidden surfaces |
Framework Guides | Implement in React/Next/vanilla | Framework-specific bootstrap + lifecycle + cancellation guidance | Reader can integrate without semantic violations |
Replay + Diagnostics | Debug failures with deterministic evidence | Trace schema, replay workflow, artifact commands, failure taxonomy | Reader can reproduce a failure from provided artifacts |
Security + Performance | Validate production-readiness gates | Threat model, policy checks, budgets, CI gates, waiver/escalation rules | Reader can execute gate checks and interpret failures |
Troubleshooting | Recover from known failure patterns | Symptom -> cause -> command -> expected evidence mapping | Reader can resolve common failures without ad-hoc guesswork |
Browser Runtime Support Boundary (DX Contract)
Browser Edition is direct-runtime only where the shipped package guards and validation evidence explicitly say it is supported. All other environments are bridge-only or out of scope; there is no automatic fallback from an unsupported runtime into a partially functional direct-execution mode.
Support posture:
- direct runtime today: browser main thread with a real
window+documentenvironment andWebAssemblysupport, plus dedicated workers withDedicatedWorkerGlobalScopeandWebAssembly - bridge-only: Next.js server components, route handlers, edge runtimes, and other server-side render environments
- currently unsupported for direct runtime: Node.js-only contexts, service-worker browser contexts classified as broker/coordinator-only, and shared-worker browser contexts classified as broker/coordinator-only
- non-goals for browser runtime closure: native-only modules (
fs,process,signal,server), native DB clients, and native transport surfaces
Documentation updates for Browser Edition should keep this boundary explicit and must not imply automatic fallback from unsupported runtimes into partially functional direct execution.
Browser Support-Class Quick Reference
Use this table before debugging a Browser Edition report. The first question is not "which package failed?" but "what support class does this runtime or capability belong to right now?"
| Support class | What it means | Typical examples in the live tree | First operator action | Canonical reference |
|---|---|---|---|---|
| Direct-runtime supported | Shipped, package-guarded, and covered by Browser Edition evidence lanes | browser main thread, dedicated worker, React client tree, Next client component | keep runtime creation inside that browser boundary and debug the specific failing capability | docs/WASM.md, matrix below |
| Guarded direct-runtime support | Shipped only when explicit host or deployment prerequisites hold | WebTransport datagrams, browser-main-thread-only download helpers, localStorage substrate | check the prerequisite/denial reason first, then fall back to the documented safe lane instead of widening the support claim | docs/WASM.md, docs/wasm_troubleshooting_compendium.md |
| Guarded public browser boundary | Shipped public @asupersync/browser helpers over same-browser host APIs; not a new direct-runtime host lane | browser-native MessageChannel / MessagePort / BroadcastChannel helpers; WHATWG ReadableStream / WritableStream byte helpers | require the explicit browser-native capability token, inspect stable reason/error codes, and fall back to serialized app-boundary handoff when denied | docs/WASM.md, artifacts/wave2/browser_native_message_and_stream_apis_evidence.json |
| Broker/coordinator-only | The host may coordinate bounded work and durable handoff, but must not own a direct Browser Edition runtime | service-worker bounded broker registration and durable handoff; shared-worker bounded coordinator attach/detach/fallback | keep runtime creation out of service/shared-worker hosts; use the broker/coordinator helpers only for scoped registration, restartable work descriptors, per-client attach, detach cleanup, and handoff evidence | docs/WASM.md, docs/wasm_service_worker_broker_contract.md, docs/wasm_shared_worker_tenancy_lifecycle_contract.md |
| Direct-runtime feasible but not yet shipped | Real substrate exists, but there is no promoted public Browser Edition API/contract yet | Rust AsyncRead / AsyncWrite browser-core stream ABI | do not present it as public JS/TS SDK support; keep it on repo-internal validation lanes until promotion closes | docs/WASM.md |
| Bridge-only | Direct Browser Edition runtime execution is not allowed at that boundary; use serialization or an adapter seam instead | React SSR, Next server components, Next route handlers, Next edge runtime | move runtime creation back into a browser-owned boundary and cross the server/edge hop with serializable data only | matrix below, docs/wasm_troubleshooting_compendium.md |
| Impossible / unsupported | The browser security model or shipped package contract rules out direct Browser Edition runtime support | Node-only direct runtime, raw TCP/UDP, filesystem, process/signal, native DB clients | switch to native asupersync or an explicit bridge; do not add fake parity shims | docs/WASM.md |
The checked Browser Edition readiness matrix is
artifacts/browser_edition_readiness_matrix_v1.json, with the human review
table in docs/browser_edition_readiness_matrix.md. It extends the quick
reference above with Package ABI boundary, vanilla/Vite, Webpack, fixture,
rollback, freshness, and no-claim rows for release review.
Browser-Native Messaging And Stream Helper Contract
The promoted browser-native support class is
guarded-public-browser-boundary. The public @asupersync/browser package
exports detectBrowserNativeMessagingSupport(),
assertBrowserNativeMessagingSupport(), createBrowserMessageChannel(),
createBrowserMessagePort(), createBrowserBroadcastChannel(),
detectBrowserNativeStreamSupport(), assertBrowserNativeStreamSupport(),
createBrowserReadableStream(), and createBrowserWritableStream().
Messaging construction requires an explicit
BrowserNativeMessagingCapability; stream construction requires an explicit
BrowserNativeStreamCapability. Denials are intentionally stable:
capability_not_granted, degraded_mode_denied,
ASUPERSYNC_BROWSER_NATIVE_MESSAGING_UNSUPPORTED,
ASUPERSYNC_BROWSER_NATIVE_MESSAGING_OPERATION_FAILED,
ASUPERSYNC_BROWSER_NATIVE_STREAM_UNSUPPORTED, and
ASUPERSYNC_BROWSER_NATIVE_STREAM_OPERATION_FAILED are the operator-facing
markers. The proof artifact is
artifacts/wave2/browser_native_message_and_stream_apis_evidence.json, and the
maintained runner is scripts/run_browser_native_message_stream_evidence.sh.
These helpers are same-browser application-boundary wrappers. They do not imply
raw TCP/UDP/filesystem/process support, cross-origin federation,
service-worker or shared-worker direct-runtime support, or a public Rust
AsyncRead / AsyncWrite browser-core wasm ABI.
Browser Environment Support Matrix
This matrix is the current shipped support posture for the JS/TS packages, not an aspirational roadmap.
| Environment | Current posture | Direct runtime allowed | Canonical package surface | Shipped diagnostic contract | Required action |
|---|---|---|---|---|---|
Browser main thread (window + document + WebAssembly) | supported | yes | @asupersync/browser, @asupersync/react, @asupersync/next client target | reason = "supported" | create runtime/scope handles here |
Browser dedicated worker (DedicatedWorkerGlobalScope + WebAssembly) | supported | yes | @asupersync/browser | reason = "supported" | create runtime/scope handles inside a dedicated-worker bootstrap module |
| Browser service worker | broker/coordinator-only; direct runtime unsupported, bounded broker/handoff supported | no | @asupersync/browser service-worker broker helpers | @asupersync/browser reports reason = "service_worker_not_yet_shipped" and the Rust-side ladder maps the host to service_worker_direct_runtime_not_shipped; the package-level broker helpers expose detectBrowserServiceWorkerBrokerSupport() and BrowserServiceWorkerBrokerStore without widening that claim | keep runtime creation out of the service worker; use registerBroker(), persistBrokerWork(), and persistDurableHandoff() only for bounded broker registration/handoff per docs/wasm_service_worker_broker_contract.md, and validate the maintained browser-run fixture with scripts/validate_service_worker_broker_consumer.sh |
| Browser shared worker | broker/coordinator-only; direct runtime unsupported, bounded coordinator attach/detach/fallback supported | no | @asupersync/browser shared-worker coordinator helpers | Rust-side execution-ladder diagnostics pin shared_worker_direct_runtime_not_shipped; the JS/TS package still rejects the host for direct runtime, while the package-level helpers expose detectBrowserSharedWorkerCoordinatorSupport() and createBrowserSharedWorkerCoordinatorSelection() without widening that claim | keep runtime creation out of the shared-worker host itself; use the bounded coordinator attach/handshake/fallback helper from browser main-thread or dedicated-worker callers per docs/wasm_shared_worker_tenancy_lifecycle_contract.md, and validate the maintained browser-run fixture with scripts/validate_shared_worker_consumer.sh |
| React client-rendered tree in a browser | supported | yes | @asupersync/react | assertReactRuntimeSupport() returns success only when browser prerequisites are present | import and create runtime from client-rendered components only |
| React SSR / Node render path | bridge-only | no | @asupersync/react bridge-only usage only | REACT_UNSUPPORTED_RUNTIME_CODE with browser-derived reason/guidance | move runtime creation to the client tree and keep SSR on serialized data/bridge boundaries |
| Next.js client component | supported | yes | @asupersync/next with target = "client" | assertNextRuntimeSupport("client") succeeds only when browser prerequisites are present | import from client components only |
| Next.js server component / route handler | bridge-only | no | @asupersync/next bridge-only adapters | NEXT_UNSUPPORTED_RUNTIME_CODE with message Direct Browser Edition runtime execution is unsupported in Next server runtimes. | move runtime creation into a client component or browser-only module |
| Next.js edge runtime | bridge-only | no | @asupersync/next bridge-only adapters | NEXT_UNSUPPORTED_RUNTIME_CODE with target = "edge" | keep edge code on bridge-only adapters and do not call direct runtime APIs |
| Node.js CLI / tests / serverless code without DOM globals | unsupported for Browser Edition direct runtime | no | use native asupersync or explicit bridge code instead | browser/react guards surface missing_global_this or unsupported_runtime_context | switch to the native runtime lane or move Browser Edition code behind a browser-only entrypoint |
Rust-Authored Browser Consumer Lane
The JS/TS packages are the shipped Browser Edition product. The Rust-authored lane is narrower and should be treated as three separate workflows:
| Goal | Supported today | Canonical command / artifact | Evidence |
|---|---|---|---|
| Verify browser-safe semantic-core closure | Yes | rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_wasm_docs cargo check --target wasm32-unknown-unknown --no-default-features --features wasm-browser-<profile> | root Cargo.toml, src/lib.rs, tests/wasm_browser_feasibility_matrix.rs |
| Maintain the Rust-side ABI/package boundary that feeds the JS/TS packages | Yes, for workspace contributors | rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_wasm_docs cargo check -p asupersync-browser-core --target wasm32-unknown-unknown --no-default-features --features dev; touch asupersync-wasm only when you need to keep the retained scaffold honest | asupersync-browser-core/ (canonical owner), asupersync-wasm/ (retained non-canonical scaffold) |
| Use the maintained browser-facing Rust example the repository proves end-to-end | Yes, as an in-repo fixture workflow | PATH=/usr/bin:$PATH bash scripts/validate_rust_browser_consumer.sh | tests/fixtures/rust-browser-consumer/, tests/wasm_rust_browser_example_contract.rs |
| Construct Browser Edition runtimes directly from external Rust consumer code | Preview public lane | RuntimeBuilder::browser() for truthful lane negotiation and structured fail-closed diagnostics | src/runtime/builder.rs, tests/fixtures/rust-browser-consumer/, tests/wasm_browser_feasibility_matrix.rs |
Rules:
- Do not present
asupersync-browser-coreorasupersync-wasmas the public end-user Browser Edition SDK for Rust consumers. - Treat
asupersync-browser-coreas the canonical owner of the shipped JS/WASM boundary andasupersync-wasmas retained non-canonical scaffold rather than a second live boundary. - Do not imply external Rust
RuntimeBuilderparity onwasm32; the public Rust browser lane is still a preview dispatcher-backed surface. asupersync-j1xbon.4refreshes that decision explicitly: the lane remains artifact-contract-backed preview, not stable external Rust Browser Edition API parity.- If you need a shipped application-facing browser product surface today, start
from
@asupersync/browser,@asupersync/react, or@asupersync/next. - If you need the truthful current Rust-authored workflow, use the maintained fixture and validation script rather than inventing a broader support claim.
- If you are debugging the preview Rust builder lane, inspect
selected_lane,host_role,reason_code,preferred_lane, anddowngrade_orderbefore widening any support claim.
Runtime Capability Requirements and Compatibility Guidance
Hard prerequisites enforced today by detectBrowserRuntimeSupport(...):
- browser-like
globalThis - either
window+documentor aDedicatedWorkerGlobalScope WebAssembly
Capability snapshot fields emitted alongside unsupported-runtime diagnostics:
hasAbortControllerhasDocumenthasFetchhasWebAssemblyhasWebSockethasWindow
AbortController, fetch, and WebSocket are not currently hard gates for
basic runtime creation, but they are surfaced intentionally so feature-specific
failures can be explained without guesswork.
Shipped unsupported-runtime error contract:
| Package | Error code | Typical unsupported trigger | Correct fallback |
|---|---|---|---|
@asupersync/browser | ASUPERSYNC_BROWSER_UNSUPPORTED_RUNTIME | missing globalThis, a supported browser host (window/document or dedicated worker), or WebAssembly | load the package from a browser main-thread entrypoint, a dedicated worker bootstrap module, or use a server/client bridge |
@asupersync/react | ASUPERSYNC_REACT_UNSUPPORTED_RUNTIME | SSR or React usage outside a client-rendered browser tree | keep direct runtime creation inside the client tree |
@asupersync/next | ASUPERSYNC_NEXT_UNSUPPORTED_RUNTIME | target = "server" / target = "edge" or missing browser prerequisites in client code | move runtime creation into a client component and keep server/edge code bridge-only |
Package-selection guidance:
- Use
@asupersync/browserfor browser-only modules that directly manage runtime, region, task, fetch, or websocket handles. - Use
@asupersync/reactonly inside client-rendered React trees; do not initialize Browser Edition during SSR. - Use
@asupersync/nextonly from client components for direct runtime behavior; server and edge code should exchange serializable data with a browser-owned runtime rather than carrying live handles across the boundary.
Non-goals and fail-closed guardrails:
- no automatic downgrade from unsupported server/edge/node contexts into hidden partial direct execution
- no transfer of live browser runtime handles (
BrowserRuntime, region/task handles, cancellation tokens) across client/server boundaries - no claim that service/shared-worker direct runtime or guarded parallel worker lanes are supported before their host contracts, package diagnostics, and validation lanes are promoted together
- no support promise for native-only modules or native database/transport surfaces in Browser Edition
- no documentation that suggests
@asupersync/nextserver or edge code can safely call direct Browser Edition runtime constructors
Troubleshooting Handoff By Support Class
Once you classify the failing surface, keep the recovery path aligned with that class:
| If the surface is... | Do this next | Do not do this |
|---|---|---|
| Direct-runtime supported | stay in the current browser boundary, capture the emitted diagnostics, and follow the matching recipe in docs/wasm_troubleshooting_compendium.md | do not move runtime creation across boundaries just because one capability failed |
| Guarded direct-runtime support | verify the missing prerequisite or denial reason, then use the documented fallback (WebSocket, fetch, export handoff, etc.) | do not rewrite docs or package claims to make the guarded lane sound ambient |
| Guarded public browser boundary | require the matching BrowserNativeMessagingCapability or BrowserNativeStreamCapability, check capability_not_granted / degraded_mode_denied / ASUPERSYNC_BROWSER_NATIVE_* diagnostics, and fall back to serialized app-boundary handoff | do not treat same-browser helper wrappers as raw transports, cross-origin federation, process/filesystem access, service/shared-worker direct runtime, or Rust AsyncRead / AsyncWrite wasm ABI support |
| Direct-runtime feasible but not yet shipped | keep the behavior on a repo-internal fixture, app-boundary adapter, or explicit experimental lane until the public contract is promoted | do not present substrate existence as shipped SDK support |
| Bridge-only | move direct runtime creation into a browser main-thread or dedicated-worker entrypoint and keep the server/edge hop serialized | do not tunnel live Browser Edition handles across client/server boundaries |
| Impossible / unsupported | change runtime lane entirely: native asupersync, server-side bridge, or another explicit non-browser path | do not add hidden partial-runtime fallbacks or pretend the browser package can emulate native surfaces |
Browser Edition doc map (current canonical locations):
- Concepts and architecture:
PLAN_TO_BUILD_ASUPERSYNC_IN_WASM_FOR_USE_IN_BROWSERS.mddocs/wasm_api_surface_census.md
- Dependency/profile policy:
docs/wasm_dependency_audit.mddocs/wasm_dependency_audit_policy.md
- Scheduler/time/cancellation semantics:
docs/wasm_browser_scheduler_semantics.mddocs/wasm_cancellation_state_machine.md
- Security and hardening:
docs/security_threat_model.md
- This integration guide:
docs/integration.md(entrypoint index + integration orientation)
- Canonical framework examples:
docs/wasm_canonical_examples.md
- Troubleshooting and diagnostics cookbook:
docs/wasm_troubleshooting_compendium.mddocs/wasm_dx_error_taxonomy.md
- Rationale index and decision ledger:
docs/wasm_rationale_index.md
- Pilot triage and roadmap assimilation:
docs/wasm_pilot_feedback_triage_loop.md
- Browser quality evidence matrix contract:
docs/wasm_evidence_matrix_contract.md
Doc-drift verification hooks (required for Browser Edition doc changes):
- Link integrity check:
- ensure every Browser Edition section references at least one concrete artifact/test command.
- Invariant coverage check:
- docs must explicitly mention ownership/cancellation/obligation/quiescence impacts where relevant.
- Profile closure check:
- docs must not advertise forbidden wasm32 surfaces as supported.
- Repro command check:
- each troubleshooting or diagnostics flow must include a deterministic command path.
- Diagnostic parity check:
- unsupported-runtime guidance must reference shipped package error codes or support reasons, not invented terminology.
Recommended command bundle for doc validation workflows:
# Validate rust docs/test snippets and compile surfaces
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo check --all-targets
# Enforce lint quality on touched code/doc-adjacent surfaces
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo clippy --all-targets -- -D warnings
# Validate formatting contract
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo fmt --check
# Verify shipped browser package diagnostics and guidance strings
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo test --test wasm_js_exports_coverage_contract -- --nocapture
Examples
Examples live in examples/ and cover:
- Structured concurrency macros:
examples/macros_*.rs - Cancellation injection:
examples/cancellation_injection.rs - Chaos testing:
examples/chaos_testing.rs - Metrics dashboards:
examples/prometheus_metrics.rs,examples/grafana_dashboard.json - Browser canonical examples + replay commands:
docs/wasm_canonical_examples.md
Module dependency sketch (high level)
Cx/Scope
-> runtime (scheduler, tasks)
-> cancel + obligation (protocol + linear tokens)
-> combinator (join/race/timeout)
lab
-> runtime
-> trace
raptorq
-> encoding/decoding
-> transport
-> security
-> observability
Runtime data flow (high level)
Cx::scope or scope! macro
-> Cx::spawn / Cx::spawn_in (runtime-wired) or Scope::spawn_registered (boot path)
-> Runtime scheduler
-> Task polls
-> cx.checkpoint() (cancellation observation)
-> Effects via capabilities (channels, io, time)
-> Outcome aggregation
-> Region close = quiescence
Cancellation state machine
Running
-> CancelRequested
-> Cancelling (drain)
-> Finalizing (finalizers)
-> Completed(Cancelled)
Region lifecycle (conceptual)
Open
-> Closing (cancel requested or scope exit)
-> Draining (children finish)
-> Finalizing (finalizers run)
-> Quiescent
RaptorQ pipeline data flow
RaptorQSender / RaptorQReceiver
-> EncodingPipeline / DecodingPipeline
-> SecurityContext (sign/verify)
-> SymbolSink / SymbolStream (transport)
RaptorQ configuration surface
RaptorQConfig is the top-level configuration for the RaptorQ pipeline. It
groups all tuning knobs and is validated via RaptorQConfig::validate() before
construction.
Key knobs by component:
EncodingConfig(RaptorQConfig::encoding)repair_overhead: repair factor (e.g.,1.05= 5% extra symbols)max_block_size: max bytes per source blocksymbol_size: symbol size in bytes (typically 64โ1024)encoding_parallelism/decoding_parallelism
TransportConfig(RaptorQConfig::transport)max_paths,health_check_interval,max_symbols_in_flightpath_strategy:RoundRobin | LatencyWeighted | Adaptive | Random
ResourceConfig(RaptorQConfig::resources)max_symbol_buffer_memory,symbol_pool_sizemax_encoding_ops,max_decoding_ops
TimeoutConfig(RaptorQConfig::timeouts)default_timeout,encoding_timeout,decoding_timeoutpath_timeout,quorum_timeout
SecurityConfig(RaptorQConfig::security)auth_mode,auth_key_seed,reject_unauthenticated
RuntimeProfile::to_config() provides baseline presets (Development,
Testing, Staging, Production, HighThroughput, LowLatency).
Note: RaptorQReceiver derives a DecodingConfig from RaptorQConfig::encoding
and uses defaults for the remaining decode knobs (min_overhead,
max_buffered_symbols, block_timeout). For fine-grained decode tuning, use
DecodingPipeline directly.
RaptorQ builder example
use asupersync::config::{RaptorQConfig, RuntimeProfile};
use asupersync::raptorq::{RaptorQReceiverBuilder, RaptorQSenderBuilder};
let mut config = RuntimeProfile::Testing.to_config();
config.encoding.symbol_size = 512;
config.encoding.repair_overhead = 1.10;
let sender = RaptorQSenderBuilder::new()
.config(config.clone())
.transport(sink)
.build()?;
let receiver = RaptorQReceiverBuilder::new()
.config(config)
.source(stream)
.build()?;
RaptorQ RFC-6330-grade scope + determinism contract (spec)
This section is the internal spec for the RaptorQ pipeline. It replaces the current Phase 0 LT/XOR shortcut and defines what "RFC-6330-grade" means for Asupersync. Implementations should not require constant re-reading of external standards; where we diverge, we must document it explicitly.
Scope (non-negotiable in full mode):
- Systematic transmission (source symbols first).
- Robust soliton LT layer for repair symbols.
- Deterministic precode (LDPC/HDPC-style constraints or equivalent).
- Deterministic inactivation decoding (peeling + sparse elimination).
- Proof-carrying decode trace artifact (bounded, deterministic).
Divergence ledger (explicit design decisions):
- Determinism is stricter than RFC 6330: all randomness is derived from explicit seeds and stable hashing; no ambient RNG or wall-clock.
- Proof artifact emission is required (additional constraint, not in RFC 6330).
- Phase 0 may allow XOR-only test mode, but full mode must use GF(256).
Determinism contract
Given:
- input bytes
ObjectIdEncodingConfig/DecodingConfig- explicit seed(s) and policy knobs
Then the following are deterministic and reproducible:
- emitted
SymbolIdand symbol bytes - degree selection and neighbor sets for repair symbols
- decoding decisions (pivot selection, inactivation set, row-op order)
- proof artifact bytes and final outcome
No ambient randomness and no time-based choices.
Seed derivation (canonical)
All pseudo-random decisions are derived from a stable hash of:
seed = H(config_hash || object_id || sbn || esi || purpose_tag)
Where:
config_hashis a stable hash of the encoding/decoding configobject_id,sbn,esiare fromSymbolIdpurpose_tagdistinguishes degree selection vs neighbor selection vs pivoting
H is a fixed, documented hash function; changing it is a protocol-breaking change.
Encoder contract (per source block)
-
Segmentation + padding
- Split bytes into
symbol_sizechunks. - Pad deterministically (zero pad + pad length recorded in
ObjectParams). - Partition into source blocks with deterministic
Kper block.
- Split bytes into
-
Precode / intermediate symbols
- Map
Ksource symbols toN >= Kintermediate symbols. - Precode structure is sparse, stable, and deterministic.
- Precode parameters are explicit in config and recorded in proof metadata.
- Map
-
Systematic emission
- Emit source symbols first (
ESI < K), in deterministic order.
- Emit source symbols first (
-
Repair symbol generation
- Choose degree
dvia robust soliton distribution (configurablec,delta). - Select
dneighbors deterministically using the derived seed. - Compute repair symbol as a linear combination over GF(256) (full mode).
- Choose degree
Neighbor selection and equation construction must be reproducible given
(object_id, sbn, esi, config_hash, seed).
Decoder contract (per source block)
-
Ingest
- Track received symbols and IDs.
- Reject duplicates deterministically with a precise
RejectReason.
-
Peeling / belief propagation
- Repeatedly solve degree-1 equations and substitute into others.
- Deterministic processing order for the degree-1 queue.
-
Inactivation decoding
- When peeling stalls, pick an inactivation set deterministically.
- Perform deterministic elimination (stable row order + stable pivot choice).
-
Completion
- Recover intermediate symbols, then source symbols.
- Reassemble bytes and validate padding rule.
Proof-carrying decode trace artifact
For each decoded block, emit a compact artifact that allows offline verification:
- config hash + seeds + block sizing metadata
- equation inventory: symbol IDs + neighbor sets used
- elimination trace: pivots, inactivation choices, row ops (bounded)
- final outcome: success or
RejectReason
The artifact must be:
- deterministic
- bounded in size (explicit caps)
- sufficient to reproduce decoder state transitions and explain failures
Proof Artifact Schema + Versioning + Bounds
Schema versioning:
PROOF_SCHEMA_VERSIONis a u8 on the artifact. A breaking schema change must bump it.- Readers version-gate: unknown versions are rejected with a clear error.
- Forward-compat is allowed only for additive fields when the encoding supports it; unknown fields are ignored in that case.
Canonical serialization (for hashing):
DecodeProof::content_hash()must use a deterministic hasher (util::DetHasher) and a fixed field order.
Proof artifact API surface
InactivationDecoder::decode_with_proof(...) -> Result<DecodeResultWithProof, (DecodeError, DecodeProof)>returns a decode result plus a proof artifact (or a failure + proof).DecodeProof::replay_and_verify(symbols)replays and validates the artifact.DecodeProof::content_hash()provides a stable fingerprint for deduplication.
Example usage:
use asupersync::raptorq::decoder::{InactivationDecoder, ReceivedSymbol};
use asupersync::raptorq::DecodeProof;
use asupersync::types::ObjectId;
let decoder = InactivationDecoder::new(k, symbol_size, seed);
let object_id = ObjectId::new(42);
let sbn = 0u8;
match decoder.decode_with_proof(&symbols, object_id, sbn) {
Ok(result) => {
let proof: DecodeProof = result.proof;
let _fingerprint = proof.content_hash();
proof.replay_and_verify(&symbols)?;
}
Err((_err, proof)) => {
let _fingerprint = proof.content_hash();
proof.replay_and_verify(&symbols)?;
}
}
- Integer fields are serialized in little-endian fixed-width form.
- Vectors are serialized in recorded order with a length prefix.
Deterministic ordering requirements:
received.esis,peeling.solved_indices,elimination.inactive_cols, andelimination.pivot_eventsmust be recorded in deterministic order.- Recommended: sort
esisby ESI; record peel/inactivation/pivot events in stable row/col order used by the decoder.
Size bounds + truncation:
MAX_RECEIVED_SYMBOLSandMAX_PIVOT_EVENTSare hard caps.- When limits are exceeded, the artifact keeps the first N entries in the deterministic order and sets
truncated = true. - Counts (
total,solved,pivots,row_ops) always reflect the full execution, not just the recorded prefix.
Schema fields (v1):
version: u8 (PROOF_SCHEMA_VERSION)config: {object_id,sbn,k,s,h,l,symbol_size,seed}received: {total,source_count,repair_count,esis[],truncated}peeling: {solved,solved_indices[],truncated}elimination: {inactivated,inactive_cols[],pivots,pivot_events[],row_ops,truncated}outcome:Success { symbols_recovered }|Failure { reason }reason:InsufficientSymbols { received, required }|SingularMatrix { row, attempted_cols[] }|SymbolSizeMismatch { expected, actual }
Formal Semantics (v4.0.0)
The canonical small-step semantics live in asupersync_v4_formal_semantics.md (project root; the in-docs/ copy is now a redirect stub โ see br-asupersync-4nw2lb)
and are tagged v4.0.0. This is the ground-truth model for regions, tasks,
obligations, cancellation, scheduler lanes, and trace equivalence. It is intended
to be mechanically translatable to TLA+/Lean/Coq without a rewrite.
Proof-Impact Classification and Routing (Track-6 T6.3b)
Use this deterministic classification for runtime-facing changes:
| Class | Deterministic criteria | Required routing |
|---|---|---|
none | Changes only in docs/**, examples/**, non-conformance test text artifacts, or comments/formatting with no behavior change | 1 maintainer review |
local | Behavioral/code changes confined to one subsystem path (single src/<subsystem>/**) and no formal schema/refinement/conformance contract edits | Subsystem owner + 1 reviewer from same domain |
cross-cutting | Any of: touches multiple subsystems, touches src/cx/**/src/runtime/**/src/cancel/**/src/obligation/**/src/lab/**/src/trace/**, touches formal/lean/** coverage artifacts, touches conformance/refinement contracts, or changes public API/trace schema | Runtime core owner + formal/refinement owner + conformance owner (all required) |
Module ownership routing map:
| Path prefix | Owner group |
|---|---|
src/runtime/**, src/cx/**, src/cancel/**, src/obligation/** | Runtime Core |
src/lab/**, src/trace/**, formal/lean/**, formal/lean/coverage/** | Formal + Determinism |
conformance/**, tests/*conformance*, tests/*refinement* | Conformance |
src/raptorq/**, src/encoding/**, src/decoding/** | RaptorQ |
src/security/**, src/observability/** | Security/Observability |
If multiple prefixes match, union all owner groups and treat as cross-cutting.
PR/review artifact requirement for critical modules:
proof_impact:
class: none|local|cross-cutting
touched_paths:
- <path>
theorem_touchpoints:
- <theorem/helper/witness id>
refinement_mapping_touchpoints:
- <runtime_state_refinement_map row id or constraint id>
matched_routing_rules:
- <rule id or sentence>
owner_groups_required:
- <group>
reviewers_requested:
- <reviewer/owner>
conformance_touchpoints:
- <test or suite name>
refinement_or_schema_impact: none|yes
evidence_commands:
- rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo check --all-targets
- rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo clippy --all-targets -- -D warnings
review_artifact_location: <PR body section or attached artifact path>
Reviewers should reject PRs touching critical modules when this block is missing
or when class does not match touched paths.
Additional hard requirements for local and cross-cutting changes:
- At least one
theorem_touchpointsentry. - At least one
refinement_mapping_touchpointsentry. - At least one executable entry under
conformance_touchpoints. review_artifact_locationmust point to where the completed declaration lives.
Theorem-Assumption Guardrail Checklist (Track-6 T6.2a)
Use this checklist for reliability reviews and incident retrospectives when a change touches runtime-critical behavior.
Assumption-class mapping:
| Assumption class | Guardrail checks (deterministic) | Primary evidence anchors |
|---|---|---|
| Budget constraints | Deadline/poll/cost bounds remain monotone; no path relaxes child budget beyond parent meet | Budget semantics, region/scope budget propagation, timeout tests |
| Cancellation protocol | Request -> drain -> finalize ordering preserved; loser-drain behavior present for race paths; masked sections remain bounded | cancellation state machine, combinator race/join tests, cancel oracles |
| Region lifecycle | Region-close still implies quiescence; no child/task/finalizer leaks at close | region lifecycle invariants, quiescence oracles, close-regression tests |
| Obligation resolution | Every permit/ack/lease path resolves commit/abort; no unresolved obligation exits | obligation leak checks, obligation table metrics, leak/futurelock tests |
Deterministic review checklist (mark each as pass/fail/n/a):
budget_monotonicity: parent/child budget composition still uses tightening semantics.cancel_protocol_order: cancellation order is request -> drain -> finalize in changed paths.race_loser_drain: race/hedge paths still cancel and drain losers.region_quiescence: changed region lifecycle paths preserve close => quiescence.obligation_totality: changed reserve/commit/abort paths remain total (no silent drop).determinism_surface: no ambient randomness/time introduced in changed paths.evidence_commands: commands and artifacts recorded for reproduction.
Reliability workflow tie-in:
- During review: attach the checklist in the PR under
proof_guardrails. - During incident triage: map symptom to one assumption class first, then verify corresponding guardrails/evidence.
- During postmortem: record failed checklist items and link the exact code/test artifacts.
Guardrail-gap escalation rule:
- Any
failitem without an immediate fix must create a blocker bead (prefix:[GUARDRAIL-GAP]) before merge/sign-off. - Blocker bead must include: impacted assumption class, violated checklist item, reproducible command/artifact, and owner.
Reliability triage classification contract (Track-6 T6):
- Canonical machine-readable source:
formal/lean/coverage/invariant_theorem_test_link_map.jsonunderreliability_hardening_contract. - Required assumption classes:
budget_constraints,cancellation_protocol,region_lifecycle,obligation_resolution. - Each class maps to:
- linked invariants (
inv.*IDs), - deterministic checklist IDs from this section,
- conformance artifacts/tests,
- governance cadence IDs (
weekly,phase-exit), - explicit
failure_policy(fail-fastorfail-safe) with rationale.
- linked invariants (
Canonical incident triage flow (must be followed in order):
classify_assumption: select one assumption class + severity (sev1|sev2|sev3).verify_guardrails: run class-specific checklist + conformance artifacts.route_disposition: apply class policy (fail-fastorfail-safe) and assign mitigation owner.governance_escalation: open/update blocker bead and record governance thread/sign-off status.
Incident forensics playbook (asupersync-umelq.12.5):
- Canonical operator guidance:
docs/replay-debugging.md->WASM Incident Forensics Playbook (asupersync-umelq.12.5). - Deterministic drill command:
bash ./scripts/run_all_e2e.sh --suite wasm-incident-forensics - Contract drift gate:
python3 ./scripts/check_incident_forensics_playbook.py
Governance integration requirement:
- Every unresolved reliability guardrail failure must be reviewed on the same cadence IDs used by the refinement reporting contract in
formal/lean/coverage/runtime_state_refinement_map.json(reporting_and_signoff_contract.report_cadence).
Proof-Safe Hot-Path Refactor Checklist (Track-6 T6.1b)
Use this checklist for performance-oriented refactors that touch hot paths in:
src/runtime/scheduler/**src/cancel/**src/obligation/**src/runtime/task_table.rsandsrc/runtime/sharded_state.rs
Deterministic checklist (mark each item pass/fail/n/a):
scheduler_lane_contract: cancel > timed > ready dispatch ordering preserved, including fairness bounds for cancel streaks.lock_order_contract: lock acquisition still followsE(Config) -> D(Instrumentation) -> B(Regions) -> A(Tasks) -> C(Obligations).cancel_protocol_contract: request -> drain -> finalize ordering remains intact in modified paths.obligation_contract: reserve/commit/abort pathways remain total, and no new leak/futurelock surface is introduced.determinism_contract: no ambient time/randomness or non-deterministic iteration is introduced on hot paths.theorem_anchor_contract: touched behavior is mapped toformal/lean/coverage/runtime_state_refinement_map.jsonand invariant witnesses informal/lean/coverage/invariant_theorem_test_link_map.json.conformance_contract: executable checks tied to touched constraints are run and recorded.
Required evidence commands for checklist completion:
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo check --all-targets
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo clippy --all-targets -- -D warnings
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo test --test refinement_conformance -- --nocapture
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo test --test lean_invariant_theorem_test_link_map -- --nocapture
Performance-change review evidence example (bd-2pja4):
proof_safe_hot_path_review:
bead: bd-2pja4
review_scope:
- scheduler dispatch fast-path
- cancellation drain behavior
- obligation discharge paths
checklist:
scheduler_lane_contract: pass
lock_order_contract: pass
cancel_protocol_contract: pass
obligation_contract: pass
determinism_contract: pass
theorem_anchor_contract: pass
conformance_contract: pass
theorem_artifacts:
- formal/lean/coverage/runtime_state_refinement_map.json
- formal/lean/coverage/invariant_theorem_test_link_map.json
conformance_evidence:
- tests/refinement_conformance.rs
- tests/lean_invariant_theorem_test_link_map.rs
Optimization Constraint Sheet (Track-6 T6.1a / bd-3fooi)
Use these constraint IDs in optimization-task design notes and reviews. Each constraint is proof-linked and has an explicit detection path.
| Constraint ID | Derived from (proof/invariant anchor) | Actionable engineering rule | Detection path |
|---|---|---|---|
OPT-LOCK-001 | inv.structured_concurrency.single_owner, lock-order assumptions in formal/lean/coverage/runtime_state_refinement_map.json | Do not introduce new lock acquisition orderings; all multi-lock paths must preserve E -> D -> B -> A -> C. | Debug lock-order assertions + scheduler/runtime contention tests |
OPT-CANCEL-001 | inv.cancel.protocol, cancel-phase witnesses in src/types/cancel.rs | Optimizations may not collapse or reorder request -> drain -> finalize; cancellation-phase transitions must stay monotone. | tests/refinement_conformance.rs cancellation cases |
OPT-CANCEL-002 | inv.race.losers_drained | Any race/hedge fast path must still cancel and fully drain losers before completion is reported. | race/refinement conformance checks + trace replay assertions |
OPT-OBL-001 | inv.obligation.no_leaks, obligation theorem map in formal/lean/coverage/invariant_theorem_test_link_map.json | Never optimize by bypassing reserve/commit/abort boundaries; obligation resolution must remain total. | obligation leak/futurelock tests + invariant link-map tests |
OPT-DET-001 | deterministic replay assumptions in formal/lean/coverage/runtime_state_refinement_map.json | No ambient wall-clock or entropy on hot paths; use capability-provided time/randomness only. | replay/refinement tests + deterministic trace fingerprint checks |
OPT-HOT-001 | refinement obligations for scheduler/task hot paths | Micro-optimizations (allocation removal, queue reshaping, lock sharding) are allowed only when they preserve all above constraints. | checklist completion + required evidence command bundle |
Constraint usage rule for performance work:
- Every performance bead touching the listed hot paths must include cited constraint IDs (
OPT-*) in its notes/review payload. - A missing constraint citation is treated as an incomplete proof-impact review.
- Any violated constraint requires a blocker bead before merge/sign-off.
Proof-Guided Performance Opportunity Map (Track-6 support / bd-3cp69)
Use this map to choose optimization work that stays inside theorem-backed safety envelopes.
Prioritization rubric:
| Priority band | Expected impact | Proof coverage confidence | Risk class |
|---|---|---|---|
P0 | High (hot path, multi-workload benefit) | High | Medium |
P1 | Medium/high | High or medium | Medium |
P2 | Medium | Medium | Medium/high |
P3 | Low/uncertain | Low | High |
Opportunity map:
| Opportunity ID | Target surface | Expected impact | Allowed transformations | Prohibited transformations | Required conformance checks | Theorem / invariant anchors | Risk class |
|---|---|---|---|---|---|---|---|
PG-OPT-001 | src/runtime/scheduler/** dispatch fast path | Lower scheduler overhead and better tail latency under mixed ready/cancel load | queue layout tuning, branch elimination, cache-local metadata packing, lock-contention reduction that preserves lock order | changing cancel > timed > ready lane semantics, reordering multi-lock acquisition (E -> D -> B -> A -> C) | tests/refinement_conformance.rs scheduler/cancel cases; deterministic replay checks | OPT-LOCK-001, OPT-CANCEL-001, OPT-DET-001; formal/lean/coverage/runtime_state_refinement_map.json | Medium |
PG-OPT-002 | src/cancel/** + race/hedge combinator hot paths | Reduced cancellation-path latency and loser-drain overhead | reduce allocations on cancel/drain path, streamline witness construction, deduplicate wake/drain bookkeeping | collapsing request -> drain -> finalize phases, reporting completion before loser drain | race/hedge conformance cases; cancel protocol assertions in refinement suite | OPT-CANCEL-001, OPT-CANCEL-002; formal/lean/coverage/invariant_theorem_test_link_map.json | Medium |
PG-OPT-003 | src/obligation/**, src/runtime/obligation_table.rs | Lower obligation bookkeeping overhead in high-concurrency workflows | data-structure reshaping, indexed lookup improvements, lock-scoping reductions that preserve lifecycle semantics | bypassing reserve/commit/abort boundaries, deferred or best-effort obligation resolution | obligation leak/futurelock tests; invariant link-map checks | OPT-OBL-001, OPT-DET-001; formal/lean/coverage/invariant_theorem_test_link_map.json | Medium/high |
PG-OPT-004 | src/runtime/task_table.rs, src/runtime/sharded_state.rs | Better throughput via cache-local table operations and reduced contention | table compaction/locality improvements, sharding refinements with unchanged ownership semantics | introducing cross-shard ownership ambiguity, non-deterministic iteration order in state transitions | task/region lifecycle conformance checks; deterministic trace fingerprint checks | OPT-HOT-001, OPT-LOCK-001, OPT-DET-001; formal/lean/coverage/runtime_state_refinement_map.json | Medium |
Optimization-envelope template (required in performance beads):
proof_guided_optimization:
opportunity_id: PG-OPT-###
expected_impact: high|medium|low
risk_class: low|medium|high
allowed_transformations:
- <change type>
prohibited_transformations:
- <must not change>
theorem_links:
- <OPT-* constraint id>
- <coverage artifact path>
required_checks:
- rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo check --all-targets
- rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo clippy --all-targets -- -D warnings
- rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo test --test refinement_conformance -- --nocapture
evidence:
metrics_before: <artifact/link>
metrics_after: <artifact/link>
determinism_proof: <artifact/link>
Use this map as the default intake filter for Track-6 performance candidates:
- If a candidate cannot be mapped to one
PG-OPT-*envelope with explicit theorem linkage, do not start implementation. - If a candidate violates any prohibited transformation, create a blocker bead first and route through proof-impact review.
API Reference Orientation
Asupersync exposes a small, capability-focused public API. The canonical list of
public items lives in src/lib.rs re-exports. Use cargo doc --no-deps for full
rustdoc output.
Core types
Cx,Scope: capability context and region-scoped APIOutcome,OutcomeError,CancelKind,CancelReason,SeverityBudget,Time,PolicyRegionId,TaskId,ObligationId
Runtime
runtime::RuntimeBuilder: build and configure runtimesruntime::Runtime: runtime handle (block_on)
Cancellation + obligations
cancel/: cancellation protocol and propagationobligation/: linear obligations (permits/acks/leases)
Combinators
combinator/: join, race, timeout, hedge, quorum, pipeline patterns
Lab runtime + oracles
LabRuntime,LabConfig: deterministic testinglaboracles: quiescence, obligation leak, trace checks
RaptorQ integration
RaptorQConfig+EncodingConfig+DecodingConfigRaptorQSenderBuilder,RaptorQReceiverBuilderRaptorQSender,RaptorQReceiver,SendOutcome,ReceiveOutcome
Transport + security + observability
transport::SymbolSink/transport::SymbolStreamsecurity::SecurityContextfor signing/verifying symbolsCx::trace+observability::Metricsfor structured telemetry
Spork (OTP Mental Model on Asupersync)
Spork is the OTP-grade library layer being built on top of Asupersync's core invariants: structured concurrency, explicit cancellation, obligation linearity, and deterministic lab execution.
Think of Spork as:
- OTP ergonomics (supervision, naming, call/cast, link/monitor)
- mapped onto region ownership and outcome semantics
- with deterministic replay/debugging as a first-class feature
OTP -> Asupersync Mapping
| OTP concept | Spork / Asupersync mapping |
|---|---|
| Process | Region-owned task/actor (never detached) |
| Supervisor | Compiled restart topology over regions |
| Link | Failure coupling via supervision/escalation rules |
| Monitor + DOWN | Observation channel with deterministic ordering |
| Registry | Name leases as obligations (commit/abort, no stale ownership) |
| call/cast | Request-response vs fire-and-forget mailbox flows |
Capability Wiring Patterns (No Globals)
Spork is capability-driven: if you cannot reach it from Cx (or a handle derived
from Cx), you do not have authority to use it. This keeps the runtime free of
ambient singletons and makes lab execution deterministic and replayable.
Patterns:
-
Registry injection (capability-scoped naming):
- Construct a registry capability and pass it into your app spec.
- All child contexts spawned by the app inherit the same registry handle.
use asupersync::spork::prelude::*; use std::sync::Arc; let registry = NameRegistry::new(); let registry = RegistryHandle::new(Arc::new(registry)); let app = AppSpec::new("my_app") .with_registry(registry) .child(/* ... */); -
Remote spawning (explicit distributed authority):
- Attach a
RemoteCapto the rootCx(tests) or configure it via your runtime boundary. - Child scopes inherit the capability, so code does not reach for globals.
use asupersync::{Cx, remote::{RemoteCap, NodeId}}; let cx = Cx::for_testing() .with_remote_cap(RemoteCap::new().with_local_node(NodeId::new("origin-a"))); - Attach a
-
Trace / evidence plumbing (observability as a capability):
- Use
Cx::trace(structured) rather than stdout/stderr. - In the lab runtime, traces are collected into replayable buffers and child tasks inherit the trace context automatically.
- Use
-
Lab vs prod driver selection (determinism boundary):
- Use
lab::LabRuntimefor deterministic schedule exploration and oracle checks. - Use
runtime::RuntimeBuilderfor production configuration (drivers, pools, observability exporters).
- Use
Failure and Outcome Semantics
Spork uses Asupersync's four-valued outcome lattice:
Ok < Err < Cancelled < Panicked
Key rule: failed executions are immutable facts in traces. Recovery is modeled by starting new executions, not rewriting old outcomes.
Practical implications:
Errmay restart (policy + budget dependent)Cancelledtypically maps to stop (external directive)Panickedmaps to stop/escalate (never "healed" in place)
See:
docs/spork_glossary_invariants.md(INV-6, INV-6A)src/supervision.rs(Supervisor::on_failure)
Deterministic Incident Workflow (Spork-oriented)
- Reproduce with lab runtime using fixed seed/config.
- Capture trace/crash artifacts (canonical fingerprints + replay inputs).
- Inspect supervision decisions and ordering-sensitive events.
- Replay the same seed and verify identical decisions.
- Adjust policy/budget/topology and re-run until invariant holds.
This turns "flaky OTP behavior" into deterministic, auditable steps.
See:
docs/spork_deterministic_ordering.mddocs/spork_glossary_invariants.mdsrc/trace/crashpack.rssrc/lab/runtime.rs
Current Surface Status
The Spork layer is actively being built. For concrete API shape and module map:
docs/spork_glossary_invariants.md(Section 1 glossary, Section 6 API map)docs/spork_deterministic_ordering.md(mailbox/down/registry ordering contracts)
Tutorials
1) Getting Started: Structured Concurrency
use asupersync::{Cx, Outcome};
use asupersync::proc_macros::scope;
async fn worker(cx: &Cx) -> Outcome<(), asupersync::Error> {
cx.trace("worker start");
cx.checkpoint()?;
// ... do work ...
Outcome::ok(())
}
async fn root(cx: Cx) -> Outcome<(), asupersync::Error> {
scope!(cx, {
let _ = worker(&cx).await;
Outcome::ok(())
});
Outcome::ok(())
}
Key points:
- Always observe cancellation via
cx.checkpoint()in loops. - Leaving a region means all children are complete and drained.
2) Reliable Transfer: RaptorQ Sender/Receiver
use asupersync::config::RaptorQConfig;
use asupersync::raptorq::{RaptorQReceiverBuilder, RaptorQSenderBuilder};
use asupersync::transport::deterministic::{sim_channel, SimTransportConfig};
use asupersync::types::symbol::{ObjectId, ObjectParams};
use asupersync::Cx;
let cx = Cx::for_request();
let config = RaptorQConfig::default();
let (mut sink, mut stream) = sim_channel(SimTransportConfig::reliable());
let mut sender = RaptorQSenderBuilder::new()
.config(config.clone())
.transport(sink)
.build()?;
let mut receiver = RaptorQReceiverBuilder::new()
.config(config)
.source(stream)
.build()?;
let object_id = ObjectId::new_random();
let data = b"hello raptorq";
let _outcome = sender.send_object(&cx, object_id, data)?;
// In real systems, transmit ObjectParams alongside the payload metadata.
let params = /* ObjectParams derived from sender metadata */;
let decoded = receiver.receive_object(&cx, ¶ms)?;
assert_eq!(decoded.data, data);
Notes:
send_objectandreceive_objectuseCxfor cancellation.- For production, replace
sim_channelwith a realSymbolSink/SymbolStream.
3) Custom Transport: Implement SymbolSink / SymbolStream
Implement the transport traits to plug in a custom network backend.
use asupersync::transport::{SymbolSink, SymbolStream};
struct MySink { /* ... */ }
struct MyStream { /* ... */ }
impl SymbolSink for MySink {
// implement poll_send, poll_flush, poll_close
}
impl SymbolStream for MyStream {
// implement poll_next
}
Guidelines:
- Make cancellation checks explicit via
Cxat symbol boundaries. - Ensure
poll_closedrains buffers and releases resources.
4) Observability: Structured Tracing
cx.trace("request_start");
// ... work ...
cx.trace("request_done");
Use Cx::trace for deterministic lab traces and runtime logs. Avoid direct
stdout/stderr printing in core logic.
Tutorial: Build a Supervised Named Service (Spork, planned surface)
This walkthrough shows the intended flow for a small OTP-style service:
- define a GenServer-like process for stateful request handling
- register a stable name via registry lease semantics
- run under supervisor policy with restart budget
- use monitor/link-style failure observation/propagation
- validate behavior in lab runtime with deterministic replay
Status note:
- End-to-end Spork app wiring is still being finalized, but the core pieces below are real APIs you can use today.
Compile a deterministic supervisor topology:
use asupersync::{Budget, TaskId};
use asupersync::supervision::{
ChildSpec, RestartConfig, SupervisionStrategy, SupervisorBuilder,
};
let compiled = SupervisorBuilder::new("counter_root")
.child(
ChildSpec::new("counter_service", |_scope, _state, _cx| {
Ok(TaskId::new_ephemeral())
})
.with_restart(SupervisionStrategy::Restart(RestartConfig::default()))
.with_shutdown_budget(Budget::INFINITE.with_poll_quota(1_000)),
)
.compile()?;
assert_eq!(compiled.start_order.len(), 1);
# Ok::<(), asupersync::supervision::SupervisorCompileError>(())
Use lease-backed registry naming (no ambient globals, no stale-name ambiguity):
use asupersync::cx::NameRegistry;
use asupersync::{RegionId, TaskId, Time};
let mut registry = NameRegistry::new();
let mut lease = registry.register(
"counter",
TaskId::new_ephemeral(),
RegionId::new_ephemeral(),
Time::ZERO,
)?;
assert!(registry.whereis("counter").is_some());
// On graceful stop: resolve the obligation and remove discoverability.
lease.release()?;
registry.unregister("counter")?;
# Ok::<(), asupersync::cx::NameLeaseError>(())
Runnable minimal end-to-end example:
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_spork_integration_docs cargo run --example spork_minimal_supervised_app
This example lives at examples/spork_minimal_supervised_app.rs and demonstrates:
- app start under a supervisor-owned region
- supervised named GenServer start
- client
cast+call - cancel-correct shutdown (
request -> drain -> finalize) - deterministic lease/name cleanup (
whereis("counter") == Noneafter stop)
What to verify in lab tests:
- region close implies quiescence (no live descendants)
- no obligation leaks (reply/name leases resolve)
- restart policy behavior is deterministic for same seed
- monitor/down ordering is replay-stable
Session-Typed Obligations
The opt-in session-typed obligation surface lives in
src/obligation/session_types.rs. The code now publishes a rollout contract via
session_protocol_adoption_specs() so the typed API and the legacy
runtime-checked API stay unambiguous during adoption.
The currently supported runtime bridge is intentionally narrow: in-process
bounded mpsc transport via new_transport_pair() and the async session
transition methods. Cross-process/network bindings are still deferred.
First-wave protocol families:
send_permit: adopt first on explicit reserve/send-or-abort paths that already resolve aSendPermitthrough the obligation ledger.lease: adopt first on lease-backed naming/resource lifecycles with a single obvious holder and an explicit release path.two_phase: adopt first on reserve/commit-or-abort effect APIs where the fallback remainsObligationLedger::{commit, abort}.
Each adoption spec documents:
- Canonical states and transitions for migration review.
- Compile-time guarantees from typestate linearity.
- Runtime oracle complements that remain authoritative during rollout.
- Existing migration/compile-fail validation surfaces.
- Stable diagnostics fields required to debug typed-protocol adoption.
Current AA-05.3 validation surfaces:
- compile-fail doctests in
src/obligation/session_types.rs - typed/dynamic migration parity in
tests/session_type_obligations.rs - rollout contract/unit invariants in
src/obligation/session_types.rs
Direct rch rerun commands:
rch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo test --doc -- --nocapturerch exec -- env CARGO_TARGET_DIR=${TMPDIR:-/tmp}/rch_target_integration_docs cargo test --test session_type_obligations -- --nocapture
Troubleshooting rules:
- If a compile-fail example starts compiling, treat it as a typestate regression and keep the typed surface experimental.
- If typed and dynamic paths disagree on the valid resolution shape, treat
src/obligation/ledger.rsas authoritative and debug the typed wrapper before expanding rollout scope. - When diagnosing rollout issues, log and inspect the stable fields
channel_id,from_state,to_state,trace_id,obligation_kind,protocol, andtransition.
Current runtime-oracle complements:
src/obligation/ledger.rssrc/obligation/marking.rssrc/obligation/no_leak_proof.rssrc/obligation/no_aliasing_proof.rssrc/obligation/dialectica.rssrc/obligation/separation_logic.rssrc/cx/registry.rs
Adoption rule:
- Use the typed surface where the protocol boundary is already explicit.
- Keep the legacy dynamic surface as the fallback and audit/reference oracle.
- Do not start with open-ended adapter layers or flows that rely on implicit
cleanup by
Drop.
Restricted Static Leak Checker Pilot
The restricted AA-05.2 static-analysis pilot lives in
src/obligation/leak_check.rs. It does not attempt whole-Rust analysis.
Instead, it makes the structured-IR boundary explicit with
static_leak_check_contract() and returns a conservative graded-budget summary
through CheckResult::graded_budget.
What the pilot now guarantees on its covered surface:
- deterministic machine-readable diagnostic codes for CI/logging
- stable structured-IR locations for instruction and scope-exit findings
- remediation hints paired with each diagnostic class
- conservative peak outstanding-obligation counts on the same
BodyIR
What remains intentionally out of scope:
- loops/recursion without explicit IR unrolling
- interprocedural aliasing or ownership transfer not represented in
Body - ambient
Dropcleanup or runtime side effects outside the IR - Rust-source parsing, macro expansion, and dynamic dispatch analysis
Interpretation rule:
- A clean result means the supplied structured IR is balanced.
- It does not replace runtime enforcement for uncovered patterns.
src/obligation/ledger.rs,src/obligation/marking.rs,src/obligation/no_leak_proof.rs, andsrc/obligation/graded.rsremain the authoritative runtime/oracle surfaces.
Primary references:
docs/spork_glossary_invariants.mddocs/spork_deterministic_ordering.mdsrc/supervision.rssrc/cx/registry.rs
Evidence Ledger (Galaxy-Brain Mode)
For explainability, the runtime can emit an evidence ledger: a compact, deterministic record of why a cancellation/race/scheduler decision occurred. This is trace-backed and safe for audit/debugging.
Conceptual schema (stable, deterministic):
EvidenceEntry = {
decision_id: u64,
kind: "cancel" | "race" | "scheduler",
context: {
task_id: TaskId,
region_id: RegionId,
lane: DispatchLane
},
candidates: [Candidate],
constraints: [Constraint],
chosen: CandidateId,
rationale: [Reason],
witnesses: [TraceEventId]
}
Candidate = {
id: CandidateId,
score: i64,
delta_v: i64,
invariants: [InvariantCheck]
}
Renderer guidelines:
- One-line summary (decision + top reason).
- Optional expanded view: candidate table + constraint violations.
- Deterministic ordering of fields and candidates.
Runtime hooks (non-exhaustive):
- Cancellation: record why a task was cancelled vs drained.
- Race: record winner selection and loser-drain reasoning.
- Scheduler: record why task X was chosen over task Y (lane + score).
This ledger should be bounded in size and emitted via tracing/trace events, never stdout/stderr.
5) Distributed Regions (conceptual)
The distributed API is in-progress. The intent is to provide region-scoped
fault tolerance with explicit leases and idempotency. Today there are two
entrypoints: distributed for region snapshot/replication/recovery, and
remote for named computations with leases and idempotency. The remote
surface now has an explicit transport-agnostic contract in src/remote.rs:
message schemas, origin/remote state machines, idempotency, lease handling,
and capability gating are defined there. The core crate still separates
transport from protocol, so callers must attach a RemoteRuntime /
RemoteTransport implementation or use the deterministic no-runtime fallback.
All remote operations require RemoteCap from Cx (no closure shipping).
The shipped proof tier is protocol/state-machine plus two transport proofs.
remote_virtual_lifecycle_proof_exercises_runtime_transport_and_protocol keeps
the deterministic lab baseline. tests/remote_transport_lifecycle_contract.rs
adds a production-transport-backed loopback proof through
asupersync::net::TcpListener / TcpStream and the injected RemoteRuntime /
RemoteTransport boundaries. It covers accepted spawn/result delivery,
cancellation before ack, cancellation while running, lease renewal, lease
expiry, idempotent duplicate handling, send-failure cleanup, receive EOF,
delayed ack, malformed envelope cleanup, deterministic fallback, capability
denial, required structured logs, and trace emission. Deployment discovery,
TLS/authentication, WAN retry policy, and a frozen production wire format remain
adapter-specific responsibilities, not blanket core-runtime claims.
6) Remote Protocol Spec (Named Computations)
This section defines the current remote structured concurrency protocol.
It is transport-agnostic and uses the message types defined in src/remote.rs
(RemoteMessage, SpawnRequest, SpawnAck, CancelRequest, ResultDelivery,
LeaseRenewal).
Goals
- Deterministic, replayable message encoding.
- No closure shipping: only named computations.
- Explicit capability checks and computation registry validation.
- Idempotent spawns with exactly-once semantics (from the originator's view).
- Lease-based liveness with explicit expiry behavior.
6.1 Handshake (transport-level)
Before exchanging RemoteMessage envelopes, peers perform a transport-level
handshake:
Hello = {
protocol_version: "1.0",
node_id: "node-a",
clock_kind: "lamport" | "vector" | "hybrid",
registry_hash: "hex_sha256",
capabilities: ["remote_spawn", "lease_renewal", "cancel", "result_delivery"]
}
Rules:
- Major version mismatch -> connection rejected.
- Minor version mismatch -> allowed if receiver supports the sender's minor.
registry_hashis the hash of the named computation registry; mismatch is allowed but MUST be logged and MAY triggerUnknownComputationrejections.- Capability negotiation is deny by default: if the receiver does not list a capability, the sender MUST NOT depend on it.
RemoteTransport::send() implementations are responsible for enforcing
handshake completion and version checks.
6.2 Serialization Format (deterministic)
All protocol frames use canonical CBOR (RFC 8949) with deterministic map key ordering. Implementations MAY additionally expose JSON debug encoding for test vectors, but canonical CBOR is the wire format.
Canonical type mappings:
NodeId-> UTF-8 stringRemoteTaskId-> u64IdempotencyKey-> hex string"IK-<32 hex>"(lowercase)Time/Duration-> u64 nanosecondsRegionId,TaskId->{ "index": u32, "generation": u32 }RemoteInput/RemoteOutcome::Successpayload -> byte string (CBOR bytes)
6.3 Envelope Schema
RemoteEnvelope = {
version: "1.0",
sender: NodeId,
sender_time: LogicalTime,
payload: RemoteMessage
}
LogicalTime =
| { kind: "lamport", value: u64 }
| { kind: "vector", entries: [{ node: NodeId, counter: u64 }, ...] }
| { kind: "hybrid", physical_ns: u64, logical: u64 }
vector entries MUST be sorted by node for determinism.
6.4 Message Schemas
SpawnRequest
{
type: "SpawnRequest",
remote_task_id: u64,
computation: "encode_block",
input: <bytes>,
lease_ns: u64,
idempotency_key: "IK-...",
budget: { deadline_ns?: u64, poll_quota: u32, cost_quota?: u64, priority: u8 } | null,
origin_node: NodeId,
origin_region: { index: u32, generation: u32 },
origin_task: { index: u32, generation: u32 }
}
SpawnAck
{
type: "SpawnAck",
remote_task_id: u64,
status: { kind: "accepted" } |
{ kind: "rejected", reason: "UnknownComputation" | "CapacityExceeded" |
"NodeShuttingDown" | "InvalidInput" | "IdempotencyConflict",
detail?: "string" },
assigned_node: NodeId
}
CancelRequest
{
type: "CancelRequest",
remote_task_id: u64,
reason: CancelReason,
origin_node: NodeId
}
ResultDelivery
{
type: "ResultDelivery",
remote_task_id: u64,
outcome: RemoteOutcome,
execution_time_ns: u64
}
LeaseRenewal
{
type: "LeaseRenewal",
remote_task_id: u64,
new_lease_ns: u64,
current_state: "Pending" | "Running" | "Completed" | "Failed" | "Cancelled" | "LeaseExpired",
node: NodeId
}
CancelReason (minimal, deterministic encoding)
{
kind: "User" | "Timeout" | "Deadline" | "PollQuota" | "CostBudget" |
"FailFast" | "RaceLost" | "ParentCancelled" | "ResourceUnavailable" | "Shutdown",
origin_region: { index: u32, generation: u32 },
origin_task: { index: u32, generation: u32 } | null,
timestamp_ns: u64,
message: "static_string" | null,
cause: CancelReason | null,
truncated: bool,
truncated_at_depth: u32 | null
}
RemoteOutcome
{ kind: "Success", output: <bytes> } |
{ kind: "Failed", message: "string" } |
{ kind: "Cancelled", reason: CancelReason } |
{ kind: "Panicked", message: "string" }
Capability checks:
- Originator MUST hold
RemoteCapinCxto issue aSpawnRequest. - Remote node MUST validate computation name against its registry and
MUST reject unauthorized computations (
UnknownComputationorInvalidInput).
6.5 Idempotency Rules
- Each
SpawnRequestMUST include anIdempotencyKey. - Admission MUST atomically reserve a new key before canonical execution starts.
- While a record is retained, a duplicate request with the same key:
- If computation + input match: return an accepted acknowledgement correlated to the current attempt and attach it to the original canonical execution without re-executing; return the cached outcome if already terminal.
- If computation + input differ: respond with
SpawnAckrejectedIdempotencyConflict.
- In-flight records MUST remain resident for the operation lifetime and MUST NOT expire merely because execution exceeds the configured TTL.
- Completion starts the terminal-result retention TTL. Once that deadline elapses, or after the store is reset, the key may be admitted as a new request.
- A completion MUST identify the current canonical task for the key; delayed completions from an expired and replaced record generation are rejected.
6.6 Lease Rules
- The originator sets
lease_ns(default fromRemoteCap). - The remote node MUST send
LeaseRenewalwithin the lease window while running. - If the originator misses renewals and the lease expires, it transitions the
handle to
RemoteTaskState::LeaseExpired. Implementations MAY send aCancelRequestto request cleanup, but should not assume delivery.
6.7 Compatibility & Versioning
- Unknown fields MUST be ignored (forward compatibility).
- Missing required fields MUST reject the message.
- Major version mismatch => disconnect; minor mismatch => accept if supported.
sender_timekinds may differ; if incompatible, receivers treat causal order asConcurrentand proceed without ordering assumptions.
6.8 Test Vectors (JSON, debug-only)
For JSON debug vectors, input / output byte fields are base64 strings.
SpawnRequest
{
"version": "1.0",
"sender": "node-a",
"sender_time": { "kind": "lamport", "value": 7 },
"payload": {
"type": "SpawnRequest",
"remote_task_id": 42,
"computation": "encode_block",
"input": "AQID",
"lease_ns": 30000000000,
"idempotency_key": "IK-0000000000000000000000000000002a",
"budget": { "deadline_ns": 60000000000, "poll_quota": 10000, "cost_quota": null, "priority": 128 },
"origin_node": "node-a",
"origin_region": { "index": 12, "generation": 1 },
"origin_task": { "index": 98, "generation": 3 }
}
}
SpawnAck (accepted)
{
"version": "1.0",
"sender": "node-b",
"sender_time": { "kind": "lamport", "value": 9 },
"payload": {
"type": "SpawnAck",
"remote_task_id": 42,
"status": { "kind": "accepted" },
"assigned_node": "node-b"
}
}
ResultDelivery (success)
{
"version": "1.0",
"sender": "node-b",
"sender_time": { "kind": "lamport", "value": 14 },
"payload": {
"type": "ResultDelivery",
"remote_task_id": 42,
"outcome": { "kind": "Success", "output": "BAUG" },
"execution_time_ns": 1200000000
}
}
6.9 Current Integration Hooks
The runtime already includes hook points for integrating the protocol:
src/remote.rs:RemoteTransporttrait (send,try_recv)src/remote.rs:MessageEnvelope+RemoteMessagetypessrc/remote.rs:trace_events::*constants for structured tracingsrc/lab/network/harness.rs:encode_message/decode_messagedeterministic lab-only envelope store used as the simulated-network codec (not the production wire format)
These locations are the intended integration points for the real transport and wire codec.
Configuration Reference (high level)
Asupersync centralizes configuration in RaptorQConfig and related structs.
RaptorQConfig: primary configuration facadeEncodingConfig: symbol size, block size, repair overheadDecodingConfig: buffer caps, timeouts, verification flagsTransportConfig: buffer sizes, multipath policy, routingSecurityConfig: authentication mode and keyingTimeoutConfig: deadlines and time budgetsResourceConfig: pool sizes and backpressure limits
Use ConfigLoader for file/env based loading. Validate configs before use.
Troubleshooting
Obligation leak
A task completed while holding a permit/ack/lease.
- Ensure permits are always committed or aborted.
- Use lab runtime oracles to detect leaks deterministically.
Region close timeout
A region is waiting on children that never reach a checkpoint.
- Add
cx.checkpoint()in loops. - Avoid holding obligations across blocking waits.
Non-deterministic failures
Intermittent failures usually indicate schedule sensitivity.
- Prefer
LabRuntimewith a fixed seed for reproducibility. - Capture traces and replay to isolate schedule-dependent bugs.
- Use
lab::assert_deterministicto validate stable outcomes.
Slow shutdown or hanging tests
If shutdown never completes or tests hang:
- Ensure request/connection loops call
cx.checkpoint(). - Propagate budgets to child regions and timeouts to I/O.
- Confirm finalizers release obligations and permits.