Intake and extraction
Intake modes
Section titled “Intake modes”| 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.
Extraction job
Section titled “Extraction job”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.
Integrity
Section titled “Integrity”- Model does not define tri-state semantics.
- Real zero remains zero.
falsemeans 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.
Privacy and residual risk
Section titled “Privacy and residual risk”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.
Retries and failures
Section titled “Retries and failures”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.
Operational gaps
Section titled “Operational gaps”- 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.