Skip to content

0.5.218: adopt edge v33.0.0 / persist v51.0.0 / verify v18.0.0 (pre-staged on #710's graph) - #697

Draft
emooreatx wants to merge 32 commits into
integ/0.5.218from
chore/adopt-edge-v33
Draft

emooreatx wants to merge 32 commits into
integ/0.5.218from
chore/adopt-edge-v33

Conversation

@emooreatx

Copy link
Copy Markdown
Contributor

DRAFT until the tags land. Pinned today to edge #710's head (68bba8bb) and the persist commit it pins (789be5b3, v51), with verify at its v18.0.0 tag. At the tags: move the pins from rev to tag, re-pin the envelope-vocabulary hash once (after checking it equals persist's published constant), apply v51's differences from 789be5b3 (below), rerun the sweep and the ladders.

Source changes

  • open_mls_state(engine, path) → (store, custody). A TPM-less host now opens the MLS store on disk under its software master; Posture::Durable { custody }.
  • persist v50: withdrawn_by re-derives stored withdraws through the WRITE-form check (now a 5-hop default) — use check_withdraws_admission_as_admitted (recorded depth) #690: withdrawn_by re-derives at each row's admitted depth (check_withdraws_admission_as_admitted).
  • CIRISEdge#698, sealed descriptors: every drive path that shows, keeps or tests a name or type goes through drive::describe (listing, metadata, read, raw headers, replace, move, the notes filter). Listings say description: clear|opened|sealed. Its body opens the bytes until edge ships a descriptor-only door (asked on CIRISEdge#702).
  • CIRISEdge#675, the person authors files: the author check accepts the person's key, and a withdraws is signed by the row's own attester.
  • Strict registry (persist v50): the self-declared age row is age_self_declared:band:{band}:v1, and the old spelling still reads. New gate emitted_dimensions_are_registered.
  • The fixed CIRISEdge#687 inline band is un-marked in the corpus.

Test sweep (one binary at a time): 141/149 green on the first pass, and every red has been read. Now red only:

  • Clear at the tag switch: substrate::gate_substrate_pins_at_target, gate_no_substrate_rev_pin_at_release, readme_substrate_pins_match_cargo_toml, blocked_upstream_gate.
  • Re-pinned at the v51 tag: persist_envelope_vocabulary_hash_pinned, gate_envelope_vocabulary_is_the_one_we_adopted.
  • Rename (2 drive_crud tests): needs edge's re-seal door (CIRISEdge#702). A renamed row carries a clear name beside the old sealed descriptor, and edge refuses it (D4).

At the v51 tag (from persist/edge's notes):

  • open_descriptor_for_blob gains caller_aad; that's edge-internal plus the descriptor-only door.
  • Chunk-key grants: the server seals only through the Engine door, so persist sends them itself.
  • A stalled trust root now resolves with live=false. Re-check mesh_genesis / mesh_config_surface trusted_roots_of consumers and GET /v1/trust-root.
  • #941 refuses A→B→A ownership chains.

Ladders: not yet run on this graph. selffiles' negative rungs should go green here (CIRISPersist#919 fixed in v50; names sealed by #698).

🤖 Generated with Claude Code

https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf

emooreatx and others added 4 commits September 28, 2026 21:04
…tags

Edge v33.0.0's pre-stage branch (68bba8bb) and the persist commit it pins.
TARGET_* names the final tags, so the substrate gate stays red until the
pins move from rev to tag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
… descriptors

- open_mls_state takes the Engine and returns custody (persist v50 #920, edge
  #694): a TPM-less host opens the MLS store ON DISK under its software
  master. Posture::Durable carries `custody`.
- #690: withdrawn_by re-derives each withdraws at the depth it was ADMITTED
  under (check_withdraws_admission_as_admitted), not the new 5-hop default.
- CIRISEdge#698: a sealed row's name and type are inside sealed_descriptor.
  Every drive path that shows, keeps or tests them (listing, metadata, read,
  raw headers, replace, move, the notes filter) goes through drive::describe;
  listings say `description: clear|opened|sealed`. STOPGAP body opens the
  bytes via open_described until edge's descriptor-only door (asked on
  CIRISEdge#702).
- FileWrite.codec: None; SignedCommunity fixtures gain empty cosignatures and
  lineage (canonical-community only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…e registry is strict, Clause A closes upstream

Per-binary sweep: 141/149 green on the first pass; each red was read:

- A file row is signed by the PERSON (CIRISEdge#675, `files::file_author`).
  require_author accepts the caller's person key as well as the node's, and
  withdraw_rows signs each `withdraws` with the row's own attester (the
  owner's pen for a person-authored row).
- Persist v50's registry is strict (CC 3.1.7 R2(b)): the self-declared age
  row is `age_self_declared:band:{band}:v1` (the old spelling still parses).
  New gate tests/emitted_dimensions_are_registered.rs runs every versioned
  dimension literal in src/ through persist's matcher, with a positive control.
- covers() is grammar-aware (#924): the default-prefix gate now states the
  byte-exact prefix half instead of probing with an invented dimension.
- abuse_surface fixtures use registered spellings (the pins still measure).
- Persist refuses a {node,agent} key at registration (Clause A); the test pins
  that refusal.
- CIRISEdge#687 is fixed in v33: the inline_band corpus file uploads, so its
  KNOWN_DEFECTS mark is removed.

Still red, by design or upstream: the substrate/rev-pin/README/blocked-upstream
gates (clear at the tag switch), the envelope-vocabulary hash (re-pinned once,
at the v51 tag), and rename (needs edge's re-seal door, asked on CIRISEdge#702).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…rify v18.0.0

- rev → tag on every persist and edge line; the lock resolves to the exact
  commits the tags name.
- drive::describe is edge's FileRow::describe: a sealed row opens ONLY its
  descriptor, under the row's AAD (persist v51 refuses a transplanted pointer
  at that door). The open_described stopgap is gone.
- Envelope vocabulary re-pinned in both gates, reviewed: four rc6 trust-root
  attach keys added (#937/#938), none removed or renamed, none written here;
  a6a84cc9… → c9558c98…, equal to persist's published constant.
- README pins and the version headline's substrate clause.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
emooreatx and others added 5 commits September 29, 2026 09:06
…the #693 stopgap goes

- Pins: edge v33.1.0, persist v51.1.0 (verify v18.0.0 unchanged); no hash
  re-pin (edge's notice, and the gates agree).
- Rename is edge's `files::rename` (CIRISEdge#702): a new row over the same
  bytes, the name re-sealed for it, signed by the old row's author with the
  owner's pen; the prior is retired by a `supersedes` once the new row
  crossed. The drive's hand-built rename_row is deleted. The response says
  `superseded`, not `withdrawn`: the bytes are the same bytes.
- CIRISEdge#693 stopgap deleted: `files::belongs_to` and `in_room_with` are
  edge's. find_file answers 410 for a row edge's lifecycle calls Superseded or
  Recanted, and a `withdraws` is still re-derived. A file's metadata reads the
  prior of an edge rename off the prior's supersedes (`renamed_from`).
- selffiles diagnosis: every non-matching corpus row in full (the 3000-byte
  head cut exactly the failing rows), and a byte probe of each corrupt file
  on BOTH devices (size vs expected, first differing offset, prefix or not),
  to place the three ≥1 MiB files that came back with different bytes.

drive_crud: 16/16.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
… seconds

`python -m harness.native <scenario> --binary <test-anchor ciris-server>`:
N native processes on 127.0.0.1, the anchor block read from the mesh-repro
compose file (one copy), production peering routes by default (the ladders'
test-admit-peer is opt-in by name). Library + scenarios + CLI; `--keep`
leaves the nodes up for the next question.

Scenarios: `chat` (two people, pair room, message — the CIRISServer#698
path) and `corpus` (one person, two devices, the transfer corpus compared
byte for byte on both). First run: booted, claimed, announced, peered and
KEYED the pair room in 27 s; end to end 3.5 min against 45 for the ladder.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…tep with its log evidence, report.json, the client's values.json

Every scenario prints what it will prove and how; a failed step says what
it MEANS and shows the lines that decide it. `--keep` + `down`. Per-mesh
port base (two meshes raced for one pair). Two gates the first runs found,
each named as a step: `rooted` (edge's pair verdict, observe or wait) and
`reachable_nodes>=1` on POST /v1/contacts (a contact added at 0 keyed a room
whose bodies then read not_granted with no self-heal, 3/3 runs). `--direct`
makes the second node a direct neighbour (scoped content is one-hop,
CC 5.4.6). Chat PASSES end to end in 33 s with both.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
… apart from bytes that did not (409)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…ed (seal_mismatch), never served

The selffiles byte probe (PR #697 CI) showed a second device serving 518 /
610 / 9,529 bytes of `{"chunk_tier":…` — the chunk-DAG manifest — as 1 MiB
and 24 MiB files, status 200: edge's puller stores a DAG's manifest as an
inline blob and fetches no chunks (CIRISEdge#717). The pointer declares the
plaintext size (CIRISEdge#638), so open_whole compares and refuses under
the existing `drive.seal_mismatch` id naming both lengths. drive_crud 16/16
(the author's own sizes agree). The ladder's corpus hint names the class.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
@emooreatx

Copy link
Copy Markdown
Contributor Author

Edge side of the native-fixture findings:

  • CIRISEdge#716 (a multi-fragment frame on the reverse-path link stalls at fragment 0) and CIRISEdge#717 (the puller stores a chunk-DAG blob's manifest as the file): both are being fixed now, each with a failing-on-main witness. I'll post here when they're tagged.
  • Finding 5 (one-hop scoped content) is CIRISEdge#718, and it's an edge gap, not an open design question. CC 5.4.6 forbids announcing a group-scoped destination and dialling a derived address through a relay. It sanctions relay-blinded, announce-free reach, where the relay carries ciphertext on the identity plane and holds no group address. The A/V mesh already measures that for blobs (conformance.relay_holds_no_cohort_address). So two phones behind the canonical should chat. #718 names the candidate gates and asks for an edge-side repro first. harness.native chat without --direct is the server-side witness.

emooreatx and others added 5 commits September 29, 2026 10:41
… topology from the root(s) down, and the harness builds exactly it

The vocabulary (roots → canonicals → nodes → persons → relations → actor →
negatives), its realizability rules (§3), the derivations a CSD/4 checker
consumes (node count, devices, direct links, the root ceremony, what is not
buildable yet), and a builder that stands the declaration up layer by layer
on the native mesh, naming the first layer whose predicate does not hold.

Proving set: csd-091-user-chat, csd-092-share-contact-code,
csd-093-second-device. First builds: 093 PASS (second device joins the self
room, a file opens byte-identical on it, the outsider holds no row); the
`reachable` gate now waits through a 404 as well as reachable_nodes=0 (known
comes before reachable).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
… 41 s, 092 in 35 s, 093)

Builder fixes, each found by a failing build and named in the code: the
keyed-wait polls BOTH sides every tick (the joiner's half advances on its
transcript reads; a short-circuit never read the joiner, so it never
published its KeyPackage); a `contact` after a `reachable` gate is recorded,
not re-POSTed; `contact_code("all")` omits the parameter (a literal `all` is
read as a node id); the `reachable` gate waits through a 404 (known comes
before reachable).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…-replayable row export

roots: founders → {seated, conferrable, node_bearing} (T7 needs seated ≥ M+1
and one conferrable, or recovery never fires); `k` derived (CC T6: K=⌊n/2⌋+1,
a declared k is refused); charter{attach_window_secs, witness_cadence_secs}
→ AttachWindow; lifecycle is a row recipe + asserted verdict, not a flag;
`kind: family` refused (no model behind it, CC 4.2.6); `infrastructure` is
the T7/T8 root, declared and refused as not-buildable by name. `derive`
prints the model constants (K, AttachWindow, Founders, NodeKeys).

Every build exports, per node, rows.jsonl (every federation_attestations
column, admission order) + keys.jsonl, with count and sha256 in the report —
the input CC replays V(rows, t) over for T8 (iii) and turns a trace into a
TLC check. csd-091 rebuilt: PASS, 22 rows on each person's node.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…d a one-word `standing`; the topology report records both per node

persist v51 #938's `Engine::lineage_head(root)` → the witnessed head's
digest + instant, the charter quorum, the judged index and the latest
counting cosign — CC T8 (vii)'s per-node line (CIRISConstitution#131): every
node holding the same rows reports the same pair. `standing` is
`not_rooted` when the verdict fails or a halt is latched, else `rooted`;
`stalled` (T7 liveness) follows when the resolution's `live` is wired.

harness/native: rows_export.json / report.json carry, per node, the standing
and lineage head for every root the node considers. On the anchor's key
root the head is null by construction (no lineage chain); it fills in once
an infrastructure root can be minted.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…ity resolves live=false (CC T7)

persist v51's `resolve_community` carries the T7 liveness: `live: false` is
valid and non-admitting (fewer than M+1 active founders; attached pairs stay
rooted, new members refused — edge FIRST_CONTACT.md I12). The route now
emits `live` and folds it into the one-word `standing`: not_rooted | stalled
| rooted. A key root has no community to resolve and is never stalled.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
@emooreatx

Copy link
Copy Markdown
Contributor Author

Correction to my earlier comment on finding 5: your Rule 4 reading is right, and I was wrong to call it an edge gap. A scoped address can't be announced, so it has no multi-hop path by construction, and edge's serve gate admits scoped bodies only over a direct link. CC 5.4.6 itself calls multi-hop reach for group-scoped destinations "an amendment-plane design question". The A/V relay I cited carries identity-plane traffic, not scoped content.

One refinement: this doesn't need an N-clique. CC's model is that members relay for members, so for community rooms a connected graph of member nodes should suffice (a member that pulled a body re-serves it). That's not measured yet; CIRISEdge#718 is narrowed to that witness. Self and family rooms fetch from the author, so there a device needs a direct link to the author's node. Any member node can be the relay, a person's own home node included. The case that has no answer today is two people's phones behind the non-member public canonical in a pair room. That waits on a CC amendment, and whether to file it is the maintainer's call.

emooreatx and others added 5 commits September 29, 2026 11:18
…yed by declared id with `notes`, structured failures, 093→094

- values.json: PERSON_<id>_OWNER_KEY_ID, NODE_<id>_URL/KEY_ID, ACTOR_*, ROOM_ID
  from the room relation; PEER_* kept as the positional alias; `notes` names
  each value a flow might expect that this declaration did not produce.
- step.fail carries `layer`, `rel`, `cc` as fields; a broken build reports
  `first_failing_layer` beside its error.
- csd-093-second-device.yaml → csd-094-approve-new-device.yaml: it is
  CSD-094's post-state (the client's reading); CSD-093's own flow waits on
  CIRISServer#678's address answer.

Held locally until the queued harness run on 9b4182b completes: every
push since 7c13f96 cancelled the previous run before selffiles reported.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…ce, per-kind publish sets, first contact on the opaque plane

Edge v34.0.0 pins persist v51.1.0 / verify v18.0.0 (unchanged here); 15
release assets. Source: two new WithholdReason arms classified as their
docs read — IdentityRowNodeNotAnnounced is a verdict (Policy: the peer is
outside the audience the owner chose, CIRISServer#655's per-node announce
ruling), IdentityRowAnnounceUnresolved a read that could not be made (Fault).

SERVE_ADVERTISE_POLICY_HASH re-pinned once, reviewed against the
serve_policy.rs diff: one row — IdentityOccurrence and TransportDestination
leave "public" for "announced → public; unannounced → owner's nodes only"
(CIRISEdge#682). 6fbf0282… → e4c4d625…, equal to edge's constant.
release_gates 42/42, substrate_contract_gate 9/9, replication_policy_gate 2/2.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
… the holder negative; 6.5 min for the 45-minute reading

Relations `note` (written on one device, listed on the others) and `corpus`
(media_corpus written on one device, read raw on every other device, each
file's outcome named by layer: row never crossed / bytes not pulled / wrong
bytes / refused by name); negative `no_wider_self_rows` (every self-plane
row on the person's own devices at cohort_scope self); `holds_no_row` now
refuses to pass vacuously (the outsider must hold SOMETHING from the
person's keys — it is peered as a contact in the declaration).

topologies/selffiles.yaml on edge v34.0.0: self room on both devices, note
listed, 22/25 corpus files byte-identical on the second device, both
negatives green, control=5 on the contact's node; the three ≥1 MiB files
refused as drive.seal_mismatch (CIRISEdge#717) — the same reading the Docker
ladder gives, in a seventh of the time.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…e lists every device; an outsider sees announced devices only

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
… the author's node; community rooms a connected member graph; pair-behind-canonical waits on CIRISConstitution#132

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
@emooreatx

Copy link
Copy Markdown
Contributor Author

edge v34.1.0 is tagged (3c8f1f4): #716 fixed, #717 refused by name (full fix waits on persist v51.3.0 / CIRISPersist#947). Pin bump only; notice on CIRISServer#626.

emooreatx and others added 5 commits September 29, 2026 12:43
…8 refusals leave the debt list, 39 take the client's wording

edge v34.1.0 (3c8f1f45): a pin bump — persist v51.1.0 / verify v18.0.0
unchanged, no hash moved (three gates green). It carries the reverse-path
fix (CIRISEdge#716: fragments cut to the packet MDU 431 while the link
channel takes 425) and the named refusal for a stream pointer (#717 partial).

Client 0.5.225 shipped this afternoon and its bundle covers 78 ids the
server carried as KNOWN_UNLOCALIZED; the guard's honesty check requires paid
debt removed (61 remain) and the pyproject floor moves to 0.5.225. For 39 of
them the client wrote user-facing sentences that differ from the server's
diagnostic prose; the guard's rule is equality (a prefix reads as the 80-char
truncation defect), and the client is the tree of record for wording, so the
server now emits the client's sentence verbatim at every site (drive 5,
self_devices 16, family_api 16, contacts_chat 2). All six guard checks pass
under 0.5.225.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…es the oldest client a consumer may resolve)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…estinations) beside its rows — the #393 item-2 operands (CIRISEdge#722)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…8), the self-diagnosing item-2 refusal (#725)

persist v51.1.0 / verify v18.0.0 unchanged; no hash moved (three gates
green). Two new WithholdReason arms (#718), both the scope gate reaching a
verdict: BlobDiscriminatorUnheld, BlobDiscriminatorOnDerivedAddress → Policy.

Measured on selffiles.yaml: every item-2 refusal on the direct link prints
`held_signed_route=none` while the receiver's transport_destinations row for
the sender is complete (kind, destination, attester, envelope, both signature
halves) — the gate queries a key with no row (CIRISEdge#722, edge's).
The per-node export now carries metrics.json beside rows and routes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…p (frames that went Resource-first over the Channel fragment cap; CIRISEdge#716/#722)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
emooreatx and others added 4 commits September 29, 2026 20:31
…n-shaped three-peer topology finds a node-wide deadlock (CIRISEdge#740)

Pins: edge v34.3.0 at all three sites (root ×2, crates/ciris-lens-core), lock,
README, TARGET_EDGE; substrate/vocabulary/policy gates green, no re-pin.
v34.3.0 is #728 — a link belongs to one plane — and on a direct link the
selffiles declaration reads 22/25 (the three ≥1 MiB files wait on the DAG pull,
edge v34.4.0 / persist v51.3.0). That number is proven for the TWO-peer shape.

GET /v1/federation/metrics folds three more of edge's receive-side ledgers the
route never carried: transport_inbound_drops (#728), blob_pull_refusals (#717),
first_contact_outcomes (#683) — reason → count.

harness/native: a claimed node that dials a canonical now PEERS with it
(`canonical_peered`, after claim + announce) — the owner's HTTP act in
production (traceflow_prod.sh step 7). Dialling alone made the canonical a
Reticulum relay: in every native run so far it admitted no node key, rooted with
nobody, and distributed nothing, which is why a contact's node listed one of a
person's two announced devices (X refused D2's binding for want of D2's key).
With the canonical peered, D1 has three peers, and the node deadlocks at the
self-room Welcome's kick, 3 of 3 runs: edge's sync StateProvider::local_refs
does block_in_place + Handle::block_on per (peer, kind); each call parks a
hand-off worker in a blocking-pool slot while awaiting a persist read that needs
a slot; 3 peers × 14 kinds = 42 > 32. gdb evidence on CIRISEdge#740; fix goes
out as edge v34.3.1 with this declaration as its acceptance. The native
selffiles run is red at `self_room_NOT_joined` until then, by design — the
peering stays.

bigfile.yaml / bigfile-quick.yaml (CIRISEdge#734 lane 7): one 2 GiB (256 MiB)
self file streamed in as multipart, pull timed from the row's arrival to
byte-state `here`, read back through a streamed `?raw=1` compared by SHA-256, a
resume rung that restarts the puller at half the pull; rates recorded, never
asserted. Names the drive's own ceiling: UPLOAD_BODY_LIMIT (64 MiB whole-read
cap ×4/3 + 1 MiB) answers 413 above it today — the server's lane beside edge
#733/#737.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
… their own consent

The maintainer's ruling (2026-09-30): adding someone requires their consent, and
reverse quorum is not a membership rule. Today every roster-growing door adds on
the existing members' authority alone (family check_addable, community
require_contact — our grant toward them, not their agreement). The design:
invite = a proposal that grants nothing; the invitee's own signed acceptance is
the condition of the widening; decline and expiry are terminal; every protocol,
founder_only included. Admission rule asked of persist (CIRISPersist#955),
normative text of CC (CIRISConstitution#133); the server's interim hold is to be
deleted when persist's gate lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…ers accept too (maintainer, 2026-09-30)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…iter proposes, the quorum stays on the growth record, expiry on signed instants

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
emooreatx and others added 4 commits September 29, 2026 23:46
…igning the founding record is consent, a supersede never adds, leave/dissolve replicate at v52 (#956)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
…king pool (CIRISEdge#740)

Edge v35.0.0 (b383fde, persist v51.1.0 / verify v18.0.0 unchanged) makes the
state-provider read path async and bounds a kick, so a node with three peers no
longer parks 3 × 14 block_in_place hand-offs in a 32-slot blocking pool. Pins
at all three sites (root ×2, crates/ciris-lens-core with version = "35"), lock,
README, TARGET_EDGE; substrate / vocabulary / policy gates green.

The one server change is the in-process round harness: `tests/trace_round_e2e.rs`
drives `Session::start_round` / `on_message` and `StateProvider::local_refs`,
which are async now — `drive_round` awaits them. Production implements neither
trait.

ACCEPTANCE (the production-shaped three-peer declaration that wedged 3/3 on
v34.3.0): `harness/native/topologies/selffiles.yaml` with `canonical_peered` —
VERDICT PASS. Self room across both devices at t=72 s, roster, note, both privacy
negatives (X control 7 rows, 0 self-plane), corpus 22/25; the three ≥1 MiB
files are 409 drive.not_fetched on the second device, which is edge v36.0.0's
chunk-DAG pull on persist v51.3.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
… FileError (CIRISEdge#737)

Pins at every site (root, crates/ciris-lens-core with version = "36", lock,
README, TARGET_EDGE / TARGET_PERSIST); verify v18.0.0 unchanged; substrate /
vocabulary / policy gates green, no hash re-pinned.

`FileRow::open` now answers `FileError`: the drive's whole read and the notes
read map `Unopened(reason)` to the same byte-state words as before, edge's own
whole-read cap (reached only when a pointer declares no size) to the existing
`drive.too_large_for_whole_read`, and anything else to the existing
`drive.unopened` — no new refusal id.

MEASURED, NOT YET THE CLAIM: the three-peer selffiles declaration still reads
22/25 — the three ≥1 MiB files on the second device answer
drive.seal_mismatch (the row declares 1,048,575 / 1,048,577 / 25,165,824 bytes;
the bytes are 518 / 610 / 9,529). D2's federation_blobs holds the three
chunk-DAG MANIFESTS as `inline` blobs with the same sha256 as D1's `chunk_dag`
rows (554 / 646 / 9,565 B), zero federation_stream_chunks, zero
federation_streams, and blob_pull_refusals is empty: the DAG pull never ran for
them. Reported to edge with the rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf
… selffiles 25/25 on the three-peer shape (CIRISEdge#717)

Edge v37.0.0 (5a93a64, persist v51.3.0 / verify v18.0.0 unchanged): a
self-room chunk DAG pulls its chunks on the real replication path, and a chunk
is served only under its own file. Pins at every site (root, lens-core
version = "37", lock, README, TARGET_EDGE); gates green, no hash re-pinned.

`WithholdReason` is `#[non_exhaustive]` from v37: the operator classifier names
every variant at the pinned tag (the new `ChunkNotInNamedDag` as Policy — the
scope gate refusing a chunk outside the file it names) and reads an unknown one
from a newer edge as a Fault, never quietly as Policy.

MEASURED — harness/native/topologies/selffiles.yaml, three peers with the
canonical peered as production does: VERDICT PASS; self room across both
devices at t=71 s; corpus 25/25 byte-identical on the second device, including
the 1,048,575 / 1,048,577 / 25,165,824-byte files that were manifests on every
edge before this (compared in 50 s, 300 s on v36.1.0); both privacy negatives.
Device roster and self files work end to end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdM21U8xUmHk2TwrMTKJPf

This branch has not been deployed

No deployments
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.

1 participant