# llm-security-commons ## Kontekst Runtime-nøytral kjerne for LLM/agent-sikkerhetsdeteksjon: detektor-data, normative kontrakter og en conformance-korpus som **flere uavhengige runtimes** kan kjøre mot og få **identisk verdikt** fra. Repoet er delt kjerne, ikke et produkt. Kjente konsumenter (vendorer dette repoet, endrer det ikke): - `llm-security` — Claude Code-plugin, Node/ESM-scannere. - et Python-guard-repo — samme deteksjon i en annen runtime. - en wiki/advisory-flate — konsumerer samme lexicon og mapping. Å dele én identisk kjerne er hele poenget: to implementasjoner som gir ulikt verdikt på samme input er per definisjon en bug i én av dem — ikke en meningsforskjell. ## Charter (HARD — bryter du denne, er endringen feil uansett hvor god den er) **Ingen engine-kode. Ingenting her kjører.** - ❌ Ingen `.mjs`, `.js`, `.ts`, `.py`, `.sh` som implementerer deteksjon, scanning, normalisering, scoring eller I/O. - ❌ Ingen `package.json`, `pyproject.toml`, lockfiler, dependencies, build-steg. - ❌ Ingen import fra — eller kjennskap til — noe rammeverk, SDK eller runtime. - ❌ Ingen nettverk, ingen modellkall, ingen tidsavhengighet, ingen tilfeldighet. Alt her er **offline og deterministisk**. - ✅ Kun: JSON-data, normative spesifikasjoner (Markdown), og fixtures (`input` + `expected`). Regelen finnes fordi kjernen skal være **fork-and-own**: en konsument på en runtime vi ikke har tenkt på skal kunne vendore dette uten å arve et eneste teknologivalg. Mønsteret er kopiert fra søsterrepoet `portfolio-optimiser-commons` (samme harde charter: «nothing here may import/depend on a framework»). ## Stack Ingen. Data + prosa. Filformater: JSON (data + schema), Markdown (spec), rå tekst (conformance-input). ## Konvensjoner ### Data (JSON) - **Hver JSON-fil har et topnivå `"version"`-felt** (semver-streng). Uten unntak. - Hver JSON-fil har et topnivå `"$comment"` eller `"description"` som sier hva filen er og hvor dataene kom fra (provenance). - 2 mellomrom indentering, LF, avsluttende newline. UTF-8 uten BOM. - Kodepunkter skrives som `"U+200B"`-strenger (lesbare i review), aldri som rå usynlige tegn i JSON-kilden — bortsett fra i `conformance/*/input.txt`, som per definisjon inneholder de faktiske tegnene. - Nøkler er stabile identifikatorer. **Å endre en nøkkel er en breaking change** — konsumenter matcher på dem. ### Spec (Markdown) - Hver normativ spec har en `**Status: normative**`-markør øverst. - RFC 2119-språk (MUST / MUST NOT / SHOULD / MAY) i store bokstaver, brukt bevisst. - Informative dokumenter (`docs/`) har `**Status: informative**` og er aldri ground truth. ### Conformance - Én katalog per case: `conformance//input.txt` + `conformance//expected.json`. - `` er stabil og beskrivende. **Å endre en case-id er en breaking change.** - `expected.json` er ground truth. Er en runtime uenig med `expected.json`, er runtimen feil — med mindre fixturen selv bevises feil, og da endres fixturen i eget commit med begrunnelse. ### Sikkerhetskritiske tabeller — aldri fra hukommelse `codepoints/carriers.json` (inkl. homoglyph-map), `signatures/secret-egress.json`, `signatures/malware-signatures.json` og `signatures/active-content.json` er **deteksjonsdata**. Et gjettet kodepunkt eller et regex med feil escaping er en stille falsk negativ — en detektor som ser ut som den virker. **Disse filene endres KUN fra verifisert kildedata** (dump fra konsument-repo, Unicode-standarden, publisert leverandør-doc). Aldri fra egen hukommelse, aldri «fylt ut for konsistens». Kan en oppføring ikke verifiseres: utelat den, eller marker den eksplisitt uverifisert i `$comment`. ### Behaviour preservation (v0.1.0-invariant) v0.1.0 er en **ekstraksjon**, ikke en revisjon. Data som er hentet ut av en konsument skal gi **eksakt samme funn** når konsumenten senere leser dem herfra. Ser du noe du mener er feil i seed-dataene: **ikke fiks det her**. Dokumentér avviket, send det til konsumenten via `coord-send`, og la beslutningen tas der dataene er testet. ## Kommandoer Repoet har ingen build og ingen test-runner (charter). Validering er ad hoc: ```bash # Alle JSON-filer er velformet find . -name '*.json' -not -path './.git/*' -print0 | xargs -0 -n1 python3 -m json.tool > /dev/null # Hver JSON-fil har topnivå "version" for f in $(find . -name '*.json' -not -path './.git/*' -not -path './conformance/*'); do python3 -c "import json,sys; d=json.load(open('$f')); sys.exit(0 if 'version' in d else 1)" \ || echo "MANGLER version: $f" done # Hver spec har normativ-markør grep -L 'Status: normative' spec/*.md # Charter-guard: ingen kjørbar kode har sneket seg inn find . -type f \( -name '*.mjs' -o -name '*.js' -o -name '*.ts' -o -name '*.py' -o -name '*.sh' \) \ -not -path './.git/*' | grep . && echo 'CHARTER-BRUDD: kjørbar kode i commons' ``` ## Arbeidsflyt - **Versjonering:** semver på repo-nivå (tag `vX.Y.Z`). Hver JSON-fils `"version"` er filens egen semver og bumpes når *den filen* endres — de er ikke låst til repo-taggen. Nytt datafelt eller ny oppføring = minor. Endret/fjernet nøkkel, case-id eller disposisjon = **major** (konsumenter bryter). - **Versjonssync før commit:** endrer du en JSON-fil, bump dens `"version"`; endrer du repoets kontrakt, bump repo-taggen + CHANGELOG. - **Konsumenter varsles via `coord-send`**, ikke via antakelse. Et repo som vendorer denne kjernen får ikke vite at kontrakten endret seg med mindre du sier det. - **Aldri jobb i konsument-repoene fra en økt her.** Vendoring, oppgradering og behaviour-verifisering skjer i konsumentens egen økt, med konsumentens tester. - **Forgejo only** (`git.fromaitochitta.com`). Aldri GitHub, aldri `gh` CLI. - `STATE.md` er LOCAL-ONLY (gitignored) — remote er en offentlig flate. ## Communication patterns ### Linking to local files When pointing to local files in responses, always use markdown link syntax with a descriptive name: - Use `[Human-friendly name](file:///absolute/path)` — never bare `file:///...` URLs or autolinks ``. - Always use absolute paths. Never `~/` or relative paths. - For multiple files, render as a bullet list of named markdown links. Why: bare `file://` URLs only render the first as clickable across multiple lines. Named markdown links make each entry independently clickable and look cleaner. Example: - [Brief](file:///Users/ktg/.../brief.html) - [Research summary](file:///Users/ktg/.../research/summary.md)