Skip to content

Magic Containers UX & safety + secret redaction (iter-21)#19

Merged
ractive merged 3 commits into
mainfrom
iter-21/magic-containers-ux
May 5, 2026
Merged

Magic Containers UX & safety + secret redaction (iter-21)#19
ractive merged 3 commits into
mainfrom
iter-21/magic-containers-ux

Conversation

@ractive

@ractive ractive commented May 5, 2026

Copy link
Copy Markdown
Owner

Summary

Addresses MC.1–MC.6 from the 2026-05-05 magic-containers field report and lands the cross-cutting secret-redaction layer that iter-19 (storage zone passwords) and iter-20 (database tokens) will consume.

  • container template env no longer silently wipes env vars. Bare invocation errors with a recipe. New flags --add / --remove / --update (granular merge), --replace-all --env (explicit destructive replace), --clear (explicit wipe), --list (show, redacted). Destructive shrinks/wipes require typing "replace" / "wipe" — --yes alone isn't enough.
  • container app delete won't orphan auto-managed Pull Zones. Refuses by default if any are detected; --cascade deletes app + auto-PZs, --no-cascade deletes app and prints orphan IDs with a cleanup recipe.
  • container app create returns the full app by default so callers can chain template / endpoint ids without a follow-up app get. --minimal opts back into the legacy {"id": "..."} shape. New --env KEY=VAL (repeatable) applies env vars in one call.
  • Cross-cutting redaction layer. Env-var values are masked as <set, length=N> in JSON, table, and text output by default. Opt in with the global --reveal (all secrets) or --reveal-env KEY (a specific var). Off by default even for --format json to keep jq pipelines safe.

Test plan

  • cargo fmt
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace (all suites green; 9 new container tests covering MC.1/MC.3/MC.5/MC.6)
  • Snapshot tests confirm redaction default + --reveal raw output
  • Live E2E run on a sandbox account: env-preservation, cascade delete, no-cascade orphan listing
  • Verify auto-PZ id discovery works against real Bunny endpoints (test fixtures use stringified pullZoneId)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Granular container template env management: add/update/remove, destructive replace-all/clear, list with redaction and opt-in reveal
    • Container app create: accepts initial env vars and returns full app details by default (legacy --minimal available)
    • Global secret redaction by default with --reveal and per-key reveal options
    • Container app delete: refuses unsafe deletes unless --cascade or --no-cascade provided
  • Documentation

    • Expanded CLI docs and knowledgebase with detailed hyalo/hoppy usage examples, iteration plan, and UX/safety guidance
  • Tests

    • Expanded CLI tests covering create shapes, env operations, redaction, and cascade delete behaviors

ractive and others added 2 commits May 5, 2026 01:12
- .claude/skills/hyalo/SKILL.md: document BM25 full-text search, links auto, and updated read/find syntax
- .claude/skills/hyalo-tidy/SKILL.md: add views, types/lint, and broaden phase guidance
- .claude/rules/knowledgebase.md: align example commands with current hyalo CLI
- .gitignore: ignore .DS_Store everywhere

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses MC.1–MC.6 from the 2026-05-05 magic-containers bug report and
introduces the cross-cutting secret-redaction layer that iter-19 (storage
zone passwords) and iter-20 (database tokens) will consume.

Highlights:

- container template env: bare invocation no longer silently wipes all
  vars. New flags --add / --remove / --update (granular merge), --replace-all
  --env (explicit replace), --clear (explicit wipe), --list (show, redacted).
  Destructive shrinks/wipes require typing "replace" / "wipe".
- container app delete: refuses by default if auto-managed Pull Zones
  exist. --cascade also deletes them; --no-cascade prints orphan IDs and
  a manual cleanup recipe.
- container app create: returns the full app document by default so
  callers can chain template / endpoint ids without a follow-up app get.
  --minimal opts back into {"id": "..."}. New --env KEY=VAL (repeatable)
  applies env vars in one call.
- Cross-cutting redaction: env-var values are masked as <set, length=N>
  in JSON, table, and text output by default. Opt in with the global
  --reveal (all secrets) or --reveal-env KEY (a specific var).

Decision log + bunny-api-quirks updated. Adds wiremock tests for every
new behaviour (zero-arg refusal, --add merge, --remove, --list redaction,
cascade delete refusal/cascade/no-cascade).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown
ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Free

Run ID: eb5463f0-2349-4c86-82b3-2e135b6da3a1

📥 Commits

Reviewing files that changed from the base of the PR and between 4100e15 and 9ba8234.

📒 Files selected for processing (3)
  • hoppy-knowledgebase/api/bunny-api-quirks.md
  • hoppy-knowledgebase/iterations/iteration-21-magic-containers-ux.md
  • src/commands/container.rs
✅ Files skipped from review due to trivial changes (2)
  • hoppy-knowledgebase/api/bunny-api-quirks.md
  • hoppy-knowledgebase/iterations/iteration-21-magic-containers-ux.md

📝 Walkthrough

