8000 T76 — Reserve the local range on the macOS host by the advisory's privileged step · Issue #1817 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content
Dismiss alert

T76 — Reserve the local range on the macOS host by the advisory's privileged step #1817

Closed

Description

@norrietaylor

Task

slice size difficulty model who estimated lines
Names resolve natively in any browser M needs care strongest an agent 520 (220 code, 300 tests)

On macOS, the one advisory command configures the resolver and installs a LaunchDaemon whose plist and program sit at root-owned, non-user-writable paths, read no configuration and apply exactly 127.0.64.0/24 as lo0 aliases now and at every boot; afterwards the bind probe the daemon runs at session start, read on the host, reads present, a session publishes from the range, and the 127.0.0.1 interim ends with no prompt; custody (owner root, not user-writable, the plist pointing at the root-owned copy) is checked and a failure re-surfaces the advisory; the range comes back after the unit is loaded again as at boot, the job is loaded and enabled for boot, and both this case and a real reboot are manual checks the PR body records with the date, macOS version and the case's transcript lines from the last by-hand run; in CI the rendered command is proved by the unit tests, which parse it with /bin/sh -n; the Linux command is unchanged, its routing-domain link keeping its routable-scope address.

Covers:

  • NET-123

Layers:

  • cli:
    • crates/minimal/src/resolver.rs: on macOS the advisory command gains the range step in the same one sudo sh -c that writes the resolver file. The step writes the range program and its LaunchDaemon plist from bytes the command itself carries (no staged file, no user-writable source copied), to /Library/PrivilegedHelperTools/dev.minimal.local-range and /Li 8000 brary/LaunchDaemons/dev.minimal.local-range.plist, owned root:wheel, the program 0755 and the plist 0644, and bootstraps the unit into the system domain so it runs now and, with RunAtLoad and no KeepAlive, at every boot; a re-run boots the old unit out first, so the step is idempotent. The program is rendered from its template with the range's host addresses from switch::loopback::range_hosts filled in at render time, so it reads no argument, environment variable or file, and applies exactly the reserved range 127.0.64.0/24 as /32 lo0 aliases by absolute path (/sbin/ifconfig lo0 alias for host parts 1 to 254, the addresses the bind probe reads) and nothing else. Custody is checked where the hook is detected and covers the path, not just the two files: every directory component of both paths, from / down, is owned by uid 0 with no group or other write (never a path under $HOME or a user-owned Homebrew prefix), both files are owned by uid 0 with no group or other write, the plist's ProgramArguments names the root-owned program path, and the loaded job's Program/ProgramArguments in launchctl print system/dev.minimal.local-range names that same path, so a job loaded from elsewhere under the label fails custody; a failed check re-surfaces the advisory naming the failed check and the command, which reinstalls both files. The comment "The command rendered here does not carry that step yet" and advisory_at's doc line "not yet part of the command it renders here" are replaced: on macOS the interim fact says the command below installs the range and ends the interim, and the command line says it configures the resolver and reserves the range. The privileged step is shared with T71 as one command with two units: the range unit runs as root once per load, and T71's answerer unit runs as the operator under socket activation and must never be root, so neither unit is folded into the other, they share no file, label or program, and whichever of the two tasks lands second appends its step to the same command, which stays one command with exactly one privilege elevation (one sudo), never two invocations the user runs separately; T71's text is not changed. On Linux the command is unchanged: any 127/8 address binds on lo, so Linux takes no range step, and the dedicated link keeps its routable-scope /32 address (ZONE_LINK_ADDR), without which resolved never consults the routing domain. NamingSurface gains the range unit's state and custody verdict for the bundle
    • crates/minimal/src/resolver/reserve-local-range.sh (new): the range program's template, a /bin/sh script with no inputs that aliases each host address of the reserved range on lo0 by absolute path and exits non-zero on the first failure
    • crates/minimal/src/resolver/dev.minimal.local-range.plist (new): the LaunchDaemon plist template: label dev.minimal.local-range, ProgramArguments the root-owned program path alone, RunAtLoad true, no KeepAlive, no UserName (it runs as root), no EnvironmentVariables
    • cargo nextest run -p minimal advisory_command_reserves_the_range_on_macos
    • cargo nextest run -p minimal range_program_applies_exactly_the_reserved_range
    • cargo nextest run -p minimal range_step_custody_is_root_owned
    • cargo nextest run -p minimal range_step_custody_walks_every_path_component
    • cargo nextest run -p minimal macos_advisory_command_elevates_exactly_once
    • cargo nextest run -p minimal range_step_custody_failure_resurfaces_the_advisory
    • cargo nextest run -p minimal linux_advisory_command_is_unchanged
    • cargo nextest run -p minimal bind_probe_reads_present_after_the_range_step
    • cargo nextest run -p minimal interim_advisory_says_the_command_ends_it_on_macos
  • docs:
    • docs/specs/18-spec-box-networking/18-spec-box-networking.md: NET-123 gains the sub-requirement "WHERE the host is macOS THE SYSTEM SHALL name, in NET-122's advisory command, a privileged step that installs a boot-time service, from root-owned non-user-writable paths and reading no configuration, which applies exactly the reserved local range to the host loopback at install and at every boot", tier T0, verify cargo nextest run -p minimal advisory_command_reserves_the_range_on_macos; its comment says Linux takes no range step and keeps the routing-domain link's address
  • e2e:
    • scripts/session-e2e.sh: adds the case local_range_reserved_by_privileged_step, a privileged, operator-run case that no CI lane runs: it installs a root LaunchDaemon, and the macOS lane's runner is a persistent shared host that is not given passwordless sudo. Unless MINIMAL_E2E_PRIVILEGED=1 is set it prints SKIPPED (privileged: set MINIMAL_E2E_PRIVILEGED=1 on a macOS host with passwordless sudo) and exits 0; with it set, a missing precondition (not macOS, no launchctl, no passwordless sudo) fails rather than skips (Linux needs no range step, so it is never run there): it runs the advisory's command, asserts both files' custody and that the plist runs the root-owned copy, asserts the bind probe reads present and a session started afterwards publishes from the range with no interim and no advisory, asserts launchctl print system/dev.minimal.local-range shows the job loaded with RunAtLoad true and launchctl print-disabled system does not list it disabled, removes the aliases and kickstarts the unit as a boot would load it to show the range re-applied with no user action, then boots the unit out, removes both files and the aliases
    • ./scripts/session-e2e.sh local_range_reserved_by_privileged_step

