Files
kandev/docs/decisions/2026-08-08-owned-temp-artifact-cleanup.md
T
2026-08-09 17:57:47 +01:00

75 lines
4.8 KiB
Markdown

# ADR-2026-08-08-owned-temp-artifact-cleanup: Clean only registered Kandev temporary artifacts
**Status:** accepted
**Date:** 2026-08-08
**Area:** backend, frontend, infra, security
## Context
Kandev host-local agents intentionally inherit the service's `TMPDIR`, `TMP`, and `TEMP`, so the
operating-system temporary directory can contain both Kandev scratch and unrelated user, tool, CI,
preview, or other-installation data. A name such as `kandev-*`, an old modification time, or a live
path prefix does not prove that a directory belongs to the current Kandev installation.
The Storage page should still give operators a safe way to reclaim abandoned temporary directories
created by Kandev service components. This requires a narrower ownership boundary than a general
`/tmp` sweep.
## Decision
Add a typed `temporary_artifacts` storage provider with these rules:
- The provider acts only on artifact records created by the current Kandev storage registry. Each
record stores the exact absolute path, artifact kind, opaque artifact ID, lifecycle timestamps,
owner lease/heartbeat state, and a marker filename inside the artifact root. The marker and record
must match before the path is considered.
- The registry accepts only compiled-in service artifact kinds and creates top-level directories
beneath the effective service temporary root. It rejects symlinked roots, nested paths, and
arbitrary caller-supplied prefixes. The first producers are long-lived backend service roots such
as Improve Kandev bundles and the host-utility parent; standalone CLI, preview, CI, and test
harness roots are not implicitly registered.
- An active lease or recent heartbeat protects an artifact. A closed or abandoned artifact becomes
eligible only after a fixed 24-hour stale interval. Unreadable records, missing or mismatched
markers, path replacement, uncertain liveness, and filesystem errors are skipped fail-closed.
- The provider is manual-only in its first release. `POST /storage/run` with the explicit
`resources: ["temporary_artifacts"]` selection invokes it; scheduled maintenance and an
unscoped full manual run do not delete these artifacts. No new persisted policy toggle is added.
- Eligible roots are moved by same-filesystem rename into the existing Kandev quarantine before
permanent deletion. Cross-device moves have no copy/delete fallback. Existing quarantine
retention, restore, and permanent-delete safety rules apply.
- Legacy `/tmp/kandev-agent/*`, generic `tmp.*` paths, dependency and package caches, Go/Node/
Playwright caches, PR/preview folders, E2E/dev-isolated roots, and artifacts belonging to another
Kandev installation remain outside the provider.
This supplements ADR 0045: inherited shared temporary data remains unowned by default, while a
durable registry record plus matching marker creates a deliberately narrow, typed exception for
specific service-created roots.
## Consequences
- Operators can reclaim known abandoned service scratch from the Storage page without granting
Kandev authority to recursively delete shared `/tmp` contents.
- The first release may report zero eligible artifacts even when `/tmp` is large; unregistered
folders require their owning producer or host temporary-file policy to clean them.
- Producers must keep registry leases and markers correct, and new long-lived service temp roots
need an explicit registration decision before they become reclaimable.
- Quarantine can temporarily move bytes from `/tmp` into Kandev's trash, but preserves restore and
fail-closed behavior rather than deleting a possibly misclassified root immediately.
- The fixed stale interval is intentionally conservative. Scheduled cleanup or a configurable
temp policy requires a later product and operational decision.
## Alternatives Considered
- **Delete `/tmp/kandev-*` by name and age.** Rejected because names do not identify the current
installation and the same temporary root is shared with unrelated work.
- **Scan every file below `TMPDIR` and infer ownership from mtime or process names.** Rejected
because it is a general-purpose sweeper, is vulnerable to path replacement, and cannot prove
task or installation ownership.
- **Move all agent scratch beneath `KANDEV_HOME_DIR`.** Rejected by ADR 0045 because it mixes
transient process data with persistent application state and changes cache-sharing behavior.
- **Use only an on-disk marker without a durable registry record.** Rejected because a stale or
copied marker is not enough to establish lifecycle state after restart; the provider needs an
exact path and lease record owned by the current installation.
- **Enable the provider for scheduled and unscoped manual runs immediately.** Rejected because
shared-temp cleanup needs an explicit operator action and more operational evidence first.