mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
Merge pull request #691 from MBombeck/fix/gate-blind-spots
Let the structural guards see the directories they were skipping
This commit is contained in:
32 files changed
+432
-165
No files matched your search
@@ -55,6 +55,12 @@ const CONSUMER_ROOTS = [
|
||||
join(SRC, "app"),
|
||||
];
|
||||
|
||||
/**
|
||||
* Pruned on purpose: the generated Prisma client, build output, vendored
|
||||
* dependencies, and the suites themselves are not the tree under audit. Note
|
||||
* what is NOT pruned — this walk descends into dot-prefixed directories, so
|
||||
* `src/app/.well-known` is inside the sweep. `fs.globSync` would drop it.
|
||||
*/
|
||||
const SKIP_DIRS = new Set([
|
||||
"__tests__",
|
||||
"__mocks__",
|
||||
|
||||
@@ -15,19 +15,17 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { globSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.filter(
|
||||
(p) => !p.startsWith(`generated${sep}`) && !p.startsWith("generated/"),
|
||||
)
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.startsWith("generated/"))
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
.sort();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,20 +33,18 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { globSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
/** Every non-test `.ts` / `.tsx` under `src/`, minus the generated client. */
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.filter(
|
||||
(p) => !p.startsWith(`generated${sep}`) && !p.startsWith("generated/"),
|
||||
)
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.startsWith("generated/"))
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
.sort();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { globSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
@@ -24,13 +25,10 @@ const SRC = join(process.cwd(), "src");
|
||||
* client (9 MB; never read it) and test files themselves.
|
||||
*/
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.filter(
|
||||
(p) => !p.startsWith(`generated${sep}`) && !p.startsWith("generated/"),
|
||||
)
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.startsWith("generated/"))
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
.sort();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,12 @@ const ROOT = process.cwd();
|
||||
|
||||
/** Client-side code: the component tree, the hooks, and the app's pages. */
|
||||
const CLIENT_ROOTS = ["src/components", "src/hooks", "src/app"];
|
||||
/**
|
||||
* Pruned on purpose: the generated Prisma client, build output, vendored
|
||||
* dependencies, and the suites themselves are not the tree under audit. Note
|
||||
* what is NOT pruned — this walk descends into dot-prefixed directories, so
|
||||
* `src/app/.well-known` is inside the sweep. `fs.globSync` would drop it.
|
||||
*/
|
||||
const SKIP_DIRS = new Set(["__tests__", "node_modules", ".next", "generated"]);
|
||||
|
||||
function walk(dir: string, out: string[] = []): string[] {
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { globSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
@@ -49,13 +50,10 @@ const INVALIDATION =
|
||||
const REFETCH = /refetchInactiveDailyReads\(/g;
|
||||
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.filter(
|
||||
(p) => !p.startsWith(`generated${sep}`) && !p.startsWith("generated/"),
|
||||
)
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.startsWith("generated/"))
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
.sort();
|
||||
}
|
||||
|
||||
@@ -108,6 +106,13 @@ const NO_REFETCH_ALLOWLIST = [
|
||||
].sort();
|
||||
|
||||
describe("daily-reads refetch guard", () => {
|
||||
// A sweep that finds nothing agrees with every allowlist, so the size of
|
||||
// the tree being read is asserted before anything is concluded from it.
|
||||
// Pinned below the real source-file count with headroom, not at one.
|
||||
it("reads the tree it claims to sweep", () => {
|
||||
expect(sourceFiles().length).toBeGreaterThan(1500);
|
||||
});
|
||||
|
||||
it("the blessed helper pairs the bundle invalidation with the inactive refetch", () => {
|
||||
const src = read(FACTORY);
|
||||
// The one canonical entry point every intake surface routes through.
|
||||
|
||||
@@ -49,8 +49,10 @@
|
||||
* red at the call site.
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync, globSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
@@ -558,8 +560,7 @@ const CONTROL_ROOTS = ["app/", "components/", "hooks/"];
|
||||
const EXCLUDED_PREFIXES = ["app/api/", "generated/", "lib/"];
|
||||
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
.sort();
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
* are pinned to a named allowlist, so a new converted-value surface
|
||||
* cannot quietly join them.
|
||||
*/
|
||||
import { readFileSync, globSync } from "node:fs";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import {
|
||||
@@ -69,7 +71,7 @@ const RAW_SCALE_READ =
|
||||
/\b\w*[Tt]ransform(?:For\([^)]*\))?\??\.(factor|offset)\b/;
|
||||
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC }).filter(
|
||||
return walkSourceFiles(SRC, { floor: 3000 }).filter(
|
||||
(rel) =>
|
||||
// Never walk the Prisma client, and skip the suites that legitimately
|
||||
// exercise the raw arithmetic they are asserting about.
|
||||
|
||||
@@ -132,6 +132,12 @@ const REGISTRY: readonly KeySpace[] = [
|
||||
];
|
||||
|
||||
describe("dynamic-key exhaustiveness (enum-derived)", () => {
|
||||
// Six shipped locales. An empty read of `messages/` would register zero
|
||||
// per-locale cases and the suite would report green over nothing.
|
||||
it("reads every shipped locale bundle", () => {
|
||||
expect(LOCALES.length).toBeGreaterThanOrEqual(6);
|
||||
});
|
||||
|
||||
it("discovers all six shipped locales", () => {
|
||||
expect(LOCALES.map((l) => l.locale).sort()).toEqual([
|
||||
"de",
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
* a runtime property, proven by the suite itself.
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync, globSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const E2E = join(process.cwd(), "e2e");
|
||||
|
||||
@@ -33,9 +35,7 @@ const DIRECT_IMPORT_ALLOWLIST: Record<string, string> = {
|
||||
};
|
||||
|
||||
function e2eFiles(): string[] {
|
||||
return globSync("**/*.ts", { cwd: E2E })
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
.sort();
|
||||
return walkSourceFiles(E2E, { floor: 40, extensions: [".ts"] }).sort();
|
||||
}
|
||||
|
||||
function read(rel: string): string {
|
||||
|
||||
@@ -23,20 +23,18 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { globSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
const VALIDATOR_MODULE = "@/lib/validations/external-id";
|
||||
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.filter(
|
||||
(p) => !p.startsWith(`generated${sep}`) && !p.startsWith("generated/"),
|
||||
)
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.startsWith("generated/"))
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
.sort();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* The one file walker the structural guards share.
|
||||
*
|
||||
* ## Why this exists rather than `fs.globSync`
|
||||
*
|
||||
* A guard that freezes a discovered set against an allowlist is only as
|
||||
* honest as its idea of "every source file". `fs.globSync` has a rule that
|
||||
* silently narrows that idea: a glob's `*` never matches a leading dot, so
|
||||
* `**\/*.{ts,tsx}` skips every dot-prefixed directory without saying so.
|
||||
*
|
||||
* `src/app/.well-known/` holds three live route modules — the two OAuth
|
||||
* discovery documents the MCP server publishes and the
|
||||
* apple-app-site-association handler. Every guard built on `globSync` walked
|
||||
* straight past all three and reported a clean sweep over a tree with a hole
|
||||
* in it. Demonstrated, not assumed: an unlisted `getSession()` call planted
|
||||
* in `app/.well-known/oauth-authorization-server/route.ts` left
|
||||
* `session-surface-guard` at 9 passed, and fails it once the walk goes
|
||||
* through here.
|
||||
*
|
||||
* `readdirSync(root, { recursive: true })` has no dot rule. It is the reason
|
||||
* `delegable-surface-guard.test.ts` already walks by hand; this helper makes
|
||||
* that the shared behaviour instead of one guard's private correction.
|
||||
*
|
||||
* ## Why `floor` is required and not optional
|
||||
*
|
||||
* The other way a sweep goes quiet is by finding nothing at all: an empty
|
||||
* match set agrees with an empty allowlist, and the guard passes on a tree it
|
||||
* never read. A wrong root, a renamed directory, or a walk that throws away
|
||||
* every entry all look exactly like compliance. So every caller states the
|
||||
* size it expects to walk, pinned below the real count with headroom, and a
|
||||
* walk that comes back smaller throws instead of reporting a clean sweep.
|
||||
* The floor covers the walk; a guard that filters further is still on the
|
||||
* hook for a floor over its own narrowed set.
|
||||
*
|
||||
* ## What it returns
|
||||
*
|
||||
* Posix-separated paths relative to `root`, sorted, so a guard's output and
|
||||
* its failure message read the same on every platform. Directory entries are
|
||||
* dropped by the extension filter.
|
||||
*
|
||||
* ## What it does not do
|
||||
*
|
||||
* It applies no exclusions of its own — not `generated/`, not `__tests__`,
|
||||
* not `.test.ts`. Each guard states its own, because what counts as out of
|
||||
* scope is the guard's claim to make, not the walker's.
|
||||
*
|
||||
* And it must not be rooted at the repository root. Descending into
|
||||
* dot-prefixed directories is the whole point, but at the root that means
|
||||
* `.git` and — on a maintainer's machine mid-release — the `.wt-*` sibling
|
||||
* worktrees, each a full second copy of the tree that would double every
|
||||
* match. Every caller roots at `src/`, `e2e/` or a subtree of one.
|
||||
*/
|
||||
import { readdirSync } from "node:fs";
|
||||
import { sep } from "node:path";
|
||||
|
||||
export function walkSourceFiles(
|
||||
root: string,
|
||||
options: { floor: number; extensions?: readonly string[] },
|
||||
): string[] {
|
||||
const extensions = options.extensions ?? [".ts", ".tsx"];
|
||||
const files = readdirSync(root, { recursive: true })
|
||||
.map((entry) => String(entry).split(sep).join("/"))
|
||||
.filter((rel) => extensions.some((ext) => rel.endsWith(ext)))
|
||||
.sort();
|
||||
|
||||
if (files.length < options.floor) {
|
||||
throw new Error(
|
||||
`walkSourceFiles(${root}) found ${files.length} file(s) matching ` +
|
||||
`${extensions.join(", ")}, below the stated floor of ${options.floor}. ` +
|
||||
`A sweep this small is a broken walk, not a clean tree — check the ` +
|
||||
`root before lowering the floor.`,
|
||||
);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
@@ -27,6 +27,12 @@ const ROOT = join(__dirname, "../..");
|
||||
const SRC = join(ROOT, "src");
|
||||
const EN_BUNDLE_PATH = join(ROOT, "messages/en.json");
|
||||
|
||||
/**
|
||||
* Pruned on purpose: the generated Prisma client, build output, vendored
|
||||
* dependencies, and the suites themselves are not the tree under audit. Note
|
||||
* what is NOT pruned — this walk descends into dot-prefixed directories, so
|
||||
* `src/app/.well-known` is inside the sweep. `fs.globSync` would drop it.
|
||||
*/
|
||||
const SKIP_DIRS = new Set(["__tests__", "node_modules", ".next", "generated"]);
|
||||
|
||||
function walk(dir: string, out: string[] = []): string[] {
|
||||
|
||||
@@ -115,6 +115,12 @@ const REQUIRED_KEY_SETS: Array<{
|
||||
];
|
||||
|
||||
describe("v1.4.27 B6 i18n drift-guard — required keys present in every locale", () => {
|
||||
// Six shipped locales. An empty read of `messages/` would register zero
|
||||
// per-locale cases and the suite would report green over nothing.
|
||||
it("reads every shipped locale bundle", () => {
|
||||
expect(LOCALES.length).toBeGreaterThanOrEqual(6);
|
||||
});
|
||||
|
||||
for (const { label, required } of REQUIRED_KEY_SETS) {
|
||||
describe(label, () => {
|
||||
it.each(LOCALES)(
|
||||
|
||||
@@ -35,6 +35,12 @@ const ROOT = join(__dirname, "../..");
|
||||
const SRC = join(ROOT, "src");
|
||||
const EN_BUNDLE_PATH = join(ROOT, "messages/en.json");
|
||||
|
||||
/**
|
||||
* Pruned on purpose: the generated Prisma client, build output, vendored
|
||||
* dependencies, and the suites themselves are not the tree under audit. Note
|
||||
* what is NOT pruned — this walk descends into dot-prefixed directories, so
|
||||
* `src/app/.well-known` is inside the sweep. `fs.globSync` would drop it.
|
||||
*/
|
||||
const SKIP_DIRS = new Set(["__tests__", "node_modules", ".next", "generated"]);
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,12 @@ import { join, relative, sep } from "node:path";
|
||||
const ROOT = join(__dirname, "../..");
|
||||
const SRC = join(ROOT, "src");
|
||||
|
||||
/**
|
||||
* Pruned on purpose: the generated Prisma client, build output, vendored
|
||||
* dependencies, and the suites themselves are not the tree under audit. Note
|
||||
* what is NOT pruned — this walk descends into dot-prefixed directories, so
|
||||
* `src/app/.well-known` is inside the sweep. `fs.globSync` would drop it.
|
||||
*/
|
||||
const SKIP_DIRS = new Set(["__tests__", "node_modules", ".next", "generated"]);
|
||||
|
||||
/**
|
||||
@@ -61,6 +67,13 @@ function walk(dir: string, out: string[] = []): string[] {
|
||||
}
|
||||
|
||||
describe("medicationInventoryItem write isolation", () => {
|
||||
// A sweep that finds nothing agrees with every allowlist, so the size of
|
||||
// the tree being read is asserted before anything is concluded from it.
|
||||
// Pinned below the real source-file count with headroom, not at one.
|
||||
it("reads the tree it claims to sweep", () => {
|
||||
expect(walk(SRC).length).toBeGreaterThan(1500);
|
||||
});
|
||||
|
||||
it("no file outside the consumption module + inventory surfaces writes inventory items", () => {
|
||||
const offenders: string[] = [];
|
||||
for (const file of walk(SRC)) {
|
||||
|
||||
@@ -80,6 +80,12 @@ function flatten(obj: unknown, prefix: string, out: [string, string][]): void {
|
||||
}
|
||||
|
||||
describe("medications.efficacy — banned verdict/advice verbs", () => {
|
||||
// Six shipped locales. An empty read of `messages/` would register zero
|
||||
// per-locale cases and the suite would report green over nothing.
|
||||
it("reads every shipped locale bundle", () => {
|
||||
expect(LOCALES.length).toBeGreaterThanOrEqual(6);
|
||||
});
|
||||
|
||||
it.each(LOCALES)("%s carries no forbidden verb", (file) => {
|
||||
const bundle = JSON.parse(readFileSync(join(MESSAGES, file), "utf8")) as {
|
||||
medications?: { efficacy?: unknown };
|
||||
|
||||
@@ -64,6 +64,9 @@ describe("prisma migrations — numeric prefixes are unique", () => {
|
||||
const numbered = readdirSync(MIGRATIONS_DIR, {
|
||||
withFileTypes: true,
|
||||
}).filter((e) => e.isDirectory() && NUMBERED_MIGRATION.test(e.name));
|
||||
expect(numbered.length).toBeGreaterThan(0);
|
||||
// Not `> 0`: a walk that returns a single directory is as broken as one
|
||||
// that returns none, and both would pass a zero floor. Pinned below the
|
||||
// real migration count with headroom.
|
||||
expect(numbered.length).toBeGreaterThan(200);
|
||||
});
|
||||
});
|
||||
@@ -19,6 +19,12 @@ import { readFileSync, readdirSync, statSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
const SRC = join(__dirname, "..");
|
||||
/**
|
||||
* Pruned on purpose: the generated Prisma client, build output, vendored
|
||||
* dependencies, and the suites themselves are not the tree under audit. Note
|
||||
* what is NOT pruned — this walk descends into dot-prefixed directories, so
|
||||
* `src/app/.well-known` is inside the sweep. `fs.globSync` would drop it.
|
||||
*/
|
||||
const SKIP_DIRS = new Set(["__tests__", "node_modules", ".next", "generated"]);
|
||||
|
||||
/**
|
||||
@@ -52,6 +58,13 @@ function stripComments(source: string): string {
|
||||
}
|
||||
|
||||
describe("doctor-report aggregator egress", () => {
|
||||
// A sweep that finds nothing agrees with every allowlist, so the size of
|
||||
// the tree being read is asserted before anything is concluded from it.
|
||||
// Pinned below the real source-file count with headroom, not at one.
|
||||
it("reads the tree it claims to sweep", () => {
|
||||
expect(walk(SRC).length).toBeGreaterThan(1500);
|
||||
});
|
||||
|
||||
it("keeps the set of aggregator callers frozen", () => {
|
||||
const found: string[] = [];
|
||||
for (const file of walk(SRC)) {
|
||||
|
||||
@@ -34,8 +34,9 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { globSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
@@ -46,8 +47,8 @@ const SRC = join(process.cwd(), "src");
|
||||
* `app/`) and never read — see CLAUDE.md.
|
||||
*/
|
||||
function appFiles(): string[] {
|
||||
return globSync("app/**/*.{ts,tsx}", { cwd: SRC })
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => p.startsWith("app/"))
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
.sort();
|
||||
|
||||
@@ -24,19 +24,17 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { globSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.filter(
|
||||
(p) => !p.startsWith(`generated${sep}`) && !p.startsWith("generated/"),
|
||||
)
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.startsWith("generated/"))
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
.sort();
|
||||
}
|
||||
|
||||
@@ -120,6 +118,13 @@ const ELEVATION_ROUTES = [
|
||||
].sort();
|
||||
|
||||
describe("S1 — the elevation-accepting route set is frozen", () => {
|
||||
// A sweep that finds nothing agrees with every allowlist, so the size of
|
||||
// the tree being read is asserted before anything is concluded from it.
|
||||
// Pinned below the real source-file count with headroom, not at one.
|
||||
it("reads the tree it claims to sweep", () => {
|
||||
expect(sourceFiles().length).toBeGreaterThan(1500);
|
||||
});
|
||||
|
||||
it("only the known MFA-management mutations call the gate", () => {
|
||||
const found = callers("requireMfaManagementAuth", API_HANDLER).filter(
|
||||
(rel) => rel !== "lib/api-handler.ts",
|
||||
|
||||
@@ -493,6 +493,13 @@ function markerCounts(
|
||||
}
|
||||
|
||||
describe("success affordance — owned by the outcome module, pinned everywhere else", () => {
|
||||
// A sweep that finds nothing agrees with every allowlist, so the size of
|
||||
// the tree being read is asserted before anything is concluded from it.
|
||||
// Pinned below the real component-file count with headroom, not at one.
|
||||
it("reads the tree it claims to sweep", () => {
|
||||
expect(componentSourceFiles().length).toBeGreaterThan(400);
|
||||
});
|
||||
|
||||
it("lets no unlisted component reach for the success affordance", () => {
|
||||
const unlisted = componentSourceFiles()
|
||||
.filter((path) => !path.startsWith(PRESENTATION_DIR))
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
* Mutation check: add `unit="kg"` back to any swept page and this goes red.
|
||||
*/
|
||||
import { readFileSync } from "node:fs";
|
||||
import { globSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import {
|
||||
@@ -74,9 +75,11 @@ const HEIGHT_CONTROL = join(
|
||||
function sweptFiles(): string[] {
|
||||
return [
|
||||
join(SRC, "app", "page-client.tsx"),
|
||||
...globSync("app/insights/**/page.tsx", { cwd: SRC }).map((rel) =>
|
||||
join(SRC, rel),
|
||||
),
|
||||
...walkSourceFiles(SRC, { floor: 700, extensions: [".tsx"] })
|
||||
.filter(
|
||||
(rel) => rel.startsWith("app/insights/") && rel.endsWith("/page.tsx"),
|
||||
)
|
||||
.map((rel) => join(SRC, rel)),
|
||||
...TARGET_SURFACES,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
* settles is that there is only one of it.
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync, globSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
@@ -71,8 +73,7 @@ const FIX_THE_ZONE = [
|
||||
].join(" ");
|
||||
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.startsWith("generated/"))
|
||||
.filter((p) => !p.includes("__tests__/"))
|
||||
.sort();
|
||||
@@ -94,6 +95,13 @@ function declaresTheBucket(source: string): boolean {
|
||||
}
|
||||
|
||||
describe("the checkup due-day bucket has one home", () => {
|
||||
// A sweep that finds nothing agrees with every allowlist, so the size of
|
||||
// the tree being read is asserted before anything is concluded from it.
|
||||
// Pinned below the real source-file count with headroom, not at one.
|
||||
it("reads the tree it claims to sweep", () => {
|
||||
expect(sourceFiles().length).toBeGreaterThan(1500);
|
||||
});
|
||||
|
||||
it("is declared in exactly one file", () => {
|
||||
const declaring = sourceFiles().filter((rel) =>
|
||||
declaresTheBucket(read(rel)),
|
||||
|
||||
@@ -21,8 +21,9 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { globSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
@@ -52,8 +53,7 @@ const IDENTITY_OWNER: Record<string, string> = {
|
||||
const EXPECTED_CALL_SITES = Object.keys(IDENTITY_OWNER).sort();
|
||||
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.startsWith("generated/"))
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
@@ -81,6 +81,13 @@ function invokesPicker(source: string): boolean {
|
||||
}
|
||||
|
||||
describe("the picker's call-site set is frozen", () => {
|
||||
// A sweep that finds nothing agrees with every allowlist, so the size of
|
||||
// the tree being read is asserted before anything is concluded from it.
|
||||
// Pinned below the real source-file count with headroom, not at one.
|
||||
it("reads the tree it claims to sweep", () => {
|
||||
expect(sourceFiles().length).toBeGreaterThan(1500);
|
||||
});
|
||||
|
||||
it("has exactly the call sites this file acknowledges", () => {
|
||||
const found = sourceFiles()
|
||||
.filter((rel) => rel !== PICKER)
|
||||
|
||||
@@ -20,20 +20,18 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
import { globSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { walkSourceFiles } from "./helpers/source-files";
|
||||
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
/** Every non-test `.ts` / `.tsx` under `src/`, minus the generated client. */
|
||||
function sourceFiles(): string[] {
|
||||
return globSync("**/*.{ts,tsx}", { cwd: SRC })
|
||||
.filter(
|
||||
(p) => !p.startsWith(`generated${sep}`) && !p.startsWith("generated/"),
|
||||
)
|
||||
return walkSourceFiles(SRC, { floor: 3000 })
|
||||
.filter((p) => !p.startsWith("generated/"))
|
||||
.filter((p) => !p.includes("__tests__"))
|
||||
.filter((p) => !p.endsWith(".test.ts") && !p.endsWith(".test.tsx"))
|
||||
.map((p) => p.split(sep).join("/"))
|
||||
.sort();
|
||||
}
|
||||
|
||||
@@ -131,6 +129,13 @@ const READ_TIME_NARROWERS = [
|
||||
];
|
||||
|
||||
describe("T1 — the set of sport-label mappers is frozen", () => {
|
||||
// A sweep that finds nothing agrees with every allowlist, so the size of
|
||||
// the tree being read is asserted before anything is concluded from it.
|
||||
// Pinned below the real source-file count with headroom, not at one.
|
||||
it("reads the tree it claims to sweep", () => {
|
||||
expect(sourceFiles().length).toBeGreaterThan(1500);
|
||||
});
|
||||
|
||||
it("every exported sport-type resolver is registered", () => {
|
||||
const found = new Set<string>();
|
||||
for (const rel of sourceFiles()) {
|
||||
|
||||
+21
-7
@@ -8,9 +8,11 @@ import Link from "next/link";
|
||||
*
|
||||
* 1. The runtime image bundles MaxMind GeoLite2-City and
|
||||
* GeoLite2-ASN databases for offline IP-to-location and
|
||||
* IP-to-ASN lookups. The CC BY-SA 4.0 licence requires the
|
||||
* attribution to be reachable from the running application,
|
||||
* not just the source repository.
|
||||
* IP-to-ASN lookups. They ship under the GeoLite End User
|
||||
* License Agreement, which incorporates CC BY-SA 4.0 by
|
||||
* reference and controls over it; both want the attribution
|
||||
* reachable from the running application, not just from the
|
||||
* source repository.
|
||||
* 2. A general home for open-source credits as the project
|
||||
* accumulates more third-party data sources (already true for
|
||||
* the upcoming ICD-10 reference table in the iOS Health import
|
||||
@@ -35,7 +37,7 @@ import Link from "next/link";
|
||||
// weakening the CSP with `unsafe-inline`.
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const LAST_UPDATED = "2026-05-15";
|
||||
const LAST_UPDATED = "2026-08-02";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "About — HealthLog",
|
||||
@@ -119,7 +121,9 @@ export default function AboutPage() {
|
||||
>
|
||||
github.com/MBombeck/HealthLog
|
||||
</a>{" "}
|
||||
and is licensed under the GNU Affero General Public License v3.0.
|
||||
and is licensed under the PolyForm Noncommercial License 1.0.0.
|
||||
Releases up to and including v1.15.18 were published under AGPL-3.0
|
||||
and stay available under it.
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
@@ -156,6 +160,15 @@ export default function AboutPage() {
|
||||
) power the offline IP-to-location and IP-to-carrier lookups that
|
||||
decorate the admin login-overview audit table. They are distributed
|
||||
under the{" "}
|
||||
<a
|
||||
href="https://www.maxmind.com/en/geolite/eula"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
GeoLite End User License Agreement
|
||||
</a>
|
||||
, which incorporates the{" "}
|
||||
<a
|
||||
href="https://creativecommons.org/licenses/by-sa/4.0/"
|
||||
target="_blank"
|
||||
@@ -163,8 +176,9 @@ export default function AboutPage() {
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
Creative Commons Attribution-ShareAlike 4.0 International License
|
||||
</a>
|
||||
.
|
||||
</a>{" "}
|
||||
by reference and controls wherever the two disagree. The attribution
|
||||
above is what that licence asks for.
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
|
||||
Reference in new issue
Block a user