Skip to content

CEC diagnostic purchase: wire protocol, node relay, technician controls#167

Open
mrjeeves wants to merge 1 commit into
mainfrom
claude/cec-diagnostic-purchase-integration-hgphzb
Open

CEC diagnostic purchase: wire protocol, node relay, technician controls#167
mrjeeves wants to merge 1 commit into
mainfrom
claude/cec-diagnostic-purchase-integration-hgphzb

Conversation

@mrjeeves

@mrjeeves mrjeeves commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Adds inline purchasing of the $50 CEC Diagnostic Session to the CEC Support system — the AllMyStuff side of a three-repo change (see the sibling PRs in CECSupport and support.cec.direct).

What a technician gets

A Request $50 diagnostic control in the CEC tab, available at every point of a help call:

  • Before answering — on a help-queue row, so the diagnostic can be billed before taking the call. The node reaches the machine exactly like a dial (pin-connects on the shared support area) with no screen session and no approval needed to ask.
  • Mid-session — on the machine's Client-meshes row; the ask rides the live connection and is tied to the session.
  • After disconnecting — the same row control works sessionless over the still-standing (or re-established) connection.

Live status streams back per customer: waiting → on their screen → at the checkout → says it's paid → declined, with Confirm received (after checking the order in the store admin) and Withdraw. Toasts fire on the two beats worth interrupting a phone call for (claimed / declined).

How it works — and why a purchase link, not a payments API

