Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
306d912
feat: complete runtime protocol identity semantics
Jul 17, 2026
79b147d
test: select the intended state lock fixture
Jul 17, 2026
661703e
feat: bound operations with cross-process leases
Jul 17, 2026
4327c60
feat: add durable request journal and exec replay
Jul 17, 2026
1a26e65
refactor: simplify journal path validation
Jul 17, 2026
d74d0ac
test: freeze runtime wire protocol fixtures
Jul 17, 2026
b258d8d
style: format protocol golden tests
Jul 17, 2026
420ae4c
fix: replay completed requests beyond deadlines
Jul 17, 2026
a7b8d01
style: format completed replay paths
Jul 17, 2026
0608ab4
test: scope runtime state fixture directories
Jul 17, 2026
33d8b35
test: prove generation reconciliation recovery
Jul 17, 2026
45bc439
style: format generation recovery tests
Jul 17, 2026
cf29ac3
test: cover durable exec fault boundaries
Jul 17, 2026
18373b5
style: format exec fault tests
Jul 17, 2026
740e718
fix: preserve pending exec deadlines
Jul 17, 2026
56cb6c9
test: kill receipt-first completion processes
Jul 17, 2026
897f97d
test: generate complete state transition matrix
Jul 17, 2026
086667f
test: harden hostile state file boundaries
Jul 17, 2026
52d80c9
test: add deterministic provider fault matrix
Jul 17, 2026
c2b5bae
test: import fault feature from contract
Jul 17, 2026
37b1f2a
ci: require stable and MSRV runtime gates
Jul 17, 2026
92f24a9
fix: recover atomic state writes after crashes
Jul 17, 2026
0414c78
fix: expose state failpoint after module split
Jul 17, 2026
113d7f8
style: simplify staging file predicate
Jul 17, 2026
0afc1f0
test: cover cross-process generation races
Jul 17, 2026
ce07b16
feat: add capability-driven conformance profiles
Jul 17, 2026
2fd08d1
test: scope duplicate injection to race suite
Jul 17, 2026
cf63627
docs: explain profile-driven conformance
Jul 17, 2026
da7514c
test: require behavior-level provider evidence
Jul 17, 2026
f1161b2
docs: make Docker certification gate explicit
Jul 17, 2026
e680546
fix(exec): forward durable effective deadline
Jul 17, 2026
91a1b4c
docs(exec): define durable provider deadline
Jul 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: CI

on:
pull_request:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

concurrency:
group: runtime-ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: "1"

jobs:
linux:
name: Linux / Rust ${{ matrix.toolchain }}
runs-on: ubuntu-24.04
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
toolchain:
- "1.85.0"
- stable

steps:
- name: Check out exact commit
uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
components: clippy, rustfmt

- name: Verify formatting
run: cargo fmt --all --check

- name: Run unit, integration, process, and golden tests
run: cargo test --locked --all-targets

- name: Reject Clippy warnings
run: cargo clippy --locked --all-targets -- -D warnings

- name: Reject rustdoc warnings
env:
RUSTDOCFLAGS: -D warnings
run: cargo doc --locked --no-deps
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "a3s-runtime"
version = "0.2.0"
edition = "2021"
rust-version = "1.85"
description = "Provider-neutral execution contract and client for A3S runtimes"
license = "MIT"
repository = "https://github.com/A3S-Lab/Runtime"
Expand All @@ -14,7 +15,7 @@ serde_json = "1"
sha2 = "0.10"
tempfile = "3"
thiserror = "2"
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] }
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread", "sync", "time"] }

[target.'cfg(unix)'.dependencies]
libc = "0.2"
92 changes: 63 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ their owning applications.
cross-process locks without following symbolic-link state boundaries
- **Logs and Exec**: Expose generation-bound log and exec surfaces only when a
provider reports the corresponding capability
- **Conformance Suite**: Exercise the common Task and Service lifecycle against
provider-owned disposable resources
- **Capability-Driven Conformance**: Always run complete Base and Recovery
profiles, automatically activate advertised optional profiles, and reject
missing fixtures, incomplete evidence, or provider inventory leaks

## Runtime Model

Expand Down Expand Up @@ -82,6 +83,8 @@ A unit specification includes:
- an optional digest binding caller-owned execution semantics.

All wire records use explicit schema identifiers and reject unknown fields.
`RuntimeUnitSpec` v2 makes the ephemeral-storage quota optional; a provider
needs that resource control only when a specification requests the quota.
Protocol validation occurs before state reservation or provider work.

### Observations
Expand Down Expand Up @@ -110,8 +113,14 @@ The `RuntimeClient` contract exposes:

