Skip to content

feat(cli): --features strict-network — stack presets instead of the wildcard - #106

Merged
adamw merged 1 commit into
masterfrom
feat/2-strict-network
Sep 7, 2026
Merged

adamw merged 1 commit into
masterfrom
feat/2-strict-network

Conversation

@shejnowicz

@shejnowicz shejnowicz commented Sep 3, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #105 (network presets) — the base branch is feat/2-network-presets; retarget to master after #105 merges. Follow-up to #2; no separate issue, so no close keyword.

Summary

sandcat init --features strict-network (or SANDCAT_STRICT_NETWORK=true) generates project settings whose network list holds one {"preset": "<stack>"} entry per resolved stack and no allow-all-GET wildcard. Everything beyond the stack registries and the user-settings layer (the agent's own API hosts) is then denied by default — including DNS resolution, so blocked hosts never even resolve.

  • Opt-in by design: flipping the default would surprise every new project with "sandcat blocks the internet". The init summary states which policy the project got (Network: strict — stack presets: python, java vs default (allow all GET; tighten with --features strict-network)).
  • init settings grows --strict-network / --stacks flags; with no stacks the strict list is empty (user-settings layer only).
  • Only preset names land in the project file — the addon expands them at proxy start, so domain lists update with the sandcat version instead of freezing per project.
  • scala resolves to java scala via the existing stack-deps mechanism, so both presets are seeded.

Test plan

  • bats: init 167/167 (new: feature parsing incl. error-message listing, strict/default summary lines, settings --strict-network seeding, empty-stacks case, unknown-option rejection; interactive stubs updated for the new feature label)
  • Full bats: 16/16 suites
  • Hands-on integration in a real container: init --stacks python --features strict-network generates {\"network\":[{\"preset\":\"python\"}]} (no wildcard); stack healthy; pypi.org 200 (stack preset), www.anthropic.com + github.com 200 (presets expanded from the user-settings layer — expansion works across layers), example.com DNS REFUSED (rc=6 before HTTP); real PyPI package fetch end-to-end through the proxy (JSON API → wheel from files.pythonhosted.org, valid zip). Note: pip download itself is unavailable in the devbox/nix python (no ensurepip) — toolchain quirk, not policy; the fetch above covers the network path.

🤖 Generated with Claude Code

Base automatically changed from feat/2-network-presets to master September 4, 2026 09:10
@adamw

adamw commented Sep 4, 2026

Copy link
Copy Markdown
Member

I guess the predefined network settings should hold as many presets, as stacks have been chosen? so each stack chosen (to install dependencies) translates to a network preset?

…ildcard

Builds on the network presets (#2/#105). `sandcat init --features
strict-network` (or SANDCAT_STRICT_NETWORK=true) generates project settings
whose `network` list holds one `{"preset": "<stack>"}` entry per resolved
stack and no allow-all-GET wildcard, so anything beyond the stack
registries and the user-settings layer (the agent's own API hosts) is
denied by default — including DNS resolution.

Kept opt-in on purpose: flipping the default would surprise every new
project with "sandcat blocks the internet"; the summary line now states
which policy the project got and how to switch.

`init settings` grows --strict-network/--stacks flags; with no stacks the
strict list is empty (user-settings layer only). Preset names are expanded
by the addon at proxy start, so domain lists update with the sandcat
version instead of freezing in the project file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@shejnowicz
shejnowicz force-pushed the feat/2-strict-network branch from a7cd279 to a3de325 Compare September 7, 2026 08:32
@shejnowicz

Copy link
Copy Markdown
Collaborator Author

Exactly — that's what this PR does: with --features strict-network, every resolved stack becomes one {"preset": ""} entry in the project settings (so --stacks python,java → presets python + java; scala resolves to java scala via the existing stack-deps mechanism and gets both). A test keeps STACK_NAMES and the preset registry in sync so a new stack can't ship without a matching preset.

@adamw

adamw commented Sep 7, 2026

Copy link
Copy Markdown
Member

Ah ok, thanks :)

@adamw
adamw merged commit b240941 into master Sep 7, 2026
5 checks passed
@adamw
adamw deleted the feat/2-strict-network branch September 7, 2026 08:54
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