Docs / Help / Changelog
Help

Changelog

What changed.

Unreleased#

  • Public try page (router/http/public.mjs, panel/try/, opt-in ELYRA_PUBLIC_TRY=1): signed-out visitors of the admin hostname get a real streamed chat on the node's local model, never a peer, hosted key or simulated answer; per-client hourly limit, daily cap, concurrency cap, strict CSP. Tests: router/test/public.test.mjs.
  • Wallet connect (Reown AppKit, ELYRA_REOWN_PROJECT_ID): fund the escrow from your own wallet (depositFor the node address). Bundle built by tools/wallet/. Tests: router/test/fund.test.mjs.
  • Control panel restyled as a plain product dashboard; sign-in page and sign-out button for remote admin.
  • Routing fix: a live listing now always beats the simulated market within a request (plan()). Before, after connecting Ollama model: auto was still answered by a simulated peer with canned text. See docs/DECISIONS.md. Tests: router/test/market.test.mjs.
  • Opt-in remote admin (router/http/remote.mjs, ELYRA_ADMIN_HOST + ELYRA_ADMIN_TOKEN): the real panel, /api and /v1 on one named host behind a login (signed cookie, rate limits, CSRF check, proxied traffic never gets the localhost path, /metrics never). Off by default; loopback rules otherwise unchanged. Tests: router/test/remote.test.mjs (11). Docs: docs/REMOTE-ADMIN.md.
  • Remote admin login page: Referrer-Policy: same-origin (was no-referrer, which made Chrome send Origin: null and the login was refused). Regression test added (12 tests in remote.test.mjs).
  • Panel UX: next-step banner on Overview (connect a real model / hide the simulated market), one-click Ollama detection from Overview, "connected" card in Connect, live models first in the Playground with an honest empty state and a wait indicator for cold model loads, tidier result badges. Mobile: fixed grid minimum widths that pushed every card past the screen (0 overflowing elements in all 8 views at 390 px), topology graph scrolls inside its box.
  • Test router/test/panel.test.mjs: every panel module must parse and every relative import must resolve to an export (the panel has no build step, so nothing else catches this).
  • Open-source readiness: LICENSE (MIT, matching the contract SPDX headers), SECURITY.md, CONTRIBUTING.md, rewritten README.md; new docs INSTALL, OLLAMA, USAGE, CONFIGURATION, DEPLOY-CLOUDFLARE, and a docs index.
  • Cloudflare Pages: tools/pages/ renders the landing + docs into dist/; wrangler.toml; .github/workflows/deploy-pages.yml. /app/* redirects to the install guide because the panel needs a local router.
  • Static demo removed. /app/ on the website redirects to the live node at app.elyrainference.com.
  • New docs: PANEL, API (control API reference), PROVIDER, FAQ, GLOSSARY.
  • Pages bundle ships a 404.html (otherwise Pages answers unknown paths with 200 and the landing). First live deploy: elyra-5cg.pages.dev.
  • Tests: node boot wait raised from 5 s to 30 s (router, TEE) and the encryption-at-rest test now stops each child once the boot banner is printed instead of after a fixed 4 s. On a loaded host boot took 4.5 s and tests failed spuriously. No runtime change.

0.2.0 — 2026-11-04#

Architecture (2026-11-06)#

  • Repo restructured: vpr/ → router/, app/ → panel/, landing mirror → site/. URLs unchanged (/, /app/).
  • router/node.mjs (920 lines) split into router/core/ (+ consumer/, provider/), router/http/ (route table per surface), router/lib/; router.mjs renamed policy.mjs. No wire, API or on-disk format change; the 47 tests are unchanged.
  • Panel app.js (735 lines) split into ES modules (lib/, components/, views/, css/); more remote strings escaped; dead code removed.
  • Added docs/LANDSCAPE.md (competitors and reusable repos), docs/VPS.md (seller node on a VPS), docs/HANDOFF.md (agent onboarding) and docs/REGISTRY.md (discovery design, not built).

Rename (2026-11-06)#

  • New logo: supplied "E" mark everywhere (app, favicon, landing header/footer) and the 3D hero + token models regenerated from it (tools/brand/).
  • Solais → Elyra everywhere (see docs/STATUS.md → Naming). Wire-breaking: PROTOCOL 3, ElyraEscrow redeployed + verified on Robinhood testnet, ELYRA_* env vars, .elyra data dir (legacy .solais adopted).

TEE (2026-11-05)#

  • Real attestation verification for Google Confidential Space (router/tee.mjs), buyer-pinned image digests, VERIFIED vs CLAIMED, stricter teeOnly, TEE-mode seller (attestation in hello, local upstreams only), payout sweep, boot env config, redeem on shutdown, deploy/tee/ kit, docs/TEE.md. Breaking for routing: self-declared and demo TEE no longer count as private.

Roles (2026-11-05)#

  • Overview onboarding for buyers and sellers, seller Earnings panel (earnDaily in /api/ledger stats), app talks to its own origin on any port, no-store for app assets, landing marks 600+/150+ as a launch target.

Security review fixes (2026-11-05)#

  • Found while testing live: vouchers are bound to the escrow they were signed for; the voucher baseline is max(local cumulative, on-chain claimed) + amount (provider mirrors it). Mainnet-fork rehearsal script (npm run rehearse:mainnet) and its report.
  • Receipts are validated strictly and the amount is derived locally; vouchers must be canonical 65-byte signatures; provider credit is keyed by wallet with a fail-closed on-chain deposit check, worst-case admission control (max_tokens capped at 8192) and auto-redeem; requests are ed25519-authenticated with replay protection; wallet control is proven (EIP-191); voucher pushes are sealed; settlement is per-wallet and fault tolerant. Escrow v2: withdraw requests are single-use and expire (7 days). See docs/STATUS.md for the finding table.

Operations#

  • Protocol version negotiation (PROTOCOL = 2, mismatch refused with a clear error, x-elyra-protocol header), Prometheus /metrics, /healthz, structured JSON logs, GitHub Actions CI. Tests: metrics never contain prompt text; old-protocol peers are refused.

USDG settlement (supersedes the ETH design below)#

  • Deployed and exercised on Robinhood Chain Testnet: MockUSDG + ElyraEscrow verified on Blockscout; two-node paid trade settled on chain (addresses and tx hashes in docs/STATUS.md).
  • ElyraEscrow(token) is ERC-20: deposit(amount)/depositFor, balance-delta check, safe transfers; MockUSDG for testnet/local (open mint, labelled). Amounts are token units (USDG 6 decimals) = dollars × 1e6: no oracle, no usdPerEth. Receipts carry amountUnits.
  • router/net.mjs: DoH resolver so Robinhood hosts work behind DNS-hijacking ISPs; chain ids verified live.
  • Deploy: npm run chain:deploy:testnet (uses the node wallet). Panel: token/balances, mint (mock only), approve+deposit.

Added#

  • On-chain settlement for Robinhood Chain (Arbitrum Orbit, ETH gas): contracts/ElyraEscrow.sol (deposit, cumulative EIP-712 vouchers, redeem, delayed withdraw; 12 hardhat tests), router/chain.mjs adapter, consumer vouchers after every verified receipt, provider credit limit and escrow-funding check, /api/chain*, Payments → Escrow panel, explorer links. Verified end to end against a local EVM (router/test/chain.test.mjs). Not yet exercised on the live Robinhood testnet (RPC unreachable from the dev machine).
  • Sealed transport (protocol v2): prompts and completions encrypted to the provider's X25519 key; unsealed requests refused.
  • Token-inflation audit: receipts claiming far more output tokens than the received text are rejected.
  • SSRF guard for gossip-learned peers, per-consumer rate limit, deny list, startup re-contact of remembered peers, wallet/box-key binding in hello.
  • Landing: legal pages, removed agency trackers/socials, honest TEE wording.

Network view#

  • Rebuilt: ring topology (live / bridge / community), vendor logos on bridge nodes, animated packets on recent routes, hover tooltip, click-for-detail with per-peer model table and TRY, filters, stat tiles.

Fixed#

  • Hosted upstreams (OpenRouter, OpenAI, …) are no longer labelled LOCAL/private: they show HOSTED · CLEAR, score 0 on privacy, and are excluded by teeOnly / auto:private. Only localhost/LAN upstreams count as local.

Security#

  • Optional encryption at rest via ELYRA_PASSPHRASE (router/vault.mjs), tested (encrypted files, same identity across restarts, refuses without/with wrong passphrase).

Blockscout#

  • contracts/verify.mjs (+ artifacts/standard-input.json from the build), explorer address links and a verified-source badge in Payments. Tip: if the primary RPC is down, a Blockscout instance may serve JSON-RPC at <explorer>/api/eth-rpc; paste it as the RPC override.

Changed#

  • Receipts now carry amountWei/providerWallet in chain mode. /p2p/infer body is {from, sealed}.
  • Node address is now the real secp256k1 wallet (was a derived placeholder). Runtime dependency: ethers.
  • Client hang-ups no longer count as peer failures.

0.1.0 — 2026-11-04#

Added#

  • router/: Virtual Private Router daemon. OpenAI-compatible endpoint, policy ranking, failover, ed25519 signed receipts, peer gossip, provider mode, ledger + simulated-testnet settlement, loopback-only control API, static hosting of site and panel.
  • panel/: control panel rewritten in the landing's visual language (indigo gradient, paper surface, NB Architekt, bracketed cards). Views: Overview, Playground, Models, Routing, Network, Payments, Provide, Connect. Provider/model logos from assets/logos.
  • Simulated demo market (labelled) so routing works on a fresh install.
  • npm test: ranking rules + two-node integration (billing equals receipt, streaming, price-bait refusal, TEE-only, local-only API).
  • AGENTS.md, PRD.md, ROADMAP.md, docs/.

Changed#

  • Landing copy, meta, 3D labels and dashboard image rewritten from "AI visibility analytics" to "peer-to-peer AI inference".

Removed#

  • server.mjs and start-mirror.bat (superseded by router/server.mjs, start.bat).