Walkthrough

Adds a cross-cutting secret redaction layer and CLI reveal controls; implements granular container template env operations (add/update/remove/replace-all/clear/list) with typed confirmations; changes container app create to support repeatable --env and default full-object output with --minimal; makes app delete refuse orphaning auto-managed Pull Zones unless --cascade/--no-cascade is provided. Also updates extensive hyalo and knowledgebase docs and tests.

Changes

Documentation & Knowledgebase

Layer / File(s) Summary
Knowledgebase rules & examples
.claude/rules/knowledgebase.md
Concrete hyalo read/frontmatter/content examples and auto-link guidance added; older generic read wording replaced with explicit hyalo find --file <path> / hyalo read <path> forms.
Hyalo skill docs
.claude/skills/hyalo/*.md, .claude/skills/hyalo-tidy/*.md
Expanded hyalo find BM25 full-text guidance, --index standardization (no hardcoded .hyalo-index), new view-driven diagnostics and Phase 3/4 examples, and updated command/flag examples (--title, --section, --fields, --limit, etc.).
API quirks & decision log
hoppy-knowledgebase/api/bunny-api-quirks.md, hoppy-knowledgebase/decision-log.md
Documented Magic Containers API quirks (env PUT replaces whole set; delete leaves auto-managed Pull Zones; plaintext envs in responses) and recorded decisions: default redaction with --reveal / --reveal-env, typed-phrase confirmations, safer delete/create semantics.
Iteration spec & changelog
hoppy-knowledgebase/iterations/iteration-21-magic-containers-ux.md, CHANGELOG.md
Added Iteration-21 plan covering redaction foundation and MC.1–MC.6 behavioral changes; new Unreleased changelog notes describing CLI flag/behavior changes.
Misc
.gitignore
Added .DS_Store and **/.DS_Store ignore patterns.

Magic Containers UX & Safety Implementation

Layer / File(s) Summary
Dependency / CLI shape
Cargo.toml, src/cli.rs
Enabled serde_json preserve_order feature. Added global flags --reveal and repeatable --reveal-env <KEY>. Extended container app create with repeatable --env KEY=VALUE and --minimal. Extended app delete with mutually exclusive --cascade / --no-cascade. Replaced container template env CLI shape with granular --add/--update/--remove plus --replace-all/--clear/--list.
Redaction foundation
src/redact.rs
New RedactConfig (reveal_all + case-insensitive reveal_env_keys), placeholder() formatting (<unset> / <set, length=N>), is_secret_field_name() heuristic, and redact_env_in_json() to recursively redact environmentVariables[*].value except for allowed keys. Unit tests included.
Core command behavior
src/commands/container.rs
Wired redaction into handlers; added print_json_with_redaction. app create validates --env placement, applies --env post-create via template env replace-all, and in non---minimal mode fetches and prints full app details (including template and endpoint IDs). app delete discovers auto-managed Pull Zone IDs, refuses unsafe deletion unless --cascade/--no-cascade provided, and implements cascading deletion with failure aggregation. container template env refactored into handle_template_env supporting mutual-exclusion of modes, typed-phrase confirmations for destructive ops ("wipe" / "replace"), and granular merge semantics.
Wiring
src/main.rs
New mod redact; and construction of RedactConfig from CLI flags; passes &RedactConfig into container command handler.
Tests
tests/cli_container.rs
Expanded create tests to cover --minimal and default full-object flows. Replaced/expanded template env tests to cover replace-all, zero-arg refusal, merging with --add, removing keys with --remove, and redaction/list behavior with --reveal. Added app-delete tests covering refusal without cascade flags, --no-cascade printing orphans/cleanup recipe, and --cascade deleting pull zones.

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Commands as "commands::container"
  participant API as "bunny API"
  participant Redact as "redact::redact_env_in_json"

  CLI->>Commands: container app create --env KEY=VAL (no --minimal)
  Commands->>API: POST /apps (create)
  API-->>Commands: 201 { id }
  Commands->>API: GET /apps/{id} (fetch full object)
  API-->>Commands: 200 { app with containerTemplates, endpoints, environmentVariables }
  Commands->>Redact: redact_env_in_json(app_json, redact_cfg)
  Redact-->>Commands: redacted app_json
  Commands-->>CLI: print redacted JSON/table output

  CLI->>Commands: container app delete {id}
  Commands->>API: GET /apps/{id} (enumerate endpoints)
  API-->>Commands: 200 { endpoints with pullZoneId }
  alt auto-PZ found & no cascade flags
    Commands-->>CLI: abort with orphan IDs and guidance
  else cascade requested
    Commands->>API: DELETE /apps/{id}
    API-->>Commands: 204
    Commands->>API: DELETE /pull-zones/{pzId} (for each)
    API-->>Commands: 204 / error
    Commands-->>CLI: report success/failure
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 I tidy envs with careful delight,
Secrets masked softly in morning light,
Creates fetch full objects, not just an id,
Deletes ask first—no orphans hid,
Reveal if you must, but otherwise quiet.


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the Magic Containers CLI UX/safety (env-var management, safer deletes, richer create output) and introduces a cross-cutting secret redaction layer that masks sensitive values by default unless explicitly revealed.