Payment never touches the mesh or either app. The customer's app opens its own hardcoded checkout page (support.cec.direct/buy/diagnostic/) in their own browser, which lands on the store's hosted Shopify checkout via a cart permalink. Chosen over the Storefront/Admin APIs deliberately:

  • No secrets anywhere — no API tokens in shipped binaries, nothing to rotate, no server to run (this product's core promise is no central server).
  • Highest customer confidence — the customer pays where their password manager, the real address bar, Shop Pay/Apple Pay, receipts, and refunds already live. Nobody types a card into a desktop app.
  • Verification without webhooks — the checkout URL carries Support Number / Technician / Reference as cart attributes, so the order that lands in Shopify admin names the session. The technician (already on the phone) verifies and clicks Confirm: person checks person, the same shape as the agent-name verification.

The wire contract

New ControlMessage::Purchase family in allmystuff-cec-protocol: Request (ids, the asker's agent_name, display strings only) → customer Status beats (seen/opened/claimed/declined) → technician Confirm/Cancel. Same forward-compat discipline as the rest of the wire (internally tagged, Unknown catch-alls): an older customer app silently drops the whole envelope, and no seen coming back is the technician's cue to take payment by phone.

Trust model, deliberately the connect prompt's: no grant is required to ask (a technician quotes the work before the customer has ever let them in). The ask travels the same path as a dial on the shared support area; the prompt names the asker; the customer verifies that name against the person on the phone and declines freely. When a grant exists, the prompt prefers the grant's name — the one the customer actually approved — over the wire's claim. The checkout URL is never taken from the wire, so nothing a peer sends can steer a customer's browser.

Node relay

  • cec.rs: PurchaseFlow bookkeeping — in-memory only, one live ask per peer (a re-ask supersedes), confirmed/cancelled terminal, session→peer links, agent_name_for() (grant-name lookup).
  • mesh.rs: cec_purchase_request (pin-connects like a dial when the peer isn't already reachable, then delivers under the daemon's acknowledged contract — queued until the customer's link is up, retransmitted across session rebuilds, exactly like the connect request; an undelivered ask settles itself cancelled so the strip tells the truth; the customer dedupes by id and re-asserts current state on duplicates), cec_purchase_status/_confirm/_cancel (settle locally at once, deliver acked in the background), cec_purchases (GUI re-sync). Only the ask's own peer can move it; a session End auto-cancels its ask.
  • node_control.rs: the five dispatch arms — the same surface the standalone CEC Support client drives.

Rebased across main's CEC daemon-contract work (#170#175): the flow now rides the shared support area and the acked-delivery contract that landed there — the 2s retransmit loop and per-number rooms this was first written against are gone.

Verification

  • cargo fmt / clippy -D warnings / cargo test green on the root workspace (protocol: 19 tests, incl. wire-form pinning, skew tolerance, sessionless round-trips) and the node workspace (156 tests, plus the --no-default-features mobile config) — the full CI battery, run locally after each rebase.
  • GUI: svelte-check 0 errors, production build clean; gui/src-tauri cargo check green.
  • End-to-end contract compile: the CECSupport client's Rust side was compile-checked against this branch via a temporary path override (not committed).

Release ordering

The customer app lights the flow up at runtime once its bundled/running node carries this relay. CECSupport main already forward-pins the next release (v0.2.39 in .allmystuff-rev + its git-dep tags), so the one remaining step is cutting that AllMyStuff release with this PR in it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MzGQaTFkYtzYR7Hq1jBoGR


Generated by Claude Code

…n UI

A technician can now require the $50 diagnostic session at any point in a
help call — before answering (straight from the help queue), mid-session,
or after disconnecting (the request control on a stored machine). It is
optional, technician-triggered only, and no payment data ever rides the
mesh: the customer's app opens its own built-in checkout page in their
browser, and the technician confirms against the order that lands in the
store (it carries the customer's support number), person checking person,
no webhooks, no server.

allmystuff-cec-protocol:
- New ControlMessage::Purchase family — Request (ids, the asker's
  agent_name, display strings), customer Status beats (seen / opened /
  claimed / declined), and the technician closes (Confirm / Cancel) —
  with the same internal-tag + Unknown-catch-all skew discipline as the
  rest of the wire: an older peer drops the whole envelope, and no Seen
  coming back is the technician's cue to handle payment by phone.
  session_id is empty for asks made outside a session.
- The ask carries the connect prompt's trust, deliberately: no grant is
  needed to ASK (a technician quotes the work before the customer has
  ever let them in), the prompt names the asker exactly like the connect
  prompt does, and the customer verifies by phone and declines freely.
- DIAGNOSTIC_BUY_URL / _ITEM / _PRICE constants: the checkout URL is a
  client-side constant by design, never wire-supplied, so no peer can
  steer a customer's browser. Wire form pinned by tests (20 total).

node:
- cec.rs: PurchaseFlow bookkeeping (in-memory, one live ask per peer —
  a re-ask supersedes; confirmed/cancelled terminal), session->peer
  links so a live session is attached when one exists, agent_name_for()
  so a prompt prefers the grant's name (the one the customer actually
  approved) over the wire's claim.
- mesh.rs: cec_purchase_request reaches the customer in every shape a
  help call takes — a known/connected machine directly, a never-dialed
  one by joining its number room, discovering, and connecting exactly
  like a dial — then re-sends the Request every 2s until the customer's
  app answers (their `seen` is the ack; the customer re-asserts current
  state on a duplicate), the same delivery discipline as the connect
  handshake. cec_purchase_status / _confirm / _cancel + cec_purchases;
  only the ask's own peer can move it; a session End cancels its ask.
- node_control.rs: the five dispatch arms.

gui (technician CEC tab):
- "Request $50 diagnostic" on help-queue rows (bill before answering)
  and on Client-meshes rows (works connected or not), with live status
  from the customer (waiting / on their screen / at the checkout / says
  paid / declined), Confirm received (after checking the order in the
  store admin) and Withdraw; toasts on the two beats worth interrupting
  a phone call for.
- cecPurchase* bridge wrappers + cec://purchase listener + re-sync pull.

Also refreshes the stale node/ and gui/src-tauri lockfiles (workspace
crates 0.2.34 -> 0.2.35 to match the manifests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MzGQaTFkYtzYR7Hq1jBoGR
@mrjeeves
mrjeeves force-pushed the claude/cec-diagnostic-purchase-integration-hgphzb branch from 9d39e30 to 01b1e17 Compare July 12, 2026 23:28
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