Skip to content

Epic: Distributed application contract, runtime, and deployment lifecycle - #172

Open
patrickleet wants to merge 32 commits into
tasks--graphql-qs-epicfrom
tasks--contract-lifecycle-tooling-1
Open

Epic: Distributed application contract, runtime, and deployment lifecycle#172
patrickleet wants to merge 32 commits into
tasks--graphql-qs-epicfrom
tasks--contract-lifecycle-tooling-1

Conversation

@patrickleet

Copy link
Copy Markdown
Collaborator

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

Task Status Notes
2 Catalog / provenance done (prior)
3 Migration inventory done (prior)
9 ApplicationManifest / macros done + eligible/schema role wire cutover
4 Semantic snapshots / classification done snapshots, classification, chain diagnostics
10 DeploymentPlan / mount algebra done presets, Atomic collocation, capabilities
5 distributed CLI + contracts check/accept done bin rename from dctl, check/accept transactions
20 Remote dispatch trust contract done (approved profile) HTTPS mTLS service-identity profile constant + adapter
11 CommandDispatcher local/remote done (core) trait + local + remote loopback parity
12 RuntimeHost done (skeleton) capability/dispatcher bind, fail-closed
13 e2e service collapse started application composition root; service.rs still present

Remaining (follow-up commits on this PR or stacked PRs)

  • 6 CI/dev gates, 7 client-program descriptors, 8 CTL closeout
  • Full GraphQL engine decoupling from Service (extend 11)
  • Full e2e service.rs / runner collapse (finish 13)
  • 14–19 deploy render + Hops XR + live proof
  • 16 epic closeout

Branch base

  • Local GraphQL epic tip 681e17e is an ancestor of this branch.
  • Codex worktrees 2, 3, 9 were integrated into tasks--contract-lifecycle-tooling-1.

Test plan

  • cargo test --test application_composition --all-features
  • cargo test --test application_plans --all-features
  • cargo test -p distributed --lib --features graphql -- client_manifest
  • cargo test -p distributed --lib command_dispatch --features graphql,sqlite
  • cargo test -p distributed --lib application::runtime_host --features graphql
  • cargo test -p distributed_cli --lib contracts::
  • cargo check --manifest-path tests/e2e-ui/crates/service/Cargo.toml
  • Full workspace CI / e2e-ui suite

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 44f4e2b1-b603-49a1-bc28-5d63094ee789

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@patrickleet

Copy link
Copy Markdown
Collaborator Author

Progress update (no K8s / tasks 14–19)

Skipped deploy/Hops/XR work as requested. Finished the remaining non-K8s epic slice:

Task Status
11 GraphQL dispatcher host API done — graphql_router_with_dispatcher
6 CI/make contract gates done — make contracts-check, PR job, pre-push template
7 Client program descriptors done — build + 3-way compatibility
8 CTL local chain closeout done — app→plan→program (no render/XR)
13 e2e host collapse done for runner — one-screen run_e2e_host; plan inventories checked in; service.rs still holds handlers/GraphQL composition (next thin-down is optional)

Latest tip: 1887dfa

@patrickleet

Copy link
Copy Markdown
Collaborator Author

Latest push: auto-optimism + domain command transitions

Framework

  • Auto-derive client projection previews from input / defaults / row-policy claims when .applies is empty
  • CommandEventSet + command_transition / Routes::command_transition (emit set from domain witness)
  • #[sourced] generates domain_commands::* from public methods that call domain event recorders
  • distributed client --surface reads eligible/schema roles from the manifest (unblocks make gen-client)

e2e demos

  • todo / chat / blob modules: command_transition only — no .applies / hand-written events!
  • blob move input thinned to { game_id, direction }; removed client simulate-move twin
  • regenerated clients via make gen-client; walkthrough demos + README updated

Verify

  • cargo test -p e2e-service --lib client_surface
  • make check-client (e2e-ui)

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.
@patrickleet
patrickleet force-pushed the tasks--contract-lifecycle-tooling-1 branch from ad60b26 to 8137264 Compare August 4, 2026 05:11
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant