@wenathlan/argan 2.0.154 → 2.0.158

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,10 +19,11 @@ pnpm dev
19
19
 
20
20
  # The family contract (wave 6-a)
21
21
 
22
- - `family.ts` — the single table of the eight siblings beside argan with the
23
- spec §12 accent of each one; the shell rail foot, the landing footer and
24
- `tests/family.test.ts` all consume this one table.
25
- - `familyurl.ts` — the verbatim relative-url contract (`"../" + slug + "/"`)
22
+ - `family.ts` — the family keyword file (the fold law): the single table of
23
+ the eight siblings beside argan with the spec §12 accent of each one — the
24
+ shell rail foot, the landing footer and `tests/family.test.ts` all consume
25
+ this one table — plus the retired `familyurl.ts` arm riding as the
26
+ familyurl lane: the verbatim relative-url contract (`"../" + slug + "/"`)
26
27
  that keeps every cross-app link mount-proof.
27
28
  - `restore:entry` — the entry-face guard: a no-op while `index.html` rides the
28
29
  canonical source face (the `./App.tsx` script plus the font triad link), a
package/cli.ts ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @file cli.ts — the argan binary seat of the clibin wave (PR13 — CLI
4
+ * binário mesmo design): the same Windows 11 chat console as the web and
5
+ * desktop surfaces, rendered inside the terminal as a subapp — the only
6
+ * difference is responsiveness / DPI (the 28px top rule becomes one line
7
+ * and the accent falls back to the ANSI 256 palette).
8
+ * @module argan/cli
9
+ * @family wave/clibin
10
+ * @law same design as web / desktop, difference only responsiveness / DPI
11
+ * @seat 2026 · rung 2.0.157 · hierarchical JSDoc, tokens/flags, no hardcoded
12
+ * data — the version is read from package.json at runtime and the engine
13
+ * one-liner is quoted from the app docs.
14
+ * @runtime node strips the types; the shebang hands the file to the runtime
15
+ * (the saddle law).
16
+ * @deps zero — node builtins only (readline/promises, process, fs/promises).
17
+ */
18
+
19
+ import { createInterface } from "node:readline/promises";
20
+ import { argv, exit, stdin, stdout } from "node:process";
21
+ import { readFile } from "node:fs/promises";
22
+
23
+ /* ════════════════════════════════════════════════════════════════════ */
24
+ /* Section 1: the chrome tokens — the windows 11 palette folded to the DPI of the terminal (the accent #a3d7e6 lands on ansi 117, the focus #4cc2ff on 75, the hover red rgb(232,17,35) on 203; the 28px top rule becomes one line). */
25
+ /* ════════════════════════════════════════════════════════════════════ */
26
+
27
+ /** the chat accent of the prompt and the titlebar name. */
28
+ const ACCENT = "\x1b[38;5;117m" as const; // #a3d7e6
29
+ /** the focus ink of the active top rule. */
30
+ const FOCUS = "\x1b[38;5;75m" as const; // #4cc2ff
31
+ /** the hover red of the unknown-command rows. */
32
+ const HOVER = "\x1b[38;5;203m" as const; // rgb(232, 17, 35)
33
+ /** the dim ink of the description rows (the minimal text law). */
34
+ const INK = "\x1b[2m" as const;
35
+ /** the reset token that closes every colored run. */
36
+ const RESET = "\x1b[0m" as const;
37
+ /** the single glyph of the rules and the rails. */
38
+ const BAR = "─" as const;
39
+
40
+ /** the app name of this binary seat — the titlebar text. */
41
+ const APP = "argan" as const;
42
+ /** the engine ownership one-liner, quoted from the app docs. */
43
+ const ENGINE =
44
+ "the network, DNS and edge engine of the devthink family — authoritative zones, record snapshots, dnssec validation math, a 231-protocol gateway mesh and a 3217-row media type catalog (docs/engine.md)" as const;
45
+
46
+ /** the titlebar bar: the app name on the left rail, the window controls on the right — the windows 11 chrome inside the terminal. */
47
+ function titlebar(): string {
48
+ return `${ACCENT}┌ ${APP} ─ cli${RESET} ${INK}${BAR.repeat(24)} ─ ❐ ✕${RESET}`;
49
+ }
50
+
51
+ /** the top rule: the 28px divider of the web surface folded to one terminal line. */
52
+ function toprule(): string {
53
+ return `${FOCUS}${BAR.repeat(3)} ${APP} ${BAR.repeat(3)}${RESET}`;
54
+ }
55
+
56
+ /* ════════════════════════════════════════════════════════════════════ */
57
+ /* Section 2: the runtime reads — no hardcoded data; the version comes from package.json at runtime. */
58
+ /* ════════════════════════════════════════════════════════════════════ */
59
+
60
+ /** reads the version of this seat from the sibling package.json — never a literal. */
61
+ async function readversion(): Promise<string> {
62
+ try {
63
+ const manifest = JSON.parse(await readFile(new URL("./package.json", import.meta.url), "utf8")) as { version?: string };
64
+ return manifest.version ?? "0.0.0";
65
+ } catch {
66
+ return "0.0.0";
67
+ }
68
+ }
69
+
70
+ /* ════════════════════════════════════════════════════════════════════ */
71
+ /* Section 3: the chat console — the REPL with the ❯ prompt, the command dispatch and the same chat look as the web surface. */
72
+ /* ════════════════════════════════════════════════════════════════════ */
73
+
74
+ /** the command help of the console — minimal text law: title + description only. */
75
+ function help(): string[] {
76
+ return [
77
+ `${INK}commands${RESET}`,
78
+ ` help ${INK}this list${RESET}`,
79
+ ` version ${INK}the package version, read from package.json at runtime${RESET}`,
80
+ ` engine ${INK}the engine ownership one-liner of the app${RESET}`,
81
+ ` exit ${INK}close the console${RESET}`,
82
+ ];
83
+ }
84
+
85
+ /** runs the chat console: the titlebar, the top rule, the ❯ prompt and the dispatch (help, version, engine, exit); an eof on stdin closes the console the same way exit does. */
86
+ export async function main(): Promise<void> {
87
+ /* the version read happens before the interface exists, so a piped stdin never races the readline open (node buffers the pipe until the reader resumes it). */
88
+ const version = await readversion();
89
+ const rl = createInterface({ input: stdin, output: stdout });
90
+ let eof = false;
91
+ rl.on("close", () => { eof = true; });
92
+ console.log(titlebar());
93
+ console.log(toprule());
94
+ console.log(`${ACCENT}${APP}${RESET} ${INK}v${version}${RESET}`);
95
+ console.log(`${INK}the ${APP} console — same design as web / desktop, only the DPI differs. type help.${RESET}`);
96
+ rl.setPrompt(`${ACCENT}❯${RESET} `);
97
+ rl.prompt();
98
+ for await (const raw of rl) {
99
+ const line = raw.trim();
100
+ const command = line.length > 0 ? line.split(/\s+/)[0]!.toLowerCase() : "";
101
+ if (command === "exit") rl.close();
102
+ else if (command === "help") for (const row of help()) console.log(row);
103
+ else if (command === "version") console.log(`${ACCENT}${APP}${RESET} ${version}`);
104
+ else if (command === "engine") console.log(`${INK}${ENGINE}${RESET}`);
105
+ else if (command.length > 0) console.log(`${HOVER}✕${RESET} ${INK}unknown command: ${command} — type help${RESET}`);
106
+ if (command === "exit") break;
107
+ /* the prompt is cosmetic chrome: a piped stdin that already reached eof skips it, the buffered lines still answer. */
108
+ if (!eof) rl.prompt();
109
+ }
110
+ console.log(`${INK}${APP} console closed.${RESET}`);
111
+ }
112
+
113
+ /* the autorun guard (the saddle law): only a direct `node cli.ts` (or a bun run) boots the console here — an import stays quiet. */
114
+ if (import.meta.url === `file://${argv[1]}`) main().catch((error) => { console.error(error); exit(1); });
package/docs/engine.md ADDED
@@ -0,0 +1,60 @@
1
+ # argan engine
2
+
3
+ The network, DNS and edge engine of the devthink family: authoritative zones, record set snapshots, DNSSEC validation math, a 231-protocol gateway mesh, a 3217-row media type catalog and a self-hosted SQLite data layer, served to a Vite + React Sol surface.
4
+
5
+ ## Overview
6
+
7
+ Argan is the DNS and gateway library of the wenathlan family (`@wenathlan/argan`, version 2.0.155). The engine lives as library-grade TypeScript modules at the app root; the web surface lives in `sol/` and renders every row from the data layer (seed rows offline, the site API over HTTPS when configured). The published package exports `./mimetypes` for family consumers (the vault storage engine among them).
8
+
9
+ ## Module inventory
10
+
11
+ - `argan.ts` — the domain core: types for zones (`ZoneSnapshot`), record sets (`RecordSetRow`), publication steps, feature cards, signal badges, DNS transports, config blocks, rollover steps and option choices; helpers `formatSerial` (YYYYMMDDNN serials), `nextSerial` (revision bump, rolls at 99), `findZone`, `transportsByPort`, `apexZoneFile` (verbatim zone file rebuild) and `findConfigBlock`.
12
+ - `dnssec.ts` — the DNSSEC validation math: RRSIG presentation parsing (RFC 4034 §3.1), the RFC 4034 Appendix B key tag checksum, signature validity window with clock skew, RRset/RRSIG TTL equality, the label-count wildcard rule and the DS→DNSKEY structural match. Answers 8 IANA algorithms (5, 7, 8, 10, 13, 14, 15, 16) and 3 DS digest types (SHA-1, SHA-256, SHA-384); every failed check names one of 11 typed failure codes. Cryptographic signature verification itself is deliberately out of scope.
13
+ - `mimetypes.ts` — the media type catalog: 3217 rows across 10 families (application 2245, text 260, audio 255, video 138, image 170, chemical 54, model 45, message 27, multipart 17, font 6). Extension collisions resolve in family order (`.ts` answers `video/mp2t`, `.tsx` answers `application/typescript`). The engine tail adds the corpus layer: `parseMimeCorpus` and `createMimeCatalog` (families, type/extension/entry counts, `mimeTypeFor`, `extensionsFor`, `contentTypeFor` with the `application/octet-stream` default).
14
+ - `protocols.ts` — the gateway protocol mesh: 231 protocol rows in 15 family groups (web 17, api 23, messaging 25, tunnel 25, legacy 29, file 16, stream 15, overlay 14, ops 14, dns 12, directory 11, mail 10, remote 9, data 7, collab 4). Each row names its port, governing spec and security posture — 84 encrypted, 60 opportunistic, 87 cleartext; `tlsCapableProtocols()` answers the 144 wires that run or upgrade to TLS-grade crypto.
15
+ - `zonediff.ts` — the planned change set engine: a master-file parser (RFC 1035 §5.1 — `$ORIGIN`/`$TTL` directives, `@` apex, owner inheritance, parenthesized continuations, quoted strings, RFC 2308 TTL units) and an external-dns style planner (`diffZones`, `diffZoneFiles`, `recordsFromRows`, `serialForPublication`) that groups records by owner and type, compares targets as a set, reports `create`/`delete`/`update` with reason `targets` or `ttl`, and suggests the next serial through `argan.nextSerial`.
16
+ - `catalog.ts` — the typed accessor the Sol pages call: 14 list functions (`listZones`, `listApexRecordSets`, `listTransports`, `listConfigBlocks`, `listProtocols`, `listMimetypes` and friends) that fetch from `VITE_CATALOG_URL` over HTTPS when configured or answer from the in-memory seed, behind a memoized promise cache that retries failed fetches.
17
+ - `db.ts` — the self-hosted SQLite runtime: opens better-sqlite3 through `openStorageLane` from `@wenathlan/vault/storagelane` (default file `./local.db`), re-exports the parameterized helpers `execute`, `queryAll`, `queryOne` — no SQL is ever assembled by string concatenation.
18
+ - `seed.ts` — the in-memory content tables: 5 zones, the apex `devthink.pro` record set snapshot (A, AAAA, CAA, MX, NS, SOA, TXT rows), 5 publication steps, 4 library cards, 2 DNSSEC key cards, 3 DoH-first cards, 3 hero badges, 4 algorithm badges, 8 transports, 2 config blocks, 4 rollover steps, 5 resolver choices and 2 locale choices.
19
+ - `labels.ts` — the copy law: an English manifest of 183 interface strings (`LABEL_MANIFEST`, revision 2) with the accessors `label`, `labelfill` and the browser-side `seedLabels`; the store factory comes from `@wenathlan/vault/labelstore`. Translated rows are protected from seed overwrites.
20
+ - `cleanurl.ts` — the clean URL bar: hash routes become paths, `index.html` and duplicate slashes disappear, and campaign trackers (utm, gclid, fbclid, msclkid, dclid, igshid, yclid, twclid, `_tt`, srsltid and friends) are stripped with `replaceState` — no reload, no history pollution.
21
+ - `theme.ts` — the light-fusion theme default: `dark`/`light` on the `data-theme` document attribute, session scope only, no cookies or storage.
22
+ - `motionpref.ts` — the in-session reduce-motion switch: rides session storage under `argan.motion.reduced` and the `data-motion="reduced"` document flag, additive on top of `prefers-reduced-motion`.
23
+ - `reveal.ts` — scroll reveal: an IntersectionObserver at 12% visibility adds the `in` class once per element.
24
+ - `onboardingstate.ts` — the first-run state: the only writer of the intro/onboarding seen flags; DB is the source of truth over `GET`/`POST /api/v1/onboarding` (base `VITE_ONBOARDING_URL`, host-validated — localhost, loopback, private and reserved ranges refused), with the localStorage key `argan.onboarding.seen` as a pure cache mirror and a stable per-browser visitor id.
25
+ - `sandboxmodality.ts` — the workload lane declaration: 4 mirrored lanes (`dnssec-validate`, `zonefile-parse-diff`, `catalog-registry-serve`, `label-store-seed`) with role, demand and boot budget; resolves the deploy's `ARGAN_SANDBOX_LANE` seat (local, join, or a pinned modality id).
26
+ - `family.ts` — the family keyword file (the fold law): the family table — the 8 sibling slugs (cadria, debonair, forge, foundry, getry, saddle, stealthhead, vault) with the spec §12 accent and dot-ink of each, consumed by the shell rail, the landing footer and the family test — plus the retired `familyurl.ts` arm riding as the familyurl lane: the cross-app URL contract where `familyurl(slug)` answers the relative `"../" + slug + "/"` path so every family link survives any mount point.
27
+
28
+ ## Data layer
29
+
30
+ - Storage: better-sqlite3 via the vault `storagelane` (`openStorageLane`, default file `./local.db`); the schema mirrors `schema.prisma`.
31
+ - Tables: 7 — `zones`, `record_sets`, `dnssec_keys` (algorithm default 15, ED25519), `gateway_routes`, `content_rows`, `onboarding_state` and `labels`.
32
+ - Bootstrap: `ensureSchema()` creates the tables idempotently; `seedIfEmpty()` inserts the 11 seed content kinds plus zones and record sets inside one transaction on first run.
33
+ - Accessors: `zoneRow`, `recordSetRows`, `getonboardingstate`, `setonboardingstage` (seen-monotonic upsert), `saveLabel`, `readLabel`, `readAllLabels`, `seedLabelRows` (ingests the labels manifest, protects translated rows; rides the boot best-effort).
34
+ - Serving: `catalog.ts` serves the same tables to the Sol pages over HTTPS when `VITE_CATALOG_URL` points at the site API; a page never hardcodes a row.
35
+
36
+ ## Sol surface
37
+
38
+ - `sol/Sol.tsx` — the theme anchor and route tree: `/intro`, `/onboarding`, `/`, `/zones`, `/dnssec`, `/gateway`, `/settings`, `/404` plus the catch-all.
39
+ - `sol/home/` — the landing: a dig-style local resolver over the served apex snapshot (query types A, AAAA, MX, NS, TXT, SOA, CAA; wildcard honored; honest ok/nodata/nxdomain verdicts), hero badges, the zones and library ledgers, publication steps, the apex CTA and the family footer; the entry gate decides between intro, onboarding and the landing.
40
+ - `sol/zones/` — the zones console: the zone ledger with the apex featured and the newest serial pulsing, the 5-step publication rail, the apex record set ledger and the verbatim zone file one summary away.
41
+ - `sol/dnssec/` — the DNSSEC console: the KSK/ZSK key ledger, the algorithm badges, the sign-pipeline output as a terminal and the 4-step rollover ladder.
42
+ - `sol/gateway/` — the gateway console: the transport table (8 transports — classic 53, DoT 853, DoH 443, DoH JSON, DoQ, DoH3, DNSCrypt, ODoH), the 3-step DoH-first rail and the staging Corefile terminal.
43
+ - `sol/settings/` — the settings console: three numbered sections (appearance, clean URLs, network) with the theme switch, the reduce-motion switch, resolver and locale selects and a live clean-URL demo.
44
+ - `sol/intro/`, `sol/onboarding/` — the first-run flow: a 1.6s splash with the drawn mark and three Windows 11-style first-run frames; both mark their stage through `onboardingstate.ts`.
45
+ - `sol/shell/` — the app frame: full-bleed standalone law, the page rail, the family foot with one accent dot per sibling, the theme flip and the `ArganMark` icon.
46
+ - `sol/notfound/` — the single 404 (RCODE 3, NXDOMAIN).
47
+ - `sol/toast/` — the toast surface: a role=status live region with success, error and info tones.
48
+ - `sol/wingets/` — the shared widgets: `HomeEntrygate` (the first-run gate) and `ShellEmptystate` (glyph, one line of truth, one action, pending shimmer).
49
+
50
+ ## Family integration
51
+
52
+ - `@wenathlan/vault/storagelane` — the SQLite lane `db.ts` opens (`openStorageLane`, `SqlParam`).
53
+ - `@wenathlan/vault/labelstore` — the label store factory `labels.ts` rides; the vite and vitest configs bridge the specifier to the monorepo source.
54
+ - `saddle/workloadlaw.ts` — the `FAMILYLANES` engine of record that `sandboxmodality.ts` mirrors (rows mirrored, not imported; the vitest battery pins the mirror against the engine source through the library bridge).
55
+ - `family.ts` — the 8 sibling deploy units in rail order, linked out through relative URLs (the familyurl lane of the fold answers the links).
56
+ - Runtime dependencies include `@wenathlan/cadria`, `@wenathlan/debonair`, `@wenathlan/devthink`, `@wenathlan/getry`, `@wenathlan/saddle` and `@wenathlan/vault` (all `~2.0.155` family envelopes).
57
+
58
+ ## Testing
59
+
60
+ Seven vitest batteries at `tests/`: `design.test.ts`, `dnssec.test.ts`, `family.test.ts`, `mimetypes.test.ts` (pins the 3217 count), `protocols.test.ts` (pins 231 rows and the 144 TLS-capable wires), `sandboxmodality.test.ts` and `zonediff.test.ts`.
@@ -0,0 +1,75 @@
1
+ # argan features
2
+
3
+ Real feature list of the argan engine and its Sol surface, extracted from the code — every entry names a module.
4
+
5
+ ## DNS
6
+
7
+ - Zone table — `argan.ts` types the managed zones (origin, master/slave kind, YYYYMMDDNN serial, signed state); the seed carries 5 zones with `devthink.pro` as the apex.
8
+ - Serial management — `formatSerial` builds the YYYYMMDDNN serial (UTC date plus daily revision) and `nextSerial` bumps it, rolling the revision at 99.
9
+ - Record set snapshots — `RecordSetRow` carries the verbatim zone-file line of every apex record (A, AAAA, CAA, MX, NS, SOA, TXT in the seed); `apexZoneFile` rebuilds the zone file text from the rows.
10
+ - Zone file parser — `zonediff.ts` `parseZoneRecords` handles `$ORIGIN`, `$TTL`, the `@` apex, owner inheritance on indented lines, parenthesized continuations, quoted strings, both `[ttl] [class]` orders and RFC 2308 TTL units (s/m/h/d/w), throwing `ZoneDiffError` with the offending line number.
11
+ - Zone planner — `diffZones`/`diffZoneFiles`/`recordsFromRows` diff two zone versions into create/delete/update changes grouped by owner and type; round-robin order never produces a change and an unconfigured TTL never triggers an update.
12
+ - Publication serial — `serialForPublication` keeps the serial when the diff is empty and bumps it through `nextSerial` otherwise.
13
+ - Dig resolver — `sol/home/home.tsx` parses dig-style queries (`dig <name> [TYPE]`, verb optional) and resolves them against the served apex snapshot with the wildcard honored, answering ok, nodata or nxdomain.
14
+ - Record type chips — the home resolver offers A, AAAA, MX, NS, TXT, SOA and CAA, intersected with the served rows.
15
+ - Publication flow — the 5-step rail (Validate, Write zone, Persist, Republish, Serve) served from `seed.ts` through `catalog.ts` to the zones page.
16
+
17
+ ## DNSSEC
18
+
19
+ - RRSIG parsing — `parseRrSig` reads the RFC 4034 §3.1 presentation fields, including zone-file UTC timestamps (YYYYMMDDHHmmSS), and rejects broken rows with `DnssecValidationError`.
20
+ - Key tag checksum — `keyTag` computes the RFC 4034 Appendix B checksum over the DNSKEY rdata (`dnsKeyRdata`).
21
+ - Validity window — `validateSignatureWindow` checks inception/expiration with a configurable clock skew on both edges.
22
+ - TTL rules — `validateSignatureTtl` enforces the RRset/RRSIG TTL equality and the original-TTL ceiling.
23
+ - Wildcard label rule — `validateSignatureLabels` checks the label count against the owner name with the wildcard drop rule.
24
+ - DS match — `validateDsMatch` and `validateChainLink` check the DS→DNSKEY structural match over the IANA registries (key tag, algorithm, digest type, zone-key flag, protocol).
25
+ - Typed verdicts — every failed check answers one of 11 `DnssecFailureCode` values, traceable from the resolver answer back to the row.
26
+ - Algorithm registry — `DNSSECALGORITHMS` answers 8 IANA algorithms (RSASHA1 through ED448); `DNSSECDIGESTTYPES` answers 3 DS digest types.
27
+ - Key cards — the dnssec page serves the KSK (360-day rollover, DS in the parent) and ZSK (90-day rollover, NIST SP 800-81r3) ledger from the data layer.
28
+ - Rollover ladder — the 4-step key rotation timeline (Pre-publish T−30d, Switch T0, Retire T+TTL, Remove T+2TTL) with CDS/CDNSKEY DS swap.
29
+
30
+ ## Edge and gateway
31
+
32
+ - Transport table — `seed.ts` carries the 8 DNS transports the gateway speaks: classic UDP+TCP 53, DoT 853, DoH 443, DoH JSON, DoQ 853/UDP, DoH3 443/UDP, DNSCrypt 443 and ODoH 443; `transportsByPort` filters by port.
33
+ - Protocol mesh — `protocols.ts` registers 231 protocol rows in 15 family groups (web through legacy), each with scheme, port, governing spec and security posture; `findProtocol`, `protocolsByGroup`, `protocolSchemes` and `protocolGroups` serve the lookups.
34
+ - TLS-capable count — `tlsCapableProtocols` answers the 144 wires that run encrypted or upgrade to it (84 encrypted, 60 opportunistic).
35
+ - Security tones — `protocolTone` derives the badge tone of one protocol row from its posture and state.
36
+ - Media type catalog — `MIMETYPES` carries 3217 media types across 10 families; `mimeTypeForExtension` resolves extensions in family order (`.ts` → `video/mp2t`), plus `findMimeType`, `extensionsForType`, `mimeFamilyOf` and `mimetypesByFamily`.
37
+ - Corpus engine — `parseMimeCorpus` parses any registry corpus (the vault's `mime.types` lane among them) and `createMimeCatalog` builds the served catalog: families, type/extension/entry counts, `mimeTypeFor`, `extensionsFor`, `extensionOf` and `contentTypeFor` with the `application/octet-stream` default.
38
+ - DoH-first strategy — the 3-step gateway rail (Probe on UDP/53, Switch to DoH on 443, Serve the same TTL-cached answers on every transport) served to the gateway page.
39
+ - Staging Corefile — the gateway page renders the staging CoreDNS Corefile and the `argan sign` pipeline output as config blocks from `seed.ts`.
40
+ - Clean URLs — `cleanurl.ts` rewrites hash routes to paths, drops `index.html` and duplicate slashes, strips campaign trackers (utm, gclid, fbclid, msclkid, dclid, igshid, yclid, twclid, `_tt`, srsltid) with `replaceState` and keeps the canonical link in sync.
41
+
42
+ ## Storage
43
+
44
+ - SQLite runtime — `db.ts` opens better-sqlite3 through the vault `storagelane` (default file `./local.db`); every statement is prepared and parameterized.
45
+ - Schema — 7 tables: `zones`, `record_sets`, `dnssec_keys`, `gateway_routes`, `content_rows`, `onboarding_state` and `labels`, mirroring `schema.prisma`.
46
+ - First-run seed — `seedIfEmpty` inserts the 11 content kinds plus zones and record sets inside one transaction when the content rows are empty.
47
+ - Typed accessors — `zoneRow`, `recordSetRows`, `getonboardingstate`, `setonboardingstage`, `saveLabel`, `readLabel` and `readAllLabels` serve parameterized reads and upserts.
48
+ - Catalog accessor — `catalog.ts` serves the same tables to the pages over HTTPS (`VITE_CATALOG_URL`) with a memoized promise cache and the offline seed fallback; a failed fetch retries on the next call.
49
+ - Label store — `labels.ts` seeds the 183-entry English manifest (revision 2) through the vault `labelstore`, protecting translated rows from overwrite; the db-side twin `seedLabelRows` rides the boot.
50
+ - Onboarding state — `onboardingstate.ts` keeps the first-run flags in the DB over `GET`/`POST /api/v1/onboarding` (host-validated against localhost, loopback, private and reserved ranges), with the localStorage key `argan.onboarding.seen` as a cache mirror and a seen-monotonic merge.
51
+ - Workload lanes — `sandboxmodality.ts` declares the 4 lanes the app owns (`dnssec-validate`, `zonefile-parse-diff`, `catalog-registry-serve`, `label-store-seed`) with role, demand and boot budget, and resolves the `ARGAN_SANDBOX_LANE` seat (local, join, pinned modality).
52
+
53
+ ## UI
54
+
55
+ - Route tree — `sol/Sol.tsx` mounts `/intro`, `/onboarding`, `/`, `/zones`, `/dnssec`, `/gateway`, `/settings` and the `/404` catch-all behind the wouter router.
56
+ - Entry gate — `HomeEntrygate` reads the first-run state and routes unseen visitors to the intro or the onboarding; only a finished flow sees the landing.
57
+ - Intro splash — the 1.6s opening splash with the drawn mark, skippable by click or key, straight hand-over under reduced motion.
58
+ - Onboarding frames — three first-run frames (what the app is, what it hosts, the enter hand-over); finish and skip both mark the stage seen.
59
+ - Zones console — the zone ledger with the apex featured and the newest serial pulsing, the publication rail, the record set ledger and the verbatim zone file.
60
+ - DNSSEC console — the KSK/ZSK ledger, the algorithm badges with tone dots, the sign-pipeline terminal and the rollover ladder.
61
+ - Gateway console — the transport ledger (ports in kbd, states as dots), the DoH-first rail and the Corefile terminal.
62
+ - Settings console — three numbered sections (appearance, clean URLs, network): theme switch, reduce-motion switch, resolver select (5 choices), locale select (2 choices) and a live tracker-stripping URL demo with toast feedback.
63
+ - Shell frame — `Shell.tsx` renders full-bleed at the app's own URL (the standalone law) or identical under the DevThink OS embedded seat, with the page rail, the family foot of 8 sibling accent dots and the theme flip.
64
+ - Theme — `theme.ts` applies the light-fusion default and the dark variant through the `data-theme` attribute, session scope only.
65
+ - Reduce motion — `motionpref.ts` rides the `argan.motion.reduced` session key and the `data-motion="reduced"` document flag, additive on top of `prefers-reduced-motion`.
66
+ - Scroll reveal — `reveal.ts` adds the `in` class at 12% visibility through one shared IntersectionObserver.
67
+ - Toast — `Toast.tsx` answers action feedback in success, error and info tones through a role=status live region (2600 ms fade, 3000 ms remove).
68
+ - Empty states — `ShellEmptystate` renders the glyph-in-wash, one line of truth and one real action, with the pending shimmer while tables are in flight.
69
+ - Family rail — `family.ts` links the 8 siblings in rail order with their spec §12 accents through mount-proof relative URLs (the familyurl lane of the fold).
70
+ - 404 — `notfound.tsx` renders the single NXDOMAIN (RCODE 3) page.
71
+ - Error boundary — `App.tsx` wraps the router in a theme error boundary with a reload action and seeds the label store before the first paint.
72
+
73
+ ## Dependencies
74
+
75
+ - synchronized dependency union — the eleven family apps share one dependency tree: identical `dependencies`, `devDependencies` and `peerDependencies` (same keys, same versions, nothing removed, highest semver wins on conflicts) and one `engines` catalog with node as maestro and the V 0.5.2 seat as catalog annotation (@family wave/depssync).