Repository navigation
feat(minzoned,minvmd,minimal): one box-name service for a Mac's users, admitting a group - #2976
bryan-minimal wants to merge 2 commits into
Conversation
…, admitting a group `minzoned --admit-group GROUP`: the installed service admits, besides its own uid, root and every member of the group, judged on the peer's uid from the kernel before a byte of it is read (getgrouplist, the primary group and every supplementary one, with the buffer grown on truncation). A node is the hello's node id qualified with that uid, so another user speaking the same id is another node: nobody can replace or release another user's rows by naming their daemon, a clash between them is the ordinary first-publisher clash with the holder named, uid included, and the service keeps no state across a restart. The refusal a non-member reads names their account and the one command that admits them. `min finalize-install --show` knows such a shared service: the unit's `--admit-group`, the socket expected to be the group's (0660, the group's write bit) and the service account's, not the operator's; an operator outside the group is told the way in. The step never replaces the shared service, for a member or root either: over a custody failure or a protocol mismatch it is unavailable, with the package that installed the service named as the remedy, and `--undo` is refused over a unit that admits a group. With no user daemon reporting a port, the names item judges by the port the host's resolver hook names, when the service answers there. The macOS system package (next) runs the service this way under a role account. Spec 18's open question on several users of one host, option 2. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
|
|
Lab prepush on anvil for this commit (6a4e81c on PR 1; job 01828, CI's commands on the box): fmt, clippy |
…caps each user, keeps a released name theirs The four things the pre-PR read of #2976 found, and the smaller ones: - A group member is judged on the connection's own thread; the accept loop judges only what needs no lookup (the own uid, root, every peer of a single-operator answerer). On macOS membership asks the membership API (nested groups, more than sixteen groups), with getgrouplist behind it. - The shared service caps each user: 32 open channel connections, a quarter of the box range. A single-operator answerer caps nothing. - A box name stays its last user's for the answer TTL after its row goes, as an address does, so a reconnect never loses a name to another member. Across a service restart nothing is remembered; spec 18 says so. - The CLI's `--undo` and reinstall guards fail closed on a unit file that is there but not text (a binary plist, an unreadable file), naming the file. - `--admit-group` is read from the unit's program arguments, not anywhere in the file. A refusal names another user's node by uid, never by its state directory. The add-to-group line is the service's, by platform. - The admission test reads the account's groups, not the process's, and holds under root. Misplaced doc comments sit on their items. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Spec lint
Advisory. None of this blocks the merge; the review decides. Advisory, and never a merge gate. Linter: |
minzoned --admit-group GROUP: the installed service admits, besides itsown uid, root and every member of the group, judged on the peer's uid
from the kernel before a byte of it is read (getgrouplist, the primary
group and every supplementary one, with the buffer grown on truncation).
A node is the hello's node id qualified with that uid, so another user
speaking the same id is another node: nobody can replace or release
another user's rows by naming their daemon, a clash between them is the
ordinary first-publisher clash with the holder named, uid included, and
the service keeps no state across a restart. The refusal a non-member
reads names their account and the one command that admits them.
min finalize-install --showknows such a shared service: the unit's--admit-group, the socket expected to be the group's (0660, the group'swrite bit) and the service account's, not the operator's; an operator
outside the group is told the way in. The step never replaces the shared
service, for a member or root either: over a custody failure or a protocol
mismatch it is unavailable, with the package that installed the service
named as the remedy, and
--undois refused over a unit that admits agroup. With no user daemon reporting a port, the names item judges by the
port the host's resolver hook names, when the service answers there.
The macOS system package (next) runs the service this way under a role
account. Spec 18's open question on several users of one host, option 2.
Context
Second of three stacked PRs for the macOS system install (gominimal/inbox#1179), on top of #2975. Spec 18 (
docs/specs/18-spec-box-networking.md) leaves the question of several users of one host open and lists the options; this is option 2: one box-name service for the Mac, admitting a group, with a node keyed by its id and the peer's uid. The per-user service's single-uid rule is unchanged; nothing changes on Linux.Proof
Three review rounds on the minfarm found and fixed, in order: a bindings file (removed; the pair keying replaced it), a takeover through
finalize-installby a group member, the ERANGE handling, the refusal wording, the mode check. The design, probes and rounds are in the farm'sdocs/research/box-name-service-users.md(gominimal/minfarm). minimal's Linux PR gates reproduced on the farm's Linux lane (the first run caught a getgrouplist buffer type that isinton macOS andgid_ton Linux); minvmd's tests on macOS (685); the lab prepush on anvil.The pre-PR review (2026-11-04), settled in the second commit
The four things the read found, and the smaller ones, are in
5f8f7cb6:mbr_check_membership(nested groups, more than sixteen), withgetgrouplistbehind it. The admission test reads the account's groups, not the process's, and holds under root.--showoffer nothing and--undorefuse, both naming the file and theplutilline that reopens it.--admit-groupis read from the unit's program arguments (the plist'sProgramArgumentsarray, the unit'sExecStart=), not from anywhere in the file.--showagree.Proof of the second commit
cargo nextest run -p minimal --libin a box): 702 passed, 1 skipped (j-4f06879a0ed6efb6).cargo nextest run -p minvmd --libon a Mac: 689 passed. Clippy clean on the three crates.dseditgroupline; a member published a name and went, root was refused it (another user's node (uid 501) released this name less than 15 s ago; it stays theirs for 14 s more), the member took it straight back; the 33rd connection of one user was refused with the count and the 32nd served;plutil -convert binary1on the plist made--showand--undorefuse naming the file, exit 1, andxml1reopened them. The package journey itself passed on the same build (j-dfb7a945fce76e81).Still to decide, not code: the package README's open questions (#2977).
🤖 Generated with Claude Code