Hygiene: name the FHIR immunization gap, cache the digest offline, freeze the no-FK pair, document the pin bump

Four small debts from the audit tail. The FHIR bundle's missing
Immunization resource gets the same written-decision paragraph the visits
exclusion carries — deliberate follow-up, not oversight. The service
worker's offline allowlist gains /api/daily/digest (both copies, policy
module and sw.js, plus the test) so the Today rail renders on an offline
reopen. The two Telegram plumbing tables that link to an account by a
bare userId string are frozen as a closed NO_FK_BY_DESIGN set in the wipe
guard — a third such table now fails the test instead of passing rule 1
silently. And deploy.md documents the manual digest-pin bump end to end:
imagetools inspect, the env update, and the three-probe /api/version
verification with the too-fast-deploy warning.
This commit is contained in:
Marc-André Bombeck committed 2026-08-14 09:56:45 +02:00
1 parent 9d64eb6aa2
commit bcabd43ca7
6 files changed
+79

No files matched your search

+8
View File
@@ -269,6 +269,14 @@ export function buildFhirDocumentBundle(
// no route module lies. The PDF carries the visits; the Bundle does not, and
// a reader who notices the gap should find this comment rather than a bug.
//
// No vaccinations either, on the same terms (v1.37.20, A6-21). FHIR has
// `Immunization` and the model would map cleanly, but a resource type in
// the Bundle without its REST route module and capability entry is the
// exact half-shipped state the visits paragraph refuses; emitting it is a
// deliberate follow-up, not an oversight. The Impfpass PDF and the backup
// both carry the doses; the Bundle does not, and this comment is where a
// reader who notices should land.
//
// held an episode (the aggregator gates `data.illnessEpisodes`). Each
// episode emits a patient-reported Condition (generic SNOMED root, label on
// `code.text`) plus a bounding Encounter that references it.
@@ -14,6 +14,9 @@ describe("isAllowlistedApiRead — offline read boundary", () => {
it("caches the curated safe GET read endpoints", () => {
expect(isAllowlistedApiRead("/api/dashboard/snapshot")).toBe(true);
expect(isAllowlistedApiRead("/api/dashboard/widgets")).toBe(true);
// v1.37.20 — the Today rail's offline read. Watched red before the
// allowlist entry landed.
expect(isAllowlistedApiRead("/api/daily/digest")).toBe(true);
expect(isAllowlistedApiRead("/api/measurements")).toBe(true);
expect(
isAllowlistedApiRead("/api/measurements/series-batch?types=WEIGHT"),
+5
View File
@@ -27,6 +27,11 @@
export const API_READ_ALLOWLIST = [
"/api/dashboard/snapshot",
"/api/dashboard/widgets",
// v1.37.20 — the daily digest read: the Today rail is the first thing an
// offline reopen renders, and the digest is an idempotent GET with no
// secret in the body. The deny guard and the body-level refusal still
// apply on top, like every entry here.
"/api/daily/digest",
"/api/measurements",
"/api/medications",
"/api/version",