From 095d69cf1ed342883261be414bbc0d2ab0ea518b Mon Sep 17 00:00:00 2001 From: Ray Walker Date: Fri, 7 Aug 2026 14:47:31 +1000 Subject: [PATCH 1/6] docs: index all 9 feature guides on every surface + drift guard (LAB-1013) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five of nine docs/features/ guides (interop-mode, l1-invalidation, reference-caching, rust-serialization, ssrf-protection) were unreachable from README.md, docs/README.md, and llms.txt — born orphaned because nothing checked index reachability. - Link all nine guides from all three index surfaces (deliberate call: the top-level README indexes the full set, not a curated subset). - Add tests/unit/test_feature_guide_index.py: globs docs/features/*.md and fails with the offending filenames if any guide is missing from an index. Lives in tests/unit/ because CI's PR lane only collects tests/unit/ and tests/critical/ — a guard in tests/docs/ would never run in CI. --- README.md | 10 ++++++ docs/README.md | 5 +++ llms.txt | 5 +++ tests/unit/test_feature_guide_index.py | 50 ++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 tests/unit/test_feature_guide_index.py diff --git a/README.md b/README.md index 23fa6a3..2b94450 100644 --- a/README.md +++ b/README.md @@ -397,6 +397,11 @@ info = expensive_func.cache_info() | [Distributed Locking][distributed-locking-url] | Cache stampede prevention | | [Prometheus Metrics][prometheus-url] | Built-in observability | | [Zero-Knowledge Encryption][encryption-url] | Client-side security | +| [Interop Mode][interop-url] | Cross-SDK cache sharing with cachekit-ts/rs | +| [L1 Invalidation & SWR][l1-invalidation-url] | Process-local invalidation, stale-while-revalidate | +| [Reference Caching][reference-caching-url] | `@cache.local()` for non-serializable objects | +| [Rust Serialization][rust-serialization-url] | ByteStorage layer: LZ4, xxHash3, AES-256-GCM | +| [SSRF Protection][ssrf-url] | URL allowlisting for the CachekitIO backend | --- @@ -479,6 +484,11 @@ MIT License - see [LICENSE][license-file-url] for details. [distributed-locking-url]: docs/features/distributed-locking.md [prometheus-url]: docs/features/prometheus-metrics.md [encryption-url]: docs/features/zero-knowledge-encryption.md +[interop-url]: docs/features/interop-mode.md +[l1-invalidation-url]: docs/features/l1-invalidation.md +[reference-caching-url]: docs/features/reference-caching.md +[rust-serialization-url]: docs/features/rust-serialization.md +[ssrf-url]: docs/features/ssrf-protection.md [contributing-url]: CONTRIBUTING.md [license-file-url]: LICENSE [github-url]: https://github.com/cachekit-io/cachekit-py diff --git a/docs/README.md b/docs/README.md index fd99e40..3ed3b97 100644 --- a/docs/README.md +++ b/docs/README.md @@ -56,6 +56,11 @@ Choose how data is stored: | [Distributed Locking](features/distributed-locking.md) | Prevent thundering herd | | [Zero-Knowledge Encryption](features/zero-knowledge-encryption.md) | Client-side AES-256-GCM | | [Prometheus Metrics](features/prometheus-metrics.md) | Production observability | +| [Interop Mode](features/interop-mode.md) | Cross-SDK cache sharing with cachekit-ts/rs | +| [L1 Invalidation & SWR](features/l1-invalidation.md) | Process-local invalidation, stale-while-revalidate | +| [Reference Caching](features/reference-caching.md) | `@cache.local()` for non-serializable objects | +| [Rust Serialization](features/rust-serialization.md) | ByteStorage layer: LZ4, xxHash3, AES-256-GCM | +| [SSRF Protection](features/ssrf-protection.md) | URL allowlisting for the CachekitIO backend | ## Architecture & Reference diff --git a/llms.txt b/llms.txt index 6e2e122..7055653 100644 --- a/llms.txt +++ b/llms.txt @@ -179,6 +179,11 @@ CACHEKIT_MASTER_KEY=hex-encoded-32-byte-key - [Distributed Locking](docs/features/distributed-locking.md): Cache stampede prevention - [Zero-Knowledge Encryption](docs/features/zero-knowledge-encryption.md): Client-side AES-256-GCM - [Prometheus Metrics](docs/features/prometheus-metrics.md): Built-in observability +- [Interop Mode](docs/features/interop-mode.md): Cross-SDK cache sharing (interop/v1) +- [L1 Invalidation & SWR](docs/features/l1-invalidation.md): Process-local invalidation, stale-while-revalidate +- [Reference Caching](docs/features/reference-caching.md): @cache.local() for non-serializable objects +- [Rust Serialization](docs/features/rust-serialization.md): ByteStorage layer (LZ4, xxHash3, AES-256-GCM) +- [SSRF Protection](docs/features/ssrf-protection.md): CachekitIO URL allowlisting - [Architecture](docs/data-flow-architecture.md): L1+L2 internals ### Development diff --git a/tests/unit/test_feature_guide_index.py b/tests/unit/test_feature_guide_index.py new file mode 100644 index 0000000..791849d --- /dev/null +++ b/tests/unit/test_feature_guide_index.py @@ -0,0 +1,50 @@ +"""Guard against feature-guide index drift (LAB-1013). + +Every guide in docs/features/*.md must be reachable from the repo's index +surfaces. Historically guides were "born orphaned": five of nine were listed +in no index at all because nothing checked reachability. This test is that +check — a new guide added without index links fails here with its filename. +""" + +from __future__ import annotations + +import re +from pathlib import Path + +import pytest + +REPO_ROOT = Path(__file__).resolve().parents[2] + +# All three surfaces index the full guide set (deliberate call on LAB-1013; +# the top-level README is NOT a curated subset). +INDEX_FILES = ["README.md", "docs/README.md", "llms.txt"] + + +def _is_linked(index_text: str, guide_name: str) -> bool: + """True if the guide is reachable as a rendered link in the index text. + + Two link forms exist across the surfaces (paths are features/x.md or + docs/features/x.md): + - inline: ``[Name](docs/features/x.md)`` + - reference-style (README.md): ``[Name][label]`` + ``[label]: docs/features/x.md``. + A definition whose label is never used renders as nothing, so the bare + path substring is not enough — the label must appear as ``][label]``. + """ + target = re.escape(f"features/{guide_name}") + if re.search(rf"\]\([^)]*{target}\)", index_text): + return True + for m in re.finditer(rf"^\[([^\]]+)\]:\s*\S*{target}\s*$", index_text, re.MULTILINE): + if f"][{m.group(1)}]" in index_text: + return True + return False + + +@pytest.mark.parametrize("index_file", INDEX_FILES) +def test_every_feature_guide_is_indexed(index_file: str): + """Each docs/features/*.md must be linked from every index surface.""" + guides = sorted((REPO_ROOT / "docs" / "features").glob("*.md")) + assert guides, "docs/features/ contains no guides — glob path broken?" + + index_text = (REPO_ROOT / index_file).read_text(encoding="utf-8") + orphans = [g.name for g in guides if not _is_linked(index_text, g.name)] + assert not orphans, f"Feature guides missing from {index_file}: {orphans}" From e797ba57e5b7e57d90338493493ca41a4557fe1e Mon Sep 17 00:00:00 2001 From: Ray Walker Date: Fri, 7 Aug 2026 15:10:08 +1000 Subject: [PATCH 2/6] =?UTF-8?q?test:=20guard=20counts=20rendered=20links?= =?UTF-8?q?=20only=20=E2=80=94=20strip=20fenced=20code=20and=20HTML=20comm?= =?UTF-8?q?ents=20(LAB-1013)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit: link-shaped text inside a fenced code block or HTML comment satisfied _is_linked without rendering, so the guard could pass while a guide stayed unreachable. Strip non-rendered content before matching, fail loud on unpaired fences (silent pairing skew would reopen the same false-pass), and pin both cases with a regression test. --- tests/unit/test_feature_guide_index.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/unit/test_feature_guide_index.py b/tests/unit/test_feature_guide_index.py index 791849d..10e0d20 100644 --- a/tests/unit/test_feature_guide_index.py +++ b/tests/unit/test_feature_guide_index.py @@ -20,6 +20,20 @@ INDEX_FILES = ["README.md", "docs/README.md", "llms.txt"] +def _strip_non_rendered(text: str) -> str: + """Remove markdown content that never renders: fenced code blocks and HTML comments. + + A link-shaped string inside either would satisfy the regexes below without + being reachable by a reader. Backtick fences only — that is what these + index files use. + """ + text = re.sub(r"```.*?```", "", text, flags=re.DOTALL) + # An odd fence count skews the non-greedy pairing and silently un-strips a + # block — the exact false-pass this helper exists to prevent. Fail loud. + assert "```" not in text, "unpaired ``` fence — stripping unreliable" + return re.sub(r"", "", text, flags=re.DOTALL) + + def _is_linked(index_text: str, guide_name: str) -> bool: """True if the guide is reachable as a rendered link in the index text. @@ -30,6 +44,7 @@ def _is_linked(index_text: str, guide_name: str) -> bool: A definition whose label is never used renders as nothing, so the bare path substring is not enough — the label must appear as ``][label]``. """ + index_text = _strip_non_rendered(index_text) target = re.escape(f"features/{guide_name}") if re.search(rf"\]\([^)]*{target}\)", index_text): return True @@ -39,6 +54,15 @@ def _is_linked(index_text: str, guide_name: str) -> bool: return False +def test_is_linked_counts_rendered_links_only(): + """Link-shaped text in fenced code or HTML comments must not satisfy the guard.""" + assert _is_linked("[X](docs/features/x.md)", "x.md") + assert _is_linked("See [X][x-url].\n\n[x-url]: docs/features/x.md", "x.md") + assert not _is_linked("```\n[X](docs/features/x.md)\n```", "x.md") + assert not _is_linked("", "x.md") + assert not _is_linked("[x-url]: docs/features/x.md", "x.md") # definition never used + + @pytest.mark.parametrize("index_file", INDEX_FILES) def test_every_feature_guide_is_indexed(index_file: str): """Each docs/features/*.md must be linked from every index surface.""" From 031c7cab76eac4e00a8409167ec5869df07926d3 Mon Sep 17 00:00:00 2001 From: Ray Walker Date: Fri, 7 Aug 2026 16:08:16 +1000 Subject: [PATCH 3/6] test: strip non-rendered content in one pass; match local paths only (LAB-1013) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two CodeRabbit findings on the previous fix, both reproduced against e797ba5 before changing anything: - Sequential strip passes are wrong in *both* orderings. Fences-first made a ``` inside a closed look like an unpaired fence and raised AssertionError; the reordering CodeRabbit proposed only moves the bug, since a `` looking like an + unpaired fence, and comments-first lets a ``", "", text, flags=re.DOTALL) # An odd fence count skews the non-greedy pairing and silently un-strips a # block — the exact false-pass this helper exists to prevent. Fail loud. assert "```" not in text, "unpaired ``` fence — stripping unreliable" - return re.sub(r"", "", text, flags=re.DOTALL) + return text def _is_linked(index_text: str, guide_name: str) -> bool: @@ -43,12 +50,18 @@ def _is_linked(index_text: str, guide_name: str) -> bool: - reference-style (README.md): ``[Name][label]`` + ``[label]: docs/features/x.md``. A definition whose label is never used renders as nothing, so the bare path substring is not enough — the label must appear as ``][label]``. + + The path is anchored to the link target's start, so it matches only + repo-relative paths. An unanchored match would also fire on + ``https://elsewhere.example/features/x.md`` — a same-suffix URL on another + host, which is not this repo's guide and would be a false pass. """ index_text = _strip_non_rendered(index_text) - target = re.escape(f"features/{guide_name}") - if re.search(rf"\]\([^)]*{target}\)", index_text): + path = re.escape(f"features/{guide_name}") + target = rf"(?:\./)?(?:docs/)?{path}" + if re.search(rf"\]\({target}(?:[#?][^)]*)?\)", index_text): return True - for m in re.finditer(rf"^\[([^\]]+)\]:\s*\S*{target}\s*$", index_text, re.MULTILINE): + for m in re.finditer(rf"^\[([^\]]+)\]:\s*{target}\s*$", index_text, re.MULTILINE): if f"][{m.group(1)}]" in index_text: return True return False @@ -63,6 +76,21 @@ def test_is_linked_counts_rendered_links_only(): assert not _is_linked("[x-url]: docs/features/x.md", "x.md") # definition never used +def test_is_linked_ignores_offsite_paths(): + """A same-suffix path on another host is not this repo's guide.""" + assert not _is_linked("[X](https://example.test/features/x.md)", "x.md") + assert not _is_linked("See [X][x].\n\n[x]: https://example.test/docs/features/x.md", "x.md") + + +def test_strip_handles_interleaved_fence_and_comment(): + """Whichever marker opens first consumes the other — neither order may mis-strip.""" + # A ``` inside a closed comment is not an unpaired fence, and must not + # swallow the rendered link that follows it. + assert _is_linked("\n[X](docs/features/x.md)", "x.md") + # A `` looking like an - unpaired fence, and comments-first lets a ``", "", text, flags=re.DOTALL) # An odd fence count skews the non-greedy pairing and silently un-strips a @@ -41,25 +43,21 @@ def _strip_non_rendered(text: str) -> str: return text -def _is_linked(index_text: str, guide_name: str) -> bool: +def _is_linked(index_text: str, guide_name: str, prefix: str) -> bool: """True if the guide is reachable as a rendered link in the index text. - Two link forms exist across the surfaces (paths are features/x.md or - docs/features/x.md): + ``prefix`` is the surface's exact link prefix from INDEX_FILES, anchored + to the link target's start — so an offsite same-suffix URL or a + wrong-prefix path that 404s on this surface does not count. Two link + forms exist: - inline: ``[Name](docs/features/x.md)`` - reference-style (README.md): ``[Name][label]`` + ``[label]: docs/features/x.md``. A definition whose label is never used renders as nothing, so the bare path substring is not enough — the label must appear as ``][label]``. - - The path is anchored to the link target's start, so it matches only - repo-relative paths. An unanchored match would also fire on - ``https://elsewhere.example/features/x.md`` — a same-suffix URL on another - host, which is not this repo's guide and would be a false pass. """ index_text = _strip_non_rendered(index_text) - path = re.escape(f"features/{guide_name}") - target = rf"(?:\./)?(?:docs/)?{path}" - if re.search(rf"\]\({target}(?:[#?][^)]*)?\)", index_text): + target = re.escape(f"{prefix}{guide_name}") + if re.search(rf"\]\({target}\)", index_text): return True for m in re.finditer(rf"^\[([^\]]+)\]:\s*{target}\s*$", index_text, re.MULTILINE): if f"][{m.group(1)}]" in index_text: @@ -69,34 +67,31 @@ def _is_linked(index_text: str, guide_name: str) -> bool: def test_is_linked_counts_rendered_links_only(): """Link-shaped text in fenced code or HTML comments must not satisfy the guard.""" - assert _is_linked("[X](docs/features/x.md)", "x.md") - assert _is_linked("See [X][x-url].\n\n[x-url]: docs/features/x.md", "x.md") - assert not _is_linked("```\n[X](docs/features/x.md)\n```", "x.md") - assert not _is_linked("", "x.md") - assert not _is_linked("[x-url]: docs/features/x.md", "x.md") # definition never used - + assert _is_linked("[X](docs/features/x.md)", "x.md", "docs/features/") + assert _is_linked("See [X][x-url].\n\n[x-url]: docs/features/x.md", "x.md", "docs/features/") + assert not _is_linked("```\n[X](docs/features/x.md)\n```", "x.md", "docs/features/") + assert not _is_linked("", "x.md", "docs/features/") + # Definition never used renders as nothing. + assert not _is_linked("[x-url]: docs/features/x.md", "x.md", "docs/features/") -def test_is_linked_ignores_offsite_paths(): - """A same-suffix path on another host is not this repo's guide.""" - assert not _is_linked("[X](https://example.test/features/x.md)", "x.md") - assert not _is_linked("See [X][x].\n\n[x]: https://example.test/docs/features/x.md", "x.md") +def test_is_linked_requires_the_surfaces_own_prefix(): + """A link that 404s on its own surface must not count as indexed. -def test_strip_handles_interleaved_fence_and_comment(): - """Whichever marker opens first consumes the other — neither order may mis-strip.""" - # A ``` inside a closed comment is not an unpaired fence, and must not - # swallow the rendered link that follows it. - assert _is_linked("\n[X](docs/features/x.md)", "x.md") - # A