Units and the database¶
A repository is a set of units (the images of snow.yml, or the entries of .model-wtf.yml), each with its own codebase, plus one SQLite database at the repository root, compliance.db, holding everything a human or an agent declares — for the product as a whole and for each unit.
The database is committed like any other file. It is tuned to diff well
(WAL journal, no auto-vacuum, a checkpoint on every close) and the
transient sidecars (*.db-wal, *.db-shm, *.db-lock) are ignored by git.
Nothing generated is stored: models, routes and stores from the settings
are introspected from the code on every run. The schema is versioned
(PRAGMA user_version): a database written by an older release is
migrated in place the first time a newer one opens it, and a file from a
newer release is refused rather than misread.
- the
approw —name,description,controller(party id, the client), optionalprocessor(party id, the agency),large_scale(Art. 35(3)(b); absent means no: a DPIA is then only required for special-category data;!todoasks the question once). parties— one row per organisation:name,country(ISO alpha-2),address,email; optionalphone,website,hosts(API hostnames the code calls when they differ from the website, e.g.api.hubapi.com: a call to one is a transfer to this party),registration,dpa(where the processing agreement lives),safeguard/dpf_certified,dpoandrepresentativecontact blocks,distinct_from(ids of parties this one resembles but is not). A party is role-less: controller, processor or recipient is decided per processing activity. A party nothing refers to (no transfer, no role, norecipients) is a Todo. One organisation is one row:party_addrefuses a party whose name normalises to a declared one's (case, accents, punctuation and legal forms such asInc,SAS,GmbHignored; a word added or a typo in a long name still matches), whose website orhostsshare a registrable domain or a setting name with one, or whose id is a respelling of one; it also refuses a party that is really a store of the project (Sentry, an "SMTP mail server", a party claimingEMAIL_HOST). The refusal is final for an agent. A human resolves the rare real case on the command line:parties distinct <id> <id>records that two lookalikes are two organisations (Mailgun and Mailjet),parties merge <id>... --into <id>folds duplicates into one (transfers, recipients, roles, stamps move; the winner's!todofacts take the losers' answers),parties to-store <id> <unit:slug>turns a party that was infrastructure into store writes,parties to-flow <id>drops a party that was the project itself (its own endpoint: the edge is the derivedcallsflow, nothing leaves). Two lookalikes that already coexist are aparty-duplicateerror incheck.
uv run model-wtf compliance app show [--format table|json]
uv run model-wtf compliance app set [--name N] [--description D] [--controller ID] [--processor ID] [--large-scale|--no-large-scale] [--todo FIELD]... [--clear FIELD]...
uv run model-wtf compliance parties list [--unused] [--format table|json]
uv run model-wtf compliance parties show <id> [--format text|json]
uv run model-wtf compliance parties add [<id>] --name N [--country CC] [--website URL] [--host H]... [--distinct-from ID]...
uv run model-wtf compliance parties set <id> [--name N] [--country CC] [--address A] [--email E] [--safeguard S] [--host H]... [--todo FIELD]... [--clear FIELD]...
uv run model-wtf compliance parties remove <id> [--force]
uv run model-wtf compliance parties merge <id>... --into <id>
uv run model-wtf compliance parties to-store <id> <unit:slug>
uv run model-wtf compliance parties to-flow <id>
uv run model-wtf compliance parties distinct <id> <id>...
uv run model-wtf compliance parties duplicates [<candidate-id> --name N] [--all]
Unit discovery¶
Units are read from snow.yml at the repo root: every images[] entry that
carries a compliance: block is a unit. discover names the discovery backend
for that codebase (django, sveltekit, none) and is the only key: the
unit's code is the Dockerfile's folder, its declarations live in the
database. An image without compliance produces a warning (an error under
--strict).
images:
- id: api
context: api # Dockerfile at api/Dockerfile
compliance:
discover: django # code in api/
- id: front
context: .
dockerfile: front/Dockerfile
compliance:
discover: sveltekit # code in front/
- id: docs
context: .
compliance:
discover: none
Repos not deployed through Snow can use .model-wtf.yml instead
(units: [{id, context, dockerfile, compliance}]). When both files exist
snow.yml wins.
The product-level rows (the app, the parties, the activities, the findings register) form the shared scope; each unit's rows (data items, reviews, touchpoint declarations, stores, stamps) its own.