# UAT: FDA Label Paradigm Shift (Epoch Supersession) **Date:** YYYY-MM-DD **Feature:** Epoch-Based Invalidation **Status:** [ ] PASS / [ ] FAIL / [ ] BLOCKED ## Scenario FDA updates the drug label for Semaglutide with significant new safety information. This creates a new "epoch" that supersedes hundreds of pre-existing assertions based on outdated label information. Key validation: The epoch switch must invalidate O(1), not iterate O(N) through all assertions. ## Acceptance Criteria | Criterion | Expected | Met? | |-----------|----------|------| | Old epoch assertions | Exist in storage | [ ] | | New epoch created | Hash returned | [ ] | | EpochAware query | Returns only new epoch | [ ] | | Invalidation performance | O(1) not O(N) | [ ] | | Old data still queryable | With explicit epoch filter | [ ] | ## Test Matrix | Step | Action | Expected | Actual | Status | |------|--------|----------|--------|--------| | 1 | Create 100 old-epoch assertions | 100 hashes returned | | [ ] | | 2 | Create new epoch | Epoch hash returned | | [ ] | | 3 | Create new-epoch assertion | Hash returned | | [ ] | | 4 | Query with EpochAware lens | Only new assertion | | [ ] | | 5 | Query old epoch explicitly | Old assertions returned | | [ ] | | 6 | Measure invalidation time | < 10ms | | [ ] | ## Setup Commands ```bash # Start StemeDB cargo run --bin stemedb-api & sleep 2 ``` ## Test Commands ### Step 1: Ingest Old-Epoch Assertions (Pre-FDA Update) ```bash # Create 100 assertions in the "pre-2024-label" epoch for i in $(seq 1 100); do curl -s -X POST http://localhost:18180/v1/assertions \ -H "Content-Type: application/json" \ -d "{ \"subject\": \"Semaglutide\", \"predicate\": \"has_boxed_warning\", \"object\": {\"Boolean\": false}, \"confidence\": 0.9, \"source_class\": \"Clinical\", \"epoch\": \"0000000000000000000000000000000000000000000000000000000000000001\" }" > /dev/null done echo "Created 100 old-epoch assertions" ``` **Expected:** 100 assertions created **Actual:** **Status:** [ ] ### Step 2: Create New Epoch (FDA Label Update) ```bash curl -X POST http://localhost:18180/v1/epochs \ -H "Content-Type: application/json" \ -d '{ "name": "FDA Label Update 2024", "description": "New boxed warning added for thyroid C-cell tumors", "supersedes": "0000000000000000000000000000000000000000000000000000000000000001", "effective_date": "2024-06-15T00:00:00Z" }' ``` **Expected:** `{"epoch_id": "..."}` **Actual:** **Status:** [ ] ### Step 3: Create New-Epoch Assertion ```bash curl -X POST http://localhost:18180/v1/assertions \ -H "Content-Type: application/json" \ -d '{ "subject": "Semaglutide", "predicate": "has_boxed_warning", "object": {"Boolean": true}, "confidence": 1.0, "source_class": "Regulatory", "epoch": "" }' ``` **Expected:** Hash returned **Actual:** **Status:** [ ] ### Step 4: Query with EpochAware Lens ```bash curl "http://localhost:18180/v1/query?subject=Semaglutide&predicate=has_boxed_warning&lens=epoch-aware" ``` **Expected:** Only the new-epoch assertion (has_boxed_warning = true) **Actual:** **Status:** [ ] ### Step 5: Query Old Epoch Explicitly ```bash curl "http://localhost:18180/v1/query?subject=Semaglutide&predicate=has_boxed_warning&epoch=0000000000000000000000000000000000000000000000000000000000000001" ``` **Expected:** Returns old assertions (has_boxed_warning = false) **Actual:** **Status:** [ ] ### Step 6: Measure Invalidation Performance The epoch creation (Step 2) should complete in O(1) time, regardless of how many assertions exist in the old epoch. ```bash # Time the epoch creation time curl -X POST http://localhost:18180/v1/epochs \ -H "Content-Type: application/json" \ -d '{ "name": "Performance Test Epoch", "supersedes": "0000000000000000000000000000000000000000000000000000000000000001" }' ``` **Expected:** < 10ms (should not scan 100 assertions) **Actual:** **Status:** [ ] ## Sign-Off Checklist - [ ] Old epoch assertions preserved in storage - [ ] New epoch created successfully - [ ] EpochAware lens filters to current epoch - [ ] Time-travel query to old epoch works - [ ] Invalidation is O(1) not O(N) ## Notes *Verify that epoch supersession happens at query time (via lens), not at write time (no mass updates).* --- **Tester:** **Date:** **Result:**