● Zion Boggan
repos/Drophawk/PHASE1_STATUS.md
zionboggan.com ↗
41 lines · markdown
History for this file →
1
# DropHawk - Phase 1 build status
2
 
3
**Built:** 2026-06-22 · **Scope:** Phase 1 vertical slice (Ticketmaster → ntfy → dashboard), per `CLAUDE.md` / `SPEC.md` §14 / `CONTRACTS.md`.
4
**Source of truth:** this repo, `/shared/projects/drophawk` (RAG-indexed + PBS-backed). Original GLM seed lives at CT247 `/root/drophawk`.
5
 
6
## What's implemented
7
 
8
| Layer | State | Notes |
9
|---|---|---|
10
| **Backend** (Rust/Axum/sqlx) | ✅ code complete | Ticketmaster-only adapter. 12 migrations (DDL verbatim from §G). Every §B.3 endpoint + §B.1 envelope. SSE `/api/drops/stream` with `Last-Event-ID` replay + 15s heartbeat. §D `content_hash` with golden-vector test (`tests/hash_golden.rs`). §E classification. §I ntfy publisher + watchlist/dedupe/quiet-hours filter. §C adaptive poller + circuit breaker. `#![forbid(unsafe_code)]`. |
11
| **Frontend** (Next.js 16 / Tailwind v4 / Framer Motion) | ✅ code complete | Honors binding OKLCH/teal tokens (§H). Live SSE feed, spring drop cards + teal flash, count-up KPIs, ⌘K palette, collapsible sidebar, watchlist CRUD, source health grid, settings + test push. WCAG 2.2 AA intent. |
12
| **Infra** (compose/Caddy/ntfy/observability) | ✅ code complete | `docker-compose.yml` (+ prod overrides), `Makefile` (12 targets), SSE-safe Caddy, Prometheus/Grafana/Loki, backup + healthcheck scripts. |
13
| Python scrapers (FIFA/AXS/…) | ⛔ Phase 3 | Not in Phase 1 scope. |
14
| Meilisearch / explore / heatmap | ⛔ Phase 2 | `Explore` nav item shows "soon". |
15
 
16
## Cross-stack alignment (verified statically)
17
- Backend binds `0.0.0.0:8080`; Caddy proxies `/api/*` → `backend:8080` with `flush_interval -1`; frontend dev rewrites `/api` → `backend:8080`.
18
- SSE path `/api/drops/stream` + event names (`drop.new|status|price|inventory|announcement`, `source.health`) match the frontend client.
19
- Response envelope (`data`/`meta`/`error.{code,message,request_id}`) matches the frontend `ApiError` parser.
20
 
21
## Not yet done (requires a real host + operator input)
22
Builds were **not** run here - `/shared/projects` is noexec CIFS with no Rust/Node toolchain. Code is compile-intentional. To bring it up:
23
 
24
1. **On a Docker host** (e.g. CT120): `cp -r /shared/projects/drophawk /opt/drophawk && cd /opt/drophawk`.
25
2. `cp .env.example .env` and fill in:
26
   - `TICKETMASTER_API_KEY` - free at developer.ticketmaster.com (operator action).
27
   - ntfy topic/token (default topic `drophawk-drops`).
28
   - Postgres/Redis/NATS creds (any strong values).
29
3. `make up` → `make migrate` → open the dashboard via Caddy (`http://<host>/`).
30
4. On your phone: install **ntfy**, subscribe to the `drophawk-drops` topic.
31
5. Add **"Taylor Swift"** in Watchlist → when a TM event flips on-sale you get a push + it streams into the live feed. That's the Phase 1 success criterion (CLAUDE.md).
32
 
33
## Key decisions / deviations (full list in commit + agent reports)
34
- Backend added 4 deps the contracts require but §A.1 omitted: `regex` (watchlist validation, §B.3), `rand` (jitter, §C), `tokio-stream` (SSE bridge). Flagged, behavior-only.
35
- Migration `set_updated_at` fn reordered before `sources` (sqlx runs in filename order); DDL bytes unchanged.
36
- Error envelope follows §B.1 (includes `request_id`) where it conflicted with §K.
37
- SSE heartbeat uses Axum `KeepAlive` (`: heartbeat`) at 15s; the live-epoch suffix is omitted (Axum limitation).
38
- Infra uses `timescale/timescaledb-ha:pg16` instead of building Timescale into `postgres:16.10` - cleanest path; swap to a custom Postgres Dockerfile if exact base is required.
39
- Frontend uses a styled native `<select>` for the watchlist form (full a11y) rather than Radix Select; reserved Radix Select for richer menus.
40
 
41
## Do NOT start Phase 2 until the operator verifies Phase 1 end-to-end (CLAUDE.md hard rule #1).