Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions context/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ connector (separate repo) ── the ILP payment engine: validates claims, fees
## Runtime topology (one paid write)

```
client ─(1) BTP PREPARE + signed claim─► connector (apex, g.connector)
client ─(1) BTP PREPARE + signed claim─► connector (apex, g.proxy)
(2) ClaimReceiver verifies claim, takes fee,
routing table → g.connector.relay
routing table → g.proxy.relay
(3) localDelivery HTTP POST /handle-packet ─► relay BLS
client ◄─(5) BTP FULFILL─ connector ◄─(4) accept (event stored) ◄──────────────────┘
(6) at threshold → SettlementMonitor →
Expand All @@ -39,8 +39,8 @@ discovery: nodes publish kind:10032 peer-info on Nostr; clients read it to find
## Load-bearing invariants

1. **Claim validation happens once, in the connector.** Nodes receive an already-paid `PaymentRequest` and only run business logic — they never re-verify signatures/balances (and couldn't; they don't hold channel state). See [decisions.md](./decisions.md).
2. **Parent→child forwarding is free** (settled in aggregate). The child must be registered `relation:'child'` AND tag the apex nodeId `g.connector` as its parent (`TOON_PARENT_PEER_ID`); get either wrong and paid traffic to the child is rejected (T00/F06).
3. **The apex nodeId is an on-wire ILP nodeId** baked into the connector + every child's parent tag — load-bearing: the connector and every child must agree on it, or paid forwarding breaks (T00/F06). The canonical term is **`g.connector`** (used by code, infra, and live edge); a cleanup to purge ~60 legacy `g.townhouse` references still on `origin/main` is pending.
2. **Parent→child forwarding is free** (settled in aggregate). The child must be registered `relation:'child'` AND tag the apex nodeId `g.proxy` as its parent (`TOON_PARENT_PEER_ID`); get either wrong and paid traffic to the child is rejected (T00/F06).
3. **The apex nodeId is an on-wire ILP nodeId** baked into the connector + every child's parent tag — load-bearing: the connector and every child must agree on it, or paid forwarding breaks (T00/F06). The canonical apex nodeId is **`g.proxy`** (children `g.proxy.<type>`, env prefix `PROXY_*`; used by the live devnet and epic-44); a cleanup to purge remaining legacy `g.connector` references in favor of `g.proxy` is pending. "Connector" stays the repo/product name.
4. **Reads are free** Nostr WS and bypass the payment path entirely.

## Payment model
Expand Down
2 changes: 1 addition & 1 deletion context/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Guiding thesis: **"sending a message and sending money are the same action."** E
- **store** — NIP-90 **Arweave DVM** (kind:5094): pay to store a blob permanently; the FULFILL returns the Arweave tx id.
- **swap** — multi-chain swap peer: pay asset A, receive a signed target-chain claim redeemable for asset B (EVM / Solana / Mina).

Operators run the **connector as a proxy-server layer** — the apex (nodeId `g.connector`) sitting in front of child relay/swap/store containers. Clients pay the proxy over BTP; it validates, fees, and **free-forwards** to the child.
Operators run the **connector as a proxy-server layer** — the apex (nodeId `g.proxy`) sitting in front of child relay/swap/store containers. Clients pay the proxy over BTP; it validates, fees, and **free-forwards** to the child.

## Current state (2026-06)

Expand Down
4 changes: 2 additions & 2 deletions context/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Curated, durable decisions. ADR-lite: each is *decision → why*.
## Boundaries

- **Claim validation lives ONLY in the connector.** `core` never imports the connector (structural `EmbeddableConnectorLike` interface); `sdk` dynamically imports it only to auto-create one; the `payment-handler-bridge` dispatches an *already-paid* packet to business logic. *Why:* the connector is the only component holding channel state — re-validating downstream is double work and incorrect.
- **Apex / free-forward.** Operators run an apex (the connector as a proxy-server layer, `g.connector`) + child nodes; parent→child packets carry no per-packet claim (settled in aggregate). Children must be `relation:'child'` and tag `g.connector` as parent. *Why:* one paid hop at the edge; children earn via aggregate settlement.
- **Apex / free-forward.** Operators run an apex (the connector as a proxy-server layer, `g.proxy`) + child nodes; parent→child packets carry no per-packet claim (settled in aggregate). Children must be `relation:'child'` and tag `g.proxy` as parent. *Why:* one paid hop at the edge; children earn via aggregate settlement.
- **Trust degrades; money doesn't.** (TEE) Attestation state changes never trigger payment-channel closure. *Why:* trust is a gradient, not a gate.

## Repo split (2026-06)
Expand All @@ -23,7 +23,7 @@ Curated, durable decisions. ADR-lite: each is *decision → why*.
- **`toon` (core+sdk) is libraries only; connector is an optional peer.** *Why:* the library layer must build/publish independent of the payment engine.
- **The connector owns & publishes `@toon-protocol/mina-zkapp`.** *Why:* one canonical Mina channel contract; the connector already depends on it, and it was unpublished/`private`, breaking installs.
- **Publish via `pnpm publish` / changesets, never `npm publish`.** *Why:* `npm publish` shipped unresolved `workspace:*`, making `sdk@0.5.0`/`town@0.4.0` uninstallable.
- **`g.connector` is the canonical apex wire nodeId.** *Why:* it's baked into the connector + child parent tags and every party must agree on it, or paid forwarding breaks (T00/F06) — so it's a load-bearing on-wire term, not cosmetic. **Status:** the code, infra, and live edge all use **`g.connector`** (vhost `connector.<domain>/ilp`). A cleanup to purge the ~60 legacy `g.townhouse` references still on `origin/main` in favor of `g.connector` is a **pending follow-up**.
- **`g.proxy` is the canonical apex wire nodeId.** *Why:* it's baked into the connector + child parent tags and every party must agree on it, or paid forwarding breaks (T00/F06) — so it's a load-bearing on-wire term, not cosmetic. **Status:** the live devnet and the epic-44 docs use **`g.proxy`** (children `g.proxy.<type>`, env prefix `PROXY_*`; live ILP edges e.g. `connector.pay.toonprotocol.dev/ilp`, `proxy.store.devnet.toonprotocol.dev/ilp`). "Connector" remains the repo/product name — only the on-wire nodeId + env prefix are the `g.proxy` axis. A cleanup to purge remaining legacy `g.connector` references in favor of `g.proxy` is a **pending follow-up**.

## Knowledge architecture

Expand Down
8 changes: 4 additions & 4 deletions context/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

**BTP** — Bilateral Transfer Protocol (RFC-0023). WebSocket session between two peers carrying ILP packets. TOON's **only** transport; clients pay an apex over BTP.

**ILP address** — hierarchical routing label, e.g. `g.connector`, `g.connector.relay`. Longest-prefix matched by the connector's routing table. `g.connector` is the canonical apex term (see *Apex / proxy*).
**ILP address** — hierarchical routing label, e.g. `g.proxy`, `g.proxy.relay`. Longest-prefix matched by the connector's routing table. `g.proxy` is the canonical apex nodeId (see *Apex / proxy*).

**PREPARE / FULFILL / REJECT** — the three ILPv4 packet types. A TOON write is one PREPARE; the node answers FULFILL (accepted) or REJECT (with an error code, e.g. F06/T00/T04).

Expand All @@ -14,7 +14,7 @@

**Settlement** — redeeming accumulated claims on-chain via `claimFromChannel` once a threshold is crossed. In-process, multi-chain.

**Apex / proxy** — an operator's deployment: the connector acting as a payment **proxy-server layer** in front of child relay/swap/store nodes. Clients pay the apex; it free-forwards to children. (No separate "hub" product — the proxy role lives in the connector itself.) **Naming:** the canonical term is **`connector` / `g.connector`** (apex `g.connector`, children `g.connector.<type>`, vhost `connector.<domain>/ilp`). Pending cleanup: `origin/main` still has ~60 legacy `g.townhouse` references to purge toward `g.connector`. The Path A payment-proxy **core is shipped on connector `main`** (proven live at `connector.pay.toonprotocol.dev`); only the devnet roundtrip harness (PR #245) and the `deploy/pay-edge/` bundle (PR #246) remain open PRs.
**Apex / proxy** — an operator's deployment: the connector acting as a payment **proxy-server layer** in front of child relay/swap/store nodes. Clients pay the apex; it free-forwards to children. **Naming:** the canonical apex on-wire nodeId is **`g.proxy`** (children `g.proxy.<type>`, e.g. `g.proxy.relay`; env prefix `PROXY_*`). "Connector" remains the correct name for the repo and the payment-engine product — the `g.proxy` axis is only the on-wire nodeId + env prefix. There is no single canonical vhost scheme; live ILP edges include `connector.pay.toonprotocol.dev/ilp`, `proxy.devnet.toonprotocol.dev`, and `proxy.store.devnet.toonprotocol.dev/ilp`. Pending cleanup: purge remaining legacy `g.connector` references in favor of `g.proxy`. The Path A payment-proxy **core is shipped on connector `main`** (proven live at `connector.pay.toonprotocol.dev`); only the devnet roundtrip harness (PR #245) and the `deploy/pay-edge/` bundle (PR #246) remain open PRs.

**Parent / child / peer** — connector peer relations. Child packets are claim-free (settled in aggregate); a child must tag the apex as parent.

Expand All @@ -26,7 +26,7 @@

**NIP** — Nostr Improvement Proposal. TOON implements many on its ILP-gated relay (see the NIP skills).

**Rig** — a browser-only frontend (`@toon-protocol/rig`) that interprets TOON events and renders them: it subscribes to a relay (free reads), decodes the events, and fetches git objects from Arweave. It speaks the NIP-34 git vocabulary today — so it resembles a read-only git forge — but is **not** a GitHub clone. Because the state lives as paid, permanent events on TOON rather than on an origin server, the Rig is a **decentralized control plane**, with the git view as its first surface. See [docs/rig-guide.md](../docs/rig-guide.md).
**Rig** — a browser-only frontend (`@toon-protocol/rig`) that interprets TOON events and renders them: it subscribes to a relay (free reads), decodes the events, and fetches git objects from Arweave. It speaks the NIP-34 git vocabulary today — so it resembles a read-only git forge — but is **not** a GitHub clone. Because the state lives as paid, permanent events on TOON rather than on an origin server, the Rig is a **decentralized control plane**, with the git view as its first surface. See [docs/rig-guide.md](../docs/rig-guide.md). **Disambiguation:** "control plane" canonically refers to this — the Rig's event-space (the shared, signed TOON event log and the views over it). The `toon-clientd` daemon's loopback HTTP surface is the **control API**, not a control plane; avoid the collision.

**DVM** — Data Vending Machine (NIP-90). Pay a kind:5xxx request, get a kind:6xxx result. On TOON only **kind:5094** (Arweave blob storage) is live.

Expand All @@ -36,4 +36,4 @@

**relay / swap / store** — the three TOON node products (Nostr relay / multi-chain swap / Arweave DVM). Formerly town / mill / dvm.

**connector apex nodeId (`g.connector`)** — the apex's on-wire ILP nodeId and the canonical apex term; load-bearing (baked into the connector + every child's parent tag, so it must match across the deployment). A cleanup to purge ~60 legacy `g.townhouse` references on `origin/main` in favor of `g.connector` is pending.
**apex nodeId (`g.proxy`)** — the apex's on-wire ILP nodeId and the canonical apex term; load-bearing (baked into the connector + every child's parent tag, so it must match across the deployment). A cleanup to purge remaining legacy `g.connector` references in favor of `g.proxy` is pending.
2 changes: 1 addition & 1 deletion context/repos.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ The pet-game packages (`pet-dvm`, `pet-circuit`, `mina-zkapp` [the game one], `m

