Epic: Distributed application contract, runtime, and deployment lifecycle - #172
Conversation
|
Important Review skippedToo many files! This PR contains 250 files, which is 150 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (19)
📒 Files selected for processing (250)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Progress update (no K8s / tasks 14–19)Skipped deploy/Hops/XR work as requested. Finished the remaining non-K8s epic slice:
Latest tip: |
Latest push: auto-optimism + domain command transitionsFramework
e2e demos
Verify
|
ad60b26 to
8137264
Compare
Implements [[tasks/contract-lifecycle-tooling-2]]
Implements [[tasks/contract-lifecycle-tooling-2]]
Implements [[tasks/contract-lifecycle-tooling-2]]
Implements [[tasks/contract-lifecycle-tooling-2]]
Implements [[tasks/contract-lifecycle-tooling-3]]
Implements [[tasks/contract-lifecycle-tooling-3]]
Implements [[tasks/contract-lifecycle-tooling-3]]
Implements [[tasks/contract-lifecycle-tooling-9]]
Close the next-major surface identity cutover for task 9: application surfaces carry distinct eligible_roles (who may open) and schema_roles (privilege intersection), end-to-end across Surface IR, client manifest, protocol authority, projection deltas, CLI selectors, and TS replica validation/clone. Also land remaining application composition fixtures (contract-only artifact bin, runtime/unlisted packages, renamed-dependency trybuild) and remove the dual manifest owner path. Implements [[tasks/contract-lifecycle-tooling-9]]
Add the pure deployment-plan compiler for task 10: composable MountSelector presets (Full/Writer/Projector/QueryApi), Atomic collocation validation, explained capability closure with single schema-lifecycle owner, topology intent inventory, and byte-deterministic plan identity linked to ApplicationManifest. Implements [[tasks/contract-lifecycle-tooling-10]]
Add contract lifecycle snapshot flattening, path-level semantic diffs, distinct manifest-wire vs protocol decision classification, and no-write predecessor chain diagnostics with owner/path/expected/observed facts. Implements [[tasks/contract-lifecycle-tooling-4]]
Rename the standalone binary from dctl to distributed, add top-level DistributedArgs with contracts check/accept, and implement exact-scope accept transactions with staging, atomic replace, and rollback. Update in-repo product docs, workflows, skills, and generated client banners to invoke distributed. Implements [[tasks/contract-lifecycle-tooling-5]]
Introduce the versioned command dispatch boundary used by API-only and writer processes: object-safe CommandDispatcher, LocalCommandDispatcher over Service, and the task-20 approved HTTPS mTLS remote profile with loopback parity tests that strip forwarded role claims. Implements [[tasks/contract-lifecycle-tooling-11]] and [[tasks/contract-lifecycle-tooling-20]]
Introduce the task-12 process host skeleton: bind one DeploymentPlan process against explicit capability providers and an optional CommandDispatcher, failing closed when required capabilities or dispatch are missing. Implements [[tasks/contract-lifecycle-tooling-12]]
Add an explicit application composition module for e2e-ui surface and module identities, re-export it from the service crate, migrate read models to ReadModelCatalog, and update GraphQL surface registration for eligible/schema role split. Partial [[tasks/contract-lifecycle-tooling-13]]
Expose graphql_router_with_dispatcher as the host-facing mutation path, keep graphql_router_with_service as the local adapter implementation, and update dispatcher-not-configured diagnostics. Implements [[tasks/contract-lifecycle-tooling-11]]
Add make contracts-check, e2e-ui Makefile routing, an opt-in pre-push template, and a PR contracts job that other broad jobs can depend on. Implements [[tasks/contract-lifecycle-tooling-6]]
Add deterministic ClientProgramDescriptor building, asset hashing, and three-way Current / asset-only / incompatible classification, with program:<id> accept scopes. Implements [[tasks/contract-lifecycle-tooling-7]]
Verify application → plan → optional program predecessor links and release program classification for CTL closeout outside K8s/Hops work. Implements [[tasks/contract-lifecycle-tooling-8]]
Move process wiring into e2e_service::run_e2e_host with LocalCommandDispatcher at the host boundary, shrink the runner binary to env selection + host call, and check in selectable deployment-plan inventories for full/api/writer/ projector/mixed/split cuts. Implements [[tasks/contract-lifecycle-tooling-13]]
Replace the ~900-line central service.rs wiring file with explicit todo/chat/blob modules, a compose root listing them into one Service, GraphQL/surface exports, and a thin compatibility façade. Runner remains one-screen host invocation. This is the DX outcome of the application-composition epic for e2e-ui: module inventory is review-visible; infrastructure stays in host. Implements [[tasks/contract-lifecycle-tooling-13]]
Re-export compose/graphql APIs from lib.rs and keep client-surface tests next to graphql module. No intermediate service.rs re-export layer. Implements [[tasks/contract-lifecycle-tooling-13]]
Add LocalProjectionMountsBuilder so apps declare program+model+epoch only, Routes::for_aggregate to hide QueuedRepository wiring, and shared outbox/ consumer worker helpers. Rewrite e2e projection mounts and host loops to use them — product code keeps command intent, not topology ceremony. Implements [[tasks/contract-lifecycle-tooling-13]]
Derive client projection previews from command input, defaults, and row-policy claims when .applies is omitted. Add command_transition and sourced domain_commands witnesses so emit sets come from domain methods. Migrate todo/chat/blob to that path, thin blob move to game_id+direction, delete client simulate_move, and fix distributed client --surface to read roles from the manifest for gen-client.
Drop simulate-move unit test, stop requiring fat blob preview fields, and assert eligible/schema application roles on generated clients.
…tests Workers require tokio spawn/sleep — compile them only when a feature enables the optional tokio dep so default-feature checks pass. Rename integration test env! paths from CARGO_BIN_EXE_dctl to CARGO_BIN_EXE_distributed after the binary rename.
Defer --surface kind/name mismatches to the client compiler so CLI stderr keeps client.manifest.surface_mismatch. Use Session::new() in the default- feature typed guard dispatch test so session_with_role is not required without the graphql feature.
describe no longer wraps DistributedManifestEnvelope { project }; it emits
ApplicationManifest with name/modules/surfaces. Align CLI validation so
cli_manifest describe_emits_manifest_json matches the composition contract.
After the eligible/schema role split, ClientSurfaceIdentity expects eligible_roles (not legacy roles). Update GraphQL surface parity fixtures and the e2e suite helper so multi-role and anonymous application opens deserialize and authorize correctly.
Update typed_commands to expect auto-derived preview occurrences when .applies is empty. Silence svelte-check on the inventory config script, fix the HowItsBuilt dialog markup, and relax Playwright assertions that required pre-wire board/status paint (thin move + domain status constants are not client-derivable without a residual applies map).
Without domain status constants in auto-optimism, a double-click on Done is not client-suppressed before Eventual seals. Use one click and assert exactly one todos_complete request.
Reopen list membership depends on status, which auto-optimism does not constant-map. Assert Open-column paint after the delayed wire returns.
Add projection.pureReduces: named pure functions run over a known cache row at optimistic-apply time (fail closed if missing). Register blob.simulate_move (TS twin of domain simulate_move), wire the user command artifact, and restore pre-wire board paint in Playwright. Next: emit pureReduces from Rust TypedCommand + gen-client so generated artifacts stay durable across regenerate.
Wire TypedCommand.preview_reduce_known_record through the client manifest, CLI pure-reduce IR, and durable generated pures.ts so blob.simulate_move is no longer hand-patched into GENERATED commands. Blob move registers the domain pure (client twin at $lib/blob/simulate-move); createCommands spreads PURE_FUNCTIONS into the replica runtime.
8b265f4 to
367f191
Compare
Squash the complete stacked change set through PR #178 after GitHub's stack merge operation landed only the bottom layer. Includes PRs #172, #173, #174, #177, and #178. BREAKING CHANGE: the standalone CLI binary is named distributed instead of dctl, and application surface roles use the eligible/schema split.
|
Stack merge recovery: GitHub’s stack operation partially landed the stack. The complete stack through #178 is now preserved on main as aggregate squash b97f96a, whose tree matches the original #178 head exactly. This PR is superseded by that commit; its source branch is being retained. The prior broken main is preserved at recovery/github-stack-broken-main-20260813-031051. |
Summary
Implements the contract-lifecycle / application-composition epic (
tasks/contract-lifecycle-tooling-1) on top of the GraphQL epic baseline (tasks--graphql-qs-epic@681e17e).Landed in this branch
distributedCLI + contracts check/acceptdctl, check/accept transactionsRemaining (follow-up commits on this PR or stacked PRs)
Service(extend 11)service.rs/ runner collapse (finish 13)Branch base
681e17eis an ancestor of this branch.tasks--contract-lifecycle-tooling-1.Test plan
cargo test --test application_composition --all-featurescargo test --test application_plans --all-featurescargo test -p distributed --lib --features graphql -- client_manifestcargo test -p distributed --lib command_dispatch --features graphql,sqlitecargo test -p distributed --lib application::runtime_host --features graphqlcargo test -p distributed_cli --lib contracts::cargo check --manifest-path tests/e2e-ui/crates/service/Cargo.toml