mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
docs(sharing): the booster needs two sections, and the guide promised it at one level
The write-level row listed "a vaccination dose and the booster reminder it suggests" three paragraphs under a section table that puts the vaccination record in Health background. Read together, that tells a self-hoster a health-background WRITE grant can plan a booster — which the route beside it now refuses, because the reminder it mints lives under Readings. The row lists the dose alone, and the exceptions paragraph, which is where a reader looks for exactly this, carries the two-section case and says the dose logs either way. With it, the small things the same pass turned up: The cycle-insights fixture asserted a property it could not show. Its docblock claims the cycle-native answer survives the fence, and it seeded no symptom at all, so `symptomPatterns` was empty in every leg and a regression that emptied it along with the foreign columns would have passed green. One catalogue symptom on the luteal days, asserted on the owner leg and on the cycle-only one. The immunization rows matched on a bare `role="button"`, which passes vacuously the day the card becomes a real button and fails for the wrong reason if anything else in the subtree grows one. They carry the same stable marker the visit card took. `/api/cycle/calendar` reads the same wrist-temperature channel the crosstab does and is deliberately not fenced, and it was the only one of the pair with nothing saying why: no value from it reaches the response. The encrypted export's new 403 documented the switch refusal and not the narrow-scope one it answers first, unlike the two settings operations beside it. Both sheets say at the top that their Save and Delete are gated at the caller, so a third mount reads the constraint before it violates it. And one docblock line ran past the wrap.
This commit is contained in:
1 parent
681e69a723
commit
83b7cd223a
10 files changed
+111
-18
No files matched your search
@@ -165,6 +165,29 @@ async function seedRecord() {
|
||||
today,
|
||||
);
|
||||
|
||||
// One catalogue symptom, logged on enough phase-labelled days to clear the
|
||||
// pattern floor. Without it `symptomPatterns` is empty in every leg and the
|
||||
// "the cycle-native answer still arrives" property could not be shown even
|
||||
// by a leg that asserted it.
|
||||
//
|
||||
// Upserted rather than created: the symptom catalogue is seeded by migration
|
||||
// and survives the per-test truncation, so a plain create passes on the
|
||||
// first leg and collides on the second.
|
||||
const category = await prisma.cycleSymptomCategory.upsert({
|
||||
where: { key: "cycle-insights-cat" },
|
||||
update: {},
|
||||
create: { key: "cycle-insights-cat", labelKey: "cycle.category.test" },
|
||||
});
|
||||
const symptom = await prisma.cycleSymptom.upsert({
|
||||
where: { key: "cycle-insights-cramps" },
|
||||
update: {},
|
||||
create: {
|
||||
categoryId: category.id,
|
||||
key: "cycle-insights-cramps",
|
||||
labelKey: "cycle.symptom.cramps",
|
||||
},
|
||||
});
|
||||
|
||||
let luteal = 0;
|
||||
let follicular = 0;
|
||||
for (const [day, phase] of phaseByDay) {
|
||||
@@ -195,6 +218,18 @@ async function seedRecord() {
|
||||
tz: "UTC",
|
||||
},
|
||||
});
|
||||
// Cycle-native data, logged on the luteal days only so the pattern has a
|
||||
// dominant phase to report.
|
||||
if (high) {
|
||||
await prisma.cycleDayLog.create({
|
||||
data: {
|
||||
userId: OWNER_ID,
|
||||
date: day,
|
||||
tz: "UTC",
|
||||
symptomLinks: { create: [{ symptomId: symptom.id }] },
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
expect(
|
||||
@@ -211,7 +246,7 @@ interface InsightsBody {
|
||||
rows: Array<{ metricKey: string }>;
|
||||
headline: { metricKey: string } | null;
|
||||
lagged: { discovered: unknown[] };
|
||||
symptomPatterns: unknown[];
|
||||
symptomPatterns: Array<{ symptomKey: string; topPhase: string }>;
|
||||
}
|
||||
|
||||
async function readInsights(): Promise<InsightsBody> {
|
||||
@@ -243,6 +278,10 @@ describe("cycle insights fence the sections it reads across", () => {
|
||||
"weight",
|
||||
);
|
||||
expect(keys, "and the mood contrast beside it").toContain("mood");
|
||||
expect(
|
||||
body.symptomPatterns.map((row) => row.symptomKey),
|
||||
"and the cycle-native patterns the fence must not touch",
|
||||
).toContain("cycle-insights-cramps");
|
||||
});
|
||||
|
||||
it("gives an entire-record delegate the same figures", async () => {
|
||||
@@ -267,6 +306,13 @@ describe("cycle insights fence the sections it reads across", () => {
|
||||
body.lagged.discovered,
|
||||
"the lagged matrix is built from the same two sections",
|
||||
).toHaveLength(0);
|
||||
// The other half of the property, and the one a blanket refusal would
|
||||
// break: the symptom-by-phase patterns are cycle data and the grant opens
|
||||
// cycle, so they arrive in full.
|
||||
expect(
|
||||
body.symptomPatterns.map((row) => row.symptomKey),
|
||||
"the cycle-native answer still arrives",
|
||||
).toContain("cycle-insights-cramps");
|
||||
});
|
||||
|
||||
it("gives a cycle+mind delegate the mood figure and not the weight", async () => {
|
||||
|
||||
Reference in new issue
Block a user