## Package names (final)

`mill→swap` is the active published swap-package name, and cross-repo deps resolve cleanly. `@toon-protocol/mill` is fully gone (404); `@toon-protocol/swap` is the live swap package. The former operator product — `@toon-protocol/townhouse`, later renamed `@toon-protocol/hub`/`hub-web`/`hub-mcp` — is **removed**: the proxy-server role now lives in the **connector** itself. `@toon-protocol/townhouse` was already deprecated/redirected (completed 2026-06-22, issue #44), and the `hub*` packages are likewise deprecated. The wire vocabulary's **canonical term** is apex nodeId **`g.connector`**, child addresses `g.connector.<type>`, vhost `connector.<domain>/ilp` — used by the code, infra, and live edge. **Pending cleanup:** `origin/main` still carries ~60 legacy **`g.townhouse`** references to purge in favor of `g.connector` (and stray `terminator` from the older retired name); that is a naming-cleanup follow-up, not a "proxy rename". The `town`/`mill`/`dvm` node-**type** terms are a separate naming axis and remain live wire-protocol identifiers, left intact. Epic [toon-meta#42](https://github.com/toon-protocol/toon-meta/issues/42) swept the last stale `@toon-protocol/mill` ref in `store`.
`mill→swap` is the active published swap-package name, and cross-repo deps resolve cleanly. `@toon-protocol/mill` is fully gone (404); `@toon-protocol/swap` is the live swap package. The former operator product (`@toon-protocol/hub`/`hub-web`/`hub-mcp`) is **removed**: the proxy-server role now lives in the **connector** itself. The hub packages are deprecated (completed 2026-06-22, issue #44). The wire vocabulary's **canonical term** is apex nodeId **`g.proxy`**, child addresses `g.proxy.<type>` (e.g. `g.proxy.relay`), env prefix `PROXY_*` — used by the live devnet and the epic-44 docs. "Connector" remains the repo/product name; only the on-wire nodeId + env prefix are the `g.proxy` axis. Live ILP edges include `connector.pay.toonprotocol.dev/ilp` and `proxy.store.devnet.toonprotocol.dev/ilp` (no single canonical vhost scheme). **Pending cleanup:** purge remaining legacy `g.connector` references in favor of `g.proxy`; that is a naming-cleanup follow-up, not a "proxy rename". The `town`/`mill`/`dvm` node-**type** terms are a separate naming axis and remain live wire-protocol identifiers, left intact. Epic [toon-meta#42](https://github.com/toon-protocol/toon-meta/issues/42) swept the last stale `@toon-protocol/mill` ref in `store`.

## Outstanding follow-ups

Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Validation order matters — TOON format is checked **before** payment. Malforme

#### Multi-Chain Settlement

The payment a write carries is a signed payment-channel balance proof, and that proof can be denominated on **EVM, Solana, or Mina**. A client built from a single BIP-39 mnemonic derives an identity on each chain (Nostr/EVM share secp256k1; Solana is Ed25519; Mina is Pallas) and signs the claim format that chain's connector verifier expects — EIP-712 for EVM, a raw Ed25519 message for Solana, a Pallas-Schnorr claim over a Poseidon commitment for Mina. When the destination is the proxy apex (`g.connector`), the apex validates the claim, fulfills, and auto-drives the on-chain redemption on the matching chain once the per-channel settlement threshold is exceeded. The EVM and Solana paths credit the recipient on-chain (Solana at channel close via `SETTLE_CHANNEL`); on Mina the per-publish claim redeems on-chain (`claimFromChannel`, apex co-signs the counterparty signature) but recipient credit-at-close is a deferred follow-up (Story 34.4). Full detail: [Settlement →](settlement.md).
The payment a write carries is a signed payment-channel balance proof, and that proof can be denominated on **EVM, Solana, or Mina**. A client built from a single BIP-39 mnemonic derives an identity on each chain (Nostr/EVM share secp256k1; Solana is Ed25519; Mina is Pallas) and signs the claim format that chain's connector verifier expects — EIP-712 for EVM, a raw Ed25519 message for Solana, a Pallas-Schnorr claim over a Poseidon commitment for Mina. When the destination is the proxy apex (`g.proxy`), the apex validates the claim, fulfills, and auto-drives the on-chain redemption on the matching chain once the per-channel settlement threshold is exceeded. The EVM and Solana paths credit the recipient on-chain (Solana at channel close via `SETTLE_CHANNEL`); on Mina the per-publish claim redeems on-chain (`claimFromChannel`, apex co-signs the counterparty signature) but recipient credit-at-close is a deferred follow-up (Story 34.4). Full detail: [Settlement →](settlement.md).

### Reading (Free)

Expand Down
Loading