# Security

The default policy favors a useful local work wiki over aggressive blocking.

The runtime does not deny tool calls only because an input looks sensitive. It preserves operational context by default, including phone numbers, emails, dates, and business identifiers.

Before writing durable summaries, the runtime redacts authentication values such as:

- token-like values
- password-like assignments
- private key blocks
- bearer credentials
- Basic authentication headers and URL user information
- sensitive keys in structured tool/MCP inputs, recursively, before those inputs are serialized
- command-line forms such as `--password value`, `--password=value`, `cmdkey /pass:value`, `az`/`docker`/`sshpass -p`, `sqlcmd -Pvalue`, `ConvertTo-SecureString 'value' -AsPlainText`, `curl -u user:password`, and database `user=`/`password=` arguments
- Windows remote/session forms such as `winrs -p:value`, `net use ... password /user:name`, and `sqlcmd /P:value`

Manual and hook context output also runs through redaction before returning excerpts or search hits. `llm-wiki lint` reports remaining secret-like wiki content as an error so it can be removed or rewritten before it becomes reusable project memory.

`evidence_refs` are pointers, not a place to paste secrets or transcripts. `llm-wiki lint` rejects secret-like evidence values, unsafe `file:` paths, credential-bearing `url:` values, unsupported prefixes, and unsafe commands. Missing local `file:` or `raw:` targets are warnings so agents can fix references without losing the surrounding durable note.

`llm-wiki export` redacts generated `llms.txt`, `llms-full.txt`, and `llm-wiki.json` output. Exports must not contain npm tokens, WinRM credentials, private keys, raw `.env`, or full raw transcripts. `llms.txt` is an agent onboarding/handoff manifest and follows the same durable visibility policy as retrieval eval, so archived/superseded/default episodic pages are excluded by default.

Hook payloads are stored as append-only, schema-bounded event envelopes, not full raw transcripts. Envelopes contain only the allowed event metadata and do not persist a working directory, transcript path, prompt/tool body, credential, or provider session identifier. `PreCompact` never opens the file named by `transcript_path`; it builds checkpoints only from bounded, redacted turn state captured by hook events. Raw transcript capture is intentionally unsupported by the default runtime. A project that needs it must implement a separate, explicit, project-local consent and redaction path.

Opt-in full Q&A audit log: setting `LLM_WIKI_KIT_FULL_QA=1` records every turn's redacted prompt/assistant/tool bodies under `raw/qa/<day>/<session>-NNN.md`. Bodies pass through the same `redactText` pipeline as durable summaries (pattern-based, not exhaustive), and `raw/qa/` is gitignored so redaction misses never reach a commit. This is per-turn completeness, not raw transcript capture: `transcript_path` is never read or stored. The durable `outputs/questions` gate is unchanged. See decision `2026-08-07-full-qa-capture-channel.md`.

Transient turn, compact, language, and recovery records require a stable provider session or conversation identifier. If one is absent, the runtime fails closed instead of sharing a `default` state across unrelated sessions. Operators who accept project-scoped sharing when a provider emits no session id may opt in with `LLM_WIKI_KIT_PROJECT_SCOPED_TRANSIENT=1`; this derives a per-project key (scoped to one workspace, never a shared `default`) so transient features degrade gracefully instead of failing closed. It is off by default. Runtime retention may remove only expired external runtime files that match the expected schema and safe filename; it never deletes project `llm-wiki/raw/` evidence or curated wiki content.

When a provider supplies `turn_id`/`turnId` or `prompt_id`/`promptId`, the runtime hashes only the identifier value, treats those aliases as the same canonical turn identity, and rejects later question, tool, or Stop events whose identity is missing or different. This prevents correlated late events from a previous prompt from changing or closing the current prompt. Some providers do not emit any per-turn correlation identifier; in that case the runtime can reject known duplicate event IDs/timestamps and duplicate Stop fingerprints, but it cannot prove that an otherwise uncorrelated late tool or Stop belongs to an older prompt. That provider limitation remains a documented residual risk.

The filesystem hardening assumes ordinary project races and cooperating kit writers. A malicious process running as the same OS user can still attempt ancestor-path swaps in the small interval between pathname validation and an operation because Node.js does not expose a portable directory-handle-relative `openat`/`unlinkat` API. The runtime revalidates identity and containment, uses no-follow/exclusive opens where available, and quarantines retention targets, but it does not claim to be a security boundary against an actively hostile same-user process. Run the kit only in workspaces and user accounts whose filesystem is trusted at that level.
