1
0
Fork 0

docs(changelog): record the three post-v0.2.0 behaviour changes; next cut is 0.3.0

A downstream consumer (llm-ingestion-okf) found that main had diverged from
v0.2.0 on okf.import_bundle: 0772daf adds allow_reserved defaulting to True,
so a reserved index.md/log.md in a received bundle is now scanned rather than
unconditionally rejected. Their tests pin the v0.2.0 reject, so a 0.2.1 cut
from main would have changed downstream behaviour silently.

Checking that turned up a wider hole: [Unreleased] documented only the
coverage matrix and the docs work, while three commits since the tag change
what an unchanged caller observes -- 0772daf (loosens), 4d53765 (active
content now reaches decide(), HIGH/MEDIUM with compound escalation) and
f4e89d2 (base64-decoded plaintext now hits secret-egress). None were listed,
so CHANGELOG could not answer "is this bump safe?".

Records all three under Changed, and states that the next release is 0.3.0 --
under 0.x a >=0.2,<0.3 pin absorbs a 0.2.1 silently but stops at 0.3.0, which
is exactly the signal a gate-loosening change should send.
This commit is contained in:
Kjell Tore Guttormsen 2026-07-25 07:15:57 +02:00
commit 80f741e9cc

View file

@ -7,6 +7,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
> **The next release is 0.3.0, not 0.2.1.** The changes in *Changed* below alter what
> an existing caller observes without any code change on their side. A `>=0.2,<0.3`
> pin therefore stops here deliberately — re-test that branch before widening it.
### Changed — observable gate behaviour (re-test before upgrading)
Three commits since v0.2.0 change dispositions for an unchanged caller. Two tighten
the gate; one loosens it.
- **`okf.import_bundle` no longer path-rejects reserved basenames.** At v0.2.0,
`index.md` / `log.md` anywhere in a received bundle was an unconditional
per-concept hard reject (FAIL_SECURE), and `import_bundle` took no keyword for it.
The new `allow_reserved` keyword **defaults to `True`** on this mode-b
*received-bundle* path, so those files are scanned — their body is the
highest-priority injection surface — rather than refused, and may clear the floor
and become mergeable. **This is the one loosening change:** content a v0.2.0
consumer never saw can now reach it, so a consumer whose tests pin the v0.2.0
reject must re-check, not just bump. A front-end materialising individual
*uploads* must pass `allow_reserved=False` to keep the shadow-reject there;
`validate_concept_path` still defaults to `False`.
- **Active content now reaches the disposition engine.** `scan_output` step 6 runs
`scan_active_content`, so markdown images/links, reference definitions, autolinks,
raw active HTML and `data:` URIs surface as `active:*` findings (OWASP LLM05 — the
EchoLeak / CVE-2025-32711 class) instead of being admitted with `findings=[]`.
These carry real severities (zero-click auto-fetch/execute HIGH, click-required
MEDIUM), and two MEDIUM+ findings compound-escalate one tier, so a document that
passed clean at v0.2.0 can now WARN, quarantine, or fail secure in both
`screen_output` and `okf.import_bundle`.
- **Base64-wrapped secrets are now caught as egress.** The output gate's
decode-and-rescan feeds decoded base64 plaintext through both the lexicon and the
LLM02 secret-egress detector, so a base64-wrapped credential surfaces as
`decoded:egress:*` instead of disappearing. Hex-wrapped remains a documented gap
(`docs/LIMITATIONS.md`).
### Added — runnable threat-coverage matrix
A single declarative manifest (`llm_ingestion_guard.coverage`) that proves, in one