Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
# Descrybe v2  status, gaps, and next work
|
||||
|
||||
Last updated: 2026-08-08
|
||||
Location: `f:/laragon/www/_MY/descrybe-v2`
|
||||
Legacy app (still live until cutover): `f:/laragon/www/_MY/descrybe`
|
||||
|
||||
This document is the honest gap analysis vs the rewrite plan and the legacy product. Use it to prioritize work. Related docs:
|
||||
|
||||
- [features.md](features.md) — phase checklist (kept in sync with this status)
|
||||
- [schema-map.md](schema-map.md) — MySQL → Postgres ID/field mapping
|
||||
- [migration-readiness.md](migration-readiness.md) — ETL status + post-import set-password
|
||||
- [migration-run-log.md](migration-run-log.md) — live MySQL→PG dry-run + load evidence (2026-08-03 **SUCCESS**)
|
||||
- [go-live-checklist.md](go-live-checklist.md) — staging GO / production NO-GO
|
||||
- [cutover.md](cutover.md) — production cutover runbook (not yet executed)
|
||||
- [forgot-password.md](forgot-password.md) — self-serve reset gap + recommended design (deferred)
|
||||
- [ux-backlog.md](ux-backlog.md) — UX P0/P1; **P0-8 / P0-9 signed cutover waivers** (2026-08-08)
|
||||
- [production-readiness.md](production-readiness.md) — Wave 8 verdict + remaining blockers
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Area | Status | Notes |
|
||||
|------|--------|--------|
|
||||
| Scaffold / monorepo | **Done** | Go API + SvelteKit + Docker Postgres |
|
||||
| Auth (no Clerk) | **Mostly done** | Register/login/invite/session/CSRF; **no self-serve forgot-password** — see [forgot-password.md](forgot-password.md) |
|
||||
| Platform (team, settings, keys, billing) | **Mostly done** | `/readyz`, profile PATCH, invites, SMTP + `cmd/mailhooks`, admin UI, plans/credits; see [ops-runtime.md](ops-runtime.md) |
|
||||
| Catalog API | **Mostly done** | ListFilter pagination, search/edit, CSV, tree/attr links/formulas; leftovers: drag-drop formula UI, S3 (`UPLOAD_DIR` only), merge-by-GTIN beyond CSV, trees >2000 |
|
||||
| Feeds / export | **Partial** | URL CSV/XML sync + export streaming; FTP/Excel/schedule/disk leftovers |
|
||||
| AI processing | **Mostly done** | OpenAI + optional Pinecone; heuristic fallback; DB claim queue; Needs Review MVP (P0-8 [w] — proposal API waived) |
|
||||
| WooCommerce | **Partial MVP** | REST + worker claim + 15m `EnqueueDueScheduled`; set `CREDENTIALS_ENCRYPTION_KEY` in prod; leftovers: rich maps UI, live E2E |
|
||||
| Migrator | **Live load succeeded** | Staging PG loaded 2026-08-03 (orphans 16/16); follow-ups: synthetic emails, all `member` roles, `plan_id=6` skipped — see [migration-run-log.md](migration-run-log.md) |
|
||||
| Public `/api/v1` | **Mounted** | Bearer/`X-API-Key`; CSRF skipped on `/api/v1` only; OpenAPI YAML |
|
||||
| Admin ops | **Mostly done** | Platform-admin APIs + `/admin` UI + stuck cleanup; polish leftovers |
|
||||
| Cutover | **Not started** | Data on staging ≠ production ready; **blocked** on emails/roles/SMTP login proof + phase gates in [cutover.md](cutover.md) |
|
||||
| CI / tests | **Partial** | `go test` unit suite + Makefile; no GitHub Actions |
|
||||
|
||||
**Bottom line:** Major workstreams (WS1–WS9) are Done or Partial. **Live MySQL→Postgres migration succeeded on staging** (27 companies, 21 users, 15 memberships, 8278 categories, 57630 attributes, 118784 raw products, 7219 processed, 31 feeds, 8 export feeds). Production cutover remains **blocked** until Clerk emails, membership roles, SMTP/set-password login, and [cutover.md](cutover.md) gates are green.
|
||||
|
||||
---
|
||||
|
||||
## What is done
|
||||
|
||||
### Infrastructure
|
||||
- [x] Sibling monorepo (`apps/api`, `apps/web`, `docs`, `scripts`)
|
||||
- [x] `docker-compose.yml`  Postgres 16 on host port `5433`
|
||||
- [x] Goose migrations `001`–`007` applied on staging PG (platform, catalog, feeds, processing, WooCommerce, feed_sync, …)
|
||||
- [x] sqlc config + generated queries (handlers often still use raw pgx)
|
||||
- [x] `cmd/api`, `cmd/worker`, `cmd/migrator`, `cmd/mailhooks` build and run
|
||||
- [x] Root `Makefile`, `scripts/migrate.sh` / `migrate.ps1`
|
||||
- [x] SvelteKit 2 + Svelte 5 + Tailwind shell with CSRF-aware `api()` helper
|
||||
|
||||
### UI / design
|
||||
- Visual shell now aligned to legacy design tokens (seasalt / russian-violet / majorelle-blue) across Nav, auth, catalog, and settings; shared `$lib/components/ui` kit + `layout.css`. Not pixel-perfect feature parity with the legacy Next.js UI.
|
||||
|
||||
#### Pixel-clone pass (2026-08-03)
|
||||
Screens cloned into SvelteKit (layout/Nav + page shells against live APIs):
|
||||
|
||||
- Dashboard (`/`), Products, Feeds (+ mapping), Export Feeds
|
||||
- Categories (+ title/description formula builders)
|
||||
- Attributes, Standard Fields
|
||||
- Background Tasks (`/processing`; `/tasks` redirects)
|
||||
- Billing, Settings, WooCommerce, Admin (+ subpages: users, billing/plans, analytics, logs, stuck-products, settings, bootstrap, migrate-orgs, tasks-cleanup)
|
||||
- Auth: login, register, accept-invite
|
||||
- `/plans` (customer plans page — admin plans live under `/admin/billing`)
|
||||
- `/structured-descriptions` (UI cloned; backend APIs still gap)
|
||||
- `/vector-categories` (UI cloned; backend APIs still gap)
|
||||
|
||||
Nav order (legacy-aligned + v2 extras): Products → Feeds → Export Feeds → Categories → Attributes → Standard Fields → Background Tasks → Usage & Billing → Settings → WooCommerce → Admin.
|
||||
|
||||
Still missing vs legacy UI (no v2 routes yet): none of the leftover screens above — UI shells exist. Backend gaps remain for structured-descriptions and vector-categories.
|
||||
|
||||
### Auth & platform (Phase A  largely working)
|
||||
- [x] Email/password with argon2id
|
||||
- [x] Session cookies via `alexedwards/scs` + Postgres `sessions` table
|
||||
- [x] CSRF double-submit cookie (`descrybe_csrf` + `X-CSRF-Token`)
|
||||
- [x] Register (creates company + admin membership + credit_balances row)
|
||||
- [x] Login / logout / `/api/auth/me` / select company / set password
|
||||
- [ ] Self-serve forgot / reset password (accounts with password already set) — **gap**; design in [forgot-password.md](forgot-password.md). Existing set-password tokens/mail are `must_set_password` / admin-only (P0-10), not reusable safely.
|
||||
- [x] Accept invite flow (API + Svelte page)
|
||||
- [x] Team list, create invite, remove member
|
||||
- [x] Company get/patch + JSON settings
|
||||
- [x] API keys create/list/revoke (hashed)
|
||||
- [x] Billing credits overview + `ConsumeCredits` used by processing stub
|
||||
- [x] `/healthz` + `/readyz` (DB ping; exempt from maintenance gate)
|
||||
- [x] Profile `PATCH /api/auth/me`; invite list + revoke
|
||||
- [x] Svelte: login, register, accept-invite, settings (profile/company/team/keys), billing
|
||||
|
||||
### Catalog (Phase B — mostly done)
|
||||
- [x] Categories CRUD + title/description formula PATCH + tree/CSV + attr links
|
||||
- [x] Attributes CRUD + `ListFilter` SQL pagination/search (shared with products; `ProductFilter` alias)
|
||||
- [x] Custom variables CRUD
|
||||
- [x] Products list/search/edit + CSV import (local `UPLOAD_DIR`; merge-by-GTIN in CSV path)
|
||||
- [x] Migrator paths for categories, attributes, variables, products, feeds (best-effort)
|
||||
|
||||
### Feeds / export (Phase C — partial)
|
||||
- [x] Input feed CRUD + mapping get/put
|
||||
- [x] Export feed create/list + generate + public XML/CSV streaming
|
||||
- [x] Real URL sync (CSV/XML) → `raw_products` (FTP/Excel leftover; `SyncStub` aliases `Sync`)
|
||||
|
||||
### Processing (Phase D — mostly done)
|
||||
- [x] Processing jobs create/list/get/cancel + start → `/api/processing/jobs`
|
||||
- [x] Worker claims pending jobs; OpenAI/heuristic pipeline + optional Pinecone
|
||||
- [x] Credit consumption hook on processed items
|
||||
|
||||
### WooCommerce (Phase E — Partial MVP)
|
||||
- [x] Config get/put (URL validated; credentials AES-GCM encrypted at rest)
|
||||
- [x] Real REST connection test (Basic Auth over HTTPS)
|
||||
- [x] Queued product sync (batch create/update; SKU / product_ids map idempotency)
|
||||
- [x] Worker claim hook for pending Woo syncs
|
||||
- [x] Worker 15m cron: billing cycles, stuck jobs, `EnqueueDueScheduled`
|
||||
- [~] Category/attribute map APIs exist; rich mapping UI / live E2E still open
|
||||
- **Prod:** set `CREDENTIALS_ENCRYPTION_KEY` (falls back to derived material — prefer explicit key)
|
||||
- See [ops-runtime.md](ops-runtime.md) for SMTP, mailhooks, encryption, billing
|
||||
|
||||
### Docs
|
||||
- [x] Schema map, cutover runbook, features checklist
|
||||
|
||||
---
|
||||
|
||||
## What is missing or incomplete
|
||||
|
||||
### Critical for any real use (P0)
|
||||
|
||||
1. **Feed sync leftovers** (URL+CSV/XML done; not full parity)
|
||||
- [x] Download URL, parse CSV/XML, mappings -> upsert `raw_products`, chunked progress
|
||||
- [ ] FTP|FTPS / Excel / uploaded-file paths as in legacy
|
||||
|
||||
2. **Export generation** — **mostly done** (`internal/feeds/export.go`)
|
||||
- [x] Build XML/CSV from processed products + export template (streamed)
|
||||
- [x] On-demand generate; public XML/CSV stream real rows
|
||||
- [ ] Schedule/cron generation; persist files to object storage
|
||||
|
||||
3. **AI processing pipeline** — **mostly done**
|
||||
- [x] Categorize -> attributes -> enhance; OpenAI + optional Pinecone; credits/retries
|
||||
- [~] River client deferred (DB claim + NOTIFY); tune prompts / enable Pinecone index
|
||||
|
||||
4. **Public `/api/v1` surface** — **mounted**
|
||||
- [x] Bearer / `X-API-Key`; products/categories/attributes/feeds/export-feeds/process
|
||||
- [x] OpenAPI YAML at `/api/v1/openapi.yaml` (Redoc/Scalar UI optional)
|
||||
- [ ] Live DB integration test for API-key round-trip (**BLOCKER:** needs `DATABASE_URL` harness)
|
||||
|
||||
5. **Migrator production readiness** — **live dry-run + staging load done; cutover follow-ups open**
|
||||
- [x] Fixture offline path (`-dry-run -fixture ./cmd/migrator/testdata/fixture.json`); id-map + validation artifacts gitignored
|
||||
- [x] `admin_users` -> `is_platform_admin`; feed mappings; count/orphan report; set-password hooks
|
||||
- [x] Live MySQL dry-run + staging PG load (2026-08-03) — orphans **16/16 pass**; evidence in [migration-run-log.md](migration-run-log.md)
|
||||
- [ ] **BLOCKER (cutover):** synthetic `@legacy.local` emails — export Clerk emails and patch before invites
|
||||
- [ ] **BLOCKER (cutover):** all memberships imported as `role=member` — promote company admins
|
||||
- [ ] **BLOCKER (cutover):** SMTP + set-password login smoke (this load used `-skip-post-import`)
|
||||
- [ ] Data: 2 `company_plans` skipped (`plan_id=6`); api_keys / blobs / full company_settings still not migrated
|
||||
- Ops: local PG on host port **5433**; see [cutover.md](cutover.md) / [go-live-checklist.md](go-live-checklist.md)
|
||||
|
||||
### Important product gaps (P1)
|
||||
|
||||
6. **Catalog leftovers** (WS6 API largely done)
|
||||
- [x] Category tree API/CSV + attr links + formula JSON; product search/edit/CSV; ListFilter pagination
|
||||
- [ ] Drag-drop formula builder UI (legacy editors)
|
||||
- [ ] S3/object storage (local `UPLOAD_DIR` only today)
|
||||
- [ ] Merge-by-GTIN beyond CSV import path; category trees >2000 rows
|
||||
|
||||
7. **Feeds UX / advanced**
|
||||
- Mapping UI (schema extraction, XPath, transforms)
|
||||
- Preview APIs (input + export)
|
||||
- River (or real queue) instead of poll stub in `jobs/river.go`
|
||||
- Schema extraction tasks worker
|
||||
- Feed tags, templates, priorities, vendor IDs as in legacy
|
||||
|
||||
8. **Billing / usage completeness**
|
||||
- [x] Plans / assign / add-credits admin APIs + token packs + billing cycles cron (WS7)
|
||||
- [ ] Usage metrics / daily stats APIs polish
|
||||
- [ ] Low-credits UX polish
|
||||
- Stripe still out of scope unless requested
|
||||
|
||||
9. **Platform polish**
|
||||
- [x] `/readyz` (DB ping)
|
||||
- [x] Profile name update (`PATCH /api/auth/me`)
|
||||
- [x] Invite revoke + list pending invites
|
||||
- [x] SMTP + `cmd/mailhooks` (operator: `SMTP_ENABLED` + host; run mailhooks after migrator)
|
||||
- Session idle policy documented in [ops-runtime.md](ops-runtime.md)
|
||||
|
||||
10. **Admin**
|
||||
- [x] Platform admin gate on routes (`is_platform_admin`)
|
||||
- [x] Admin APIs + `/admin` UI (WS7); polish leftovers
|
||||
- [x] Migrate `admin_users` in migrator
|
||||
|
||||
11. **WooCommerce**
|
||||
- [x] Real REST client + connection test + batched product push (MVP)
|
||||
- [x] Worker sync claim hook + 15m `EnqueueDueScheduled`
|
||||
- [ ] Rich category/attribute mapping UI / auto-map
|
||||
- [ ] Live E2E against a real store
|
||||
- **Prod:** set `CREDENTIALS_ENCRYPTION_KEY`
|
||||
|
||||
### Engineering / ops gaps (P2)
|
||||
|
||||
12. **`packages/migrator` layout**  migrator lives in `apps/api/cmd/migrator` (fine); plan mentioned `packages/migrator` (optional move)
|
||||
13. **Handlers still raw pgx**  sqlc generated but not fully wired
|
||||
14. **CI** — [~] Makefile test/vet/check-web + go test ./...; no GitHub Actions yet
|
||||
15. **Automated tests** — [~] unit auth/CSRF/v1/tenant/migrator; live API-key DB round-trip blocked
|
||||
16. **Object storage** — uploads/exports files on disk/S3
|
||||
17. **Observability** — structured logs, request IDs (chi has RequestID), metrics
|
||||
18. **Deploy** — reverse proxy, TLS, env secrets, worker process supervision
|
||||
19. **WebSocket / live feed updates** — legacy had WS; not in v2
|
||||
20. **Cron equivalents** — worker 15m: billing cycles, stuck reset, Woo `EnqueueDueScheduled`; feed sync schedule still open
|
||||
|
||||
---
|
||||
|
||||
## Stubs to replace (code pointers)
|
||||
|
||||
| Stub | File | Replace with |
|
||||
|------|------|----------------|
|
||||
| Feed sync | `internal/feeds` `Sync` (was SyncStub) | Done for URL+CSV/XML; FTP/Excel leftover |
|
||||
| Export XML/CSV | `internal/feeds/export.go` public generators | Done: template XML/CSV stream + generate hook; schedule/disk still open |
|
||||
| Processing | `internal/processing` pipeline (OpenAI/heuristic + optional Pinecone) | Tune prompts / enable Pinecone index; River client optional later |
|
||||
| Job queue | `internal/jobs/river.go` | Real River client or keep DB claim + document |
|
||||
| Woo test/sync | `internal/woocommerce` | Partial MVP done; rich maps UI / live E2E leftover |
|
||||
|
||||
---
|
||||
|
||||
## Recommended work order
|
||||
|
||||
Do not start cutover until P0 items for the phases you actually use in production are green.
|
||||
|
||||
```text
|
||||
1. P0 Clerk email patch + set-password invites + SMTP login smoke (staging data already loaded)
|
||||
2. P0 promote membership roles; fix skipped plan_id=6 company_plans
|
||||
3. P0 feed sync leftovers (FTP/Excel) if required for cutover tenants
|
||||
4. P0 export schedule/disk if required; AI prompt/index tuning
|
||||
5. P0 /api/v1 API-key re-issue runbook for customers
|
||||
6. P1 catalog formula UI + S3 leftovers
|
||||
7. P1 billing / Woo polish if required for cutover
|
||||
8. P2 CI/tests/deploy
|
||||
9. Execute cutover.md only after gates green
|
||||
```
|
||||
|
||||
### Phase “done when†(practical gates)
|
||||
|
||||
- **Phase A done for cutover:** invites email, `/readyz`, admin flag migrated, API keys work with `/api/v1`
|
||||
- **Phase B done:** CSV import + product edit/search parity for daily ops
|
||||
- **Phase C done:** sync + export non-stub for all active feed types
|
||||
- **Phase D done:** processing quality acceptable vs legacy sample set; credits match expectations
|
||||
- **Phase E done:** Woo sync if used; admin stuck-job tools; cutover checklist executed
|
||||
|
||||
---
|
||||
|
||||
## Parity snapshot vs legacy Descrybe
|
||||
|
||||
| Legacy capability | v2 today |
|
||||
|-------------------|----------|
|
||||
| Clerk auth / orgs | Replaced by first-party auth |
|
||||
| Dashboard products table + filters | List + ListFilter SQL pagination/search |
|
||||
| Title/description formula builders | API formulas; no drag-drop UI |
|
||||
| XML/CSV/Excel/FTP ingest | URL CSV/XML sync done; FTP/Excel open |
|
||||
| Field mapping + schema extract | Mapping JSON store; no extractor |
|
||||
| Export feeds builder | Streaming generate + public XML/CSV |
|
||||
| AI pipeline + queue/cron | OpenAI/heuristic + DB claim worker |
|
||||
| Pinecone auto-categorize | Optional; needs index config |
|
||||
| WooCommerce sync | Partial MVP (REST + worker + schedule enqueue) |
|
||||
| Billing plans/cycles/admin | Plans/credits/token packs + 15m cycles |
|
||||
| Public v1 API + OpenAPI docs | Mounted + OpenAPI YAML |
|
||||
| Admin analytics / stuck cleanup | APIs + `/admin` UI (polish open) |
|
||||
| Org export/import | Missing |
|
||||
| WebSocket live updates | Missing |
|
||||
|
||||
---
|
||||
|
||||
## How to run what exists
|
||||
|
||||
```bash
|
||||
cd f:/laragon/www/_MY/descrybe-v2
|
||||
docker compose up -d
|
||||
cd apps/api && go run ./cmd/api
|
||||
# optional worker
|
||||
go run ./cmd/worker
|
||||
# web
|
||||
cd ../web && npm install && npm run dev
|
||||
```
|
||||
|
||||
Migrator: live staging load already done — see [migration-run-log.md](migration-run-log.md). For login rehearsal:
|
||||
|
||||
```bash
|
||||
cd apps/api
|
||||
export DATABASE_URL="postgres://descrybe:descrybe@localhost:5433/descrybe?sslmode=disable"
|
||||
go run ./cmd/migrator -issue-set-password-invites -postgres "$DATABASE_URL" -maps-dir ../../artifacts
|
||||
# Dev-only bootstrap one user:
|
||||
go run ./cmd/migrator -set-password "email@example.com:YourPass123" -postgres "$DATABASE_URL"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tracking
|
||||
|
||||
Update this file when a gap closes. Keep [features.md](features.md) checkboxes aligned. Do not mark cutover complete until emails/roles/SMTP login and P0 for in-use phases are verified on staging.
|
||||
Reference in New Issue
Block a user