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
- Synonyms are comma-separated in the term, most-commonly-used first. e.g. Record, Durable message — both name the same thing and "record" is heard more often. Overlap is intentional: it marks where a conversation most needs clarification.
- Each term is linkable. Every entry has a stable
anchor — click a term to get its link, or deep-link from any page as
glossary.html#ledger. - Kept short, links out. The glossary is meant to grow wide (many terms) but stay shallow: each entry is a one- or two-line orientation that links to the group page or code where the concept is explained in full.
- Focus is app-specific terms. Generic/industry terms (WebRTC, STUN, Nostr…) appear only when crucial and used in a project-specific way.
- Scope is the Tally app only (
app/,server/,tests/,TIPs/).GraphEditor/andweb/are separate projects and are not covered. - Definitions are definitional, not implementation docs — what a term means, not how the code currently does it, so they age well.
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
transactionpeer 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, ordisabled(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).
- 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_prefsledger 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
buildViewon 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 pertypeand 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_VERSIONstamps 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) andnip07(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) ornip07(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.