Source commit: 309831e1e021f962c118452336776fd9a94025f9 Public tree identity: sha256:6fa95c1745579bd6256dbeb3d476db0b07c2f24aa9213b0f7783ce1adfc8aca5
27 KiB
Disasmer MVP Acceptance Criteria
Every criterion below must be covered by automated verification; when behavior crosses coordinator, node, CLI, DAP, browser, storage, or network boundaries, that verification should include integration coverage. The final product should be exercised as much as possible as if it were live infrastructure: separate services, real process boundaries, real auth boundaries, real quota decisions, realistic networking, realistic retention/GC, and realistic failure behavior. Because the main environment is NixOS, the live-infra shape can be credibly simulated with NixOS-based service and VM setups.
Windows-specific runtime behavior does not need to be validated by the main acceptance suite for the MVP. The Windows implementation should still be best-effort correct, kept behind clean interfaces, avoid false sandboxing claims, and be structured so it can be validated and fixed independently later.
These criteria intentionally avoid implementation detail. Architecture, protocol, and milestone details live in the MVP and feasibility documents.
Important reading note: an item marked Partial or Open does not automatically mean new product code, a new feature, or even actual implementation work is required. It means the item must become a proven fact about the system. Many items describe facts that may already be true, or should have been fundamental invariants from the start, but still need stronger evidence at the required boundary. Before adding implementation, first check whether the fact is already true in the current system and prefer proving, documenting, or tightening that existing behavior over duplicating capability or overengineering a parallel mechanism.
Status Prefixes
- Passed: implemented with focused automated/source-scan coverage or a narrow source-level guard in the current tree; this is not final MVP acceptance until the full release gates run.
- Partial: modeled or covered at unit/smoke/source-scan level, but missing live boundary coverage, packaging coverage, hosted coverage, or end-to-end acceptance.
- Open: not implemented, not yet wired through the required boundary, or not yet covered by an appropriate acceptance gate.
For release-blocker lists, Passed means the listed blocker condition is currently guarded as absent; Open means absence has not been proven by the release gate yet.
1. Public product bar
-
Passed: A user can run Disasmer locally with the open-source runtime, coordinator, node runtime, SDK, CLI, and VS Code extension.
-
Passed: A user can use the hosted coordinator as a control plane without receiving arbitrary hosted compute.
-
Passed: Public-release dry-run wording must not imply that
disasmer.michelpaulissen.com:9443runs the standalone public/open-source coordinator. The default operator is the private hosted coordinator fromprivate/hosted-policy;publicrefers to public repo/assets, selected-user reachability, and the public client protocol used by released binaries. -
Partial: Public-release dry-run evidence validates both coordinator implementations: the private hosted coordinator as the live default operator, and the standalone public/open-source coordinator as the local/self-hosted coordinator shipped in the public release assets. Current public-tree/assets preparation is fresh for the current acceptance commit, but the live service, Forgejo Release, and e2e evidence must be rerun for that commit.
-
Passed: A user can attach their own node and run actual build work on that node.
-
Passed: The flagship build workflow is expressed as Rust source code, not CI YAML.
-
Passed: Public-facing docs and repo text avoid naming any external launch forum or traffic source as a product goal.
-
Passed: User-facing docs, UI, CLI, and plan language use
community tierconsistently. -
Passed: The public story remains: one virtual process, many virtual threads/tasks, ordinary source-level debugging, and local-first distributed execution.
2. Repository and release split
-
Passed: Public source can be produced by excluding
private/**without breaking the open-source runtime, local coordinator, node runtime, CLI, SDK, or VS Code extension. -
Passed: Hosted-only Authentik/OIDC, community quota enforcement, hosted zero-capability limits, abuse tooling, and admin controls live in
private/**or equivalent filterable modules. -
Passed: Public crates expose clear policy/auth interfaces that private hosted modules implement.
-
Passed: The open-source coordinator remains useful for local clouds, trusted team use, and VPN deployments without hosted-service-only modules.
-
Passed: Hosted and self-hosted nodes use the same node runtime code path; hosted restrictions are policy modules, not a separate node implementation.
3. Coordinator state model
-
Passed: Postgres is used only for data that must survive coordinator restart.
-
Passed: Tenants, users, projects, node identities, credentials, source-provider configuration, and durable service policy records persist across coordinator restarts.
-
Passed: Active virtual processes, live virtual threads, live scheduler state, debug epochs, ephemeral VFS manifests, and transient artifact locations may live in RAM for MVP.
-
Passed: Coordinator restart requires active virtual processes to restart rather than pretending live execution survived.
-
Passed: Nodes reconnect cleanly after coordinator restart and cannot continue an old virtual process under stale coordinator state.
-
Passed: Persistent project state remains intact after coordinator restart.
4. Auth and identities
-
Passed: Browser login works through the hosted identity flow.
-
Partial: Public released binaries default to a real human browser/account flow for
disasmer login --browser: source and local binary smoke cover the browser path, account/login handoff, and local callback behavior, and raw JSON login-plan output is opt-in or diagnostic. This remains partial until the current Forgejo Release binaries are published and rerun through the hosted service flow. -
Passed: CLI login works for human users without manually copying long-lived secrets.
-
Passed: Agent/worker authentication supports public-key identity without requiring browser interaction on every run.
-
Passed: Node enrollment converts a short-lived enrollment grant into a scoped long-lived node identity.
-
Passed: User OAuth/session tokens are never passed to nodes as task credentials.
-
Passed: Node identity, user identity, project identity, and task identity are distinct in coordinator authorization decisions.
5. CLI behavior
-
Passed:
disasmer rundefaults to the current project directory. -
Passed:
disasmer run --project <path>runs a project other than the current directory. -
Passed:
disasmer runuses the hosted coordinator implicitly when the user is logged in and no local override is selected. -
Passed:
disasmer run [entry]selects a named entrypoint while preserving a sensible default when omitted. -
Passed: One project can define multiple entrypoints such as build, test, package, release, watch, or custom workflows.
-
Passed:
disasmer node attachauto-detects OS, architecture, environment backends, source providers, and ordinary node capabilities. -
Passed:
disasmer node attach --cap ...remains available for explicit overrides and advanced cases. -
Passed: CLI commands are usable non-interactively by agents once their public-key identity is enrolled.
6. Project and bundle model
-
Passed: A project works without requiring a hand-written configuration file for the common case.
-
Passed:
envs/<name>/Containerfileorenvs/<name>/Dockerfiledefines an environment named<name>. -
Passed: Source code can reference discovered environments with
env!("name"). -
Passed: Missing environment references produce clear build/editor diagnostics.
-
Passed: Bundle identity changes when Wasm code, task ABI, environment recipe, source-provider manifest, or selected inputs change.
-
Passed: Bundles do not embed full container images by default.
-
Passed: Generated environment and bundle metadata are inspectable by the user.
7. Source-provider modularity
-
Passed: Git support is an optional source-provider module included by default.
-
Passed: The VFS core does not require Git as a hard dependency.
-
Passed: Users can add non-Git source providers without rewriting the VFS core.
-
Passed: Source snapshot creation can run as a node task instead of requiring coordinator filesystem or Git access.
-
Passed: Coordinator-run code remains zero-capability and does not directly inspect the user checkout.
-
Passed: A task can wait for any capable node to pick up source-preparation work rather than failing immediately when the coordinator lacks source access.
8. Wasmtime and task execution
-
Passed: Disasmer programs compile to Wasm and run under Wasmtime on node runtimes.
-
Passed:
#[disasmer::main]defines a virtual-process entrypoint. -
Passed:
#[disasmer::task]defines named, remotely startable task entrypoints. -
Passed:
spawn::task(...).start().awaitcreates a debugger-visible virtual thread/task. -
Passed:
TaskHandle::join().awaitreturns small serialized results or runtime handles. -
Passed: Task arguments reject host-only values such as raw pointers, references, local files, sockets, and process handles.
-
Passed: Large data crosses task boundaries through handles such as
SourceSnapshot,Blob,Artifact, or VFS references. -
Passed: Small data can move into and out of tasks without awkward user ceremony.
9. Native command execution
-
Passed: Native commands are invoked from Wasm tasks through node host capabilities.
-
Passed: A virtual process remains Wasmtime-backed even when a task calls into the node to run shell/native commands.
-
Passed: Hosted coordinator control-plane code cannot run native commands or containers.
-
Passed: Open-source/private deployments can allow normal local-node command capabilities by default.
-
Passed: Command stdout and stderr are associated with the virtual thread that started the command.
-
Passed: Native command execution is denied when the selected node or task lacks the required capability.
10. Linux execution backend
-
Passed: Linux nodes can materialize Containerfile-based environments with rootless Podman.
-
Passed: Linux nodes can run command tasks inside the selected environment.
-
Passed: Linux command outputs can be staged into the VFS artifact namespace.
-
Passed: Local Linux source checkouts stay local when the local node can run the task.
-
Passed: Linux command tasks participate in virtual process lifecycle, cancellation, logging, and debug freeze/resume behavior.
11. Windows execution backend
-
Passed: Windows node support is represented by the same node protocol and capability model as Linux.
-
Passed: Windows command execution is clearly labeled as user-attached development execution, not production-grade untrusted sandboxing.
-
Passed: Windows sandboxing exists behind an explicit backend interface or stub.
-
Passed: Windows-specific code does not infect the Linux backend or generic node runtime model.
-
Passed: Windows tasks can publish artifacts through the same VFS/artifact APIs once the backend is enabled.
12. Scheduler and placement
-
Passed: Scheduler placement is based on logical environment requirements, not hard-coded runner names.
-
Passed: Scheduler prefers nodes with the source snapshot, environment cache, dependency cache, and required artifacts already local.
-
Passed: Scheduler avoids network transfer when a compatible local/warm node exists.
-
Passed: Scheduler can place a task on any capable node when the program asks for capability rather than a specific node.
-
Passed: Scheduler failure messages explain which capability, environment, source, or connectivity constraint could not be satisfied.
-
Passed: The scheduler is a replaceable module with a simple default implementation.
13. QUIC transport and networking
-
Passed: QUIC transport is behind a transport abstraction.
-
Passed: The MVP default uses a Rust-native QUIC implementation.
-
Passed: Node-to-node bulk transfer uses authenticated direct connections when possible.
-
Passed: The coordinator can aid rendezvous but does not silently relay bulk artifact/source/blob data.
-
Passed: Failed direct connectivity results in a clear placement/export/sync error.
-
Passed: Each data-plane transfer is scoped to tenant, project, process, object, and authorization context.
14. VFS and local-first behavior
-
Passed:
flush()publishes metadata and visibility information without uploading large bytes by default. -
Passed:
sync()is explicit and may move bytes according to user code or configured policy. -
Passed: A local build from an existing checkout does not create a full-repo tarball by default.
-
Passed: Coordinator-routed compiler file reads are not part of the normal local-first path.
-
Passed: Source bytes, build-cache bytes, and artifact bytes remain node-local unless a consumer/export/sync/download path requires movement.
-
Passed: VFS overlays provide task-local writes and published manifest epochs.
-
Passed: Parent/downstream tasks can consume artifacts after the producing task flushes them.
-
Passed: Same-node artifact reuse avoids unnecessary copying where the platform supports it.
15. Artifact lifecycle and downloads
-
Passed: Artifacts and other large blobs are best-effort retained on nodes by default, not durable coordinator objects.
-
Passed: Artifact metadata can exist after
flush()even when artifact bytes are only present on a retaining node. -
Passed: Artifact bytes may be garbage collected according to node retention policy unless explicitly exported or stored by user code.
-
Passed: Loss of a node-local unsynced artifact is surfaced as artifact unavailability, not silent recovery.
-
Passed: The operator/control panel can expose a download button for a best-effort retained artifact.
-
Passed: Artifact download streams from a retaining node or explicit user-provided storage path, not from default durable coordinator artifact storage.
-
Passed: A download action is not created when the artifact cannot be downloaded within current retention, location, size, authorization, or community tier limits.
-
Passed: A failed download-link creation returns a clear error before showing a user-facing link.
-
Passed: Artifact download links are authenticated, authorized, scoped, and not usable merely by guessing a URL.
-
Passed: Cross-tenant and cross-project artifact downloads are denied even if an artifact ID or link-like value is known.
-
Passed: Download usage is accounted against the relevant limits before and during streaming.
16. Checkpoint and restart semantics
-
Passed: Task restart is based on task entrypoint, serialized args, environment handle, and VFS/artifact checkpoint boundaries.
-
Passed: The MVP does not claim live stack migration, live socket checkpointing, or arbitrary hot code replacement.
-
Passed: Restarting a failed or selected task after source edit works when task compatibility checks pass.
-
Passed: Compatibility failure requires a whole virtual-process restart with a clear message.
-
Passed: Unflushed task-local filesystem changes are discarded or explicitly preserved according to documented policy.
-
Passed: Best-effort retained artifacts can help restart, but restart never depends on pretending ephemeral artifacts are durable.
17. Debugging and DAP
-
Passed: VS Code F5 can launch a Disasmer virtual process.
-
Partial: F5/live-services starts the coordinator-side virtual process without requiring a node at launch; when that process reaches a virtual task with capability/environment requirements, the coordinator places that task on a capable node. The DAP adapter must not secretly start a worker node or make node availability a prerequisite for starting the coordinator-side process. Missing capable nodes must surface as normal task placement/unavailable-capability state. This is covered by local coordinator/worker DAP smoke, quick-test binary smoke, and live private-hosted-coordinator protocol smoke against
disasmer.michelpaulissen.com:9443, but remains partial until the released public-repo assets and VS Code/DAP path are rerun end to end against the live private hosted coordinator. -
Passed: The debugger presents one process with multiple virtual threads/tasks.
-
Passed: Breakpoints in
mainand spawned task code stop the virtual process. -
Passed: A breakpoint in one virtual thread creates a Debug Epoch for the whole virtual process.
-
Passed: Wasm tasks and controlled native-command tasks participate in all-stop debug behavior.
-
Passed: If a node cannot freeze a controlled task, the debugger reports failure instead of claiming all-stop succeeded.
-
Passed: The debugger shows coherent virtual process identity, virtual thread names, stack frames, task args, Disasmer handles, command status, recent output, and artifact references for the current flagship demo.
-
Passed: The normal debugger Variables pane exposes launchable MVP variable categories: task arguments, task return values, target structured fields, selected Rust locals around Disasmer API calls, runtime-captured Wasmtime frame locals,
Artifact,SourceSnapshot, andBlobhandles, current command spec/status, VFS mounts, and recent stdout/stderr tail. -
Passed: Top-level source locals around Disasmer API calls are visible from virtual-thread runtime state in the shippable DAP path. This is implemented outside
experiments/**and is not satisfied by hardcoded experiment-local variable mapping. -
Passed: The shippable node/DAP path captures real Wasmtime frame-local slots from guest-debug runtime state and exposes them through a normal DAP Variables scope. This is implemented outside
experiments/**; the experiment remains proof only, not implementation basis. -
Passed: Arbitrary Rust locals use best-effort source metadata when full value snapshots are unavailable, and variables that cannot be inspected are reported clearly while task args and handles remain visible.
-
Passed: The debugger exposes per-task stdout/stderr tails, VFS/artifact state, and command status in normal scopes or optional Disasmer views without requiring users to understand node IDs, transport links, VFS manifests, or environment-cache internals.
-
Passed: Continue resumes every frozen participant in the Debug Epoch.
-
Passed: Pause requests stop the whole virtual process, not just the currently selected thread.
-
Passed: Restart selected/failed task is available from the debugging workflow.
-
Passed: The DAP adapter targets VS Code first while remaining ordinary enough for other DAP clients to integrate later.
-
Passed: The launch-critical DAP surface required by the MVP is implemented and acceptance-tested:
initialize,launch/attach,setBreakpoints,configurationDone,threads,stackTrace,scopes,variables,continue,pause,next/step-over at probe granularity,disconnect,stoppedevents, andcontinuedevents.
18. VS Code extension
-
Passed: The extension discovers environment resources and provides useful diagnostics for
env!(...)references. -
Passed: The extension builds or refreshes the Disasmer bundle before launch/debug when needed.
-
Passed: Normal VS Code thread, breakpoint, stack, output, continue, pause, restart, and Variables-pane flows work for the flagship demo, including selected source-local values around Disasmer API calls.
-
Passed: Disasmer-specific views show nodes, virtual processes, logs, artifacts, and inspector state without replacing the normal debugger UX.
-
Passed: Error messages guide the user toward missing nodes, missing environments, quota limits, unavailable artifacts, or failed debug freezes.
19. Operator/control panel
-
Passed: The MVP includes protocol and state foundations for immediate-mode operator panels.
-
Passed: Program-defined panels use built-in typed widgets only.
-
Passed: User-provided panel content cannot inject custom HTML or JavaScript.
-
Passed: Panel state is scoped to tenant, project, and virtual process.
-
Passed: Panel events are typed, rate-limited, and delivered back to the virtual process only when allowed.
-
Passed: A stopped debug process shows the last rendered panel state without executing program UI logic.
-
Passed: Control-plane actions such as restart, cancel, debug, and artifact download can remain available while program UI events are disabled.
20. Hosted/community service policy
-
Passed: Community hosted mode can create or use a project, attach user nodes, run tasks on those nodes, debug, and view logs/artifact metadata.
-
Passed: Community hosted mode does not provide arbitrary hosted native commands or hosted containers.
-
Passed: Hosted zero-capability Wasm has strict fuel, memory, wall-clock, state, log, and event limits.
-
Passed: Hosted community policies are enforced before work starts, not only after resource usage is observed.
-
Passed: Quota failures are explicit and actionable.
-
Passed: Public hosted endpoints treat users, nodes, programs, logs, artifacts, UI events, source manifests, and capabilities as hostile input.
21. Authorization and tenant isolation
-
Passed: Every user-owned or project-owned object has tenant ownership.
-
Passed: Users cannot list, inspect, debug, download, or mutate another tenant's nodes, processes, logs, artifacts, projects, or panel state.
-
Passed: Nodes cannot claim tasks or publish artifacts outside their authorized tenant/project/process scope.
-
Passed: Debug attach requires explicit project permission.
-
Passed: Debug memory/variable/handle reads are authorized and scoped.
-
Passed: Artifact provenance includes producer task, process, project, and node identity.
-
Passed: Tenant isolation failures are treated as release blockers.
22. Abuse and resource limits
-
Passed: API calls, spawns, logs, metadata, debug reads, UI events, rendezvous attempts, and artifact downloads are subject to resource policy.
-
Passed: Log output is capped, backpressured, and associated with the producing virtual thread.
-
Passed: Large task arguments are rejected or warned before causing accidental distributed copies.
-
Passed: Community hosted tasks cannot use network, secrets, host filesystem, native commands, containers, inbound ports, or arbitrary syscalls.
-
Passed: Operator panels cannot collect passwords or initiate OAuth-like flows inside user-defined widgets.
-
Passed: Admin controls can suspend abusive tenants, revoke node credentials, and stop active hosted processes.
23. Documentation and examples
-
Passed: The README shows the build-system workflow with Rust source, environments, attached nodes, debugging, and artifacts.
-
Passed: Docs explain
flush()versussync()without implying default durability. -
Passed: Docs explain that artifacts are best-effort retained unless explicitly exported or stored.
-
Passed: Docs explain node trust, user-attached execution, and Windows sandbox limitations honestly.
-
Passed: Docs explain hosted/community limits without framing them as a compute giveaway.
-
Passed: Docs explain how agents authenticate with public keys.
-
Passed: Docs explain how to add non-Git source-provider support.
-
Passed: Example code avoids coordinator-side filesystem, Git, shell, or container assumptions.
24. Flagship demo acceptance
-
Passed: A clean developer setup can install the CLI and VS Code extension.
-
Passed: The user can sign in, create or select a project, and attach at least one Linux node.
-
Passed: The demo project recognizes
env!("linux")and, when available,env!("windows"). -
Passed: Pressing F5 starts one virtual process through the Disasmer debugger.
-
Partial: The flagship demo requires an explicitly attached/running worker node for command/container-style work; the coordinator-side process remains the limited orchestration path and worker placement is implicit in task launch requirements, not a user-facing direct scheduler call. Local quick-test binaries prove this against a fresh coordinator, and the live private hosted coordinator accepts the current
launch_task/ worker-assignment protocol; hosted dry-run acceptance still requires the released public-repo assets and VS Code/DAP path to be rerun end to end. -
Passed: The Linux build task runs as a node-hosted command from a Wasmtime-backed virtual task.
-
Passed: A second task can run concurrently as another virtual thread when a capable node is available.
-
Passed: A breakpoint in a spawned task all-stops the virtual process.
-
Passed: Task args, command status, logs, and artifact handles are inspectable through synthetic runtime scopes or Disasmer views.
-
Passed: The flagship demo lets the user inspect selected locals around Disasmer API calls, task args, command status, logs, stdout/stderr tails, VFS mounts, and artifact handles from the normal VS Code debugging experience.
-
Passed: A failed task can be restarted after a source edit when compatibility permits.
-
Passed: Final artifacts can be exported, downloaded from retained nodes, or otherwise handled explicitly by user code.
-
Passed: The coordinator does not route bulk source or artifact bytes by default during the demo.
25. Non-goals preserved
-
Passed: The MVP does not imply transparent raw remote pointers.
-
Passed: The MVP does not imply global consensus on every memory access.
-
Passed: The MVP does not imply live native process migration.
-
Passed: The MVP does not imply durable artifacts without explicit export/storage policy.
-
Passed: The MVP does not imply public hosted compute for arbitrary workloads.
-
Passed: The MVP does not imply secure managed Windows compute.
-
Passed: The MVP does not require users to understand distributed internals for the normal debug/build path.