Each mutating request carries its own request ID and optional absolute deadline.
An exact retry returns or reconstructs the same logical result. Reusing a
request ID with different content fails with `RequestConflict`. A deadline is
checked independently before provider dispatch.
request ID with different content fails with `RequestConflict`. A completed
receipt remains replayable after its original deadline and after later
lifecycle operations; an expired pending request is not redispatched. A
deadline is checked independently before new provider work. On the first exec
reservation, Runtime persists the smaller of `started_at + timeout_ms` and the
optional caller deadline. `RuntimeDriver::exec` receives that effective
absolute deadline in `deadline_at_ms`, and every pending replay receives the
same value, so retrying cannot restart or extend the execution window.

## Capabilities

Expand All @@ -132,8 +141,12 @@ provider integration:

```text
state root/
├── locks/ # per-unit cross-process locks
└── units/ # atomic JSON records and request receipts
├── locks/ # short per-unit record locks
├── operations/ # full-operation cross-process leases
└── units/
└── <unit-key>/
├── record.json # active unit record
└── requests/ # one durable receipt per request ID
```

The store uses a SHA-256 storage key derived from the validated unit ID. Records
Expand Down Expand Up @@ -166,34 +179,52 @@ ManagedRuntimeClient

Provider `apply` must be idempotent for the supplied unit ID and generation.
After an ambiguous acknowledgement, a repeated call must discover or converge
the same resource rather than create another one. Provider-specific labels,
SDK handles, container fields, and transport details stay behind the driver.
the same resource rather than create another one. A successful generation
handoff must retire all older provider generations and verify that exactly the
current resource remains; interrupted handoffs finish on exact retry.
Provider-specific labels, SDK handles, container fields, and transport details
stay behind the driver.

## Conformance

Provider repositories should run `verify_runtime_provider` against real,
disposable infrastructure:
Production provider repositories should implement `RuntimeConformanceFixture`
and run `verify_runtime_profiles` against real, disposable infrastructure:

```rust,ignore
use a3s_runtime::{verify_runtime_provider, RuntimeConformanceCase};

let case = RuntimeConformanceCase {
task_apply,
task_remove,
service_apply,
service_stop,
service_remove,
};

let report = verify_runtime_provider(client.as_ref(), &case).await?;
assert!(report.task.converges(&task_spec));
assert!(report.service.converges(&service_spec));
use a3s_runtime::{verify_runtime_profiles, RuntimeConformanceFixture};

let fixture: &dyn RuntimeConformanceFixture = provider_fixture;
let report = verify_runtime_profiles(client.as_ref(), fixture).await?;
assert_eq!(report.inventory_before, report.inventory_after);
```

The shared suite validates capability matching, exact apply replay, inspection,
stop replay, removal replay, and generation-aware absence for both lifecycle
classes. Provider repositories remain responsible for crash injection,
reconstruction, provider-specific security, and resource-leak tests.
The mandatory Base profile covers successful, failed, and timed-out Tasks;
Service apply, inspect, stop, and removal; exact replay; generation conflicts;
and tombstones. Recovery is mandatory for every production provider.
Networking, Mounts, Health, Resources, Logs, Exec, Security, Outputs, and
Evidence activate from reported capabilities. A fixture must return the shared
stable case IDs and capability claims for every activated profile, perform
cleanup even after a failed profile, and prove that its canonical provider
inventory returned to the pre-run baseline.

Profile requirements expand to one case ID per advertised behavior rather than
accepting a generic family-level claim. For example, every reported network
mode, mount kind, health probe, and resource control activates its own
configuration and behavioral cases. `NetworkMode::Service` activates both TCP
and UDP because the current protocol has no narrower transport-protocol
capability. Logs separately require filtering, total order, cursor resume,
same-timestamp handling, limits, explicit rotation gaps, terminal retention,
and bounded large records.

`verify_runtime_provider` remains available as the lower-level successful Task
and Service lifecycle check. It is not, by itself, production certification.
Provider-specific fixtures still own real daemon restart, external deletion,
security, resource-behavior, and destructive cleanup mechanics; the shared
harness owns activation, required case/claim coverage, Base semantics, and the
zero-inventory-delta oracle.

See the [deep test plan](docs/deep-test-plan.md) for the full contract,
durability, real-provider, fault, performance, soak, and A3S OS release gates.

## Architecture

Expand All @@ -213,8 +244,11 @@ managed durability and validation
provider driver and external runtime
```

See [ADR 0001](docs/adr/0001-general-runtime-contract.md) for the ownership,
identity, retry, and migration decisions behind the contract.
See [ADR 0001](docs/adr/0001-general-runtime-contract.md) for the general
ownership model, [ADR 0002](docs/adr/0002-complete-protocol-and-operation-semantics.md)
for the completed protocol and operation semantics, and the
[implementation plan](docs/implementation-plan.md) for the dependency-ordered
delivery tasks.

## Development

Expand Down
Loading
Loading