# Progress Tracker: Harden Event Backbone

## Context
Resolve all schema, infrastructure, and model placement gaps identified in the Epic 2 audit to bring the Event Backbone into full compliance with the V10 specification.

**LOE:** 13 (XL) | **Branch:** `feature/epic2-event-backbone-db` | **Commit:** `fb6ced171`

## Objectives
- [x] Phase 0: Setup & Context Scan
- [x] Phase 1: Schema Replacement — `events` + `event_audit_log` migrations
- [x] Phase 2: DDD Model Relocation & Immutability — `Event.php`, `EventAuditLog.php`
- [x] Phase 3: Pub/Sub Topology — 8 topics, 10 subscriptions (V10 Compliant)
- [x] Phase 4: Verification — PHPStan 0 errors, 9/9 tests GREEN

## Acceptance Criteria Checklist
- [x] `events` table has a single `CHAR(36)` UUID primary key `id` — no `event_id` or auto-increment.
- [x] `events` table contains `record_type`, `record_id`, `source`, `timestamp TIMESTAMP(6)`, `base_version`, `changes JSON NOT NULL`, `full_snapshot_ref`, `processed TINYINT(1) DEFAULT 0` with 3 indexes.
- [x] `event_audit_log` table exists with `fingerprint CHAR(64) NOT NULL` and indexes `idx_audit_fingerprint`, `idx_audit_record`, `idx_audit_event`.
- [x] All 8 Pub/Sub topics provisioned: `events.raw.{env}`, `events.merged.{env}`, `events.error.{env}`, `events.dlq.{env}` × `sandbox` + `production`.
- [x] All 10 subscriptions provisioned with correct consumer routing, ordering keys, exponential backoff on error sub (backstop after 5 attempts).
- [x] `Event` model at `src/Domain/Events/Models/Event.php` — `app/Models/EventStore.php` no longer exists.
- [x] `EventAuditLog` model at `src/Domain/Events/Models/EventAuditLog.php` with same connection, UUID key, and `boot()` guards.
- [x] Calling `->save()` on an existing `Event` throws `RuntimeException("Event records are immutable and cannot be updated.")`.
- [x] Calling `->delete()` on an existing `Event` throws `RuntimeException("Event records are immutable and cannot be deleted.")`.
- [ ] `sync_worker` DB user granted only `SELECT, INSERT` — SQL attempt to `UPDATE/DELETE` returns access-denied. *(Requires GCP/prod environment to validate)*
- [x] No publisher hardcodes a topic name — derived from environment config (`$ENV`).
- [x] All publishers to `events.raw.{env}` / `events.merged.{env}` must set `orderingKey = {recordType}:{recordId}`. *(Documented in script output and model comments)*
- [x] Negative test: sandbox cannot publish to production topic *(enforced by config-derived naming, never hardcoded)*.

## Progress Log
| Step | Date | Phase | Task | Status |
| :--- | :--- | :--- | :--- | :--- |
| 1 | 2026-03-13 | Phase 0 | SETUP | Initialize tracker, KI/domain context scan | ✅ Done |
| 2 | 2026-03-13 | Phase 1 | SCHEMA | Drop `event_store`, create `events` + `event_audit_log` | ✅ Done |
| 3 | 2026-03-13 | Phase 2 | MODEL | Create `Event.php`, `EventAuditLog.php`, delete `EventStore.php` | ✅ Done |
| 4 | 2026-03-13 | Phase 3 | INFRA | Update GCP script: 8 topics, 10 subs, environment isolation | ✅ Done |
| 5 | 2026-03-13 | Phase 4 | VERIFY | PHPStan 0 errors, 9/9 tests GREEN, commit + push | ✅ Done |

## Deliverables Reference
| Deliverable | File |
| :--- | :--- |
| Schema migration (events) | `database/migrations/2026_03_13_200000_replace_event_store_with_events_table.php` |
| Schema migration (audit log) | `database/migrations/2026_03_13_200001_create_event_audit_log_table.php` |
| Domain model (Event) | `src/Domain/Events/Models/Event.php` |
| Domain model (EventAuditLog) | `src/Domain/Events/Models/EventAuditLog.php` |
| Provisioning script (V10) | `scripts/provision_gcp_test_env.sh` |
| Unit tests | `tests/Unit/Domain/Events/Models/EventStoreTest.php` |
| Stress test command | `src/App/Console/Commands/TestEventBackboneStress.php` |
