<!-- SOLIDIVISM · part 27 -->
ation role: can INSERT and SELECT, nothing else
CREATE ROLE solidivism_app WITH LOGIN PASSWORD '<from vault>';
GRANT CONNECT ON DATABASE epistles TO solidivism_app;
GRANT USAGE ON SCHEMA public TO solidivism_app;
GRANT SELECT, INSERT ON solidivism_events TO solidivism_app;
GRANT SELECT, INSERT ON solidivism_entities TO solidivism_app;
GRANT SELECT, INSERT ON solidivism_edges TO solidivism_app;
-- Explicitly: NO UPDATE, NO DELETE, NO TRUNCATE, NO ALTER

-- Admin role (for schema changes only, not application use)
-- Application NEVER uses this role at runtime
```

### Correction Pattern

```sql
-- Original event (immutable)
INSERT INTO solidivism_events (idempotency_key, actor_id, action, ...)
VALUES ('evt-001', 'solid', 'building.create', ...);
-- Returns event_id: aaa-...

-- Correction (new row, not UPDATE)
INSERT INTO solidivism_events (idempotency_key, actor_id, action, corrects_event_id, ...)
VALUES ('evt-002', 'solid', 'building.create', 'aaa-...');
-- Both rows exist. Queries for "current truth" follow the correction chain.
```

### Checksum Verification

```javascript
// On read: verify checksum
function verifyEvent(event) {
  const computed = sha256(
    event.event_id + event.event_time + event.actor_id +
    event.action + event.target_id + JSON.stringify(event.inquiry)
  );
  if (computed !== event.checksum) {
    // Corruption detected
    Ledger.reportCorruption(event.event_id, computed, event.checksum);
    return null;  // Do not trust corrupted record
  }
  return event;
}
```

---

## SAFEGUARD 3: READ-ONLY OBSERVATION INTERFACE

### The Boundary

```
┌─────────────────────────────────────────────────┐
│  3D WORLD (foundation.js Solidivism module)     │
│                                                 │
│  Exposes: Solidivism.observe(type, data)        │
│  Receives: NOTHING from Epistemology            │
│  Depends on: NOTHING from Epistemology          │
└──────────────────────┬──────────────────────────┘
                       │ one-way: events flow out
                       │ zero-way: no calls flow in
┌──────────────────────▼──────────────────────────┐
│  EPISTEMOLOGY (separate closure)                │
│                                                 │
│  Subscribes to: observe() events                │
│  Calls into 3D: NEVER                           │
│  Modifies 3D: NEVER                             │
└─────────────────────────────────────────────────┘
```

### Interface Definition

```javascript
// In Solidivism module (3D side) — minimal addition
function observe(eventType, data) {
  // Fire-and-forget. No return value used. No exceptions propagated.
  try {
    if (typeof Epistemology !== 'undefined' && Epistemology.handleObservation) {
      Epistemology.handleObservation(eventType, data);
    }
  } catch (e) {
    // Observation failure must NEVER break 3D
    // Silent catch: 3D continues, observation is lost (acceptable)
    // Could log to console in debug mode
  }
}

// Usage in 3D code (3 call sites in Phase 1):
// In addBuilding():  observe('building.create', { label, position, dimensions })
// In checkCollision(): observe('collision.detect', { position }) // throttled
// In init(): observe('session.start', { timestamp, userAgent })
```

### Rules

1. **3D never imports Epistemology.** The `typeof` guard ensures 3D works if Epistemology is absent.
2. **Epistemology never calls 3D methods.** It only receives observation events.
3. **Observation is fire-and-forget.** 3D does not wait for Epistemology. No promises, no callbacks.
4. **Observation failure is silent.** A broken Epistemology must not break the game.
5. **No shared mutable state.** Observation data is deep-copied at the boundary.

### What This Prevents

- Epistemology bugs cannot crash the 3D world
- Removing Epistemology requires only deleting the `observe()` calls (3 lines)
- 3D performance is unaffected (observe is a guarded function call)
- Testing 3D does not require Epistemology to be present

---

## SAFEGUARD 4: ROLLBACK vs EVIDENCE SEPARATION

### The Distinction

**Application Rollback:** Restoring previous code. Affects what RUNS.

**Evidence Preservation:** Maintaining the historical record. Affects what is KNOWN.

These are independent. Rolling back code must not erase the record that the code existed, was deployed, failed, and was rolled back.

### Rollback Procedure (Revised)

```
Step 1: Record rollback intent
  → INSERT INTO solidivism_events (action: 'rollback.initiated', target: 'foundation.js:v15')
  → Reason, who authorized, what version restoring to

Step 2: Restore previous code
  → cp foundation.js.pre-epistemology-20261008 foundation.js
  → This is a FILE operation. Does NOT touch the database.

Step 3: Record rollback completion
  → INSERT INTO solidivism_events (action: 'rollback.completed', target: 'foundation.js:v14')
  → Verification: 3D loads, screenshot comparison

Step 4: Deploy new version (if applicable)
  → INSERT INTO solidivism_events (