docs(nav): say why Insights stays closed under a switch, since the old reason lapsed

The entry carried "Non-delegable in v1, server-side and here". That was true at
v1.36.0 and is not true now: twenty-seven `/api/insights/*` reads plus
`/api/dashboard/summary` and `/api/export/health-record` declare
`("manage", "record")`, and the AI-egress objection they were closed for is
answered by construction rather than by the flag — the record resolver stamps
`setDelegatedGenerationSuppressed`, so a delegate reads what the owner's own
account generated and causes no egress.

What keeps the door shut is the overview's own reads rather than the tiles':
`/api/insights/layout` and `/api/insights/generate` both resolve `requireAuth()`
and refuse any switch at any level. Opening the entry without first deciding
what those two mean for a delegate — whose saved layout, and whether the
briefing reads or regenerates — would hand a whole-record MANAGE delegate a page
whose chrome 403s while its tiles answer, which is the failure the presentation
inventory exists to prevent. That is a decision about two more routes, not a
flag on this one, so the comment now says what is actually load-bearing and the
Coach's own reason is stated separately.
This commit is contained in:
Marc-André Bombeck committed 2026-09-10 11:22:06 +02:00
1 parent 4410a496cc
commit 0e4619a0c0
1 file changed
+22 -5
+22 -5
View File
@@ -224,11 +224,28 @@ export const NAV_DESTINATIONS: ReadonlyArray<NavDestination> = [
tourId: "nav-documents",
requiresModule: "inboundDocuments",
},
// v1.36.0 — Insights and the Coach carry no `sharedRecord` flag, so they
// drop out under a switch. Both are AI surfaces, and AI egress of a
// person's health data rides the consent THAT person gave for their own
// use; a delegate triggering it would create a consent-shaped act the owner
// never made. Non-delegable in v1, server-side and here (design §4).
// Insights and the Coach carry no `sharedRecord` flag, so they drop out
// under a switch. The reason has changed since v1.36.0 and the old wording
// ("non-delegable, server-side and here") is no longer true of the tiles:
// twenty-seven `/api/insights/*` reads plus `/api/dashboard/summary` and
// `/api/export/health-record` declare `("manage", "record")`, and the
// AI-egress objection they were closed for is answered by construction —
// the record resolver stamps `setDelegatedGenerationSuppressed`, so a
// delegate reads what the owner's own account generated and causes no
// egress.
//
// What keeps the door shut is the OVERVIEW's own reads rather than the
// tiles': `/api/insights/layout` (`insights/layout/route.ts`) and
// `/api/insights/generate` (`insights/generate/route.ts`) both resolve
// `requireAuth()`, which refuses any switch at any level. Opening the entry
// without deciding what those two mean for a delegate — whose saved layout,
// and whether the briefing reads or regenerates — would hand a MANAGE
// delegate a page whose chrome 403s while its tiles answer. That is a
// decision about two more routes, not a flag on this one.
//
// The Coach stays closed on the original argument, unchanged:
// `/api/insights/chat` is genuinely not delegable, and the page is a
// generation surface rather than a read of one.
{
href: "/insights",
tKey: "nav.insights",