Formal functional testing of all Module 1 features
POST /api/v1/ingestion/trigger with mode='daily'. Verify sites created/updated in DB.
HTTP 200, sites count > 0, data_provenance record created
POST /api/v1/ingestion/trigger with enrich_pubmed=true. Verify h_index and pub_count populated.
Investigators updated with h_index > 0
Trigger daily mode (24h window) and full mode (broad search). Compare record counts.
Daily returns recent updates; full returns comprehensive dataset
GET /api/v1/compliance/data-provenance. Verify entries exist with source, hash, record_count.
Provenance records with SHA-256 hashes
GET /api/v1/sites/{id}/score. Verify 5 dimension values and total between 0-100.
score_total = weighted sum of 5 dimensions * 100
GET /api/v1/sites/{id}/score/explain. Verify factors array and source attribution.
Explainability includes factors, sources, confidence
POST /api/v1/sites/{id}/score/customize with custom weights summing to 1.0.
Recalculated score with custom weights, response < 2s
Score same site twice with identical parameters. Compare results.
Identical scores on both runs (no random variance)
POST /api/v1/sites/search with filters: therapeutic_area=Oncology, country=Switzerland.
Results filtered correctly, paginated, org_id isolated
POST /api/v1/sites/search with query='oncology sites in Switzerland with 50+ trials'.
AI interprets query, returns relevant results with synonym expansion
POST /api/v1/site-agent with message and session_id. Send follow-up query.
Agent maintains context, returns sites and suggestions
GET /api/v1/investigators?page=1&size=10. GET /api/v1/investigators/{id}.
List with h_index, pub_count, trial_count. Detail with all fields.
POST /api/v1/investigators/compare with 3 investigator IDs.
Full profiles for all 3 investigators returned
POST /api/v1/exports/sites/pdf and /excel with search filters.
StreamingResponse with correct content-type
POST /api/v1/projects (create). POST /api/v1/projects/{id}/shortlist (add site).
Project created. Site added to shortlist with status.
POST /api/v1/predictions/recruitment with site IDs.
Predictions with optimistic/realistic/pessimistic + confidence
Login as user A (org X), search sites. Login as user B (org Y), search sites.
Each user sees only their org's data. No cross-tenant leakage.
POST /api/v1/auth/login with valid credentials. Use token for protected endpoint. Wait 15min, verify expiry.
Login returns access + refresh tokens. Protected endpoints work. Expired token returns 401.
Login as read_only user. Attempt POST to admin endpoint.
Admin endpoint returns 403 for read_only user
POST /api/v1/auth/2fa/setup. Verify TOTP code. Login with 2FA.
TOTP setup returns secret + QR URI. Valid code accepted.
Perform POST action. Check audit_log. Attempt UPDATE on audit_log row.
Audit record created. UPDATE blocked by trigger with error message.
Query audit_log for org. Verify record_hash matches recomputed hash. Verify prev_hash chain.
Hash chain intact. Each prev_hash matches previous record's record_hash.
SHOW ssl (DB). Check pgcrypto extension. List encrypted columns.
SSL on. pgcrypto installed. 6 encrypted columns found.
Run site search 10 times, measure p95 latency.
p95 < 5 seconds for up to 500 results
Check /health endpoint every 5 minutes over 24 hours.
100% uptime during test period
GET /api/v1/ai-modules/registry. Verify models listed with versions.
Registry contains model entries with versioned IDs
GET /api/v1/ai-explain/audit-log. Verify inference entries.
Audit entries with input_hash, output_hash, model_id
Navigate to /legal/disclaimer. Check sidebar badges.
Disclaimer page loads. Module 1 shows 'Validated' badge.
Switch language to FR, DE, JA. Verify UI labels change.
Labels translated. Fallback to EN for missing keys.
Navigate to /dashboard/sites. Switch between card, table, map views.
All three views render correctly with site data.
Conclusion: All 30 test cases passed. Module 1 operates as specified in URS and FS.
Automated coverage: 188 E2E API tests provide continuous regression testing.
Tester: ClinicalOS QA / Automated test suite