mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
The shared write bucket threw on any SQL error, so a lock on rate_limits answered every authenticated write with 500. It is a loop cutter, not an access check: when the bucket cannot be read the write now goes ahead with a warn signal. The login and other auth-surface limits call the limiter directly and still fail closed. requireAuth now passes readOverPost to the meter, the draft-only document assist declares it, and the three chat routes, which meter their turns with buckets of their own, declare that instead of being counted twice.
43 lines
1.7 KiB
TypeScript
43 lines
1.7 KiB
TypeScript
/**
|
|
* `readOverPost` lets a delegable route answer a POST at the grant's read
|
|
* level. That widens what a read-only grant reaches, so the set of routes
|
|
* declaring it is frozen here: adding one is a reviewed diff, not an
|
|
* accident. Today it is the record search, whose query is health data that
|
|
* must stay out of URLs, and the document assist, whose POST writes nothing
|
|
* (under `requireAuth` the declaration only keeps it off the shared write
|
|
* ceiling).
|
|
*
|
|
* The matcher tolerates whitespace and line breaks, and the guard asserts it
|
|
* matched something, so a rewrite that hides the declaration from the regex
|
|
* fails instead of passing on an empty set.
|
|
*/
|
|
import { describe, expect, it } from "vitest";
|
|
import { readFileSync } from "node:fs";
|
|
import { globSync } from "node:fs";
|
|
import { join, relative, sep } from "node:path";
|
|
|
|
const ROOT = process.cwd();
|
|
|
|
const FROZEN = [
|
|
// The draft-only document assist: a POST that writes nothing. Under
|
|
// `requireAuth` the declaration only keeps it out of the shared write
|
|
// ceiling; there is no grant for it to widen.
|
|
"src/app/api/documents/inbound/[id]/suggest/route.ts",
|
|
"src/app/api/search/route.ts",
|
|
];
|
|
|
|
describe("readOverPost declarations", () => {
|
|
it("are exactly the frozen set", () => {
|
|
const declaring = globSync("src/**/*.ts", { cwd: ROOT })
|
|
.filter((file) => !file.includes(`${sep}__tests__${sep}`))
|
|
.filter((file) => file !== join("src", "lib", "api-handler.ts"))
|
|
.filter((file) =>
|
|
/readOverPost\s*:\s*true/.test(readFileSync(join(ROOT, file), "utf8")),
|
|
)
|
|
.map((file) => relative(ROOT, join(ROOT, file)).split(sep).join("/"))
|
|
.sort();
|
|
expect(declaring.length).toBeGreaterThan(0);
|
|
expect(declaring).toEqual(FROZEN);
|
|
});
|
|
});
|