Skip to content

network-tiers: map neutral network.tier to sbx + msb egress primitives; ship balanced default #294

Open

Description

@wz-gsa

Part of the neutral-network-tiers epic (patterns ADR 0002 isolation / patterns PR #299).

Scope

Consume the neutral network.tier (strict|balanced|open) + the curated balanced baseline (patterns data file, SHA-pinned) in the acq adapters, so both backends apply the same tiered egress.

Adopt existing work — feat/msb-balanced-egress (ADR-0018)

The msb half already exists and is default-on: vendored acq.backends/msb-balanced-hosts.txt + _acq_msb_balanced_rules_into (--net-default deny + translated --net-rule allow@…, DNS grant, crl* widening logged, SI-10 hardening, ACQ_MSB_BALANCED_EGRESS toggle). Adopt/rename this emitter under the neutral network.tier contract — do not re-implement. Decide the canonical baseline location (ADR-0018 anticipates migrating the vendored list into a patterns kit / #301).

Requirements

  • kit-translate.sh / adapters: compute the effective allowlist = tier baseline (balanced) ∪ per-kit caps.network.allow ∪ per-sandbox user additions. Deny-by-default preserved.
    • msb (acq.backends/msb.sh): tier balanced → the ADR-0018 emitter path; strict → kit-hosts-only (ACQ_MSB_BALANCED_EGRESS=0 behavior); reconcile the toggle with the tier selector so they don't conflict.
    • sbx (acq.backends/sbx.sh / kit-translate): map the tier to the appropriate sbx policy posture + merged allow hosts. Note sbx policy is currently a manual user step / passthrough — decide whether acq now drives it or documents it.
  • Default: network.tier: balanced (matches the msb default ADR-0018 already ships and the sbx baseline the project recommends). strict and open explicitly selectable; GFE / high-assurance SHOULD pin strict.
  • open tier gated/warned (testing only; never GFE).
  • Tests in scripts/test-acq: strict = kit-hosts-only; balanced = baseline ∪ kit hosts emitted; per-sandbox add still works; omission → balanced; parity asserted across both backends.
  • Docs: BACKEND_GUIDE + QUICKSTART explain the tiers, the default, and how to change tier / add a domain. Fold ADR-0018 into this neutral framing.

Depends on the patterns schema (#300) + baseline data (#301). AI-assisted (OpenCode); consensus-reviewed. Requires human review.

Activity

  1. mogul commented on Aug 7, 2026

    @mogul
    Contributor

    Adopt existing work — feat/msb-balanced-egress (ADR-0018)

    This branch is now in a PR.

  2. wz-gsa commented on Aug 12, 2026

    @wz-gsa
    ContributorAuthor

    Design proposal — network.tier adapter migration (held for maintainer sign-off)

    Ran the migration approach through a 7-voter higher-order consensus: 7/7 approve, 100%. Because this edits acq.backends/msb.sh (mogul's actively-iterating file) and changes a shipped user-facing toggle, I'm posting the design for sign-off rather than surprise-PRing it — especially the msb-emitter half.

    Decision: Option A — neutral selector + deprecated alias (no silent flip)

    • ACQ_NETWORK_TIER — the single neutral selector, values strict | balanced | open, default balanced (unchanged posture; backend-consistent with the shipped msb default + the sbx baseline).
    • ACQ_MSB_BALANCED_EGRESS becomes a deprecated ALIAS: if set, map 1 → balanced, 0/empty → strict, and print a one-time deprecation notice pointing at ACQ_NETWORK_TIER. ACQ_NETWORK_TIER wins when both are set. Remove the alias in a future major.
    • Fail-safe (the panel's key point): old-on users stay balanced; old-off users move to strict (more restrictive, not looser). No upgrade silently loosens egress. This is why we reject a hard-replace (would silently flip a security-relevant setting).
    • Effective allowlist (both backends): tier baseline (balanced) ∪ per-kit caps.network.allow ∪ per-sandbox additions, deny-by-default preserved. strict = kit hosts only. open = unrestricted.
    • open tier is gated: requires explicit confirmation (ACQ_NETWORK_TIER_CONFIRM_OPEN=1 or interactive), warns on every invocation, is logged, and is never a default / never for GFE — treated like --privileged.

    sbx backend (the one split in the vote)

    Consensus resolution: document the tier→sbx-policy mapping now + provide an explicit override escape hatch, but defer actually driving sbx policy to its own follow-up PR (enforcement path = bigger blast radius, deserves dedicated tests). So PR1 maps + documents; a follow-up makes acq drive sbx policy.

    Rollout — split into two PRs (unanimous)

    • PR1 (I own, no msb.sh churn): ACQ_NETWORK_TIER selector + the alias/deprecation shim + the open gate + documented sbx mapping + tests. Lives in common.sh / kit-translate.sh. The neutral layer reads the tier and, for msb, calls the EXISTING _acq_msb_balanced_rules_into emitter unchanged (translate, don't rename) — so it does not conflict with mogul's active msb.sh work.
    • PR2 (coordinated with @mogul): rename/retire ACQ_MSB_BALANCED_EGRESS + _acq_msb_balanced_rules_into internals to consume the tier directly, after PR1 lands and the deprecation window opens.

    Tests (PR1)

    Alias table (unset→balanced, 1→balanced+notice, 0→strict+notice, ACQ_NETWORK_TIER wins over alias, notice fires exactly once); tier→emitted-rules per backend; open without the confirm token fails fast; parity asserted across sbx/msb.

    Held for sign-off

    @mogul — this touches your msb.sh emitter + the ACQ_MSB_BALANCED_EGRESS toggle you shipped default-on. I'll implement PR1 (neutral selector, no msb.sh changes) once you're OK with the alias mapping + the split, and we coordinate PR2 (the msb rename) against your branch cadence. Flag anything you'd map differently.

    Consensus record: 7/7 approve (architect/security/devex/ai_ml/pm/catfish/scope_steward). AI-assisted (OpenCode).

  3. mogul commented on Aug 12, 2026

    @mogul
    Contributor

    @mogul — this touches your msb.sh emitter + the ACQ_MSB_BALANCED_EGRESS toggle you shipped default-on. I'll implement PR1 (neutral selector, no msb.sh changes) once you're OK with the alias mapping + the split, and we coordinate PR2 (the msb rename) against your branch cadence. Flag anything you'd map differently.

    Go for it.

  4. wz-gsa commented on Aug 18, 2026

    @wz-gsa
    ContributorAuthor

    Grooming: PR1 landed (neutral ACQ_NETWORK_TIER selector, strict|balanced|open default balanced; deprecated ACQ_MSB_BALANCED_EGRESS alias with fail-safe 0→strict; open-gate; sbx tier→policy mapping documented). Remaining scope for this issue is PR2: rename/retire the msb balanced-egress emitter internals to consume the tier directly, and make acq actually drive sbx policy from the tier (PR1 documents the mapping but defers enforcement). Coordinated with @mogul against the active msb work. Recommend relabeling this issue to 'PR2 only' so it accurately reflects what's left.

  5. Santoshkumarpuppala commented on Sep 23, 2026

    @Santoshkumarpuppala

    This issue depends on the kit field from GSA-TTS/agentic-coding-patterns#300 (GSA-TTS/agentic-coding-patterns#313: "Unblocks … quickstart #294 (adapter mapping)"), but nothing in acq reads caps.network.tier, and it isn't in the PR2 scope above. On msb the tier comes only from ACQ_NETWORK_TIER or the deprecated ACQ_MSB_BALANCED_EGRESS (acq.backends/msb.sh:487-520); sbx reads no tier yet. So on msb a kit with tier: strict gets balanced unless the operator also sets the env var.

    Checked offline on main (8e6160c) with the agentic-coding-playbook kit from patterns 5d1a877. I didn't start a sandbox.

    • kit_translate_to_sbx output is byte-identical with and without tier: strict. Control: changing one allow host changes it.
    • kit_validate (acq.backends/kit-translate.sh:1216) OKs the strict copy with no warning. Control: removing name: fails.
    • msb.sh sourced in a clean env resolves balanced, and resolves strict only through one of those two env vars.

    None of the 8 kits at that ref sets a tier, so nothing is misconfigured today. On the question in GSA-TTS/agentic-coding-patterns#300 about one kit strict and another balanced: today neither is read.

    The design comment above calls ACQ_NETWORK_TIER "the single neutral selector", so this may be deliberate. Either way one side needs to change:

    1. Read the field in PR2 and let a kit only tighten: the sandbox takes the most restrictive of the operator's tier and each kit's, so a kit's open never loosens anything. The cost is that one strict kit drops the baseline for every kit in that sandbox.
    2. Keep the env var as the only selector: have kit validate warn when the field is set (same shape as the block-volume floor warning tested at test/bats/110-volumes.bats:133), and change the patterns schema description, which says each backend maps it.

    Happy to open the PRs for 2 if that's the direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions