Back to Dashboard
Privacy & Ethics CLAUDE.md Hard Rules
These constraints are enforced in code — they are not configurable and cannot be overridden by researcher role, admin role, or any API parameter. They exist because the study involves a vulnerable population, and some risks are not acceptable regardless of research value.
| # | Rule | Why it exists |
|---|---|---|
| 1 | No direct identifiers in any database row. Phone stored as HMAC-SHA256 only. Age group is the only demographic in interaction rows. | A data breach should not expose who the participants are or allow them to be contacted. HMAC-SHA256 is one-way — even with the database, you cannot recover a phone number without the HMAC secret. Age group (not birth year, not exact age) allows demographic segmentation without being individually identifying. |
| 2 | No governance decision before calibration_cleared = true. |
A governance decision made without a personal baseline would compare the participant to population norms, producing a false signal. The first three interactions are not evaluated — they calibrate. Firing an intervention during calibration would both be scientifically invalid and potentially confusing to the participant before they've settled in. |
| 3 | Cursor/keystroke signals null on mobile. Touch/orientation signals null on desktop. API returns 422 on violation. | Cross-device signal mixing corrupts the readiness model silently. A desktop session with null cursor signals would look falsely like a low-interaction session. Enforcing this at the schema level means the model always operates on internally consistent data. |
| 4 | All timestamps UTC ISO-8601. Naive datetimes rejected at schema validation. | Timezone-aware timestamps are essential for reconstructing event sequences across participants in different locations. A naive datetime in a database that spans multiple timezones is ambiguous and cannot be reliably compared. The API rejects naive timestamps rather than silently coercing them. |
| 5 | Thresholds in config.py and task templates. Zero hardcoded magic numbers. |
A threshold buried in code cannot be found, audited, or changed without reading every function. All thresholds are named constants in one place, fetchable from the dashboard API, and logged whenever they're used in a governance decision. |
| 6 | Dashboard and CSV exports in English regardless of participant language. | Researcher tools must be consistent and unambiguous. Mixing languages in exported data would create analysis errors. The participant experience is in their language; the researcher's analytical tools are in English. |
| 7 | Explicit help request always returns Level ≥ 2. Never Level 1 on an explicit request. | A participant who asks for help made a conscious, deliberate request. Responding with a tooltip — the lightest possible touch — violates the implicit contract of the help button. They asked for real help. They get real help. |
| 8 | Redis is the primary session store. Cache miss rebuilds from PostgreSQL deterministically. Never 409 on cache miss. | A 409 (conflict) response on a cache miss would tell the participant's app that their session is invalid, forcing re-enrollment and losing their data. A cache miss is not a data loss event — the PostgreSQL record is authoritative. Rebuild and continue. The rebuild must produce identical governance decisions to what a cached session would have produced. |
| 9 | Write ADAPTATION_FAILURE on every worsened outcome. | If AGS makes things worse, it must be recorded. Not logging failures would bias the research data and prevent detection of systematic content or governance problems. Failure data is as important as success data. |
| 10 | Consent is a hard gate. No telemetry before consent_recorded = true. |
Collecting interaction data from a participant who hasn't consented is an ethics violation regardless of what the data shows. The consent gate is enforced at the API layer — the events endpoint returns 403 if consent is not recorded, and the violation is logged to the dashboard alerts as ethics_violation. |
| 11 | Study conditions invisible in the UI. | Demand characteristics. See Study Design section. |
| 12 | Config thresholds locked after transition to main phase. | Mid-study threshold changes invalidate between-session comparisons. See Study Design section. |
| 13 | Every study-relevant action written to audit_log in the same transaction. | Audit log entries that arrive after the fact (logged asynchronously) can be lost if the server crashes between the action and the log write. Writing both in the same transaction guarantees the audit log is complete and consistent — if one fails, both fail. |