Files
HealthLog/src/lib/documents/document-settings.ts
T
Marc-André Bombeck ce72fe226e refactor(ai): re-check every chokepoint through the one egress helper
The status chokepoint, the comprehensive briefing, reaction lines and
AI-composed nudges now ask `aiEgressRefusal` about exactly the chain they
are about to send to, instead of each pairing the operator-key check
with a surface receipt lookup of its own. The consent kinds come from the
capability table, so the wire and the published capability answer from
the same rule.

The document summary, its catch-up pass and the index backfill stop on a
closed switch or module before anything is picked, and leave "no
provider" and "consent needed" to the document pick, which re-checks the
wire for the provider it chose. A closed switch still only heals PENDING
to NONE; a withheld pick records UNAVAILABLE. The per-pick document
consent helper is removed, since nothing calls it any more.

The auto-read toggle mints the shared `AI_EXTRACTION_CONSENT_KIND`, and
the web grant helper goes back to minting the master grant only.

Refs #975
2026-09-24 09:29:00 +02:00

32 lines
1.3 KiB
TypeScript

/**
* Per-user document-vault AI settings.
*
* `documentAutoReadEnabled(userId)` reads the `documentsAutoAiRead` opt-in — the
* single switch that authorises ambient (no-per-document-tap) AI reading of
* uploaded documents. OFF by default: the vault stays local-first and every
* external egress needs an explicit per-document action + consent receipt.
*
* It is a trigger, not a consent. Switching it on mints an `ai_extraction`
* receipt, and that receipt is what the document egress re-check reads, so a
* revoked receipt stops external reading even with the flag still on. Readers:
* - the summary job and its catch-up pass run only while it is ON;
* - the auto-index-on-upload job stays strictly local when it is OFF and uses
* the document-order external pick when it is ON.
*/
import { prisma } from "@/lib/db";
/**
* True when the user has opted into automatic AI reading of uploaded documents.
* A missing row (deleted account raced against a job) resolves to `false` —
* fail-closed to the local-first posture, never to external egress.
*/
export async function documentAutoReadEnabled(
userId: string,
): Promise<boolean> {
const row = await prisma.user.findUnique({
where: { id: userId },
select: { documentsAutoAiRead: true },
});
return row?.documentsAutoAiRead ?? false;
}