91 lines
4.2 KiB
Markdown
91 lines
4.2 KiB
Markdown
# 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](../operations.md#local-state-layout).
|
|
|
|
## 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
|
|
cleanup roots and their descendants through no-follow directory handles before
|
|
removing them.
|
|
|
|
`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](../operations.md#workspace-permissions).
|
|
|
|
## 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
|
|
promotes the validated external bundle to the unique immutable Notarius bundle
|
|
path supplied by `internal/artifacts`. `internal/fileops.PromoteDirectory`
|
|
copies only regular files and directories to a same-filesystem temporary
|
|
sibling. Source traversal uses confined directory handles and identity checks
|
|
so replacing an inspected root, directory, or file is rejected rather than
|
|
followed. The completed tree is atomically renamed without replacing an
|
|
existing destination. Exact physical paths belong in
|
|
[Operations](../operations.md#extraction-workflow).
|
|
|
|
## 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
|
|
|
|
Automatic post-publish cleanup:
|
|
|
|
- only runs when publish actually executed and succeeded;
|
|
- requires `uploaded=true`, a remote commit key, and a current commit-pointer
|
|
key in publish metadata;
|
|
- consumes the resolved cleanup policy described in
|
|
[Configuration](../config.md);
|
|
- refuses unsafe deletes (root delete, out-of-root delete, and symlinked
|
|
ancestors or entries).
|
|
|
|
Manual cleanup uses the same root-confined deletion mechanism. Invocation
|
|
syntax and exact deletion scope belong in [CLI](../cli.md#clean) and
|
|
[Operations](../operations.md#cleanup).
|
|
|
|
## Invariants
|
|
|
|
- campaign-aware session root is mandatory.
|
|
- manifest-driven stage state is durable across runs.
|
|
- cleanup guardrails prevent destructive root/out-of-scope deletion.
|
|
- 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 promotion: `internal/fileops/directory.go`
|
|
- Workspace modes: `internal/fileops/modes.go`
|
|
- Cleanup confinement: `internal/fileops/cleanup.go`,
|
|
`internal/app/cleanup_targets.go`, `internal/app/post_publish_cleanup.go`
|
|
- Tests: `internal/artifacts/paths_model_test.go`,
|
|
`internal/artifacts/local_test.go`, `internal/stage/run_local_test.go`,
|
|
`internal/fileops/directory_test.go`, `internal/fileops/modes_posix_test.go`,
|
|
`internal/fileops/cleanup_test.go`, `internal/app/cleanup_targets_test.go`,
|
|
`internal/app/post_publish_cleanup_test.go`
|