Skip to main content

15. Facility management and AI contract extraction

Date: 2026-06-06

Status

Accepted

Context

Admins manage facilities (profile, status, payment/interest terms, contacts with billing/admin/clinical roles) and upload facility contract PDFs. The spec calls for AI extraction of key contract terms (hours, rate, interest, payment terms, dates) that the admin reviews and confirms. The owner chose Anthropic Claude as the AI provider.

Decision

  • Facility CRUD + contacts via service-role server actions behind requireAdmin, scoped to the admin's company. Facilities and contacts are admin-only under RLS (no contractor/public access). The facility form is one reusable client component used for both create and update.
  • AI adapter (src/server/integrations/ai/anthropic.ts, server-only): Claude via @anthropic-ai/sdk, model pinned to claude-opus-4-8 (swappable). The contract PDF is sent as a base64 document content block to the Messages API. Reliability is a tolerant parse (strip code fences) + Zod validation + one retry — robust to a stray fence or a transient API error. Returns Result<ExtractedContract, AiError>.
  • Contract flow: the admin uploads the PDF directly to a private facility-contracts Storage bucket from the browser (admin/company-scoped storage RLS, migration 0010), avoiding the server-action body-size limit. A server action then downloads it, runs Claude extraction, and returns the terms for admin review/correction; a confirm action saves them to facility_contracts (admin_confirmed = true, money stored as hourly_rate_cents) and syncs payment/interest terms onto the facility.

Consequences

  • The first AI integration is isolated behind one adapter with a clean Result contract, so swapping provider/model or hardening parsing later is local.
  • Privacy: the full contract PDF is sent to Anthropic. Contracts can contain facility bank details and binary-PDF redaction isn't feasible, so this is a deliberate, documented third-party processing step tied to the AI-provider choice — flagged for the owner's data-processing review.
  • AI never writes authoritative data on its own: extraction only proposes terms; an admin confirms before anything is saved.
  • The live extraction path makes a real (paid) Claude call and can't be exercised headlessly; build/typecheck/lint and the pure parse/validate logic are verified, and the flow degrades to manual term entry if extraction fails.
  • The DocuSeal e-signature side of contracts remains outstanding (contract renewals step).