Skip to content

fix(interop)!: reject reserved namespaces ns and nsapi (LAB-5876) - #350

Merged
27Bslash6 merged 1 commit into
mainfrom
lab-5876-reserve-ns-nsapi-interop-namespace
Sep 29, 2026
Merged

27Bslash6 merged 1 commit into
mainfrom
lab-5876-reserve-ns-nsapi-interop-namespace

Conversation

@27Bslash6

@27Bslash6 27Bslash6 commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

This change reserves the namespaces ns and nsapi in interop mode (interop/v1). The CachekitIO server parses any key starting with ns: or nsapi: as namespace-prefixed. Interop keys use the format {namespace}:{operation}:{args_hash}, so either namespace produced keys that the server rejected (if the operation contains .) or routed to a namespace named after the operation. These configurations now fail when the function is decorated, not at request time.

Public API changes

  • New export: cachekit.interop.RESERVED_NAMESPACES is a frozenset({"ns", "nsapi"}) and is added to __all__.
  • validate_segment(name, segment): when name == "namespace", it now raises InteropError for a reserved value. This check runs after the existing SEGMENT_RE pattern check, and the error message contains "reserved".
  • validate_interop_config(operation, namespace) and generate_interop_key(namespace, operation, args) both call validate_segment, so both now raise InteropError for a reserved namespace.
  • @cache(interop=..., namespace="ns"|"nsapi") and create_cache_wrapper now raise ConfigurationError at decoration time.

Scope of the reservation. It matches exact values and applies only to the namespace:

  • SEGMENT_RE is unchanged.
  • ns and nsapi are still valid operation names.
  • Namespaces that only start with these strings, such as nsx, nsfw, nsapi2 and nsapix, are still accepted.

Breaking impact

Existing deployments that use ns or nsapi as an interop namespace on Redis, Memcached or File backends worked before this change and must now rename the namespace. Renaming means a full cache miss for that namespace.

Conformance fixture

  • interop-mode.json is re-vendored at protocol version 1.1.0 from fix(interop)!: reserve ns and nsapi as interop namespaces (LAB-5876) protocol#78, sha256 9b1855851d888c479e37a8fff9e9bbe5738737a9a408e749d9126c7678b9e7bc. That PR must merge first.
  • Expected counts rise from 33 to 34 key vectors and from 9 to 11 error vectors. The new vectors are:
    • reject_reserved_namespace_ns
    • reject_reserved_namespace_nsapi
    • reservation_scope (namespace nsapix, operation nsapi)
  • The pinned sha now carries an inline pragma: allowlist secret, and its .secrets.baseline entry is removed. The fixture's line entries in the baseline are refreshed to match the new file.

Tests

  • test_interop_model.py: the new TestReservedNamespaces class checks that:
    • key generation rejects both reserved namespaces;
    • config validation rejects both reserved namespaces;
    • operations ns and nsapi are accepted;
    • namespaces nsx, nsfw and nsapi2 are accepted.
  • test_interop_decorator.py has two new tests:
    • a check that both reserved namespaces are rejected at decoration;
    • a check that the reservation_scope vector decorates successfully and writes its byte-pinned key.
  • Thirteen existing tests used namespace="ns" as a placeholder and now use "users".

Docs

  • docs/features/interop-mode.md:
    • The grammar bullet and the guardrails table now describe the reservation.
    • The conformance counts were stale and now read 34 key vectors and 11 must-error vectors.
  • The example comment in src/cachekit/__init__.py now uses namespace="users".

The segment grammar accepted ns and nsapi as an interop namespace, but the
CachekitIO server parses a key starting ns: or nsapi: as namespace-prefixed:
it rejects the key when the operation contains '.', and otherwise scopes it to
a namespace named after the operation. interop-mode 1.1.0 reserves both names
(exact match, namespace only); re-vendor its test vectors.

BREAKING CHANGE: @cache(interop=..., namespace="ns"|"nsapi") now raises ConfigurationError (chained from InteropError) at decoration, and generate_interop_key raises InteropError. Such keys were already rejected or misrouted by CachekitIO, but worked on Redis, Memcached and File backends.
@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: cachekit-io/cachekit-py/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: b73047a0-ac98-4f5f-97cb-636ef45b7761

📥 Commits

Reviewing files that changed from the base of the PR and between a99f8c1 and 02d6ed1.

📒 Files selected for processing (8)
  • .secrets.baseline
  • docs/features/interop-mode.md
  • src/cachekit/__init__.py
  • src/cachekit/interop.py
  • tests/unit/protocol/fixtures/interop-mode.json
  • tests/unit/protocol/test_interop_decorator.py
  • tests/unit/protocol/test_interop_model.py
  • tests/unit/protocol/test_interop_vectors.py

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

Interop validation now rejects ns and nsapi as exact namespace values. Protocol fixtures, conformance counts, documentation and decorator tests reflect this rule. Both strings remain valid as operation segments.

