Skip to content

feat: add swamp extension trust CLI commands#766

Merged
stack72 merged 2 commits intomainfrom
extension-trust-commands
Mar 18, 2026
Merged

feat: add swamp extension trust CLI commands#766
stack72 merged 2 commits intomainfrom
extension-trust-commands

Conversation

@stack72
Copy link
Copy Markdown
Contributor

@stack72 stack72 commented Mar 18, 2026

Summary

Adds CLI commands to manage trusted collectives for extension auto-resolution, solving a discoverability problem where the feature was completely invisible to both users and AI agents.

The Problem

A user asked Claude about trusted collectives in their swamp repo, and Claude responded: "The trusted collectives feature doesn't exist in swamp yet." Despite the feature being fully implemented (PRs #725 and #727), it was only configurable by manually editing .swamp.yaml — no CLI command, no --help text, no discoverability path.

The Solution

Four new commands under swamp extension trust:

swamp extension trust list                # Show explicit, membership, and resolved collectives
swamp extension trust add <collective>    # Add a collective to the trusted list
swamp extension trust rm <collective>     # Remove a collective from the trusted list
swamp extension trust auto-trust <on|off> # Enable/disable membership auto-trust

The list command shows the full picture — explicit collectives from .swamp.yaml, membership collectives from auth, and the resolved/merged effective list. This means even on a fresh repo with no config, a user sees that swamp and si are trusted by default.

Architecture

Follows the libswamp + renderer pattern (issue #739):

Layer Files Purpose
Shared types src/libswamp/extensions/trust.ts DEFAULT_TRUSTED, TrustModifyData, TrustModifyEvent, resolveTrustedCollectives()
Generators src/libswamp/extensions/trust_{list,add,rm,auto_trust}.ts Pure business logic with injected deps
Renderers src/presentation/renderers/trust_{list,modify,auto_trust}.ts Log + Json output modes
CLI commands src/cli/commands/extension_trust*.ts Pure wiring (deps → generator → renderer)

Refactoring

  • Extracted resolveTrustedCollectives() from src/cli/mod.ts into src/libswamp/extensions/trust.ts — it was domain logic living in the CLI layer
  • Moved 8 tests from src/cli/mod_test.ts to src/libswamp/extensions/trust_test.ts to follow the code
  • Single TrustModifyEvent shared by both trust_add and trust_rm generators (identical event shapes, no reason for separate types)
  • DEFAULT_TRUSTED defined once, used everywhere

Documentation Updates

  • design/extension.md — documents CLI commands in "Trusted Collectives" section
  • design/repo.md — cross-references CLI commands from trustedCollectives config
  • 7 skill files updated with swamp extension trust references for discoverability

Test Plan

  • 26 generator tests (src/libswamp/extensions/) — all pass
  • 16 renderer tests (src/presentation/renderers/trust_*_test.ts) — all pass
  • 8 resolveTrustedCollectives tests moved to proper location — all pass
  • Existing mod_test.ts tests still pass (57 tests, down from 65 after moving 8)
  • deno check passes on all files
  • deno lint passes
  • deno fmt applied

🤖 Generated with Claude Code

stack72 added 2 commits March 18, 2026 20:42
…ollectives

Add CLI commands to manage trusted collectives for extension auto-resolution,
making a previously hidden configuration discoverable via the CLI.

Commands:
- `swamp extension trust list` — show explicit, membership, and resolved collectives
- `swamp extension trust add <collective>` — add a collective to the trusted list
- `swamp extension trust rm <collective>` — remove a collective from the trusted list
- `swamp extension trust auto-trust <on|off>` — toggle membership auto-trust

Architecture follows the libswamp + renderer pattern (issue #739):
- Generators in src/libswamp/extensions/ with injected deps for testability
- Log + Json renderers in src/presentation/renderers/
- CLI commands in src/cli/commands/ as pure wiring

Also extracts resolveTrustedCollectives and DEFAULT_TRUSTED from src/cli/mod.ts
into src/libswamp/extensions/trust.ts as shared domain logic, eliminating
duplication and ensuring a single source of truth.

Updates design docs and 7 skill files to reference the new CLI commands.
The 3 new trust renderers use writeOutput from infrastructure (same
pattern as all existing renderers like auth_whoami). Bump the
KNOWN_PRESENTATION_INFRA_VIOLATIONS ratchet from 43 to 46.
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

This PR adds well-designed CLI commands for managing trusted collectives (swamp extension trust list/add/rm/auto-trust), solving an important discoverability problem.

No Blocking Issues

The PR follows all project requirements and patterns correctly.

Architecture (DDD Compliant)

The architecture properly follows the libswamp + renderer pattern:

Layer Files Assessment
Shared types src/libswamp/extensions/trust.ts DEFAULT_TRUSTED, TrustModifyData, TrustModifyEvent, resolveTrustedCollectives() properly placed
Application Services src/libswamp/extensions/trust_{list,add,rm,auto_trust}.ts Correct async generator pattern with Deps injection, LibSwampContext, and typed events using kind discriminant
Renderers src/presentation/renderers/trust_*.ts Proper log + json output modes
CLI wiring src/cli/commands/extension_trust*.ts Pure wiring as expected

Code Quality

  • Named exports throughout (no default exports)
  • All files include AGPLv3 copyright headers
  • CLI commands correctly import from src/libswamp/mod.ts
  • Input validation on collective names (/^[a-z0-9][a-z0-9_-]*$/) prevents malformed input
  • Proper error handling with SwampError types
  • The AnyOptions pattern is consistent with 68+ existing CLI commands

Test Coverage

All new source files have corresponding test files:

  • 5 generator test files in src/libswamp/extensions/
  • 3 renderer test files in src/presentation/renderers/
  • Tests cover happy paths, error cases, and edge cases (empty arrays, defaults, deduplication)

Documentation

Good updates to design docs and 7 skill files for discoverability.

Note on DDD Ratchet

The bump from 43 to 46 KNOWN_PRESENTATION_INFRA_VIOLATIONS is appropriate - the new renderers use writeOutput from infrastructure following the existing pattern.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adversarial Review

I've systematically traced code paths, examined edge cases, and stress-tested error handling across all changed files. This is a well-structured PR that follows the libswamp + renderer pattern consistently.

Critical / High

None found. The code is solid.

Medium

  1. Race condition in read-modify-write (theoretical)trust_add.ts:64-87, trust_rm.ts:52-75, trust_auto_trust.ts:60-72

    All three generators follow a read-modify-write pattern without locking:

    const marker = await deps.readMarker();
    // ... modify marker.trustedCollectives ...
    await deps.writeMarker(marker);

    Breaking scenario: Run swamp extension trust add orgA and swamp extension trust add orgB concurrently. Both read the same initial state, both append their collective, and whichever writes last wins — the first addition is lost.

    Severity: Medium because (a) atomic write prevents corruption, only data loss, (b) concurrent CLI invocations of the same command are rare in practice, (c) the effect is limited to trust configuration, not critical data.

    Suggested fix: Not required for merge. If ever needed, use file locking or optimistic concurrency (read version, fail if changed).

Low

  1. @ prefix in collective name causes confusing errortrust_add.ts:27,54-62

    Users familiar with extension types (@swamp/model) might input swamp extension trust add @myorg. The validation error says "Must match [a-z0-9][a-z0-9_-]*" but doesn't explain that collective names don't use the @ prefix.

    Example: swamp extension trust add @acme → error about regex, user confused

    Suggested fix: Add a specific check for leading @ with a clearer message: "Collective names don't include the '@' prefix. Use 'acme' instead of '@acme'."

  2. Infrastructure exceptions bubble up rawtrust_add.ts:87, trust_rm.ts:75, trust_auto_trust.ts:72

    If writeMarker throws (disk full, permission denied), the raw Deno exception propagates to the user rather than a SwampError. This produces less consistent error messaging compared to validation errors.

    Example: Deno.errors.PermissionDenied: permission denied instead of "Failed to update .swamp.yaml: permission denied"

    Suggested fix: Wrap writeMarker in try/catch and yield an error event with a user-friendly message. Not blocking since atomic write prevents partial state.

Verdict

PASS — No blocking issues found. The code is well-tested (50 new tests), follows established patterns, and handles the common paths correctly. The race condition is theoretical for a CLI tool, and the UX improvements in Low findings are polish, not correctness issues.

@stack72 stack72 merged commit c7e8f28 into main Mar 18, 2026
6 checks passed
@stack72 stack72 deleted the extension-trust-commands branch March 18, 2026 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant