Skip to content

Fabric door on a group-restricted unix socket with kernel-attested peers; placed host writes through it; retire fabric_storage_append_principal_unrefused - #12482

Merged
gunbai-bot[bot] merged 28 commits into
mainfrom
session/jolly-owl-158-socket
Sep 29, 2026
Merged

gunbai-bot[bot] merged 28 commits into
mainfrom
session/jolly-owl-158-socket

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

Depends on #12451. This branch contains #12451. Until that lands, the diff against main includes it; review the commits after 5fa60e86a9.

This PR retires gunbc.rung_drop fabric_storage_append_principal_unrefused by its trigger. The retirement is carried in the row's standing: Retired { trigger_fired } receipt, the same way every other retired drop records it. It implements the operator ruling relayed by proud-deer-538 on 2026-09-27: the fabric backend moves to a group-restricted unix socket, and FabricStorageLocalFiles is retired for the placed host, so the placed host also writes through the door.

The door

  • Seed. gunbc serve --unix-socket <path> is added to the modeled CLI surface (gunbc.cli_dispatch_surface) and to the seed.
    • It binds the socket and replaces a stale socket, but refuses to replace any other kind of file.
    • It opens the socket's mode, because the socket's directory is the filesystem wall.
    • For each connection it reads the peer from the kernel (SO_PEERCRED → account name) and passes it to the handler as peer_user. TCP attests nothing, so peer_user is "" there.
    • An unresolvable peer drops the connection.
    • Seed tests: cli_run serve_unix_socket_door_tests, 3 tests passing.
  • Placement. The door is fabric_storage_door_socket inside fabric_storage_door_directory: owner is the service account, group is ghrunner, and the group can only traverse.
    • That directory's dependents are the local writer roster, so the kernel and the handler read one declaration.
    • The store areas are now service-only (0700, entries 0400). The ghrunner group and the entry repair are removed.
  • Admission. In gunbc.fabric_writer_roster, fabric_door_principal_of sorts every connection into one of three cases:
    • peer root is the tailscale proxy, so the request's login is checked against the served roster;
    • any other peer is judged as itself against the local roster, and any header it sends is ignored;
    • no peer at all is unattested.
    • Refusals are typed FabricWriterRefusal arms: WriterLoginAbsent, WriterLoginUnrostered, WriterPeerUnrostered, WriterPeerUnattested.
  • Client. fabric_storage_binding_for binds the placed host to FabricStorageDoorSocket, which uses curl --unix-socket through the new extdeps.http.client PostStdinWithinUnixSocket. No placement derives FabricStorageLocalFiles any more; it remains only for the door's own realization and for fixtures and instruments over their own roots.
  • Deploy. The unit runs --unix-socket and binds no --host/--port. The tailscale route targets unix:<socket>. That target form is in upstream ipn/serve.go (ExpandProxyTargetValue), and since v1.98.9 only root may configure it (TS-2026-005); our apply already runs it privileged.
  • Identity reading. On srv1, the observe mode now reads local <user> through the socket (FabricIdentityLocalPeer).

Evidence (executed locally, all true)

  • Wet claims over the real handler and real files:
    • the outsider-login and absent-login REDs;
    • a_put_or_advance_from_an_unrostered_local_account_is_refused_even_with_a_rostered_login_by_real_execution (forged header from a local account);
    • a_put_or_advance_on_an_unattested_connection_is_refused_by_real_execution;
    • positive controls for a rostered login and a rostered local account.
  • The Fabric served door refuses unrostered writers (roster derived from writer-identity readings) #12451 mutation (admission forced to admitted) reds the refusal claims through the same binding.
  • The roster witness: header believed only from the proxy peer; the local roster equals the door directory's dependents; store areas admit no writer but the service.
  • The wire witness, including every writer-refusal arm.
  • test.claim.live_deploy.emit: the unit binds the socket, the route proxies to it, the areas and the door directory have the expected modes, the entry mode is 0400, and no entry repair is emitted.
  • pair_serving_d0_witness the_wet_door_refuses_while_the_fabric_storage_write_wall_drop_stands: with the row Retired, D0 still refuses, now on d0_store_operation_wall.

Not walled, stated

  • Root, and the service account itself, can still write the files directly (fabric_storage_directory).
  • The served roster is empty: no fleet host has resolved the door (srv3 and srv4 hit curl exit 6).
  • This takes effect on srv1 only once dashboard_deploy applies this revision. After deploy, check:
    • tailscale version is recent enough for unix targets;
    • entries ghrunner wrote before the cutover are still readable by the service.
  • The per-operation D0 wall remains d0_store_operation_wall (lively-dove-256).

🤖 Generated with Claude Code

Brian Searls and others added 12 commits September 27, 2026 21:07
…e writer-identity readings, FabricWriterRefused

The served handler admits put/advance only for a login in gunbc.fabric_writer_roster's roster,
derived from fabric_writer_identity_observe receipts (today none grounds a login: srv1 unproxied,
srv3/srv4 cannot resolve the door), so the door refuses every served write. The drop row stays:
the loopback listener and the in-process binding are the second half (unix-socket PR next).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…915, DESIGN §3c)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Ledger-Repair-Judged: docs/design-rung-drops.md
Ledger-Rows-Repaired: docs/design-rung-drops.md fabric_storage_append_principal_unrefused
Heal-Candidate-Run: 36353985246
…st roster rung (review 71929); schedule the new wet claims

