From 0383d7844089aa5e97093e1e199373a39953e8da Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 15 Jun 2026 01:36:51 +0200 Subject: [PATCH] =?UTF-8?q?spec(SHARD-WP-0005=20T5):=20cache=20freshness?= =?UTF-8?q?=20&=20invalidation=20protocol=20(=C2=A78.8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes C-2 (invalidation). Per-binding modes (event-driven push / validator poll / TTL), hybrid default, operational-envelope coupling (rate-limited shards must not poll-per-read), single-flight coalescing + batched bulk invalidation, freshness always represented in the provenance envelope. Co-Authored-By: Claude Opus 4.8 --- spec/CoreArchitectureBlueprint.md | 33 +++++++++++++++++++ .../SHARD-WP-0005-architecture-hardening.md | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/spec/CoreArchitectureBlueprint.md b/spec/CoreArchitectureBlueprint.md index 80ff343..753b37d 100644 --- a/spec/CoreArchitectureBlueprint.md +++ b/spec/CoreArchitectureBlueprint.md @@ -491,6 +491,39 @@ Its parameters (LSH band/row counts, shingle size, precision/recall) are tunable **false-negative rate of blocking** is a known, tracked limitation (§12) — blocking trades a small miss rate for tractability, and curator bindings are the escape hatch for misses. +### 8.8 Cache freshness & invalidation + +Replication-projection caches remote shard content; cache invalidation is the actual hard part +and was missing from the first draft (review C-2). The protocol is **per-binding, driven by the +capability profile**, with one rule: **freshness is always represented, never assumed** — every +cached page's provenance envelope carries `(observed-at, source-rev-if-known, staleness-state)`, +so a consumer can always tell live from stale. + +**Three invalidation modes, chosen by capability, not hard-coded:** + +| Mode | When | Mechanism | +|------|------|-----------| +| **Event-driven (push)** | shard has `notify` | a change event invalidates exactly the affected entries and enqueues a delta refresh (§8.7); the preferred mode | +| **Validator poll** | shard exposes ETag / Last-Modified / rev | conditional fetch (`If-None-Match`); cheap "still fresh?" checks without transferring bodies | +| **TTL** | shard offers neither | time-bounded staleness; the floor mode (Oddmuse-class shards) | + +Most real bindings are **hybrid**: event-driven for invalidation + a long TTL as a safety net +for missed events + validator polls on read when an entry is past a soft age. + +**Operational-envelope coupling.** The mode is constrained by axis-10: a **rate-limited** shard +(Notion) *must* favour event-driven + long TTL and *must not* poll per-read — the freshness +policy is capability-gated like everything else. A local file shard can watch the filesystem +(near-instant invalidation, effectively event-driven for free). + +**Thundering-herd / coalescing.** Concurrent reads of the same stale entry trigger a **single +in-flight refresh** (single-flight); other readers await it or are served the stale-but-labelled +value per policy. Bulk invalidations (a shard-wide event) are **batched and rate-shaped** to the +shard's envelope rather than fired as N concurrent fetches. + +**Staleness is a policy knob, not a correctness bug.** Whether a reader gets *stale-but-fast* or +*blocks-for-fresh* is a §10 preset (per space or per request); either way the envelope tells the +truth about what was served. This is union-without-erasure applied to time. + --- ## 9. Cross-cut — Authorization (L5) diff --git a/workplans/SHARD-WP-0005-architecture-hardening.md b/workplans/SHARD-WP-0005-architecture-hardening.md index 1c32d9b..f33d4c1 100644 --- a/workplans/SHARD-WP-0005-architecture-hardening.md +++ b/workplans/SHARD-WP-0005-architecture-hardening.md @@ -109,7 +109,7 @@ residual as open (→ T9). ```task id: SHARD-WP-0005-T4 -status: todo +status: done priority: high state_hub_task_id: "eb885f03-2569-4ade-b3aa-174bc6062672" ```