Skip to content

feat(society): N-way authenticated field-coupling swarm plane (societies epic, increment 1) - #228

Merged
NickFlach merged 1 commit into
mainfrom
feat/nway-society-keyauth
Jul 15, 2026
Merged

feat(society): N-way authenticated field-coupling swarm plane (societies epic, increment 1)#228
NickFlach merged 1 commit into
mainfrom
feat/nway-society-keyauth

Conversation

@NickFlach

Copy link
Copy Markdown
Collaborator

First increment of the N>2 field-societies epic: the ADR-0019 group session key now gates the FSYN field-coupling wire at N=3 (previously keyed operation was only ever tested at 2 VMs; boot_n had no key path).

The panel's central correction (why the naive gate was unshippable)

A 3-lens adversarial review established — confirmed on fieldsyncd.c — that an R_x / SYNCHRONIZED assertion cannot detect a keyless node. A keyed receiver rejects zero-tag frames, but an unkeyed receiver accepts everything (including keyed frames) and becomes a one-way Kuramoto follower, phase-locking to the keyed pair and printing SYNCHRONIZED anyway. So the gate discriminates purely on frame admission: the FSAUTH bad-MAC reject line + a per-source FIELDSYNC: frame from <ip> growth differential, offset-anchored at each member's FSKEY position.

Increment 0 — guest observability (user/fieldsyncd.c)

  • note_reject fires once-per-reason (bad-MAC / replay latches) — a boot-global latch swallowed the replay line behind the exclusion's bad-MAC line.
  • note_key prints on re-install (FSKEY: rekeyed…) — a rekey was console-silent.
  • Resolved the ADR-0019 n>=296 vs ==296 doc/code drift (kept >=; the MAC covers the fixed prefix). STATUS_BODY not widened — it's frozen ABI (contracts/wire/v1.golden).

Increment 1 — host + gate

  • QosSociety.admit_key_n(key, indices): the same group key to each member's attested COM2 (per-member admit_key, never attest() — which mints a random per-VM key that would make the society mutually reject).
  • since= offset anchoring through the status helpers (the sticky whole-log grep reads stale cross-phase evidence); frame_from_count for the admission differential.
  • boot_n randomizes the mcast group per boot + scales the precheck deadline with N.
  • test_qos_keyauth_n.py (3 VMs): leg (a) exclusion, leg (b) admit-and-resync, leg (c) a real host mcast capture-replay (stdlib join, verbatim re-send → valid MAC + stale seq → per-reason replay reject). make ci-smoke-keyauth-n-gate; new society-n CI job.

Verification (local WSL)

--- leg (a): EXCLUSION — key A,B only, C withheld ---
OK: A and B both reject the keyless peer's forged-MAC frames
OK: neither A nor B admits ANY frame from the keyless C (delta==0)
OK: keyless C still receives fresh frames from A(14) and B(14) — the one-way lock R_x cannot discriminate
--- leg (b): ADMIT ---   OK: coupling resumed; all three synchronized (0.99)
--- leg (c): REPLAY (real host injector) ---   OK: member rejected the replayed frame (valid MAC + stale seq)
=== N-WAY KEYAUTH gate PASSED ===

Revert-confirmed both ways (skip leg-b admit → red; collapse the per-reason flag → replay marker vanishes → red). society3 + 2-VM keyauth regressions still pass; kernel builds.

Increments 2 (the N=4 configuration) and 3 (N-way society-of-societies) follow.

🤖 Generated with Claude Code

…ncrement 1)

The ADR-0019 group session key now gates the FSYN field wire at N>2, with
a gate that discriminates on frame ADMISSION — never on R_x/SYNCHRONIZED.
A 3-lens adversarial panel established the central correction: an
R_x-based "keyless node excluded" assertion is VACUOUS, because an unkeyed
receiver accepts everything (incl. keyed frames) and one-way phase-locks
to the keyed pair, printing SYNCHRONIZED anyway.

Increment 0 (guest observability, user/fieldsyncd.c):
- note_reject fires once-per-REASON (two caller-owned latches: bad-MAC and
  replay) — a single boot-global latch swallowed the replay line behind the
  exclusion's bad-MAC line, leaving the replay leg unassertable.
- note_key prints 'FSKEY: rekeyed (replay watermarks reset)' on re-install
  (was console-silent) so a second admit is observable.
- Resolved the ADR-0019 n>=296 vs ==296 doc/code drift in favor of >= (the
  MAC covers the fixed FSYN_MAC_COVERED prefix; trailing bytes can neither
  move the tag nor forge the MAC). STATUS_BODY not widened (frozen ABI).

Increment 1 (host + gate):
- QosSociety.admit_key_n(key, indices): the SAME host-generated group key to
  every member over its attested COM2 (per-member admit_key — NEVER attest(),
  which mints a random key per VM and would make the society mutually reject).
- since= offset anchoring threaded through the status helpers (the whole-log
  sticky SYNCHRONIZED grep reads stale evidence across phases); frame_from_count
  for the per-source admission differential.
- boot_n randomizes the mcast group per boot (concurrent local runs on
  identical guest IPs + a fixed group could cross-couple) and scales the
  full-mesh precheck deadline with N, listing unheard edges on timeout.
- test_qos_keyauth_n.py (3 VMs): leg (a) EXCLUSION — key A,B only, assert the
  FSAUTH bad-MAC line on both keyed members AND frame-from-C delta==0 past
  each member's FSKEY anchor, positively confirming C's one-way lock; leg (b)
  ADMIT — key C, assert coupling resumes then await_sync_n(since=); leg (c)
  REPLAY — a real host stdlib mcast join captures one FSYN datagram verbatim
  and re-sends it (valid MAC + stale seq -> per-reason replay reject). Gate
  make ci-smoke-keyauth-n-gate (KEYAUTH_N_GATE_TIMEOUT ?= 600s); new society-n
  ci.yml job (needs: [build], no-kernel-prereq gate pattern).

Verified locally (WSL): the gate PASSES all three legs + clean reap;
revert-confirmed (skip leg-b admit -> red; collapse the per-reason flag ->
the replay marker vanishes -> red); society3 + 2-VM keyauth regressions
still pass.

ADR-0019 updated: the one-way-lock semantics, and FSYP aggregate frames
stay source-IP-filtered/unauthenticated (host value-recompute is their
integrity check) — stated explicitly so the N-way work does not read as
"the useful-work path is authenticated."

Co-Authored-By: Claude Fable 5 <[email protected]>
@NickFlach
NickFlach merged commit 7b7bcce into main Jul 15, 2026
27 checks passed
@NickFlach
NickFlach deleted the feat/nway-society-keyauth branch July 15, 2026 05:07
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.

2 participants