ben.stull
13e74f4c61
feat(products): image-phase repo helpers + run progress/outcomes/counts (SD-0002 §6.5.4)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-12 00:23:09 -07:00
ben.stull
984dc98dee
feat(products): diff resolves hosted image URLs to existing records — INV-12 over images (SD-0002 §6.3)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-12 00:19:23 -07:00
ben.stull
906bc87c96
feat(products): export hosted detail URL for fetched images; snapshot carries status (SD-0002 §6.5.5, INV-16)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-12 00:15:47 -07:00
ben.stull
da5177c950
feat(products): hosted-image URL build/parse helpers (SD-0002 §6.3.1)
...
DB-free host-agnostic helpers: image_url() builds the canonical hosted
Image Src for a fetched image; parse_image_id() recognizes one on re-import
via path-parse so exports round-trip across localhost/PPE/rebrand (INV-12).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-12 00:13:27 -07:00
ben.stull
0fc29a34dd
feat(platform): objectstore port — local + GCS adapters, config (SD-0002 §6.2)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-12 00:12:24 -07:00
ben.stull
f27a24353d
feat(platform): images port — decode, resolution bar (Q-3), WebP renditions (SD-0002 §6.2)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-12 00:09:58 -07:00
ben.stull
385df8d728
Merge pull request 'SLICE-6: export & the round-trip lock — canonical serializer + streamed export (SD-0002 §7.2)' ( #29 ) from worktree-slice-6-export-roundtrip into main
ci / check (push) Has been cancelled
v0.6.0
release/2026-06-11T22-23
2026-06-12 05:23:23 +00:00
ben.stull
af72299a57
fix(products): serialize Variant Position explicitly — INV-12 round-trip bug
...
ci / check (push) Has been cancelled
ci / check (pull_request) Has been cancelled
A stored variant position is a CatalogVariant attribute, not a fields{} entry,
so the serializer emitted an empty Variant Position cell — which re-imports as
'reset to file order'. A non-sequential stored position (a merchant can import
explicit positions) then round-tripped to a spurious update, violating INV-12.
Emit str(variant.position) explicitly (like _write_image). The property-test
generator now assigns non-sequential positions to lock the regression, plus a
targeted test. Also wires isExportEnabled into ProductsPage (was dead code).
Both caught by the final code review.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 22:22:11 -07:00
ben.stull
6f22c8b146
chore: version 0.6.0 — SLICE-6 export & round-trip
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 22:14:30 -07:00
ben.stull
767011fbae
docs(products): DOC-1 export ops + TEL-3, DOC-4 serializer/round-trip (SLICE-6)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 22:14:30 -07:00
ben.stull
8077f2e07b
test(e2e): e2e_export_download + e2e_roundtrip_noop (SD-0002 §6.8, PUC-9/10)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 22:12:53 -07:00
ben.stull
0a85c4fef8
feat(frontend): Export status-filter menu on the Products page (SD-0002 §5.2, PUC-9)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 22:08:34 -07:00
ben.stull
6f213e1f02
feat(frontend): export URL helper + status-filter list (PUC-9)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 22:07:36 -07:00
ben.stull
155f9bd147
feat(api): GET /api/products/export — streamed canonical CSV, 409 empty_catalog (§6.4, PUC-9)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 22:05:55 -07:00
ben.stull
1c2a6af986
feat(products): streamed export service + TEL-3 + EmptyCatalog (PUC-9, §9.1)
2026-06-11 22:03:09 -07:00
ben.stull
5a97b9dc59
feat(products): status-filtered export_catalog snapshot query (PUC-9)
2026-06-11 22:01:11 -07:00
ben.stull
fce0b5eaed
test(products): decimal/int variant fields round-trip clean (INV-12 coverage)
2026-06-11 21:59:06 -07:00
ben.stull
b40e4d30b5
test(products): INV-12 property test — export round-trips to a no-op (SD-0002 §6.8)
2026-06-11 21:58:47 -07:00
ben.stull
7652e92cbe
feat(products): serialize multi-variant + interleaved images (§6.5.1 row grammar)
2026-06-11 21:58:22 -07:00
ben.stull
627e257d4c
feat(products): canonical serializer skeleton — header + single product row (SD-0002 §6.5.5)
2026-06-11 21:57:48 -07:00
ben.stull
011f4d5dc1
Merge pull request 'SLICE-5: products import spine — canonical CSV → preview → confirm (SD-0002 §7.2)' ( #26 ) from worktree-slice-5-import-spine into main
ci / check (push) Has been cancelled
v0.5.0
release/2026-06-11T20-50
2026-06-12 03:50:20 +00:00
ben.stull
2606fbf826
docs(products): operator guide (DOC-1) + domain notes (DOC-4); version 0.5.0
...
ci / check (push) Has been cancelled
ci / check (pull_request) Has been cancelled
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 17:00:13 -07:00
ben.stull
ad738adbc0
test(e2e): SLICE-5 scenarios — preview/confirm, errors, rejection, cancel (§6.8)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:53:59 -07:00
ben.stull
a58f42cf86
test(e2e): stand up Playwright — fresh-DB server harness + sign-up helper
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:50:59 -07:00
ben.stull
d18a84e135
fix(products-ui): review pass — show-more race, keyboard history access, a11y glyphs/aria-live, label consistency
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:46:43 -07:00
ben.stull
87a56a66c4
feat(products-ui): import run detail (§5.5, PUC-4/5/8)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:35:49 -07:00
ben.stull
4141285b89
feat(products-ui): import preview — tiles, drill-in diffs, confirm/cancel (§5.4)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:34:33 -07:00
ben.stull
188494272a
feat(products-ui): import upload screen (§5.3, PUC-2/5a)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:30:51 -07:00
ben.stull
26f84cb916
feat(products-ui): admin nav + Products page with import history (§5.2)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:29:20 -07:00
ben.stull
b5dac8886f
feat(products-ui): typed products API client + admin hash routing
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:25:37 -07:00
ben.stull
4dacc2dafd
feat(products): /api/products/* BFF endpoints + sample.csv (DOC-3)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:18:34 -07:00
ben.stull
a8538d3ecc
fix(products): cleared Variant Position resolves to file order, not NULL
...
A blank Variant Position cell previewed position->null and aborted the
confirm transaction (variant.position is NOT NULL). Resolve the clear to
the variant's file order at diff time so preview and apply stay in
lockstep; carry file_order on VariantPlan instead of an identity-keyed
map; release the read snapshot before PreviewStale/NothingToApply.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:14:14 -07:00
ben.stull
0c7865e9e1
feat(products): confirm/apply in one transaction, runs, summary — INV-10/11/14 + TEL-2/6
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 16:02:27 -07:00
ben.stull
fcbf1393f5
feat(products): import_validate → draft, preview records, discard + TEL-1
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 15:51:03 -07:00
ben.stull
138126ab17
feat(products): repo — catalog snapshot, draft/run SQL, upsert primitives
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 15:42:42 -07:00
ben.stull
667a462e0b
fix(products): honest position compare for matched variants in diff
...
A Variant Position column previously produced a spurious update with a
false before:None (CatalogVariant keeps position as an attribute, not in
fields{}). Compare against the attribute, like images already do.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 15:37:59 -07:00
ben.stull
9bc6e4dbd2
feat(products): diff engine — add/update/unchanged/error + INV-11 fingerprint
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 15:28:03 -07:00
ben.stull
19ee695c20
feat(products): row validation — §6.5.1 rules + INV-15 sanitization
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 15:17:01 -07:00
ben.stull
f64c3fddf9
feat(products): CSV codec — file-level parse + INV-18 caps (PUC-5a)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 14:58:53 -07:00
ben.stull
c39bbd4728
feat(products): domain skeleton — errors, column registry, canonical row model
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 14:55:37 -07:00
ben.stull
0ee948b34d
feat(products): SD-0002 §6.3 schema — migration 0002 + nh3/multipart deps (SLICE-5)
...
Also updates test_migrate_from_empty_applies_0001 → test_migrate_from_empty_applies_all
to assert both migrations apply on a fresh DB (mechanical consequence of adding 0002).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 14:52:18 -07:00
ben.stull
1267d4f29d
docs: SLICE-5 implementation plan (SD-0002 §7.2 import spine)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 14:48:47 -07:00
ben.stull
6b405a0f2d
Merge pull request 'fix(signin): key the resend cooldown to the address it was set for ( #20 )' ( #22 ) from fix-20-signin-cooldown-keying into main
ci / check (push) Has been cancelled
2026-06-11 08:22:08 +00:00
ben.stull
118e925580
fix(signin): key the resend cooldown to the address it was set for ( #20 )
...
ci / check (push) Has been cancelled
ci / check (pull_request) Has been cancelled
The email-step Send button disabled on any running cooldown, so a merchant
who mistyped their address was locked out of sending to the corrected one
for the rest of the 60s window — a guard the server never had: request_code
enforces the cooldown per address (SD-0001 INV-3 -> PUC-2c).
Track which address the running cooldown belongs to (cooldownFor) and gate
the email-step button through cooldownAppliesTo(), which blocks only while
the countdown runs AND the input normalizes (strip+lowercase, mirroring
normalize_email / INV-2) to that address. Same address still shows the
honest 'Resend in Ns'; any other address sends immediately. The code-step
resend is unchanged. Verified in the live UI (wrong address -> Wrong
address? -> corrected address sends at once).
package-lock.json: sync recorded version with package.json (0.4.0).
Closes #20
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 01:21:23 -07:00
ben.stull
11acb3a5b1
Merge pull request 'docs: land session 0023 plan doc (stray untracked file)' ( #18 ) from docs-archive-0023-plan into main
ci / check (push) Has been cancelled
2026-06-11 07:56:34 +00:00
ben.stull
efc9c8edb9
docs: land session 0023's ui-designs-collection plan in-repo (was untracked; content archive already had it)
...
ci / check (pull_request) Has been cancelled
ci / check (push) Has been cancelled
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 00:56:31 -07:00
ben.stull
f7b76d5370
Merge pull request 'SLICE-4: record the first PPE bootstrap rehearsal (PUC-11) — green' ( #17 ) from slice-4-rehearsal-record into main
ci / check (push) Has been cancelled
2026-06-11 07:54:50 +00:00
ben.stull
4bb9763633
docs(slice-4): record the first PPE bootstrap rehearsal (PUC-11, 2026-06-11) — green
...
ci / check (pull_request) Has been cancelled
ci / check (push) Has been cancelled
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-11 00:54:47 -07:00
ben.stull
a456d51f17
Merge pull request 'SLICE-4: deployment.toml — the ecomm PPE record' ( #11 ) from slice-4-deployment-record into main
ci / check (push) Has been cancelled
2026-06-11 06:45:08 +00:00
ben.stull
ac3c4ffe36
feat(slice-4): deployment.toml — the ecomm PPE record (launch-app §5.1; Cloud SQL via secret ref)
...
ci / check (push) Has been cancelled
ci / check (pull_request) Has been cancelled
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-10 23:45:05 -07:00