Changes:

  • Add global redaction controls (--reveal, --reveal-env) and a new src/redact.rs redaction module; wire redaction into Container JSON output and template env --list.
  • Rework container template env into explicit modes (--add/--remove/--update, --replace-all --env, --clear, --list) and refuse the historical zero-flag footgun.
  • Make container app create return the full app object by default (with --minimal for legacy), and make container app delete detect/refuse orphaning auto-managed Pull Zones unless --cascade/--no-cascade is chosen.

Reviewed changes

Copilot reviewed 13 out of 15 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/cli_container.rs Adds/updates CLI tests for new create output, env command modes, redaction, and delete cascade behavior.
src/redact.rs Introduces redaction config + JSON redaction walker for env-var values.
src/main.rs Constructs a RedactConfig from global CLI flags and passes it into container handlers.
src/commands/container.rs Implements new env subcommand behavior, app create output changes, app delete cascade logic, and JSON printing with redaction.
src/cli.rs Adds global --reveal / --reveal-env flags; expands container app/template subcommand flags.
hoppy-knowledgebase/iterations/iteration-21-magic-containers-ux.md New iteration plan doc capturing MC.1–MC.6 scope and redaction foundation.
hoppy-knowledgebase/decision-log.md Records design decisions for redaction, destructive confirmations, cascade delete, and create output changes.
hoppy-knowledgebase/api/bunny-api-quirks.md Documents MC API quirks and the CLI mitigations (auto-PZ orphaning, env PUT semantics, plaintext env values).
CHANGELOG.md Adds Unreleased entry describing the UX/safety changes and redaction behavior.
Cargo.toml Enables serde_json preserve_order feature for deterministic JSON key ordering.
Cargo.lock Locks new transitive dep (indexmap) from serde_json/preserve_order.
.gitignore Ignores .DS_Store.
.claude/skills/hyalo/SKILL.md Expands hyalo skill docs (search modes, flags, examples).
.claude/skills/hyalo-tidy/SKILL.md Updates hyalo-tidy workflow examples to newer --index usage and adds view suggestions.
.claude/rules/knowledgebase.md Updates knowledgebase rules/examples for hyalo usage.

Comment thread src/commands/container.rs Outdated
Comment on lines +1275 to +1279
if !yes {
let prompt = format!(
"Clear ALL {n} environment variable(s) on container {container_id}? \
Type \"wipe\" to confirm:"
);
Comment thread src/commands/container.rs Outdated
Comment on lines +1296 to +1300
if !yes && cur_n > 0 && cur_n > new_n {
let prompt = format!(
"Replace {cur_n} environment variable(s) with {new_n}? \
Type \"replace\" to confirm:"
);
Comment thread src/commands/container.rs Outdated
Comment on lines +1312 to +1323
// Read current set, apply add/update/remove in order, write back.
let current = c.get_container(app_id, container_id).await?;
let mut map: HashMap<String, String> = current
.environment_variables
.iter()
.map(|e| (e.name.clone(), e.value.clone().unwrap_or_default()))
.collect();
for pair in add.iter().chain(update.iter()) {
let (k, v) = pair
.split_once('=')
.ok_or_else(|| anyhow::anyhow!("env '{pair}' is not in KEY=VALUE format"))?;
map.insert(k.to_owned(), v.to_owned());
Comment thread tests/cli_container.rs
Comment on lines 1277 to 1281
let output = mock_cmd("test-api-key", &server.uri())
.args([
"--yes",
"container",
"template",
- **Read frontmatter/metadata**: `hyalo find --file <path>`, `hyalo properties`, `hyalo tags`
- **Read content/sections**: `hyalo read <path>` or `hyalo read <path> --section "Heading"`
- **Mutate frontmatter**: `hyalo set`, `hyalo remove`, `hyalo append`
- **Auto-link**: `hyalo links auto --first-only --exclude-target-glob 'templates/*' --apply`
- Always require typed phrase for `template env --clear` and a shrinking
  `--replace-all`, regardless of `--yes` (matches the iter-21 decision-log
  promise that `--yes` alone is not sufficient for these destructive ops)
- Drop unused `yes` parameter from handle_template_env now that the gate
  no longer branches on it
- Clarify granular ordering comment: adds/updates run before removes in a
  single invocation (clap groups values by flag name)
- Document the `--clear` ↔ `--replace-all` exclusivity, the granular flag
  precedence, and the `--reveal` → `--reveal-env` precedence in the spec
- Fix awkward "no env var unlocks it" wording in api quirks doc

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ractive
ractive merged commit 0923f88 into main May 5, 2026
6 of 8 checks passed
@ractive
ractive deleted the iter-21/magic-containers-ux branch May 5, 2026 09:12
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.

2 participants