Skip to content

Fabric served door refuses unrostered writers (roster derived from writer-identity readings) - #12451

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

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

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

First half of the fabric write wall (gunbc.rung_drop fabric_storage_append_principal_unrefused). The drop row stays standing. Per the operator ruling relayed by proud-deer-538 on 2026-09-27, a second PR retires it by moving srv1's backend to a group-restricted unix socket and retiring FabricStorageLocalFiles.

What this changes

  • std.fabric_storage: adds a new fault arm, FabricWriterRefused { principal }, with its wire encode and decode in gunbc.fabric_storage_wire.
  • gunbc.fabric_writer_roster (new): holds the served door's roster of tailnet USER principals. The roster is derived from gunbc.fabric_writer_identity_observe receipts, and each receipt carries the run that took it. Nobody types a login into it.
  • gunbc.fabric_storage_serve: put and advance are admitted only for a rostered login. An outsider login and an absent login both get a typed FabricWriterRefused and no file is touched. Reads and identity are unchanged. The roster is a parameter of fabric_storage_serve_handle_over, and the served entry binds the derived roster.

The readings (2026-09-27, fleet-converge fabric_writer_identity_observe)

host run reading
srv1 36347411725 binding local, unproxied. This is the placed host, so it is not a reading of the door
srv3 36347414620 door not read: curl exit 6, Could not resolve host: srv1.tailecbe08.ts.net
srv4 36347416176 same as srv3
srv2 36347413355 queued on its runner when this PR opened

No reading grounds a login, so the derived roster is empty and the door refuses every served put and advance. This breaks no writer that works today, because no fleet host can reach the door. A host joins the roster only when a new reading is appended.

Evidence

All claims below were executed locally with gunbc run at uid 1000, and each returned true:

  • Served door, through the real handler over real files:
    • a_put_or_advance_from_a_login_outside_the_roster_is_refused_at_the_served_door_by_real_execution
    • a_put_or_advance_with_no_presented_login_is_refused_at_the_served_door_by_real_execution
    • a_rostered_login_puts_and_advances_through_the_served_door_by_real_execution (positive control)
    • The existing lost-race and identity claims still pass.
  • Discriminating mutation, run on a copy of the tree: replacing the admission binding in fabric_storage_respond with an unconditional FabricServedWriterAdmitted makes the outsider claim return false. The unmutated tree returns true.
  • Local file store: a_put_or_advance_by_a_principal_the_store_areas_do_not_admit_is_refused_by_the_real_file_store. The real file store gives a typed refusal when the kernel denies write, and nothing is created.
  • test.claim.fabric.fabric_writer_roster_witness, which covers four things:
    • the roster is derived from the receipts
    • the admission rule, exact match
    • the production door refuses a login no reading observed
    • the placed store areas grant write to exactly the operator (owner) and ghrunner (group), with no other-write

Why the row does not retire here

  • The backend listens on TCP 127.0.0.1:18090. Any srv1 local account can present a forged Tailscale-User-Login there, and the login roster cannot tell. The drop row now lists that as a population.
  • The in-process FabricStorageLocalFiles writers never reach the door.

Both are what the unix-socket PR closes. Separately, pair_serving_d0 d0_store_operation_wall is a missing construction outside this lane.

🤖 Generated with Claude Code

Brian Searls and others added 2 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>
…915, DESIGN §3c)

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

gunbai-bot Bot commented Sep 27, 2026

Copy link
Copy Markdown
Contributor Author

Addressed review 71915 in 5fa60e8: the uncalled fabric_served_writer_admission wrapper is deleted. The served door binds the roster on one path, fabric_storage_serve_handle → fabric_served_writer_roster() → fabric_served_writer_admission_over. git grep -n 'fabric_served_writer_admission(' -- dag is now empty. — sent from jolly-owl-158

gunbai-bot Bot and others added 3 commits September 27, 2026 23:59
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>
@gunbai-bot

gunbai-bot Bot commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

Review 71929 is addressed in 1cd3e24; all three findings were valid.

  1. Re-minted endpoint. fabric_srv_endpoint is deleted. Each receipt row's binding now comes from fabric_storage_binding_for(placement: fabric_storage_placement(), executor: <host>), so a moved placement moves the rows with it.
  2. Transcribed readings. The roster comment now says what it is: an authored roster of recorded readings, transcribed from the named runs. Nothing checks that a row matches its run, so that correspondence rests on review diligence: rung 1, mitigatable (DESIGN §4b(1)). The next-rung trigger is a typed receipt store that the observe mode writes and this fold reads. The rung-drop row uses the same wording.
  3. Prose in principal. FabricWriterRefused now carries FabricWriterRefusal = WriterLoginAbsent | WriterLoginUnrostered { login }, through the admission, the handler, the wire (writer-absent / writer-login <login>, where an extra word is undecodable) and the fault rendering. There is a new claim, a_writer_refusal_crosses_the_wire_as_its_arm, and the roster claims now assert which arm refused.

The same commit also schedules the four new wet claims in local_repo_wet_terminal and floor_route_gap. That was the floor's changed_witness_planned_without_terminal_verdict failure.

Executed locally at this head, all true: the 4 served-door and file-store wet claims, the wire claim, and the 4 roster-witness claims. — sent from jolly-owl-158

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit b4e25f5 Sep 28, 2026
6 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/jolly-owl-158 branch September 28, 2026 04:56
gunbai-bot Bot pushed a commit that referenced this pull request Sep 28, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Sep 28, 2026
…iter-identity readings) (#12451)

* Fabric served door refuses unrostered writers: roster derived from the 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>

* Delete the uncalled fabric_served_writer_admission wrapper (review 71915, DESIGN §3c)

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

* chore: regenerate drifted generated artifacts (ci auto-heal)

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

* Typed writer refusal, placement-derived receipt bindings, and an honest 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>

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: gunbai-bot[bot] <289086189+gunbai-bot[bot]@users.noreply.github.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