Files
narratio/docs/internal/workspace.md

4.2 KiB

Internal: Workspace

Purpose

Explain the helpers that construct local session and run paths, coordinate single-writer access, and confine cleanup. The authoritative physical layout and retention workflow belong in Operations.

Path Ownership

internal/artifacts owns canonical session, run, spool, cache, and previous-cache path construction. SessionPathsFor provides the session-scoped path model, and layout creation goes through EnsureLayoutFor. Callers should consume those helpers instead of rebuilding relative paths.

internal/pathsafe validates relative destinations. internal/fileops opens explicit cleanup roots and removes only normalized proper descendants through the resulting root handle.

internal/fileops owns the ordinary workspace mode contract. On POSIX, WorkspaceDirectoryMode is setgid 02775 and WorkspaceFileMode is 0664. EnsureWorkspaceDirectory reapplies the directory mode after creation so a restrictive umask cannot remove group access, while retaining existing ownership and group. Credential paths are outside this contract; the platform-specific operational requirements are in Operations.

Run-Local Stage Layout

internal/stage/run_local.go maps stage outputs and diagnostics into an invocation-scoped layout. Successful outputs are validated and atomically materialized into canonical session paths before stage success. Managed previous-session cache paths remain session-durable and are never redirected into run-local output space.

Extraction uses run-local receipt, stderr, and output-root helpers, then validates and renames the external bundle to the unique immutable Notarius bundle path supplied by internal/artifacts. Exact physical paths belong in Operations.

Locking

artifacts.LocalStore enforces the single-writer session lock via an operating-system lock held on .lock (ErrLockConflict on contention). The file retains owner metadata after release or process death; its existence is not evidence that a lock is active. Command and restore flows wait for this lock only while their context remains active, and report a release failure.

Cleanup Semantics

The canonical cleanup stage:

  • runs after notify only when selected by the invocation range;
  • requires a succeeded publish record with uploaded=true, the published run ID, remote commit key, and current commit-pointer key;
  • consumes the resolved cleanup policy described in Configuration;
  • refuses unsafe deletes (root delete, traversal, and out-of-root targets);
  • treats missing targets as successful, idempotent deletion; and
  • uses its ordinary failed/succeeded manifest stage record for retry. A later full run can skip reusable upstream stages and retry cleanup without republishing.

Manual cleanup uses the same root-confined deletion mechanism. Invocation syntax and exact deletion scope belong in CLI and Operations.

Invariants

  • campaign-aware session root is mandatory.
  • manifest-driven stage state is durable across runs.
  • cleanup guardrails prevent destructive root/out-of-scope deletion.
  • restore installation is confined to validated relative paths beneath the selected session root.
  • ordinary workspace paths retain group-writable directory and file modes across nested creation, replacement, and Notarius promotion.

Implementation And Tests

  • Path model and local store: internal/artifacts/paths.go, internal/artifacts/local.go
  • Run-local materialization: internal/stage/run_local.go
  • Immutable bundle installation: internal/stage/extract.go
  • Workspace modes: internal/fileops/modes.go
  • Cleanup confinement: internal/fileops/cleanup.go, internal/stage/cleanup.go, internal/stage/cleanup_plan.go, and internal/app/cleanup_targets.go
  • Tests: internal/artifacts/paths_model_test.go, internal/artifacts/local_test.go, internal/stage/run_local_test.go, internal/fileops/modes_posix_test.go, internal/fileops/cleanup_test.go, internal/app/cleanup_targets_test.go, internal/stage/cleanup_test.go, and internal/app/cleanup_orchestration_test.go