harness/ui-chat: drive a two-node chat through the real UI (blocked on CIRISEdge#552) - #523
Open
emooreatx wants to merge 2 commits into
Open
harness/ui-chat: drive a two-node chat through the real UI (blocked on CIRISEdge#552)#523emooreatx wants to merge 2 commits into
emooreatx wants to merge 2 commits into
Conversation
Three containers — a canonical and two nodes — each node running a real ciris-server AND the real Compose Desktop client, driven through the app's TestAutomationServer (java.awt.Robot at screen coordinates). No stage is performed over the node's HTTP API; HTTP is read-only, for evidence, and never makes a step succeed. mesh-repro's `chat` scenario proves the same delivery over HTTP. This proves it through the surface a person uses: the contact is added in the UI, consent given in the UI, the message typed and sent in the UI, and the assertion reads node B's on-screen transcript. A CONTAINER PER NODE, because the client resolves federation-crypto calls to a hardcoded `LOCAL_NODE_URL` of 127.0.0.1:4243 (CIRISClient#26). Three nodes on one host would send those calls to whichever node answers 4243 and mint the owner's identity on the wrong one. Separate netns makes each node genuinely 127.0.0.1:4243, so the constant is correct rather than tolerated — no client patch, no node moved off the default ports, and closer to a real install than a port-juggled host. PASSING: first_run x2 (wizard, auto-claiming from <home>/claim_pin), restart-for-opt-in, login x2. BLOCKED at discover:a_sees_b_fedid, on CIRISEdge#552. Both nodes discover each other's NODE keys and the canonical; neither obtains the other owner's FED-ID, so add_contact refuses contacts.unknown_fed_id. The canonical's own directory holds both node keys and neither owner. `Key` already serves public on the advertise axis, but the RECEIVE axis was subject-only — "un-addressable, not undisclosed", since Pull is the only by-name read and a node cannot compute the hash of a record it has never held. CIRISEdge#556 widens it; this waits on a release carrying that (CIRISServer#522). SIX DEFECTS FOUND GETTING HERE, each now prevented rather than remembered: default-jre-headless has no X11/AWT (dies HeadlessException, which reads as a missing display and is a missing toolkit); the automation server binds loopback only, so it answers `docker exec curl` and not the host; all five trust-root vars are required, and the classical two boot a node that roots then dies "PQC signature without pubkey"; a tmpfs home makes the restart wipe the identity the restart exists to apply; a stale /tmp/.X99-lock survives a restart and fails the second boot only; and clicking `toggle_announce_ownership` to "opt in" turned it OFF, because SetupState.announceOwnership already defaults true — a click is a toggle, never an assertion. TWO MORE IN THE DRIVER'S OWN ASSERTIONS, both checks that could not fail: `contact:a_adds_b` passed on the absence of a refusal banner while listContacts said "0 contact(s) of 0"; and a navigation stage left the UI on ManageNodes so the next stage reported "the contacts button never appeared" — true, and pointing at the wrong thing. Both now assert the positive. The contact is a FED-ID, never a node key: bound_nodes_of resolves the person through nodes_stewarded_by and filters to identity_type == node. An earlier revision fell back to the node key when the fed-id was missing, which made the stage pass while testing node-to-node delivery wearing a person-to-person label. The wheel and uber-jar are gitignored — 104 MB of build inputs run.sh stages and tells you how to build. Refs CIRISEdge#552/#556, CIRISServer#522, CIRISClient#25/#26, CIRISServer#520. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017gxnxsTWS8FkN3CT2JEz86
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…okup
The driver had a `discover:a_sees_b_fedid` stage that waited for node A to learn
node B's owner fed-id by discovery, and reported it as blocked on CIRISEdge#552.
That was a misreading of the boundary. CIRISServer#524 §6.3:
"Stranger contact is meant to start from a nodecode, not a directory lookup.
You hand out an identifier out-of-band, the peer dials that specific node
(which serves its own record), and consent follows. Building 'search the
federation for a person' on top of `discover` will work only for people you
already have a consented relationship with — that is the boundary, not a
gap to route around."
So the stage was not waiting for a fix. It asked the substrate for an
address-book lookup it refuses by design, because answering a third-party probe
"would make a body-holding server an address-book oracle for records it never
advertised" (§6.1). Left as it was, the harness would have re-run against
v18.12.1, failed identically, and blamed the release.
The flow now matches the product: each side reads its own node code, the harness
carries it across — that carrying IS the out-of-band channel, exactly as a person
handing over a code is — `add_peer_by_code` admits the peer through the UI's
NetworkPeers sheet, and only then is the owner behind that node resolvable.
The receive-axis widening still matters: it is what makes the by-name Pull legal
once a code names the peer. It was never going to be sufficient alone, which is
the part I had wrong.
Stages after the hand-off need a wheel built against edge v18.12.1 to run end to
end; the pins move in CIRISServer#525.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gxnxsTWS8FkN3CT2JEz86
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three containers — a canonical and two nodes — each node running a real
ciris-serverand the real Compose Desktop client, driven through the app'sTestAutomationServer(java.awt.Robotat screen coordinates). No stage is performed over the node's HTTP API; HTTP is read-only, for evidence, and never makes a step succeed.mesh-repro/scenarios/chat.shproves the same delivery over HTTP. This proves it through the surface a person uses: contact added in the UI, consent given in the UI, message typed and sent in the UI, assertion reads node B's on-screen transcript.A container per node
The client resolves federation-crypto calls to
CIRISApiClient.LOCAL_NODE_URL, hardcodedhttp://127.0.0.1:4243(CIRISClient#26). Three nodes on one host would send those to whichever node answers 4243 — a different node — and mint the owner's identity in the wrong place. Separate netns makes each node genuinely127.0.0.1:4243, so the constant is correct rather than tolerated: no client patch, no node moved off default ports, and closer to a real install than a port-juggled host.Status — blocked at
discover:a_sees_b_fedidfirst_run×2 (wizard, auto-claim from<home>/claim_pin)restart:for_announce_optinlogin×2discover:a_sees_b_fedidBoth nodes discover each other's node keys and the canonical; neither obtains the other owner's fed-id. The canonical's own directory:
Both node keys, neither owner — so
add_contactrefusescontacts.unknown_fed_idandbound_nodes_ofhas nothing to resolve.That is CIRISEdge#552's cell.
Keyalready servespublicon the advertise axis, but the RECEIVE axis wassubject-only— "un-addressable, not undisclosed":Pullis the only by-name read and a node cannot compute the hash of a record it has never held. CIRISEdge#556 widens it todata_subject+any_attributed. Waiting on an edge release carrying that (CIRISServer#522).Six defects found getting here
default-jre-headlesshas no X11/AWT — diesHeadlessException: No X11 DISPLAY variable was set, which reads as a missing display and is a missing toolkit.docker exec curlperfectly, invisible to the host. Needs thesocatforwarder. Any containerised UI platform hits this.PQC signature without pubkey.tmpfshome makes the restart wipe the identity the restart exists to apply./tmp/.X99-locksurvives a restart — second boot only, so it reads like a flake.toggle_announce_ownershipto "opt in" and turned it off;SetupState.announceOwnershipalready defaultstrue. The run then failed four minutes later in an unrelated stage.Two more in the driver's own assertions
Both the same shape — a check that cannot fail:
contact:a_adds_bpassed on the absence of a refusal banner whilelistContactsreported0 contact(s) of 0.ManageNodes, so the next stage reported "the contacts button never appeared" — true, and pointing at the wrong thing.Both now assert the positive, and
goto()confirms the landing screen.Design notes worth carrying elsewhere
/treereturning elements, never the port answering. On Android the automation server came up 200 ms before the process died (CIRISClient#25); a port check calls that green.chat.shuses when it keys on the sender'sattestation_id.Not yet aligned with #520
#520 rules promotion is opt-out, that opting out stops the agent, and that it is recorded as a
consent_state: grantedrow with specific copy. The driver currently walks the wizard's defaults; when #520 lands,first_runshould assert that shape rather than accept whatever the wizard does.The 34 MB wheel and 70 MB uber-jar are gitignored;
run.shstages them and tells you how to build either.🤖 Generated with Claude Code
https://claude.ai/code/session_017gxnxsTWS8FkN3CT2JEz86