Study participant data — system of record
- Parent: README.md
- Study graph contract: STUDY_GRAPH_SNAPSHOT.md
Non-goals (explicit)
- Firebase (Auth, Firestore, or Functions data planes) is not the system of record for study participant PII, consent records, or instrument responses in this architecture.
- Cloudflare D1 is not the system of record for those payloads. (D1 may exist elsewhere for unrelated app metadata; do not route human-subject rows there by default.)
- The Gnosis publish gate and study graph snapshot remain structural policy checks only — they do not substitute for ethics review, IRB, or lawful basis for processing.
Allowed planes
1. open-source/dash (default local-first sync)
- Use Dash-backed stores for session-local or operator-synced artifacts: recruitment lists, hashed invite tokens, form version pointers, and aggregate completion stats where policy allows aggregation only.
- Treat Dash as the coordination and replication layer for devices and rooms you already run for Edgework-style workflows — not as a generic cloud SQL substitute.
2. Encrypted Knotchain artifacts via open-source/bitwise and apps/edgework-app (preferred for durable, auditable bundles)
- Commit encrypted envelopes (payloads encoded with Bitwise/knotchain tooling) to Knotchain through the Edgework surface (
createKnotchainApp, R2-backed knotgraph paths,fabricUrl/ relay patterns already inapps/edgework-app/src/worker.ts). - Use this when you need tamper-evident, content-addressed bundles: e.g. “consent v3 + instrument v2 + response hash chain” without storing raw responses in a relational row store.
3. Email (Mailgun) — transport only
- Transactional email (invites, reminders) uses Mailgun HTTP APIs with secrets bound to
apps/edgework-app(or another worker that does not persist participant bodies in Firebase/D1). - Mailgun holds no authoritative study record; it only delivers messages. Correlation keys live in Dash/Knotchain metadata.
4. SMS (Twilio) — transport only
- Study SMS uses the same pattern as elsewhere in the monorepo (e.g.
apps/halos-agency): TwilioMessages.jsonwithTWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN,TWILIO_FROM_NUMBER. - Short bodies are built in
@a0n/gnosis/study-sms-templates; sending lives next to study mail underapps/edgework-app(/api/internal/study/sms). Twilio stores delivery metadata on their side; your system of record for consent and responses remains Dash/Knotchain, not Twilio or Firebase.
Minimum metadata fields (cross-plane)
| Field | Purpose |
|---|---|
study_id |
Matches StudyGraphSnapshotV1.study_id from Logic Studio / Gnosis export |
consent_version |
Immutable label committed before first response |
instrument_id / instrument_version |
Which form or SaaS instrument |
invite_token_hash |
Hash of opaque token; never store raw tokens in public snapshots |
Pure helpers: @a0n/gnosis/study-participant-link (buildStudyParticipantIngressRef).
Operational endpoints (Edgework)
- Email:
POST /api/internal/study/mail— Mailgun (MAILGUN_*). BearerSTUDY_MAIL_ADMIN_TOKEN. - SMS:
POST /api/internal/study/sms— Twilio (TWILIO_*). Same bearer token for ops. Does not write participant rows to Firebase or D1.