- FabricWriterRefused carries FabricWriterRefusal (WriterLoginAbsent | WriterLoginUnrostered { login })
  through the handler, the wire and the fault rendering, instead of prose in a principal field.
- Receipt rows derive their binding from the placement (fabric_storage_binding_for); no re-minted URL.
- The roster is stated as an authored roster of recorded readings: the row-to-run correspondence is
  review diligence (rung 1), next trigger a typed receipt store the observe mode writes.
- The four new wet claims are scheduled in local_repo_wet_terminal and floor_route_gap.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…y its trigger; schedule the local-peer wet claims

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…refusal gains its peer arms

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…into v2.compiler.target_serialize

Pure move: target_serialize_source_from_model and the 84 declarations it
reaches (none touch infer/resolve/ingest) now live in their own module, which
translate imports. Every renderer of target text -- the bash command fold behind
gunbc.shell_command_text, ci_failure_class, the yaml/sql folds -- no longer
compiles the pipeline stages. 59 importers and 12 qualified-name citations
repointed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

Review 72010: added a SeedGrowthJustification receipt, gunbc.fabric_door_socket_seed_growth, registered in gunbc.seed_growth_admission. It lists the five citable hand items (ServeConnection, ServeListener, ServeBoundAddress, serve_bind, serve_peer_user) and names what isn't citable (the impl blocks, the listener methods and the test module). Its reason is that a bind and an SO_PEERCRED read on an accepted connection are host facts, and the seed decides nothing: the peer reaches .dag as a value. Owning lane v1-hand-queue-drain. Trigger: serve becomes a v2-native CLI verb with an attested-peer socket effect the rendered main realizes. — sent from jolly-owl-158

Brian Searls and others added 7 commits September 28, 2026 03:27
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eceipt claim reads it, not the whole script (floor budget)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…usal arms

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rs the real script and asserts the route (DESIGN §3, proud-deer-538)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every bash command the fold serializes rebuilt the constant fold grammar inside
its own demand: bash_fold_serialize_leaf_node rebuilt the production catalog,
encoded it to a catalog node, rebuilt lex rules and transform maps, derived its
relation row twice, and handed v2.compiler.target_serialize a rules node that
the generic entry walked for its recursion budget and re-selected the same row
from, then validated against a serialize source spelled from that same row.
That is ~40k evaluator steps per one-word command, and ~1.4M for the 7 KB
approval-broker dark-install script (DESIGN 6b: a constant re-derived in
subject-local demand; 2: demand minimisation, not a cache).

- extdeps.languages.bash_command_fold: the catalog, its node, its subtree
  count, lex rules, binding spellings and emit transforms are data; the target
  model, serialize source and rules node are built from one derived row.
- target_serialize: target_serialize_source_from_selected_row serializes a row
  the caller established, with the same recursion budget and refusal as the
  generic entry; nonterminal items still go through the generic selection.
- workflow.bash_command_fold_serialize: the leaf derives the row once and uses
  that entry.

Emitted bytes are unchanged: dark-install + apply + retract scripts and a
quoting-edge argv compare byte-identical against the base (32,557 bytes).
Two claims pin the new route: the carried budget equals the rules node's count,
and the selected-row route spells what the generic route spells; each goes red
under a one-token mutation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brian Searls and others added 4 commits September 28, 2026 09:44
…e socket branch

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…socket edits re-applied)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Sep 28, 2026
…transport

Integrates the transport-specific changes from sibling PR #12482 at 6c6a238, excluding its unrelated compiler/bash-fold performance changes. Retains the allocation branch protocol split and cookie/response-header support. Protected state requires socket principal admission plus its signed envelope; production protected service writers retain their HTTPS proxy route. This is isolated draft integration, not deployment or approval of the dependency.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… 2026-09-29)

One identity, its own list in v2.workflow.floor_eval_step_cost_drop and its own gunbc.rung_drop row:
the first reader of witness_approval_broker_dark_script_text is billed the generic bash emit path's
per-step overhead, inherited from main (script bytes identical) and re-judged only because
deployment_spec_srv1 changed. Measured by floor run 36490489535. Trigger: that overhead reduced so the
first reader fits the new-witness budget; moving the bill does not retire it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Sep 29, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 29, 2026
Brian Searls and others added 2 commits September 29, 2026 08:32
…option

claim_executor --required-regen at 78c2e4c drifted the two CLI mirrors (the compiled-in surface
lacked the unix_socket row, so its first generation dropped the option from the dispatch). Installed
the surface candidate, rebuilt: first_generation_equal=true (0 drift); standalone
--required-regen-fixed-point: fixed_point_equal=true.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Sep 29, 2026
Merged via the queue into main with commit 59d71c7 Sep 29, 2026
5 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/jolly-owl-158-socket branch September 29, 2026 11:30
gunbai-bot Bot pushed a commit that referenced this pull request Sep 29, 2026
…drop projection regenerated

floor_eval_step_cost_drop keeps the boot-matrix rows and main's dark-install render rows side by
side, and floor_eval_step_cost_drop_all_rows concatenates both. docs/design-rung-drops.md is
regenerated by generated_artifact_gate main_wet over a build of the merged tree.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.

0 participants