Skip to content

v0.17.0

Choose a tag to compare

@compusophy compusophy released this 02 Jun 06:06
· 298 commits to main since this release

Device linking is reworked to Option A — identity is the seed, carried
between devices by QR seed-transport (no on-chain pairing, no per-device
keys, no glue). Platform $LH credits become the primary path to model
access (BYOK is the second option), agents pay each other in $LH over
x402, and a batch of registry quality-of-life facets land.

Added

  • Multi-device via QR seed-transport (Option A). "Add a device" (apex
    admin) encrypts this device's seed under a one-time code and renders a QR
    of localharness.xyz/?adopt=1#s=<ciphertext> — the encrypted seed rides
    the URL fragment (never sent to a server). The other device scans it,
    types the code, and imports the same seed; both devices then resolve the
    SAME owner address, so every subdomain shows and is controllable on every
    device. The chain read (list_owned_tokens = ownerOf) already worked —
    the fix was getting the same seed onto both devices, with no on-chain
    pairing, no per-device keys, and no redirect/pointer glue. The prior
    on-chain device-pairing path (PairingFacet, .lh_device_key,
    ECIES-wrap-to-device) is superseded and dormant.

Fixed

  • No-wallet claim no longer silently mints a second identity. A device
    with no wallet that claimed a name used to auto-generate a fresh seed —
    which is how a returning user on a second device ended up owning a
    different EOA's subdomains, splitting their identity. The claim flow
    now offers an explicit choice (create a new identity vs adopt an existing
    one) instead of minting silently.

Changed

  • Full on-chain reset (2026-06-01). A brand-new diamond, $LH
    token, and ERC-6551 infra were deployed; every prior address is
    abandoned and balances do not migrate. Canonical addresses now
    (Tempo Moderato, chain 42431, RPC https://rpc.moderato.tempo.xyz):
    • Diamond (registry): 0x6c31c01e10C44f4813FffDC7D5e671c1b26Da30c
    • $LH token (LocalharnessCredits): 0x90B84c7234Aae89BadA7f69160B9901B9bc37B17
    • ERC-6551 registry: 0x2795810e5dfC8bC92Ef7fc9557F6c0699E11c3B3
    • ERC-6551 account impl (MultiSignerAccount): 0x86be7c44d1940F4dE53A738153A12FaAEa68B5a7
    • Credit proxy: https://proxy-tau-ten-15.vercel.app
      Facets currently cut into the diamond: DiamondCut, Loupe, Ownership,
      LocalharnessRegistry, ERC721, Tba (MultiSigner impl), Feedback,
      MainIdentity, Pairing (v2), Credits, Redeem, Session, CreditMeter,
      X402, DeviceRegistry, Release. Registration is free; sessions are
      free (duration 3600, price 0). Per-facet implementation addresses
      are not pinned — they churn on re-cut; query the live set via the
      DiamondLoupeFacet (facets() / facetAddress(selector)).

Added

  • Credit proxy (proxy/), deployed. A separate Vercel project
    ("proxy") at https://proxy-tau-ten-15.vercel.app — a single
    TypeScript Edge Function (proxy/api/gemini.ts) that holds the
    platform GEMINI_API_KEY in env and is a transparent Gemini
    passthrough. Auth is an Ethereum personal-sign in the
    x-goog-api-key header (address:timestamp:signature); it gates on
    an active SessionFacet session OR a CreditMeterFacet balance, and in
    per-request mode debits via the meter key (viem, EIP-1559). The one
    accepted off-chain component and the only server in the system;
    everything else stays Tempo + browser. Platform credits are the
    PRIMARY model; BYOK is the second option.
  • RedeemFacet — cut into the diamond.
    Owner pre-loads keccak256(code) -> $LH amounts via
    addRedeemCodes(bytes32[],uint256); redeem(string) mints the mapped
    $LH to the caller through the diamond's ISSUER_ROLE; owner-only
    disableRedeemCodes. Bootstraps fresh wallets with zero off-chain
    payment rails. Cut via script/AddRedeemFacet.s.sol.
  • SessionFacet — cut into the diamond.
    Coarse time-boxed $LH credit sessions: openSession() spends
    sessionPrice() $LH for a window (expiry = now + sessionDuration()); owner-tunable setSessionPrice /
    setSessionDuration; view sessionExpiryOf(address) the proxy gates
    on. Currently sessionDuration = 3600, sessionPrice = 0 (free in
    beta). Cut via script/AddSessionFacet.s.sol.
  • CreditMeterFacet — cut into the diamond. Fine-grained per-request
    $LH metering: depositCredits, creditOf, meter-only meter(...),
    owner-only setMeter. The proxy's meter key EOA is setMeter'd +
    funded. Cut via script/AddCreditMeterFacet.s.sol.
  • X402Facet — cut into the diamond.
    True x402 (EIP-712 "exact" scheme) payment settlement in $LH for
    agent-to-agent: settle (EOA ecrecover + EIP-1271 verify, one-shot
    nonce), authorizationState, x402DomainSeparator (read it live —
    the separator binds chainId + the diamond address).
    The bundle's new src/x402_hook.rs injects the EIP-712 signer into
    call_agent so inter-agent calls settle in $LH. Cut via
    script/AddX402Facet.s.sol.
  • DeviceRegistryFacet — cut into the diamond. Enumerable
    linked-device index read in ONE call (linkDevice / unlinkDevice / devicesOf /
    isDeviceLinked), replacing SignerAdded log scraping that Tempo's
    RPC caps at 100k blocks. Cut via script/AddDeviceRegistryFacet.s.sol.
  • ReleaseFacet — cut into the diamond.
    releaseName(tokenId): owner-only burn that frees a name for
    re-registration; refuses the caller's MAIN. Cut via
    script/AddReleaseFacet.s.sol.
  • Agent tools list_subdomains + release_subdomain.
    list_subdomains() enumerates the owner's holdings (read-only).
    release_subdomain(name, confirmation) is DESTRUCTIVE — burns the
    name via ReleaseFacet; it requires confirmation == name (typed in
    chat), refuses the owner's MAIN, and is not given to subagents. The
    system prompt now mandates a typed, never-auto-filled confirmation for
    any destructive/irreversible action.
  • src/registry.rs client helpers for all of the above:
    redeem_sponsored, open_session_sponsored, session_expiry_of,
    session_price, credit_balance_of, deposit_credits_sponsored,
    x402_domain_separator, x402_digest, sign_x402,
    settle_x402_sponsored, x402_authorization_state, devices_of,
    is_device_linked, consolidate_into_main_sponsored,
    release_name_sponsored, release_name_calldata, erc20_balance_of,
    and remove_signer_sponsored (now also unlinks the DeviceRegistry
    index).