Waits on:

Plan block
### T76 — Reserve the local range on the macOS host by the advisory's privileged step
  slice: S3
  kind: task
  covers: NET-123
  size: M
  est: 220 code, 300 tests
  executor: agent
  difficulty: needs care
  model: strongest
  diagnostics: the bundle's naming surface records whether the range unit is installed, the owner and mode of its plist and its program, the program path the plist runs, and the custody verdict beside the bind probe's result, so a macOS host still on the 127.0.0.1 interim, or holding a range unit whose custody fails, reads why in a bundle
  observability: one info log line at session start naming the range unit's state (absent, installed, or custody failed and which check) beside the probe result and the surface chosen; the advisory stops re-surfacing for the range once the probe reads present and custody holds
  layers:
    - cli:
      - crates/minimal/src/resolver.rs: on macOS the advisory command gains the range step in the same one `sudo sh -c` that writes the resolver file. The step writes the range program and its LaunchDaemon plist from bytes the command itself carries (no staged file, no user-writable source copied), to /Library/PrivilegedHelperTools/dev.minimal.local-range and /Library/LaunchDaemons/dev.minimal.local-range.plist, owned root:wheel, the program 0755 and the plist 0644, and bootstraps the unit into the system domain so it runs now and, with RunAtLoad and no KeepAlive, at every boot; a re-run boots the old unit out first, so the step is idempotent. The program is rendered from its template with the range's host addresses from switch::loopback::range_hosts filled in at render time, so it reads no argument, environment variable or file, and applies exactly the reserved range 127.0.64.0/24 as /32 lo0 aliases by absolute path (/sbin/ifconfig lo0 alias for host parts 1 to 254, the addresses the bind probe reads) and nothing else. Custody is checked where the hook is detected and covers the path, not just the two files: every directory component of both paths, from / down, is owned by uid 0 with no group or other write (never a path under $HOME or a user-owned Homebrew prefix), both files are owned by uid 0 with no group or other write, the plist's ProgramArguments names the root-owned program path, and the loaded job's Program/ProgramArguments in `launchctl print system/dev.minimal.local-range` names that same path, so a job loaded from elsewhere under the label fails custody; a failed check re-surfaces the advisory naming the failed check and the command, which reinstalls both files. The comment "The command rendered here does not carry that step yet" and advisory_at's doc line "not yet part of the command it renders here" are replaced: on macOS the interim fact says the command below installs the range and ends the interim, and the command line says it configures the resolver and reserves the range. The privileged step is shared with T71 as one command with two units: the range unit runs as root once per load, and T71's answerer unit runs as the operator under socket activation and must never be root, so neither unit is folded into the other, they share no file, label or program, and whichever of the two tasks lands second appends its step to the same command, which stays one command with exactly one privilege elevation (one sudo), never two invocations the user runs separately; T71's text is not changed. On Linux the command is unchanged: any 127/8 address binds on lo, so Linux takes no range step, and the dedicated link keeps its routable-scope /32 address (ZONE_LINK_ADDR), without which resolved never consults the routing domain. NamingSurface gains the range unit's state and custody verdict for the bundle
      - crates/minimal/src/resolver/reserve-local-range.sh (new): the range program's template, a /bin/sh script with no inputs that aliases each host address of the reserved range on lo0 by absolute path and exits non-zero on the first failure
      - crates/minimal/src/resolver/dev.minimal.local-range.plist (new): the LaunchDaemon plist template: label dev.minimal.local-range, ProgramArguments the root-owned program path alone, RunAtLoad true, no KeepAlive, no UserName (it runs as root), no EnvironmentVariables
      test: cargo nextest run -p minimal advisory_command_reserves_the_range_on_macos
      test: cargo nextest run -p minimal range_program_applies_exactly_the_reserved_range
      test: cargo nextest run -p minimal range_step_custody_is_root_owned
      test: cargo nextest run -p minimal range_step_custody_walks_every_path_component
      test: cargo nextest run -p minimal macos_advisory_command_elevates_exactly_once
      test: cargo nextest run -p minimal range_step_custody_failure_resurfaces_the_advisory
      test: cargo nextest run -p minimal linux_advisory_command_is_unchanged
      test: cargo nextest run -p minimal bind_probe_reads_present_after_the_range_step
      test: cargo nextest run -p minimal interim_advisory_says_the_command_ends_it_on_macos
    - docs:
      - docs/specs/18-spec-box-networking/18-spec-box-networking.md: NET-123 gains the sub-requirement "WHERE the host is macOS THE SYSTEM SHALL name, in NET-122's advisory command, a privileged step that installs a boot-time service, from root-owned non-user-writable paths and reading no configuration, which applies exactly the reserved local range to the host loopback at install and at every boot", tier T0, verify cargo nextest run -p minimal advisory_command_reserves_the_range_on_macos; its comment says Linux takes no range step and keeps the routing-domain link's address
    - e2e:
      - scripts/session-e2e.sh: adds the case local_range_reserved_by_privileged_step, a privileged, operator-run case that no CI lane runs: it installs a root LaunchDaemon, and the macOS lane's runner is a persistent shared host that is not given passwordless sudo. Unless MINIMAL_E2E_PRIVILEGED=1 is set it prints `SKIPPED (privileged: set MINIMAL_E2E_PRIVILEGED=1 on a macOS host with passwordless sudo)` and exits 0; with it set, a missing precondition (not macOS, no launchctl, no passwordless sudo) fails rather than skips (Linux needs no range step, so it is never run there): it runs the advisory's command, asserts both files' custody and that the plist runs the root-owned copy, asserts the bind probe reads present and a session started afterwards publishes from the range with no interim and no advisory, asserts `launchctl print system/dev.minimal.local-range` shows the job loaded with RunAtLoad true and `launchctl print-disabled system` does not list it disabled, removes the aliases and kickstarts the unit as a boot would load it to show the range re-applied with no user action, then boots the unit out, removes both files and the aliases
      test: ./scripts/session-e2e.sh local_range_reserved_by_privileged_step
  produces: none
  consumes:
    - crates/minimal/src/resolver.rs
    - crates/switch/src/loopback.rs
  proof: On macOS, the one advisory command configures the resolver and installs a LaunchDaemon whose plist and program sit at root-owned, non-user-writable paths, read no configuration and apply exactly 127.0.64.0/24 as lo0 aliases now and at every boot; afterwards the bind probe the daemon runs at session start, read on the host, reads present, a session publishes from the range, and the 127.0.0.1 interim ends with no prompt; custody (owner root, not user-writable, the plist pointing at the root-owned copy) is checked and a failure re-surfaces the advisory; the range comes back after the unit is loaded again as at boot, the job is loaded and enabled for boot, and both this case and a real reboot are manual checks the PR body records with the date, macOS version and the case's transcript lines from the last by-hand run; in CI the rendered command is proved by the unit tests, which parse it with /bin/sh -n; the Linux command is unchanged, its routing-domain link keeping its routable-scope address.
  depends on:
    - blocked by #1656
    - assumes T71 (#1803) appends its answerer unit to the same privileged command whichever of the two lands second; the range unit shares no file, label or program with it, so neither task blocks the other

Design ruling

Design §7.1 folds the reservation of the local range into the macOS advisory command NET-122 names, but the command the advisory renders today writes only the resolver file. crates/minimal/src/resolver.rs says so itself ("The command rendered here does not carry that step yet"). Until the step exists, a macOS host stays on NET-123's 127.0.0.1 interim, and running the advisory's command never ends it. This task completes the advisory text #1656 (T15) reports from.

The architecture ruling, binding on this task:

  • The macOS advisory command gains the range step.
  • The range step is a LaunchDaemon, with its plist and its program at root-owned, non-user-writable paths. It reads no configuration and applies exactly the reserved range, 127.0.64.0/24, as lo0 aliases, now and at every boot.
  • After the command runs, the session-start bind probe reads present and the 127.0.0.1 interim ends with no prompt.
  • Custody is checked: owner root, not user-writable, and the plist points at the root-owned copy.
  • The range survives a reboot.
  • The task is macOS-only. Linux takes no range step, because any 127/8 address is bindable on lo. The Linux command stays unchanged, and so does the routable-scope address on its dedicated link, which systemd-resolved needs before it consults the routing domain. A test pins the Linux command.

The privileged step is shared with T71 (#1803) as one command with two units. The range unit runs as root, once per load. T71's answerer unit runs as the operator under socket activation and must never be root. Neither unit is folded into the other, and they share no file, label or program. Whichever of the two tasks lands second appends its step to the same command, so neither blocks the other.

Acceptance:

  • on macOS the advisory's one command writes the resolver file and installs the range unit;
  • the installed program reads no argument, environment variable or file and aliases exactly the range's host addresses;
  • the plist and program are owned by root, not user-writable, and the plist runs the root-owned copy, and a failed custody check re-surfaces the advisory;
  • after the command, the bind probe reads present, a session publishes from the range, and no interim or prompt follows;
  • the range comes back when the unit loads again, as it does at boot;
  • the Linux command is byte-for-byte unchanged.

Activity

  1. added
    kind:taskA task the plan skill rendered; the body carries ## Task
    size:M200 to 500 net lines; one PR
    model:strongestThe strongest model available: unknown ground, or large work that needs care
    on Oct 2, 2026
  2. minimal-foundry commented on Oct 2, 2026

    @minimal-foundry
    Contributor

    Done. #1825 merged.

    branch agent/1817-reserve-the-local-range-on-the-macos-host-by-the · epic #1437 · PR #1825

    Updated 2026-10-28T06:17:32.453Z.

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

    kind:taskA task the plan skill rendered; the body carries ## Taskmodel:strongestThe strongest model available: unknown ground, or large work that needs caresize:M200 to 500 net lines; one PR

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0