Skip to content

feat(cloud): coordinate quiescent Session Bundle snapshots #2369

Description

@MicroGery

Parent RFC: #1286

Depends on:

Unblocks:

Summary

Define and implement the coordinator that produces one consistent, filtered, quiescent state/ + workspace/ snapshot for SessionBundleFileService.pack.

The coordinator owns the transition from live mutable Session roots to an immutable private staging snapshot. The filesystem codec continues to own only deterministic archive encoding, validation, and hydration.

Problem

SessionBundleFileService.pack accepts a PreparedSessionBundleSnapshot and assumes that:

  • state and workspace represent one logical point in time;
  • SQLite and other mutable stores are safe to copy;
  • the roots do not change while packing;
  • credentials, temporary execution state, logs, and excluded workspace content are absent.

Those guarantees do not exist when state/ and workspace/ are copied directly from a live Session. A state export and workspace copy taken at different times can produce a structurally valid but semantically inconsistent Bundle.

Responsibility boundary

The coordinator owns:

  • acquiring a per-Session safe/quiescent boundary;
  • coordinating the state export and workspace copy under that boundary;
  • applying a versioned snapshot/filtering policy;
  • producing the opaque state-identity descriptor through the state-owning layer;
  • publishing a private immutable staging snapshot;
  • retaining cleanup ownership until the caller releases the snapshot;
  • deterministic failure cleanup and bounded stable errors.

It does not own:

  • USTAR/Zstandard encoding or Bundle validation;
  • Repository/blob persistence, revision allocation, or CAS;
  • Activation leases, deduplication, reply publication, or sandbox lifecycle;
  • Cloud Session fork orchestration or identity re-keying.

Proposed lifetime contract

V1 uses a short quiescence interval followed by a private staging copy. It does not keep the live Session blocked while compression and upload run.

Conceptually:

interface PreparedSessionBundleHandle {
  snapshot: PreparedSessionBundleSnapshot;

  /** Idempotently deletes the coordinator-owned private snapshot. */
  release(): Promise<void>;
}

interface QuiescentSessionSnapshotCoordinator {
  prepare(input: PrepareSessionSnapshotInput): Promise<PreparedSessionBundleHandle>;
}

Lifecycle:

  1. Serialize snapshot preparation for the Session and prevent new writers from entering the snapshot boundary.
  2. Wait for current state/workspace writes to settle, subject to caller cancellation/deadline.
  3. Export the single-Session state and copy the filtered workspace into a uniquely named, coordinator-owned private staging root.
  4. Keep state and workspace under the same quiescence interval until both copies and the state-identity descriptor are complete and all handles are closed.
  5. Release the live Session boundary before returning the handle.
  6. pack reads only the private staging roots; later mutations of the live Session cannot affect the snapshot.
  7. The caller invokes release() in finally; release is idempotent and removes only roots proven to be owned by this handle.

The coordinator must not return live Session paths as prepared snapshot paths.

Concurrent mutation and failure behavior

  • Concurrent snapshot preparations for one Session are serialized.
  • A writer that already owns the Session mutation boundary is allowed to finish before copying begins; preparation obeys the caller's deadline/cancellation.
  • New writers cannot overlap the coordinated state/workspace copy.
  • Unexpected source changes detected during preparation fail closed with a stable source_changed-class error; no snapshot is returned.
  • Any failure before a handle is returned removes partial staging state.
  • Any failure after a handle is returned remains the caller's responsibility through release().
  • Temporary-root ownership must be explicit and persistent enough that cleanup cannot delete unrelated directories or follow symlinks.
  • Orphan cleanup, if exposed, is scoped to an exact snapshot/owner record rather than a name-prefix sweep.

Filtering and secret-exclusion ownership

The coordinator is the enforcement point for a versioned snapshot policy. The codec and SessionRepository must not reinterpret this policy.

The V1 policy must deterministically exclude at least:

  • host/global configuration and credential stores;
  • control-plane-injected credentials and connection configuration;
  • temporary Activation input and execution scratch space;
  • logs, caches, and sandbox-local runtime state;
  • node_modules/ and .git/ from the portable workspace snapshot.

Project manifests and lockfiles remain included so project dependencies can be materialized in the target environment from a platform-keyed cache. Maka runtime dependencies belong in the versioned runtime image.

The policy must operate on normalized relative paths, fail closed on invalid or conflicting paths, and produce auditable exclusion diagnostics without exposing secret values.

Decision required before implementation: user-authored secrets

The contract still needs maintainer agreement on files deliberately present inside the user's workspace, such as .env, private keys, or credentials.json. Candidate policies are:

  1. detect and reject the complete snapshot with a bounded error (preferred over silently changing workspace semantics);
  2. deterministically exclude matched files and report the exclusions;
  3. allow them only through an explicit caller-owned policy/consent mechanism.

V1 must choose one explicit behavior before implementation. It must not rely on an undocumented best-effort scanner or silently default to including detected secrets.

Stable error model

The public error set should remain bounded, with structured details that do not expose unbounded paths or secret contents. Candidate codes:

type SessionSnapshotErrorCode =
  | "snapshot_busy"
  | "snapshot_cancelled"
  | "source_changed"
  | "unsafe_source"
  | "policy_rejected"
  | "quota_exceeded"
  | "cleanup_failed"
  | "io_failure";

Exact names remain subject to contract review.

Acceptance criteria

Consistency and lifetime

  • A private staging snapshot is produced; live Session roots are never returned to pack.
  • State, workspace, and the identity descriptor are produced under one documented quiescence boundary.
  • The live Session may resume after private staging is complete and before pack finishes.
  • Mutating the live Session after prepare returns cannot change the prepared snapshot.
  • Per-Session concurrent preparation and concurrent-writer behavior are deterministic and tested.
  • Caller cancellation/deadline behavior is pinned and tested.

Cleanup and ownership

  • Partial staging is removed on every preparation failure.
  • A successful handle retains cleanup ownership until idempotent release().
  • Cleanup cannot remove unrelated paths, the live Session root, or symlink targets.
  • Injected crash/failure cases cover preparation, publication, packing failure, and release retry.

Filtering and security

  • The coordinator, not the codec or Repository, enforces the versioned snapshot policy.
  • Known host configuration, injected credentials, temporary inputs, logs, caches, .git/, and node_modules/ are excluded.
  • Project manifests and lockfiles remain portable inputs for dependency materialization.
  • The user-authored-secret policy is explicitly decided before implementation and covered by tests.
  • Diagnostics never expose secret values.

Integration

Implementation split

This issue is one dependency-graph work item and should land independently from SessionRepository. A reviewable implementation may use two PRs if necessary:

  1. contract, quiescence/lifetime abstraction, policy boundary, and deterministic test fakes;
  2. filesystem/state integration, cleanup, race tests, and codec round-trip E2E.

Out of scope

  • SessionRepository/KV/object-store implementation;
  • revision retention, blob GC, or copy-on-write;
  • OpenSandbox transfer;
  • Activation execution and terminal-outcome persistence;
  • Cloud Session fork orchestration;
  • makaSessionId or Workspace UUID re-keying;
  • pending-approval or externally resumable action migration.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions