Glossary

Project-specific vocabulary for Tally. The goal is a shared, precise language: the same word should mean the same thing in code, docs, and conversation. When a term means something specific here that differs from its everyday or industry sense, this is where it is pinned down.

How to read this glossary

Core domain

Tally
Three related meanings, usually clear from context: (1) the app itself; (2) the running balance of debt between you and one friend — positive means they owe you (synonyms in this sense: balance, debt, stored as debt_eur); (3) the app's main page. "Signing a tally" = recording a transaction.
Transaction, IOU, Record
The act (and record) of the user taking on or settling debt with a friend — "I owe you". The most common kind of durable record. In the UI this is the record screen ("record a tally"); in the code it's a transaction peer message. "IOU" is also the project's former name. → see Tally.
Friend, Connection
An accepted peer relationship between two users. "Connection" is the legacy term (still present as deprecated data-model aliases); friend is the current word everywhere in UI and new code.
Friendship status
Where a friendship stands, from the local user's point of view: pending_outgoing (you asked), pending_incoming (they asked), accepted, rejected, or disabled (after a default). Only an accepted friendship is a friend in the everyday sense.
Default, Disabled friendship, Reactivation
Openly giving up on a friendship's tally (or absolving it, or just deactivating a zero tally), with an optional note. Both sides keep the friendship disabled: records visible as history, counted in no total, no new activity. Either side can suggest reactivation, which sends its signed copy of the history along. Deleting the history is final for the side that does it. See Defaulting.
Contact
A cached public identity (npub + display name) of a person the client has seen. Broader than friend: every friend has a contact, but a contact is not necessarily an accepted friend.
Payment request
Asking a friend to pay you. Any number can be open at once, in either direction. A request stays open until the friend pays or declines it (a response) or the requester cancels it — whichever reaches the ledger first. Paying materializes the mirroring transaction on both sides. Open requests are derived from the ledger, never stored; see the Ledger spec §4.3.
Trust limit, Credit limit
The maximum amount you allow a friend to owe you. Lowering takes effect immediately; raising requires the friend's agreement (sits pending until they echo it). "Credit limit" is the legacy term still used on the wire (credit_limit_suggestion) and in the stored fields (trust_credit_limit_eur); "trust limit" is the UI and everyday term.
Available trust
A friend's trust limit plus the current balance with them — how much more they could still owe you before hitting the limit. E.g. a 50 € limit with Bob already owing you 30 € leaves 20 € of available trust (and Bob has 80 €). Never negative: if the balance already exceeds the limit, available trust is 0. The headroom routed payments travel through.
Routed payment, Current
A payment to someone you are not friends with, made of ordinary IOUs passed along a route of friends: Alice owes Bob, Bob owes Charlie, and Bob ends up neutral. All-or-nothing, as one multi-party record that every participant signs, the payer last. Not implemented yet; see TIP-007. The website calls one a current (currency flowing friend to friend); the app says payments flow friend to friend. Formerly "chained transaction".
Route (payment), hop
The path of friends a routed payment travels along, payer to payee (Alice → Bob → Charlie). Each step between two friends is a hop, and every hop must have enough available trust. A circular cancellation runs along a cycle: a path that closes back on itself. Not the UI route. Formerly "chain".
Command
A domain module under app/js/commands/ that performs one user action (friendship, transaction, payment request, trust limit, relays, stun…). Not a CLI command. Each command loads state, validates, queues a peer message, mirrors it to the ledger, and persists.

Messages, ledger & sync

Peer message
Any JSON message exchanged between two clients (friend↔friend or a user's own device↔device). Has a type; may or may not be durable.
Record, Durable message, Ledger entry
A peer message that is a permanent fact in the ledger (a transaction, friend request/accept, name change, trust-limit change…) and therefore carries an authorship proof. "Record" is the user-facing word; "durable message" is the transport term; "ledger entry" is its stored form. Contrast: transport-only messages (ping/pong, sync, receipts) are non-durable and carry no authorship.
Ledger
The append-only local log of every durable message the user has authored or received. The source of truth from which all balances are derived. Not a blockchain and not shared wholesale — it is reconciled peer-by-peer via sync.
Outbox
The queue of outbound peer messages awaiting delivery, persisted so they survive reloads and retries.
Envelope
The encrypted wrapper around a peer message. Routing fields (id/from/to) stay in plaintext so the relay server can deliver it; the inner message is encrypted to the recipient. Versioned: v3 = NIP-44 (current), v2 = legacy AES-GCM (accepted on receipt only, to drain old messages).
Authorship proof, Authorship
A signed Nostr event embedded inside a durable message proving who authored it, so forwarded/third-party records can be trusted during sync. Replaced the older bare per-message signature.
Sync (sync_hello / sync_data)
The exchange two connected peers/devices use to reconcile their ledgers: each offers what it has, the other sends back what's missing. How a recovering or reconnecting device catches up.
Receipt
A transport-level acknowledgement that a peer message was received. Non-durable; never enters the ledger.
Push hint
A small encrypted payload attached to a queued envelope so the relay can wake an offline recipient via Web Push without learning its contents. Attached only for event types the recipient enabled (notification prefs).
Notification prefs
A user's choice of which events reach them as OS notifications, sent to friends as a notification_prefs ledger message; the latest one wins. See TIP-005.

State & rendering

View, view model
The read-only, sanitised object derived from app state and handed to the UI — balances totalled, private keys stripped. Rebuilt in full by buildView on every change; the UI never reads raw state and never writes it. See Render flow.
Binder
A page's bind* function (bindTally, bindFriends, …). It receives the view, populates that page's freshly built DOM, and wires its event handlers. Pages hold no state of their own, so a binder runs again from scratch on every render.
Route
Where the user is, parsed from window.location.hash — a main page (#tally, #friends, #logs, #settings), a subpage (#friend/<id>, #record, …), or #welcome. The only thing that decides which page renders; navigating is setting the hash.
Upcast, payload version
Reading an old-format signed record by verifying it as signed, then converting its payload to the current shape — never re-signing it. The record's payload version (payload.v, absent = 1) is per type and signed. A rule for future format changes; none has needed it yet. See the Ledger spec §10.
Routing budget
Proposed: a binding promise that up to a set amount may be routed from one friend onward through you while you can't be reached. Unlike the informal trust limit it is consumed by use and never refills. See TIP-009.
Checkpoint
Proposed: a record both friends co-sign stating the balance between them and exactly which transactions it covers, after which the history before it need never be forwarded again. Trust limits are not part of it. See TIP-008.
Model version, migration
DATA_MODEL_VERSION stamps the shape of the persisted root state. On load, versioned migrations reshape an older record forward before normalisation. Unrelated to the app version or the service worker's precache hash — see Build & runtime.

Transport & connectivity

Peer
A remote endpoint the client connects to: a friend's device, or one of the user's own other devices. Keyed by (userId, deviceId).
Device id
A stable identifier the client generates for itself on first start and persists. One user can be online on several devices at once, so a peer is addressed by (user id, device id) rather than by user alone.
Mesh
The WebRTC overlay of live peer connections. Split into two: the friend mesh (one connection per friend device) and the self-mesh (one connection per the user's own other devices, used to sync devices in lock-step). When WebRTC can't connect own devices, their sync falls back to the relay (see peer communication spec §13.8).
Relay, Relay server, Signaling server
Tally's own WebSocket server. It does two jobs: relays WebRTC signaling so peers can connect, and does store-and-forward of encrypted envelopes when a peer is offline (or when direct P2P can't form). Distinct from a TURN relay and an ICE relay candidate. The main relay is the server that served the app; secondary relays are user-added in settings.
Snapshot, Realtime snapshot
The in-memory object built from persisted state and handed to the transport layer: who to connect to, what to deliver, and the KeyProvider to sign/encrypt with. Rebuilt whenever state changes.
KeyProvider
The single abstraction through which all signing and peer encryption flow. Implementations: local (private key in-app) and nip07 (key held in a browser extension). Lets the private key live outside the app without the rest of the code touching raw key material.
WebRTC / data channel
Used here only to carry encrypted JSON app messages peer-to-peer (never audio/video). The "green icon" state.
STUN
A public server used during connection setup so each peer can discover its own public (reflexive) address, enabling direct connections across networks. User-configurable in settings; defaults to Cloudflare.
ICE candidate (host / srflx / relay)
The address options WebRTC tries when connecting: host = local network (same-LAN only), srflx = public address via STUN (cross-network), relay = via a TURN server (not used here). Note "relay" here is unrelated to Tally's relay server.

Identity & cryptography

Nostr, npub, nsec
Tally identities are Nostr keys. npub… is the public key (a user's id); nsec… is the secret key. Tally uses Nostr keys and signatures but does not publish transactions to public Nostr relays.
NIP-01 / NIP-07 / NIP-44 / NIP-49
The Nostr standards in use: event/signature format (01), browser-extension signer (07), encrypted payloads (44), and passphrase-encrypted key export / ncryptsec (49).
Signer type
Which KeyProvider a user's identity uses: local (private key stored in the app) or nip07 (key held in a browser extension). Stored on the user record and not secret. See TIP-006.
Schnorr / secp256k1
The signature scheme and curve behind Nostr identities and authorship proofs.
TIP
Tally Improvement Proposal: a design document under TIPs/. See the TIPs index for the implemented-vs-draft convention.