Skip to content

Intake and extraction

Input Original persistence Extraction timing
Pasted console text No original-file row Immediate queueing
PDF, Word, or text file Encrypted R2 object + metadata On demand from inventory
Service-key batch Encrypted per-note original Storage only; clinician extracts later
RheumAI submit for review No upload row Server re-extracts and creates held draft
Dedicated clinician agent Configured clinician’s uploads only On demand with agent key
WhatsApp study-channel document Encrypted original in R2 Immediate when channel, consent, and clinician are configured

Batch response proves storage, not extraction. One invalid note does not abort its siblings.

The server validates format, filename, and size, extracts text locally, encrypts original bytes with AES-256-GCM, stores ciphertext in R2, and stores metadata in PostgreSQL. Scope is checked before R2 retrieval or decryption. Current file ceiling is 20 MiB.

The worker obtains note text, applies best-effort de-identification, calls the configured registro-extraction model, parses JSON, converts nulls to unknown, validates schema, calculates DAS-28, calculates disease-matched missing fields, and creates a review_pending draft with encrypted source and attribution.

  • Model does not define tri-state semantics.
  • Real zero remains zero.
  • false means explicit negation except clinician-confirmed comorbidity normalization at submission.
  • Reported DAS-28 is compared; computation uses components where possible.
  • Biologic episodes retain role, drug, dates, and stop reason.
  • Requested biologic without its own date may use request/note date; current and previous episodes do not.

De-identification removes generic identifiers and patient-name tokens when found. It is not a compliance guarantee. Unlabelled names can survive, while clinically required dates and provider context may remain.

Clinical extraction job payloads can contain plaintext note text in PostgreSQL. Study jobs encrypt their note before queueing, but the clinical path does not yet share that protection.

Extraction permits five attempts with backoff. Exhaustion creates an app-visible dead letter without note text. Failed or rejected notes may be re-extracted; pending or approved drafts prevent duplicate extraction.

  • Failure between R2 storage and metadata insert can leave an orphan encrypted object.
  • Queue failure after upload persistence produces partial success: source exists without a job.
  • Draft creation followed by audit failure can create duplicate drafts on retry because success insertion has no attempt idempotency key.
  • A pasted note that dead-letters has no recoverable original in inventory.
  • Source completion fills unknown scalar fields only; it does not merge episode arrays and has no clinician UI.