complianceaudit foundationspart 03 / 05

An audit log row, not a compliance slogan.

The audit model records who acted, against which resource, in which workspace, from which session, and stops the mutation if it cannot write the row.

Patient, clinical, billing, membership, AI, and administrative events are captured with actor context, organization scope, timing, network signal, and a metadata envelope that explicitly rejects PHI-bearing keys.

Product guidance, not legal advice. Compliance claims require technical evidence, deployment configuration, provider agreements, operational policies, and legal review before they reach a customer agreement.

Illustrative record

Example: patient record update by a clinician

cat audit_log.applied.json

{
  "id": "aud_01HZJK4F2M7P3Q8RW9XK6N",
  "event": "patient.record.update",
  "mutation_class": "phi",  // blocking write
  "status": "applied",  // alternative: "aborted"
  "actor": { "type": "organization_user", "id": "usr_01HXAB72…", "org_role": "clinician" },
  "organization_id": "org_01HWVT5J7QXK4F9DR3",  // tenant scope
  "target": { "type": "patient_record", "id": "pat_01J8KM5T…" },
  "timestamp": "2026-05-14T14:32:18.421Z",  // ISO 8601 UTC
  "ip": "203.0.113.84",
  "user_agent": "MediFlow Web 3.18 (macOS 14.4; Chrome 124)",
  "metadata": { "fields_changed": ["vitals", "allergies_flag"], "vitals_threshold_override": false, "request_id": "req_01HZJK4F2…" }  // no PHI; key allow-list
}

Fictional payload. Field names match the production envelope; IDs, IP, and times are not real.

What every row carries

Twelve required fields. The metadata envelope is the only flexible part, and it is allow-listed.

  1. idULIDrequired

    Globally unique, sortable, opaque.

  2. eventdotted stringrequired

    Domain.action shape, e.g. patient.record.update.

  3. mutation_classenum(6)required

    phi · membership · billing · admin · ai · operational.

  4. statusenum(2)required

    applied or aborted. The row is written either way.

  5. actor.typeenum(3)required

    organization_user, platform_admin, or system.

  6. actor.idstringrequired

    Appwrite user id for humans, process name for system.

  7. actor.org_roleenum | nulloptional

    Resolved from membership at write time.

  8. organization_idstringrequired

    Tenant scope. Absent only for cross-tenant platform events.

  9. target{ type, id }required

    The resource the action operated against.

  10. timestampISO 8601 UTCrequired

    Server clock, not client clock.

  11. ip / user_agentstringrequired

    Session signal, captured at the boundary, not from the client body.

  12. metadataobjectrequired

    Allow-listed envelope. Unknown or PHI-bearing keys are rejected.

What gets audited

  1. Patient records: create, update, delete, vitals capture, history edits, document upload, quick-note finalization.

  2. Appointments: scheduled, rescheduled, cancelled, no-show, completed.

  3. Organization membership: invite, accept, role change, removal, active organization switch.

  4. Billing: subscription state changes, seat changes, payment outcomes.

  5. AI assistance: agent run, tool call, summary committed, grounded research execution.

  6. Administrative: feature-flag flips, threshold updates, configuration changes.

Keys the metadata envelope rejects

Hard-rejected at the audit boundary. If one of these appears in a write attempt, the row fails and the mutation aborts.

  • patient_name
  • patient_email
  • patient_phone
  • patient_address
  • patient_dob
  • national_id
  • soap_note
  • clinical_notes
  • problem_list
  • assessment_text
  • ai_prompt
  • ai_response
  • generated_summary
  • generated_html
  • document_text
  • document_ocr_text

List is rule-driven, not hand-maintained per event. New events inherit the allow-list automatically.

Fail closed

If the audit row cannot be written, the mutation does not happen.

PHI, membership, billing, and admin writes block on the audit log. Silent partial success is the failure mode we will not ship.

Out of scope by design

  • Read paths that do not change state. Read auditing is a separate, sampled subsystem and is documented elsewhere.
  • Free-text bodies. Clinical notes and AI outputs live in their own stores under their own access control.
  • Client-only events without a server effect. The audit log records the server's decision, not the browser's intent.