Commit Graph

177 Commits

Author SHA1 Message Date
76cf5c681b fix(sca): pass payment method on reconfirm so 3ds next_action surfaces 2026-05-28 12:15:23 +02:00
e6301e662f fix(sca): re-confirm payment intent on-session to surface 3ds next_action (#19) 2026-05-28 12:05:41 +02:00
8b2889a524 fix(sca): re-fetch payment intent when error response omits next_action (#18) 2026-05-28 11:53:54 +02:00
c2b2b6e834 fix: allow redirect next_action so 3ds challenge url surfaces (#17) 2026-05-28 11:37:55 +02:00
bba5a0dfa0 feat(sca): return 202 + 3ds redirect token when checkout requires auth (#16) 2026-05-28 11:20:16 +02:00
a8e45bc82b feat(sca): map stripe error codes to user-facing copy in tui (#15) 2026-05-28 10:28:47 +02:00
95b9fa91b1 feat(sca): add order status endpoint adn SCA error code mapping (#14)
* feat(sca): add order status endpoint adn SCA error code mapping

adds server-side infra for the upcoming SCA / 3DS challenge flow im
working on. No behavior change to existing checkout paths.

* fix(sca): suppress unused lint on SCA scaffolding helpers
2026-05-27 19:23:29 +02:00
0fe013c399 feat(cart): pass off_session=true on PaymentIntent for SCA exemption eligibility (#13) 2026-05-27 18:09:50 +02:00
d9404ab31e style(tui): update refund page ui (#12) 2026-05-25 23:18:42 +02:00
a21485f91d fix(tui): way to much to write (#11) 2026-05-25 22:34:25 +02:00
bce94b6d10 feat(refund): add refund request flow (#10)
* feat(refund): add refund request flow

- tui modal composer with reason select + free-form message
  (pkg/tui/refund.go)
- POST /api/v1/orders/{id}/refund-request posts to orders slack thread
- 15 min server side cooldown via Order.LastRefundRequestAt (429 +
  retry-after)
- shared refundrequestreasons + can requestrefund hoisted to pkg/models
- slack message includes customer name, email, order total, quoted body
- tests over invalid-state, missing-message, and cooldown paths

* style(tui): run gofmt to fix formatting
2026-05-25 22:04:03 +02:00
dee6172875 refactor(tui): port to charm v2 (#9)
* refactor(tui): port to charm v2

bumped bubbletea, lipgloss, bubbles, wish, and huh to v2. Mostly
mechanical chur, new import paths, vewport getter/setter api, view()
returns tea.view now, huh.theme became an interface so the theme package
needed a small reshape. Render plumbing is gone (no more lipgloss.Render
field on the Model or MakeRenderer in main.go). All pages still work
over ssh. setting up for the refund composer next

* style(tui): gofmt main.go and menu.go
2026-05-25 19:09:16 +02:00
b404303f84 feat(notify): daily slack reminder for paid orders awaiting labels (#8)
so the ain was that older paid orders were getting buried in the #orders
channel in slack and i would just forget about them. Pin/unpin from
earlier helped, but if i missed pinning one or the channel got noisy, it
was still easy to lose track.

this adds a 24h cron that queries any paid order older than 24h with no
label yet and dumps them all into one #orders message. Each line shows
the order id, how old it is, total, where it is going, and a permalink
back to the orders slack thread so i can hop in and hit Buy Label

Ports the idea from terminal.shops cron/unshipped.ts but out stuch state
is different( we auto-promote paid->shipped on label-buy so
PRE_TRANSIT-stuck can not happen), so the query is "paid + no tracking
number + >24h" instead.

NO orders get a "Bring blocked" tag since i dont have the norwegian org
set up yet and can not actually ship those today. Also fires once 40s
after startup so a deploy does not black out the reminder for a full
day.
2026-05-25 16:45:15 +02:00
48d65c48fa feat(tui): render customer-facing event timeline in order detail veiew (#7)
Pulls events off the new order_events table and shows them as a timeline
  block in the order detail view: Paid, Label created, In transit,
  Delivered (etc) with timestamps. Filters out ops-only events like
  payment_critical, label_orphaned, and tracking_marked_manually so the
  customer never sees internal plumbing.

  DisplayLabel on OrderEvent decides what's customer-visible and what's
  redacted, so the same order_events rows can later power an admin view
  with no filter.
2026-05-24 20:14:14 +02:00
c78021f520 docs(comments): add some comments (#6) 2026-05-24 18:57:58 +02:00
c429c1966e docs(comments): add some comments (#5)
this is the subject of the commit
2026-05-24 18:44:25 +02:00
50e1ba32f3 docs(comments): add some comments (#4) 2026-05-24 12:26:34 +02:00
85b0c53c0a docs(comments): cleanup comments (#3) 2026-05-24 12:02:50 +02:00
366d80a9ee test(dillydallying): testing the ci workflow (#2) 2026-05-23 22:12:46 +02:00
60f52f9851 add ci (#1)
* ci(checks): add pull request workflow and golangci-lint config

* refactor(lint): resolve golangci-lint findings

* style(tui): drop traling blank line for gofmt

* fix(cards): handle crypto/rand.Read error in storeRedirect
2026-05-23 21:43:30 +02:00
a4c446ba3c fix(tui): change the stripe abandoned payment polling duration from 2 to 10 mins
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-23 13:15:15 +02:00
491f70e935 fix: add 2-minute timeout to browser payment poll so abandoned stripe checkout sessions stop polling
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-23 12:50:35 +02:00
153e487155 chore: add reconcile-cards script to detach orphan stripe pms from customers
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-23 11:34:27 +02:00
1752ca534f chore(tui): update some typage
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-22 22:18:44 +02:00
b2bd6ed623 fix(cards): advance tui after duplicate card detection by pollin on updated_at instead of count
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-22 22:09:55 +02:00
96400ede14 fix(cards): dedupe saved cards via local-db last4+brand+exp match in checkout.sessions.completed webhook
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-22 21:38:18 +02:00
30cf46370c fix(cards): duplicate card entries after adding card through stripe webhook fixed
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-22 21:21:02 +02:00
31f0698d63 chore(gitignore): update gitignore 2026-05-22 21:19:32 +02:00
910b7f3141 chore(gitignore): update .gitignore with the claude skill to map codebase
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-22 20:05:20 +02:00
19e493a3d5 feat(bring): send X-Bring-Client-URL header on booking reqs, defaulting to https://sshops.uk and overridable via BRING_CLIENT_URL env var 2026-05-22 20:02:43 +02:00
2e6dda190f feat(audit): persist every order-scoped audit.X(...) call to a new order_events table alongside the existing slog line, builds the foundation for an admin order timeline view without changing the slog primary path 2026-05-22 20:01:29 +02:00
96e76f7e5b feat(slack): add slack mark status buttons for bring orders, post-label thread now block kit, synthesize shippo webhook over loopback to reuse state-date guard and delivered transition
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-20 18:09:34 +02:00
9d3ac9761d feat(tui): add tracking redirect endpoint, render the short uril in the tui order detail instead of the old broken stuff ive been trying. this change is made by claude code and has not been reviewed carefully, this might break
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-20 15:26:38 +02:00
e49fa01ca9 feat(tui): use BEL terminator for tracking url osc 8 link - hopefully this works
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-20 15:12:56 +02:00
d9e9895913 revert(tui): render raw tracking url, last change wouldnt render the url for some reason
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-20 15:07:14 +02:00
f73e1d18da feat(tui): make tracking url clickable osc 8 hyperlink
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-20 14:55:32 +02:00
29f57000a7 feat(notify): pin paid order messages in the #orders channel in slack, unpin on label purchase
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-20 14:01:28 +02:00
1aaf82d7d6 feat(tui): poll orders every 10 seconds so that the order status refreshes live in the tui without logging out and in
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-19 20:12:03 +02:00
9515603b32 feat(tui): split account orders into active and history tabls
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-19 19:50:21 +02:00
bfd183bfbf fix(ci): remove go module cache step since its redundant
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-15 15:34:21 +02:00
e43040f702 feat(notify): post order vents into per-order slack threads - made by claude
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-15 12:25:45 +02:00
2966474ff5 feat(notify): render slack order notification as block kit receipt with line items
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-15 12:11:16 +02:00
0e4d267adb fix(orders): write NULL instead of empty string for unpopulated shipp_transaction_id
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-15 11:27:00 +02:00
c1b3ccf302 feat(notify): add buy label button via slack
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-15 10:57:23 +02:00
f6eed76456 feat(notify): post Slack message when an order is paid
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-15 08:54:23 +02:00
e5ec247a6b feat(orders): customer-facking tracking labels and webhook response body
Some checks failed
Deploy / deploy (push) Has been cancelled
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
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-14 13:47:20 +02:00
ee6e14a424 feat(shipping): shippo webhook fro tracking status updates
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-14 13:30:37 +02:00
387758aa13 feat(shipping): add Bring booking client and country dispatch for label purchase
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-13 22:14:32 +02:00
ff9615b75a fix(shippo): fix rate-filter
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-13 08:58:09 +02:00