Skill trust and integrity controls 

Isolation controls: trust, fingerprint, injection scan, audit 

On top of the SHA-pin and checksum controls above, each source and skill carries the isolation controls introduced in ADR-061.

Publisher trust level. Every source is classified — untrusted (the default, for anonymous public GitHub content), community, verified or first_party (operator-controlled). This is provenance, independent of the partial support badge. Each synced skill denormalises its source's level, so re-classifying a source takes effect on the next sync. The instance-wide floor skills.minTrustLevel (extension configuration, default untrusted) gates use: a skill below the floor is dropped from both prompt injection and the allowed-tools union. Raising the floor to verified therefore hides every community/untrusted skill without deleting it. Trust is separate from the enabled = false default — an untrusted skill still needs an explicit enable. An unreadable or mistyped floor falls back to untrusted; the value actually in force is shown under Effective policy.

Skill-block byte budget. skills.maxBytes (extension configuration, default 24000) caps the composed block that is prepended to the user prompt. The measure is bytes, not tokens — a deliberate over-estimate, since no tokenizer is available. When the block exceeds the budget, skills are dropped from the tail first: task-additive skills go before the configuration baseline, and every drop is logged as a warning. Lower the value to reserve more of the model's context window for the conversation itself; raise it if a large configuration baseline is being trimmed. An empty, non-numeric or zero value falls back to 24000 — the cap cannot be switched off, so an emptied field never puts an unbounded block on the wire. The budget is instance-wide and independent of the model's context window; the per-request window bound is handled separately by the context-window manager (ADR-107).

The budget bounds the prompt block only, not the allowed-tools union (Gating tools). The union is computed over the effective skills before the block is assembled, so a skill dropped for the budget still grants its tools while its usage rules stay out of the prompt. That is deliberate — a budget-aware union would widen the gate, because dropping the last declaring skill removes the restriction entirely. Watch the drop warnings when lowering the value: they name every skill whose prose stopped shipping while its tools kept being offered.

Manifest fingerprint (optional). A source may declare an expected_fingerprint over its collected identifiers and body checksums. Sort the identifiers, encode each as identifier:body-checksum, join the lines with LF without a final LF, then hash those UTF-8 bytes with SHA-256. Body checksums are SHA-256 hashes of the parsed markdown bodies. This fingerprint does not include frontmatter, trust labels or approval state; the version digest used for approval is a separate control.

When an expected fingerprint is set, the digest is recomputed at sync and verified before anything is materialised; a mismatch fails closed (no skill is imported, the source goes to error) and leaves the last known-good skills untouched. Leave it empty to rely on the commit-SHA pin alone. This binds the reviewed bytes to a publisher-declared identity beyond "these bytes from this URL"; it is a declared digest, not a public-key signature.

Prompt-injection scan. Each body is scanned at ingest for known injection signatures. A high-confidence jailbreak marker (e.g. "ignore all previous instructions", role reset, chat-template control tokens) force-disables the skill at import — even a single-file source that would otherwise default enabled — and must be re-reviewed before enabling. Lower-confidence findings are recorded on the skill (Injection scan findings) for review without blocking. The scanner matches a fixed set of heuristic signatures, including control markers and long encoded blobs. It can also flag quoted examples; an absence of findings does not establish that a skill is trustworthy.

Audit trail and retention. Every ingest, enable, disable and fail-closed rejection is written to tx_nrllm_skill_audit with who / when / source / SHA / checksum / trust level. Scan output and free-form details follow the central privacy policy. Ordinary writes append rows and there is no update path. The explicit retention exception is nrllm:privacy:purge : it deletes rows created strictly before the cutoff for the skill-audit category. Retained rows support provenance reconstruction; purged rows are no longer available. See ADR-064 and Data retention.