Commit Graph

133 Commits

Author SHA1 Message Date
f6eed76456 feat(notify): post Slack message when an order is paid 2026-05-15 08:54:23 +02:00
e5ec247a6b feat(orders): customer-facking tracking labels and webhook response body
the big colored status on the order detail page used to just say
"Shipped" the moment i bought the label, which didnt really feel right
since the carrier hadnt actually picked anything up yet. now it walks
through "Label created" -> "In transit" -> "Delivered" as real scans
come in, and keeps the "Delivery Issue" / "Returned to sender" labels
for unhappy paths

also wired up the existing tracking_status_details column to the tui. i
skipped it before but the response actually includes a description of
the delivery, that is now subtext under the colored statu.

and the shippo webhook now returns a small json body instead of an empty
200. this is just for the operator that runs the curls commands to
     update the shipment, which makes debugging a lot less guesswork
2026-05-14 21:17:50 +02:00
e29dd6b30d fix(middleware): redact query strings from access logs 2026-05-14 13:47:20 +02:00
ee6e14a424 feat(shipping): shippo webhook fro tracking status updates 2026-05-14 13:30:37 +02:00
387758aa13 feat(shipping): add Bring booking client and country dispatch for label purchase 2026-05-13 22:14:32 +02:00
ff9615b75a fix(shippo): fix rate-filter 2026-05-13 08:58:09 +02:00
a2afc47f32 refactor(shipping): check ALREADY_LABELED before INVALID_STATE in PurchaseLabel 2026-05-12 21:47:06 +02:00
37ad51949b fix(shipping): require sender email on shippo address_from
Shippo's transaction validation rejects labels where the from-address
has no email — fails at the poll step with
"Attribute address_from.email must not be empty."

Add Email to Address, plumb it into addrPayload, and read
SHIP_FROM_EMAIL alongside the other SHIP_FROM_* env vars.
2026-05-12 21:17:32 +02:00
99f34788ea fix(shipping): round weights before posting to shippo
Shippo's /v1/orders endpoint rejects >2 decimal places on parcel
weight and >4 on line_items[].weight. Converting ounces to kg
(oz * 0.0283495) routinely produces 6-decimal values, so the first
real label purchase 400'd with "Ensure that there are no more than
N decimal places".

Round at the payload boundary in createShippoOrder rather than in
the caller — keeps the precision of the source (Coffee.Ounces) and
only loses it when the wire format demands it.
2026-05-12 21:12:31 +02:00
c22b64d6fa feat(shipping): shippo label purchase endpoint
Adds POST /api/v1/orders/{id}/label (admin-only) that buys a shipping
  label through Shippo and writes carrier + tracking + label fields back
  onto the order, transitioning paid -> shipped.
2026-05-12 20:57:11 +02:00
a71f72ad71 chore: update typing 2026-05-10 21:08:57 +02:00
700ad4926b feat(models): derive order state from status + tracking 2026-05-09 16:50:33 +02:00
c5f4e492c0 refactor(orders): embed tracking on orders, drop shipments table
realized per-shipment table is kinda bad, switched to single embedded tracking blob. since im only
shipping from my house  no split is needed. adds tracking_status, tracking_status_details,
tracking_status_updated_at columns. reverse-backfills any historical shipments rows back onto orders
(idempotent, table-guarded). UpdateTracking rewritten to write to otder columns direcly
2026-05-09 10:08:32 +02:00
f88fe1d8d3 fix: preload shipments on view init endpoint 2026-05-08 15:15:53 +02:00
c6ff75f2a5 chore. ignore local DB backups and prod backups 2026-05-08 14:59:47 +02:00
add6e573b3 feat: extract shipments to dedicated table 2026-05-08 14:54:17 +02:00
9b45fb5138 updating 2026-05-08 13:43:03 +02:00
1849e324fc feat: add admin tracking updates 2026-05-08 10:47:57 +02:00
c90dadf9ad test was failing after some AI change. this should fix it 2026-05-06 13:53:38 +02:00
38cdda3d54 cleanup 2026-05-06 13:41:23 +02:00
c037a6e9f9 removing unused param 2026-05-05 22:05:29 +02:00
ffb476ec2d updating variable to camelcase 2026-05-05 22:04:24 +02:00
177b080117 some change 2026-05-05 21:04:02 +02:00
9bf57b4048 perf(loadtest): retune overnight scenarios under rate limits
Document and respect per-IP rate limits (200/min global, 20/min auth,
60/min webhooks) by holding scenarios well below the ceilings so the
histogram captures real handler latency instead of 429s. Total combined
~148 req/min over ~10h. Adds summaryTrendStats so reports include
p95/p99/max alongside avg.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 09:51:27 +02:00
c96f922c70 refactor(tui): rebuild header with lipgloss/table
Replaces the manual string-concat + separator layout with a
lipgloss/table row, mirroring the reference TUI structure. Drops the
parallel bold-vs-gray styling for a single-weight accent/base scheme,
extracts a small tab() closure to remove the duplicated active/inactive
branches, and uses m.renderer.NewStyle() for the border so per-session
color profiles render correctly under SSH.

Cart label still tracks inCartFlow() (covers shipping/payment/review/
confirm), which the reference doesn't need since it has no multi-step
checkout.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 09:51:21 +02:00
4e28b812bd chore: gitignore runtime artifacts, drop orphan 00 and AI roadmap
Add loadtest/run.pid and loadtest/run.err to .gitignore so k6 runtime
state stops tagging along on git add. Also ignore the orphan /00 file
(stray redirect of pkg/observability/tracing.go) and ROADMAP.md (AI-
synthesised audit doc, not part of the project canon).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 09:51:14 +02:00
7b92636b64 add video 2026-05-02 18:16:21 +02:00
17df27ae20 some updates 2026-05-02 17:48:07 +02:00
52d58583e9 db telemetry 2026-05-02 16:29:07 +02:00
327bb9c867 cleanup 2026-05-02 11:28:28 +02:00
9a5fff81bf fix: defer component logger creation past package init
Package-level slog.With() vars are evaluated at init time, before
observability.InitLogger() runs in main. They captured the original default
slog handler and bypassed the countingHandler that increments
log_messages_total — so warn/error calls from these packages weren't being
counted.

Convert to functions so each call resolves slog.Default() at use time and
inherits the active counting handler.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 22:26:03 +02:00
1c10cf4390 feat: structured logging with component tags + severity levels
Convert log.Printf calls in webhook, reconcile, addresses, and auth handlers
to slog with a consistent `component` attribute. Severity now reflects
operational urgency:

- warn: signature failures, declined cards, unknown fingerprints, vendor
  validation rejections, reconciler patching a missed charge
- error: DB write failures, malformed Stripe payloads, token generation
  failures
- info: successful order/card events, normal reconciler ticks

Lets Loki/Prometheus filter by component (e.g. {component="webhook"}) and
gives the log-level dashboard panel real warn/error series instead of a
flat info line.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 22:14:06 +02:00
ae7eaa8e97 feat: route audit + recovery through slog levels
Audit events now emit at Info/Warn/Error so the log-level counter has variety
instead of being pinned to info. Panic recovery uses structured slog.Error
with method/path/stack attrs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 13:55:54 +02:00
8ca209a4cc feat: add cart/auth/stripe metrics and slog-based log-level counter
Adds Prometheus instrumentation across the checkout funnel, auth flow,
Stripe calls, rate limiters, and HTTP middleware (inflight gauge, request
and response sizes). Introduces a slog handler that counts log lines by
level so the dashboard can show error/warn rates; existing log.Printf
calls are routed through slog and counted as info.

Backs the new "terminalshop — Service Overview" Grafana dashboard.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 13:38:24 +02:00
9e9a8325a8 feat: track created orders metric 2026-04-30 14:37:46 +02:00
179c8011ca added logger 2026-04-30 12:07:21 +02:00
9d4549a32d feat: add OpenTelemetry tracing 2026-04-30 11:35:10 +02:00
31b8e82e47 fix: widen histogram buckets to resolve sub-5ms latency
Default prometheus.DefBuckets bottoms out at 5ms, which made every
route's p95 collapse to 4.75ms (histogram_quantile interpolation
within the smallest bucket). Custom buckets from 100µs to 5s now
distinguish microsecond-fast routes (health) from slower ones
(stripe-backed cart endpoints).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 08:44:56 +02:00
67c8a6bafb feature: expose /metrics with prometheus client_golang
Adds Counter (http_requests_total) and Histogram
(http_request_duration_seconds) labeled by method, chi route pattern,
and status. Wired through a new Metrics middleware (after Recovery so
panics-turned-500s are still counted) and an unauthenticated /metrics
endpoint at the root for Prometheus to scrape.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 20:40:39 +02:00
67f01f4a38 feature: accpet HEAD on /health and /ping for monitoring probes 2026-04-29 15:49:26 +02:00
f47c10ed8a refactor: structured error handling + CreateBox/formatListItem in checkout
Replace ErrorMsg string with typed VisibleError struct. Add catch-all
error handler at top of Update() that auto-recovers cart on shop/cart
errors. ESC now dismisses error banners. Refactor shipping address and
payment card checkout lists to use CreateBox + formatListItem for
consistent bordered cards with radio indicators.

Written with Claude Code (claude.ai/code)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 20:52:52 +02:00
b35103657d refactor: add formatListItem helper and apply address/card lists 2026-04-27 20:13:25 +02:00
42abf11d04 refactor: extract reusable CreateBox component for bordered card styling
replacing duplicated border/selection logic in
  account_orders.go and cart.go. Also fixes a latent SSH rendering bug
  in cart.go where lipgloss.NewStyle() was used instead of theme.Base().
2026-04-27 15:04:00 +02:00
96c9be61ff updating the about section 2026-04-27 10:54:58 +02:00
80166ae8d0 lets try this instead 2026-04-27 10:48:30 +02:00
6bcf651afd fix: my last change was very wrong, i think i made it in my sleep. this should do the trick though 2026-04-27 10:40:41 +02:00
cbb3e59878 update: update the not-selected address items in th address list 2026-04-27 08:15:10 +02:00
00dd63668b fix: fix address not appending to address list in account page after adding it 2026-04-26 13:16:14 +02:00
bd93989036 fix: all keybinds becoming unreactive after completing an order 2026-04-26 12:50:51 +02:00
4083495704 fix: fixed payment not going through if no address and card were saved 2026-04-26 12:21:16 +02:00