Skip to main content
← Back to list
01Issue
BugShippedSwamp CLITeam
Assigneesstack72

Relationships

#1396 data prune resolves auto-definitions at the local path, not the datastore path — deletes live models' data (verified: destroyed a working server token and an active grant)

Opened by magistr · 7/24/2026· Shipped 7/25/2026

Summary

swamp data prune resolves auto-definitions at the local .swamp/auto-definitions path instead of the datastore-resolved one. In any repo with an external datastore or a namespace configured, the liveness check therefore finds nothing, every auto-definition-backed model is judged orphaned, and all of its data is irreversibly deleted.

I reproduced this end to end. It deleted a working server token and an active access grant, and the affected models' definition files were still on disk afterwards — they were never deleted, which is the proof the check looked in the wrong directory.

Verified reproduction

Throwaway repo, filesystem datastore at a path other than the repo (exactly what swamp datastore setup filesystem --path … produces — note it lists auto-definitions among its directories):

swamp repo init
swamp datastore setup filesystem --path ../datastore
swamp vault create local_encryption v1
swamp access token mint prodtoken --principal user:alice --vault v1

State after minting — the auto-definition lives in the datastore, not in the repo:

.swamp/auto-definitions/                        (empty)
../datastore/auto-definitions/swamp/server-token/1c4bd9b4-….yaml
../datastore/data/swamp/server-token/1c4bd9b4-…/token-main/1

The token demonstrably works. Against swamp serve --auth-mode token:

  • valid token → HTTP 200
  • same name, wrong secret → HTTP 401

Then:

swamp data prune --json
{
  "modelsReclaimed": 2, "dataEntriesReclaimed": 4, "versionsDeleted": 5,
  "reclaimedModels": [
    { "type": "swamp/server-token", "modelName": "prodtoken",
      "dataNames": ["report-swamp-method-summary","token-main","report-swamp-method-summary-json"] },
    { "type": "swamp/grant", "modelName": "grant-config-dabd1db8d35ab131",
      "dataNames": ["grant-main"] }
  ]
}

Re-running serve and presenting the same token: HTTP 401. The credential is gone.

And both definition files are still present:

../datastore/auto-definitions/swamp/server-token/1c4bd9b4-….yaml
../datastore/auto-definitions/swamp/grant/e52dfeb4-….yaml

The owning definitions exist. Prune deleted their data anyway.

Cause

src/libswamp/data/prune[dot]ts:128:

const definitionRepo = new YamlDefinitionRepository(repoDir);

YamlDefinitionRepository defaults its secondary search dir to swampPath(repoDir, SWAMP_SUBDIRS[dot]autoDefinitions) — i.e. {repoDir}/.swamp/auto-definitions (yaml_definition_repository[dot]ts:64-76). But auto-definitions is a datastore-tier subdir (datastore_config[dot]ts, DEFAULT_DATASTORE_SUBDIRS), so its real location is {datastoreBase}/{namespace}/auto-definitions.

createDataPruneDeps already computes the correct path — it defines dsPath() and uses it for the data repo and the workflow-run repo — and then does not use it for the definition repo.

The sibling command gets it right, src/libswamp/data/delete[dot]ts:112-118:

const autoDefDir = dsPath(SWAMP_SUBDIRS[dot]autoDefinitions);
const definitionRepo = new YamlDefinitionRepository(repoDir, undefined, undefined, autoDefDir ?? undefined);

Most pointedly, the comment immediately above the defect describes this exact failure mode as the thing to avoid:

"The definition repository resolves models from BOTH models/ and .swamp/auto-definitions/ … isModelLive MUST use this per-item lookup — NOT model search / findAllGlobal, which skip auto-definitions and would falsely flag every auto-definition-backed model as orphaned."

The hazard was identified correctly; the wrong path was wired.

This violates the documented contract

/manual/reference/data states prune "scans all persisted data entries, checks whether each entry's owning model definition still exists in its namespace, and deletes all versions of entries whose definition is absent", and that "Deletion is irreversible". The documented behaviour is a namespace-aware lookup. The implementation performs a non-namespaced local one.

Impact

Anyone running swamp data prune on a repo with a remote/external datastore or a namespace loses data belonging to live models. Because swamp/server-token and swamp/grant are themselves auto-definition-backed, the specific losses include:

  • every server token — all remote CLI/worker access to that serve instance stops authenticating;
  • every access grant — the authorization configuration;
  • any other auto-definition-backed model's data, including @swamp/* models installed from the registry.

Deletion is a recursive Deno[dot]remove of the data-name directory — no tombstone, no trash, nothing to restore from except a datastore backup. --dry-run reports the same wrong answer, so it does not protect you; it just previews the loss accurately.

Note the interaction with the documented non-interactive behaviour: --json "implies non-interactive mode (skips confirmation prompt)", so any script or agent that prunes with --json gets no prompt before this happens.

This is the same family as swamp-club#1304 (namespace unset --migrate deleting artifact history) — a liveness/orphan check keyed on a path that moved.

Suggested fix

One line, matching delete[dot]ts: pass the datastore-resolved auto-definitions directory as the fourth constructor argument in prune[dot]ts:128.

For regression coverage, integration/data_prune_test[dot]ts currently wires the repo with no datastore resolver — the single configuration where this cannot manifest. Re-running that test under a non-default datastore path (and again with a namespace set) would have caught this.

Environment

  • Source main @ 10943ef, run from source. macOS 14.
  • Reproduced with a filesystem datastore; by inspection the same applies to S3/GCS datastores and to any repo with namespace: set, since both relocate auto-definitions away from .swamp/.
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 4 MOREPR_MERGED+ 1 MORECONTRIBUTOR_NOTIFIED

Shipped

7/25/2026, 1:10:16 AM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack727/25/2026, 12:13:24 AM
Editable. Press Enter to edit.

stack72 commented 7/25/2026, 1:10:25 AM

Thanks @magistr for reporting this! The fix has been merged and a release is on its way. We appreciate your contribution to swamp.

Sign in to post a ripple.