Changes

Interop namespace reservations

Layer / File(s) Summary
Namespace validation and contract
src/cachekit/interop.py, docs/features/interop-mode.md, tests/unit/protocol/test_interop_model.py
Adds and exports RESERVED_NAMESPACES with ns and nsapi. Namespace validation rejects these exact values, while model tests cover allowed operation values and similar, non-exact namespaces.
Protocol vectors and conformance
tests/unit/protocol/fixtures/interop-mode.json, tests/unit/protocol/test_interop_vectors.py, docs/features/interop-mode.md, .secrets.baseline
Updates the fixture to version 1.1.0 with reserved-namespace error vectors and a valid namespace-operation vector. Updates the pinned digest and vector totals. The baseline adds a finding and removes the test_interop_vectors.py finding.
Decorator coverage and examples
tests/unit/protocol/test_interop_decorator.py, src/cachekit/__init__.py
Adds decorator coverage for the reserved values and their exact-match, namespace-only scope. Changes other decorator test namespaces and the example from ns to users.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 02d6e

No actionable merge-blocking issue is identified; the change appears ready to merge after normal checks.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to 02d6e

The new validation prevents keys that the server can misinterpret, but applications using the newly reserved names need a coordinated transition. Renaming a namespace makes its existing entries unreachable through normal new-version cache operations; older workers may still use them until retired or the entries are removed.

Retained concerns

  • Medium · security · inferred: If a deployment previously used ns or nsapi, a required namespace rename prevents new-version single-key invalidation from reaching its old entries. During a mixed-version rollout, older producers may continue writing those entries. Without a verified retirement and cleanup sequence, stale or sensitive entries can remain available to legacy consumers until deletion or expiry.
Security review details

Security Blast Radius

  • inferred — The transition affects shared entries under the two formerly accepted namespace identities, including entries used by other SDKs on the same backend. The evidence does not establish which deployments use those identities or how long their entries persist.

Security Findings and Attack Paths

  • inferred — No new attacker-controlled namespace entrypoint or bypass through the inspected decorated interop path was established. A separate, conditional lifecycle risk remains if legacy consumers can read entries that a renamed deployment no longer invalidates.

Trust Boundaries and Controls

  • observed — Namespace selection is validated at decoration and again at interop key generation. Generic backend callers remain outside that interop-specific control; the inspected change does not alter their authority.

Resilience and Maintainability Implications

  • inferred — Validation itself causes no partial cache write. For a migration, however, interruption, repetition, and concurrent old-version writes matter: registry drains depend on tracking, and a renamed wrapper's specific-entry invalidation derives only the new key. Recovery coverage for old entries is not demonstrated.

Hardening Proposals

  • proposed — For deployments using a reserved namespace, document an ordered cutover: choose a replacement identity, retire every old producer before purging old entries, verify backend-specific deletion or expiry, and define rollback behavior that does not recreate the old keyspace.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.29% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 35 functions across 5 files. (3 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the breaking interop change and the exact reserved namespaces affected.
Description check ✅ Passed The description provides the change, motivation, breaking-change impact, implementation details, testing evidence, documentation updates, and migration impact. It does not reproduce every template hea…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 34.29% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 35 functions across 5 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@kodus-27b

kodus-27b Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the `@kody start-review` command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Providing Context (Files & MCPs)

Add these hints in your PR description (or a comment) to unlock deeper checks:

  • Ticket / Acceptance Criteria: `Refs: ABC-123` (Linear/Jira/Asana/ClickUp/Trello) or a direct ticket link.
  • Bugfix Validation: a Sentry/Datadog/Bugsnag event link (or paste the stack trace/error message).
  • Endpoint Risk: mention the route (e.g., `POST /api/payments`) or controller/action name.
  • Attach a repo file as context: use an explicit marker like `@file:docs/guide.mdx#L10-L50` (replace with your real path).
  • API Contract Docs: include `@file:openapi.yaml` or `@file:swagger.json` when changing routes/schemas.
  • Definition of Done / Standards: include `@file:DOD.md` or `@file:CONTRIBUTING.md` if your repo has them.
  • Design System Source of Truth: include `@file:ui/index.ts` (replace with your DS entrypoint path).
  • Feature Flags: include the flag key/name and `@file:flags.ts` / `@file:config.json` (and optionally the PostHog flag name).
  • Edge/CDN Rules: link the Cloudflare rule/zone or describe the intended redirect/header behavior.
  • Attach an MCP tool output: use `@mcp<provider|tool>` (replace with an installed MCP provider + tool, e.g., `@mcp<sentry|events.search>`).
Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ✅
Security ✅
Business Logic ✅

Access your configuration settings here.

@27Bslash6
27Bslash6 merged commit 6ba98a6 into main Sep 29, 2026
38 checks passed
@27Bslash6
27Bslash6 deleted the lab-5876-reserve-ns-nsapi-interop-namespace branch September 29, 2026 01:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant