Paste this playbook into Claude, ChatGPT, or any AI agent with access to your oneme/Titan/FoxScience systems. It will execute the migration step by step.
# Proven.dev Bootstrap Playbook # One-Time Migration: oneme + Titan + FoxScience → Proven ## What This Does You are migrating existing customer and patient data into Proven.dev's privacy-first health data infrastructure. After this bootstrap: - Customer profiles from oneme/Titan are stored in Proven - Patient identifiers are replaced with opaque subject_handles - FoxScience only has handles + science data (no PHI) - All temporary identity data is purged ## Prerequisites - A Proven.dev API key (hid_key_*) with 'mint' + 'ingest' + 'mailbox' scopes - Access to oneme, Titan, and FoxScience databases/APIs - The issuer_handle for your organization (from Proven registration) ## Order of Operations 1. Import customer profiles from oneme + Titan 2. Mint subject handles for FoxScience patient_ids 3. Link handles to customer profiles 4. Push de-identified science data 5. Verify everything 6. Purge temporary identity data ## Base URL All endpoints use: https://proven.dev/api/ ## Authentication All requests require: Authorization: Bearer hid_key_<your-key> Content-Type: application/json
# Step 1: Import Customer Profiles from oneme + Titan
## What to do:
1. Query oneme database for all customer/org records
2. Query Titan database for all customer/org records
3. Merge/dedup by company name or external ID
4. Push to Proven via POST /api/bootstrap/customers
## Endpoint
POST https://proven.dev/api/bootstrap/customers
## Payload
{
"issuerHandle": "iss_<your-issuer-handle>",
"customers": [
{
"externalId": "oneme-cust-001",
"source": "oneme",
"orgName": "Acme Health Corp",
"contactName": "John Smith",
"contactEmail": "[email protected]",
"industry": "pharma",
"tier": "enterprise",
"metadata": { "plan": "annual", "seats": 50 }
},
{
"externalId": "titan-cust-042",
"source": "titan",
"orgName": "BioGen Labs",
"contactName": "Jane Doe",
"contactEmail": "[email protected]",
"industry": "biotech",
"tier": "pro",
"metadata": { "region": "northeast" }
}
]
}
## curl Example
curl -X POST https://proven.dev/api/bootstrap/customers \
-H "Authorization: Bearer hid_key_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"issuerHandle": "iss_<handle>",
"customers": [
{
"externalId": "oneme-001",
"source": "oneme",
"orgName": "Acme Health",
"contactName": "John Smith",
"contactEmail": "[email protected]",
"industry": "pharma",
"tier": "enterprise"
}
]
}'
## Expected Response
{
"issuerHandle": "iss_abc123",
"total": 2,
"created": 2,
"updated": 0,
"skipped": 0,
"customers": [
{ "externalId": "oneme-cust-001", "customerId": 1, "status": "created" },
{ "externalId": "titan-cust-042", "customerId": 2, "status": "created" }
]
}
## Notes
- Run oneme customers first, then Titan
- If a customer with the same externalId + source exists, it will be UPDATED (not duplicated)
- contactName will be purged in Step 6 — it's only held temporarily for matching
- You can batch up to 500 customers per request# Step 2: Mint Subject Handles from FoxScience Patient IDs
## What to do:
1. Query FoxScience for all distinct patient_ids
2. Send them to Proven's mint endpoint
3. Proven returns opaque subject_handles for each patient_id
4. Write the subject_handles BACK to FoxScience (add column, drop patient_id later)
## Endpoint
POST https://proven.dev/api/healthid/mint
## Payload
{
"issuerHandle": "iss_<your-issuer-handle>",
"uuids": [
"patient-uuid-001",
"patient-uuid-002",
"patient-uuid-003"
]
}
## curl Example
curl -X POST https://proven.dev/api/healthid/mint \
-H "Authorization: Bearer hid_key_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"issuerHandle": "iss_<handle>",
"uuids": ["patient-001", "patient-002", "patient-003"]
}'
## Expected Response
{
"issuerHandle": "iss_abc123",
"totalMinted": 3,
"newMinted": 3,
"mapping": [
{
"uuid": "patient-001",
"subjectHandle": "hid_a7f3b2c1d4e5",
"healthIdDomain": "a7x9k2.healthid",
"isNew": true
},
{
"uuid": "patient-002",
"subjectHandle": "hid_b8g4c3d2e6f7",
"healthIdDomain": "b8y0l3.healthid",
"isNew": true
}
]
}
## IMPORTANT: Save the mapping!
The response contains the uuid → subjectHandle mapping.
You MUST save this mapping to update FoxScience:
For each row in the mapping:
UPDATE foxscience.patient_intake_forms
SET subject_handle = '<subjectHandle>'
WHERE patient_id = '<uuid>';
After ALL handles are written:
ALTER TABLE foxscience.patient_intake_forms
DROP COLUMN patient_id;
## Notes
- Minting is deterministic: same issuer + same UUID = same handle every time
- You can re-run this safely — existing handles won't be duplicated
- Batch up to 1000 UUIDs per request
- Each new handle automatically gets a .healthid domain# Step 3: Link Subject Handles to Customer Profiles
## What to do:
1. For each customer from Step 1, determine which patient_ids belong to them
2. Look up the subject_handles from Step 2's mapping
3. Link them via POST /api/bootstrap/link-handles
## Endpoint
POST https://proven.dev/api/bootstrap/link-handles
## Payload
{
"issuerHandle": "iss_<your-issuer-handle>",
"links": [
{
"customerExternalId": "oneme-cust-001",
"subjectHandles": ["hid_a7f3b2c1d4e5", "hid_b8g4c3d2e6f7"]
},
{
"customerExternalId": "titan-cust-042",
"subjectHandles": ["hid_c9h5d4e3f8g9"]
}
]
}
## curl Example
curl -X POST https://proven.dev/api/bootstrap/link-handles \
-H "Authorization: Bearer hid_key_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"issuerHandle": "iss_<handle>",
"links": [
{
"customerExternalId": "oneme-001",
"subjectHandles": ["hid_a7f3b2c1d4e5"]
}
]
}'
## Expected Response
{
"issuerHandle": "iss_abc123",
"total": 2,
"linked": 2,
"notFound": 0,
"results": [
{ "customerExternalId": "oneme-cust-001", "handlesLinked": 2, "status": "linked" },
{ "customerExternalId": "titan-cust-042", "handlesLinked": 1, "status": "linked" }
]
}
## Notes
- customerExternalId must match the externalId used in Step 1
- You can link multiple handles to one customer (e.g., one org has many patients)
- Re-running is safe — handles are deduplicated per customer# Step 4: Push De-identified Science Data
## What to do:
1. Query FoxScience for science data (biomarkers, panel results, features)
2. Use the subject_handles from Step 2 (NOT patient_ids)
3. Push via POST /api/healthid/ingest
4. This is the SAME endpoint used for normal operations — no special bootstrap needed
## Endpoint
POST https://proven.dev/api/healthid/ingest
## Payload
{
"issuerHandle": "iss_<your-issuer-handle>",
"packets": [
{
"subjectHandle": "hid_a7f3b2c1d4e5",
"features": {
"panel_type": "microbiome_16s",
"shannon_diversity": 3.45,
"firmicutes_ratio": 0.62,
"bacteroidetes_ratio": 0.28,
"proteobacteria_ratio": 0.05,
"actinobacteria_ratio": 0.03,
"diagnosis_codes": ["K58.0", "R19.7"],
"biomarker_calprotectin": 145.2
}
}
]
}
## curl Example
curl -X POST https://proven.dev/api/healthid/ingest \
-H "Authorization: Bearer hid_key_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"issuerHandle": "iss_<handle>",
"packets": [
{
"subjectHandle": "hid_a7f3b2c1d4e5",
"features": {
"panel_type": "microbiome_16s",
"shannon_diversity": 3.45,
"firmicutes_ratio": 0.62
}
}
]
}'
## Expected Response
{
"ingested": 1,
"packets": [
{ "subjectHandle": "hid_a7f3b2c1d4e5", "packetId": 42 }
]
}
## CRITICAL: No PHI in features!
The features object must contain ONLY science/clinical data:
✅ biomarkers, lab values, panel results, diagnosis codes, diversity indices
❌ names, DOBs, SSNs, addresses, phone numbers, emails
The subject_handle is the ONLY link to identity.
Proven's PII firewall will reject packets containing known identity fields.
## Notes
- Batch up to 100 packets per request
- Each packet creates a science record and an encounter event
- Discovery matching runs automatically after ingestion# Step 5: Verify Bootstrap Progress
## What to do:
1. Check the bootstrap status endpoint
2. Verify all customers are imported
3. Verify all handles are linked
4. Verify science data is ingested
## Endpoint
GET https://proven.dev/api/bootstrap/status
## curl Example
curl -X GET https://proven.dev/api/bootstrap/status \
-H "Authorization: Bearer hid_key_<your-key>"
## Expected Response (when complete)
{
"phase": "science_pushed",
"customers": {
"total": 150,
"purged": 0,
"unpurged": 150
},
"batches": {
"total": 5,
"completed": 5
},
"staging": {
"pending": 0,
"purged": 0
},
"readyToPurge": true
}
## Also verify with:
# List all customers
curl -X GET "https://proven.dev/api/bootstrap/customers?limit=50" \
-H "Authorization: Bearer hid_key_<your-key>"
# List all .healthid domains
curl -X GET https://proven.dev/api/healthid/domains \
-H "Authorization: Bearer hid_key_<your-key>"
# Check mailbox for any discovery events
curl -X GET "https://proven.dev/api/healthid/mailbox?issuerHandle=iss_<handle>" \
-H "Authorization: Bearer hid_key_<your-key>"
## Checklist before purging:
- [ ] All customers from oneme show up in /api/bootstrap/customers
- [ ] All customers from Titan show up in /api/bootstrap/customers
- [ ] All FoxScience patient_ids have been minted (check domain count)
- [ ] Handles are linked to correct customer profiles
- [ ] Science data packets are ingested (check encounter counts)
- [ ] FoxScience database has subject_handle column populated
- [ ] FoxScience patient_id column is ready to drop# Step 6: Purge Temporary Identity Data
## What this does:
- Deletes all staging records (raw uploaded data)
- Clears contactName from customer profiles
- Marks all customers as identity-purged
- After this, Proven only holds: org names + handles + de-identified science
## ⚠️ THIS IS IRREVERSIBLE
Make sure Step 5 verification is complete before proceeding.
## Endpoint
POST https://proven.dev/api/bootstrap/purge
## Payload
{
"confirm": true
}
## curl Example
curl -X POST https://proven.dev/api/bootstrap/purge \
-H "Authorization: Bearer hid_key_<your-key>" \
-H "Content-Type: application/json" \
-d '{ "confirm": true }'
## Expected Response
{
"success": true,
"message": "Bootstrap purge complete. Temporary identity data has been removed. Science data and handles are preserved.",
"note": "All customers marked as purged. Contact names cleared."
}
## After purge, also clean FoxScience:
ALTER TABLE foxscience.patient_intake_forms DROP COLUMN patient_id;
## Final state:
- Proven: customer profiles (org name only) + handles + science data
- FoxScience: subject_handles + science data (no patient_ids)
- oneme/Titan: unchanged (they keep their own data)
- No PHI stored anywhere in Proven
## 🎉 Bootstrap complete!
From now on, all new data flows through Proven's normal upload pipeline:
Upload → AI Map → Mint Handles → Strip PII → Emit to FoxScienceCopy the full playbook, paste it into your AI agent, and let it handle the rest. The entire migration takes about 15 minutes.