Ctrl K
ComunidadGuías…

CONTEXT.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# CONTEXT

The domain model for Squelch — the vocabulary the code, the tests, and the UI
all use for the same things. When a name here and a name in code disagree, one
of them is a bug.

This is the *shared language* file. Structure and rules live elsewhere:
`.github/PROJECT_LAYOUT.md` for layout, `.github/CONVENTIONS.md` for
the Security Rules, `docs/adr/` for decisions and why they were made.

## What Squelch is

A web-based radio call manager. Radio recorders (Trunk-Recorder, SDRTrunk, and
anything speaking the rdio-scanner upload API) push recorded transmissions to
it; Squelch stores the audio on disk and the metadata in SQLite, streams it to
browsers, and serves an admin dashboard. One Go binary with the React SPA
embedded in it.

It does not do the scanning. It is the archive and the distribution layer for
what something else scanned — which is what the name is about.

## Core nouns

**Call** — one recorded transmission: an audio file plus its metadata
(talkgroup, system, timestamp, duration, source unit). The atom of the whole
system. Table `calls`. Everything else exists to route, filter, or present
Calls.

**System** — one radio system being monitored (a P25 trunked system, typically).
Owns Talkgroups. Table `systems`.

**Talkgroup** — the channel a Call was transmitted on, within a System. What a
listener actually chooses between. Table `talkgroups`; grouped by `groups` and
labelled by `tags`.

**Unit** — the individual radio that transmitted. Table `units`.

**Recorder** — the external software producing Calls (Trunk-Recorder, SDRTrunk).
Never called a "scanner": the scanner is the hardware, the Recorder is the
software, and Squelch is neither.

**Listener** — a signed-in user consuming Calls in the browser. Distinct from
**Admin**, who configures the system. Both are rows in `users`; the difference
is the admin flag on the JWT.

## Ingest

**Upload** — a Recorder POSTing a Call to the API. The legacy rdio-scanner
upload surface is kept working on purpose; see `docs/adr/`.

**Dirmonitor** — a filesystem watcher that ingests Calls from a directory a
Recorder writes into, rather than waiting to be POSTed to. Table `dirmonitors`,
package `internal/dirmonitor`.

**Downstream** — another Squelch or rdio-scanner instance this one forwards
Calls to. Table `downstreams`, package `internal/downstream`.

**Webhook** — a URL that is sent a message about each Call (generic signed
JSON, or a Discord embed) rather than the Call itself. Table `webhooks`,
package `internal/webhook`. Downstreams and Webhooks together are
**Forwarding** in the admin.

## Listening

**Selection** — the set of Talkgroups a Listener has chosen to hear. Stored
server-side on the user (`tg_selection_json`); the browser keeps a
write-through cache only. Never modify a Listener's Selection as a side effect
of anything.

**AVOID** — a Talkgroup the Listener has temporarily muted without removing it
from the Selection.

**LIVE** — the normal listening mode: Calls arrive over the WebSocket and play
one at a time in the browser.

**BKGND** — background-audio mode. The server sends one never-ending,
silence-padded audio response so playback survives a locked phone. See
`docs/adr/0004-background-audio-server-stream.md`. Mobile only — on desktop a
background tab keeps running and the control is deliberately hidden.

**Queue** — the Calls waiting to play in LIVE mode. Meaningless in BKGND, where
the server owns the timeline; the display shows a dash rather than a count.

## Admin

**Instance** — one configured Trunk Recorder that Squelch consumes MQTT status
from. Table `tr_instances`, package `internal/trmqtt`. One Squelch can consume
many. Audio never arrives this way — MQTT carries status only.

**Setting** — a unit of application configuration. **All application
configuration lives in the database** (`settings`), not in files. Only
server-level concerns — listen address, database path, TLS, encryption key —
come from CLI, environment, or INI.

**Janitor** — the background sweep that ages out recordings and enforces the
disk-size cap.

## Cross-cutting

**enc::** — the prefix marking a secret encrypted at rest with AES-256-GCM. Its
key-derivation inputs are frozen and must never be renamed; see
`docs/adr/0003-secrets-at-rest.md`.

**v1 / legacy** — the two HTTP surfaces. `/api/v1/*` is canonical and is what
the SPA uses; `/api/*` is deprecated and exists only for Recorder
compatibility. New endpoints go on v1 only.

## Words we do not use

- **"Scanner"** for the app. Squelch is the archive; scanning happens upstream.
  (`features/scanner/` in the frontend predates the name and is the listener UI
  — rename it only as a deliberate, separate change.)
- **"Channel"** for a Talkgroup. Talkgroup is the domain term.
- **"Recording"** for a Call when the metadata matters. "Recording" is the file
  on disk; "Call" is the file plus what it means.