Files
bsncubed 408fde440d Initial commit: boarding pass to AirTrail pipeline
Photograph/screenshot a boarding pass, decode its BCBP barcode (PDF417/
Aztec/QR/DataMatrix), fetch the historical flight track from FlightAware
the day after the flight, stage it for review, and write it into AirTrail
via its REST API on approval. ntfy notifications carry signed
Approve/Deny/Investigate actions.
2026-07-04 22:21:02 +10:00

43 lines
2.2 KiB
Markdown

# Status: build complete
All 13 tasks are done. This file is now just a pointer, not a live handover -
see `README.md` for setup/deploy instructions and
`/home/ben/.claude/plans/glittery-weaving-moth.md` for the original design
rationale (AirTrail REST API choice, FlightAware two-step scrape, schema).
## What was verified, inside a real Docker build
- Built the image (`docker build .`) and ran it standalone.
- Uploaded a synthetic PDF417 boarding pass photo through `/upload` →
decoded → parsed → correctly staged as `queued` with ICAO codes resolved
(SYD→YSSY, SIN→WSSS, QF→QFA).
- A photo with no barcode correctly landed on `decode_failed` with an error
message, not a crash.
- `/flights/<id>/requery` hit real FlightAware for a real past flight
(QFA1, 2026-06-22) and got back the same 1834-point track verified earlier
in the session — end-to-end scrape confirmed working from inside the
container.
- The review detail page renders the track into a Leaflet map via
`data-track`.
- ntfy notifications fire with correctly signed Approve/Deny URLs; both
wrong and missing tokens are correctly rejected with 403.
- Approve, with no AirTrail configured, failed gracefully and pushed a
distinct "Approve failed" ntfy notification rather than crashing or
silently losing the flight — matches the design in `airtrail_client.py`.
- Reject works and is idempotent.
- The edit form re-resolves ICAO codes and `process_after` when IATA
codes/date are corrected.
## What's NOT verified (no live AirTrail instance available here)
- An actual `POST /api/flight/save` against a real AirTrail instance has
never been exercised. The payload shape matches AirTrail's source
(`build_save_payload` in `airtrail_client.py`), but the
`seat`/`seatNumber`/`seatClass` field semantics are a best-effort mapping,
not confirmed against real AirTrail behavior. **First real approve should
be checked against the AirTrail UI** to confirm the flight, seat, and
track show up as expected.
- HEIC photos from iPhones weren't tested (only a synthetic JPEG barcode was
used here). Should be fine since browsers typically convert to JPEG on
`<input type=file>`, but worth confirming on a real device.