Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
229 lines
24 KiB
Markdown
229 lines
24 KiB
Markdown
# UX backlog (P0 / P1)
|
||
|
||
Date: 2026-08-08 (P0-8 / P0-9 cutover waivers)
|
||
Lens: SaaS PIM / feed activation (not legacy-parity — see `docs/design-gaps.md`).
|
||
Paths verified under `apps/web`.
|
||
**Status legend:** [x] landed · [w] MVP landed + remainder waived for cutover · [~] partial · [ ] open — Wave 8 closeout (2026-08-04); P0-8/9 waivers 2026-08-08.
|
||
|
||
**Wave 8 closeout (executive):** Staging **GO** / production cutover **NO-GO**. Suite **PASS** ([e239d01f](e239d01f-8ba9-4d3d-92a9-8b6ad7aec7ec); earlier `-race` green). Soft Undo **PASS**; readiness **200**. Bare `/settings` re-smoke **PASS** (tabs; no `replaceState` error; Alerts 6 switches; fix [ddad0c89](ddad0c89-9a46-429f-bb7d-7ae77213b399)). Landed: **P0-10** set-password CTA; **P0-11** role repair; **P0-12** missing-plan/`past_due`; **P0-13** store reconnect; **P0-14** API-key honesty; **P1-13** migrated checklist; **P1-14** invite email mismatch; **P1-15** admin readiness; **P1-16** ETL gaps panel. **P0-8 / P0-9** MVP closed; deferred remainder **waived** for cutover (see signed waivers below). Landed **P1-17** hypercare report-missing CTA (`HYPERCARE_MODE` + support ticket create). Open: operator SMTP/Clerk/Stripe. See `docs/production-readiness.md`.
|
||
|
||
**Wave 7 closeout (retained):** Staging **GO**; production cutover **NO-GO**. Deep E2E FAIL items re-verified **PASS**: Mapping incomplete on load; Alerts 6 switches failures ON; mapping chips **PASS**. Prior PASS: login, Needs Review, processing, billing wallet, products pager.
|
||
|
||
**Wave 6 closeout (retained):** P0-7 [x]; P0-8 [~]; P0-9 [~]; Mapped vs Active + Mapping incomplete; smoke polish.
|
||
|
||
**Wave 8 landed:** P0-10 [x] login `password_not_set` CTA; P0-12 [x] missing-plan / past_due recovery + migrator plan-skip tooling; P0-13 [x] store reconnect cliff; P0-14 [x] API key reissue honesty; P1-13 [x] migrated-cohort checklist; P1-14 [x] invite email mismatch; P1-15 [x] admin readiness strip (`GET /api/admin/readiness`); FTP sync honesty; empty-shell polish (vector-categories / structured-descriptions / campaigns); bulk Accept Undo (admin→reset); Settings `replaceState` race fix; staging-auth-rehearsal scripts; security residual (team PATCH/DELETE last-admin, Stripe mock blocked in prod / live secrets runtime-gated, set-password 429, CSP connect-src); OpenAPI team PATCH + set-password; campaigns list N+1; a11y alertdialog / Alerts labels / ⌘K aria-live. Aug-8: see [production-readiness.md](production-readiness.md) (Stripe boot honesty, `mail.ApplyDryRun`, public export opaque 404 **BREAKING**, adapter pinned to `adapter-node`).
|
||
|
||
**Wave 7 landed (retained):** P1-3 [x] bulk confirms; P1-10 [x] ⌘K; P0-11 [x] role repair; P0-8 field-level accept/discard; CSP; Stripe/SMTP fail-closed; CSRF cookie sync; maintenance banner; OpenAPI drift; export-feeds empty/progress.
|
||
|
||
**Smoke polish (landed):** checklist advances from workspace evidence (P0-1); Active Feeds Mapped vs Active + Mapping incomplete (P0-6); mapping confidence chips + fuzzy confirm (P0-7); single sync-gate toast; no Cancel/Retry on completed jobs (P0-3); billing honesty (P0-12); products “Showing X–Y” (P0-5).
|
||
|
||
## P0 — ship first
|
||
|
||
| Status | ID | Item | Targets |
|
||
|--------|----|------|---------|
|
||
| [x] | **P0-1** | Activation checklist on dashboard (dismissible / resumable; advances from workspace evidence) | `src/routes/dashboard/+page.svelte`, `src/lib/components/DashboardStats.svelte`, `src/lib/tutorial/storage.ts` |
|
||
| [x] | **P0-2** | Empty-state primary CTAs (import / connect store / add feed) | `src/lib/components/products/ProductEmptyState.svelte`, `src/routes/products/+page.svelte`, `src/routes/feeds/+page.svelte`, `src/routes/stores/+page.svelte` |
|
||
| [x] | **P0-3** | Unify job progress (sync + AI): status, %, “View progress” from toast; Cancel/Retry only when actionable | `src/routes/processing/+page.svelte`, `src/lib/components/ui/Progress.svelte`, `src/lib/components/feeds/FeedActionsMenu.svelte`, `src/routes/feeds/+page.svelte`, `src/lib/components/ui/toast-state.ts`, `src/routes/+layout.svelte` |
|
||
| [x] | **P0-4** | Bulk result receipt (succeeded / skipped / failed + link to jobs) | `src/lib/components/products/ProductProcessingActions.svelte`, `src/routes/products/+page.svelte`, `src/routes/processing/+page.svelte` |
|
||
| [x] | **P0-5** | Select-all clarity: “N on this page” vs all matching; range “Showing X–Y” | `src/lib/components/products/ProductTable.svelte`, `src/routes/products/+page.svelte` |
|
||
| [x] | **P0-6** | Sync / map preflight (required unmapped fields, sample validation) — UI + API gate; feed Mapped vs Mapping incomplete | `src/routes/feeds/[feedId]/mapping/+page.svelte`, `src/lib/components/feeds/suggest-mappings.ts`, `src/routes/feeds/+page.svelte`, `apps/api/internal/feeds/sync.go` |
|
||
|
||
## P1 — next
|
||
|
||
| Status | ID | Item | Targets |
|
||
|--------|----|------|---------|
|
||
| [x] | **P1-1** | Shorten tour to ≤5–6 activation-path steps | `src/lib/tutorial/steps.ts`, `src/lib/components/tutorial/TutorialOverlay.svelte` |
|
||
| [~] | **P1-2** | `EmptyState` CTA slots (primary + secondary); audit callers | `src/lib/components/EmptyState.svelte` (+ feeds, export-feeds, campaigns, stores, …) |
|
||
| [x] | **P1-3** | Bulk confirm preview (count, credits, irreversible) | `src/lib/components/products/ProductProcessingActions.svelte`, `src/lib/components/categories/formula/ConfirmationDialog.svelte`, products reject/reset + channel overwrite Dialogs |
|
||
| [~] | **P1-4** | Channel sync UX (import vs outbound, last-sync summary, overwrite warn) — full conflict/SoT review still open | `src/routes/woocommerce/+page.svelte`, `src/routes/stores/shopify/+page.svelte`, `src/routes/shopify/+page.svelte` |
|
||
| [x] | **P1-5** | Role-based chrome (admin vs member: invites, keys, billing, delete, brand kit) | `src/routes/settings/+page.svelte`, `src/lib/components/Nav.svelte`, `src/lib/company-admin.ts` |
|
||
| [x] | **P1-6** | Nav Setup vs Operate grouping | `src/lib/components/Nav.svelte` |
|
||
| [x] | **P1-7** | Completeness / channel-ready signals on products list (lean heuristics) | `src/lib/components/products/ProductTable.svelte`, `src/lib/components/products/types.ts` |
|
||
| [~] | **P1-8** | Soft undo where API allows (job cancel Undo; bulk Accept Undo via `/api/products/reset` for admins; bulk reset/delete restore still open) | Product bulk handlers + `Toaster.svelte` / `toast-state.ts` |
|
||
| [x] | **P1-9** | 403 empty states (“ask admin”) distinct from no-data | `EmptyState.svelte`, `ForbiddenEmptyState.svelte`, settings/integrations/admin routes |
|
||
|
||
## Order
|
||
|
||
1. P0-2 + P0-1 → 2. P0-5 + P0-4 → 3. P0-3 + P0-6 → 4. P1 role / channel / nav
|
||
5. **P0-7 → P0-8 → P0-9** (research) → 6. **P1-10 → P1-11 → P1-12**
|
||
7. **P0-10 → P0-11 → P0-12** (cutover) → 8. **P1-13 → P1-14 → P1-15**
|
||
9. **P0-13 → P0-14** (integration/API cutover) → 10. **P1-16 → P1-17**
|
||
|
||
---
|
||
|
||
## Research addendum (2024–2026 operator UX) — 2026-08-04
|
||
|
||
Sources: Flatfile/CSVBox/AppMaster mapping UX; Feednode/IRONFEED/FeedOn feed ops; Refibuy/AKKO NORA/eCommerceInsights AI review; Orbix/SaaSUI command palette + notification prefs; NN/progressive disclosure.
|
||
|
||
### Theme → codebase (done vs gap)
|
||
|
||
| Theme | Already in `apps/web` | Covered by backlog | Still missing |
|
||
|-------|----------------------|--------------------|---------------|
|
||
| Progressive disclosure | Activation checklist + tour; mapping preview empty→filled | P0-1 (shipped), P1-1, P1-6 | Advanced/optional feed+AI settings behind “Advanced”; complexity preference persistence |
|
||
| Smart defaults | `suggestMappings` + `?automap=1`; exact/alias auto-apply; fuzzy Confirm gate; GTIN merge | P0-6, P0-7 | Blank-cell SoT copy |
|
||
| Inline help | Card/page descriptions | — | Field/channel tooltips (`Tooltip` / help popovers on mapping targets + export specs) |
|
||
| Undo | Toast `onClick` for job cancel + admin bulk Accept→reset | P1-8 [~] | Bulk reset/delete restore; AI accept rollback without reset |
|
||
| Status chips | `StatusBadge`, `ProductStatusBadge`; mapping confidence chips | P0-3, P0-7, P1-7 | Job next-action chips; post-sync delta chips (added/updated/removed) |
|
||
| Guided mapping | Suggest + `MappingPreviewPanel` + `evaluateMappingPreflight` + confidence chips | P0-6, P0-7 | “Issues only” sample filter |
|
||
| Conflict resolution | Company GTIN merge setting | P1-4 | Field-level SoT / AI merge vs keep / channel overwrite preview |
|
||
| Keyboard shortcuts | ⌘K/Ctrl+K command palette (P1-10); Escape/dialogs | P1-10 | Sync/process/map action entries beyond nav jumps |
|
||
| Notification prefs | Local in-app matrix (P0-9 [w]) | P0-9 MVP | Server/email prefs + terminal AI job-done toasts — **waived** for cutover (post-cutover backlog) |
|
||
|
||
### New P0 (research)
|
||
|
||
| Status | ID | Item | Targets |
|
||
|--------|----|------|---------|
|
||
| [x] | **P0-7** | Mapping confidence chips + fuzzy confirm gate (exact/alias auto-apply; fuzzy Confirm; chips on banner/table/preview) | `suggest-mappings.ts`, `feeds/[feedId]/mapping/+page.svelte`, `SchemaMappingTable.svelte`, `MappingPreviewPanel.svelte` |
|
||
| [w] | **P0-8** | AI enrichment review queue: before/after, accept / edit / reject (+ optional confidence band) — **MVP closed; proposal API waived** | `processing/+page.svelte`, `products/+page.svelte`, `ProductProcessingActions.svelte`, `ProductEditPanel.svelte`; pipeline → `needs_review` |
|
||
| [w] | **P0-9** | Operator alerts prefs: sync fail, AI job done/fail, export fail (email + in-app; defaults on for failures) — **local MVP closed; server/email waived** | `settings/+page.svelte`, `alert-prefs.ts`, `notify.ts`, sync/export call sites |
|
||
|
||
#### P0-9 notes (2026-08-04)
|
||
|
||
**Shipped (local-only, safe):**
|
||
- Browser `localStorage` prefs (`descrybe.alert-prefs.v1`): failures default **on**, completions default **off**.
|
||
- Settings → **Alerts** tab: in-app toggles (`role=switch` for E2E) + email deferred copy.
|
||
- `notifySuccess` / `notifyError` / `notifyApiError` gate on optional `alert` kind; untagged toasts (forms, validation) always show.
|
||
- Toasts with `onClick` (Undo) are never muted; stack cap (max 3) and durations untouched.
|
||
- Wired: feed sync fail/done, sync+sample fail/done, processing start fail, product export fail/done, export-feed refresh fail/done.
|
||
|
||
**Deferred (post-cutover; see signed waiver):**
|
||
- Server-backed notification preference API (cross-device, company-scoped).
|
||
- Email channel for the same event matrix.
|
||
- Terminal AI job **completed** toasts (no background completion watcher yet; job-start toast stays always-on for Undo).
|
||
|
||
##### Signed waiver — P0-9 remainder (2026-08-08)
|
||
|
||
**WAIVER ID:** `UX-P0-9-SERVER-EMAIL-2026-08-08`
|
||
**Decision:** Accept cutover / staging GO **without** server-backed alert prefs or email delivery for the operator alert matrix.
|
||
**Accepted by:** product cutover gate (per `docs/go-live-checklist.md` § “signed waiver for tenants that do not need those paths”).
|
||
**Why deferred (not small/safe now):**
|
||
- Server prefs need schema + company/user-scoped API + Settings sync (cross-device) — migration + authz surface.
|
||
- Email channel needs templates, preference gating in mail workers, and proven SMTP/Resend (already an independent cutover blocker).
|
||
- Terminal AI job-done toasts need a background completion watcher; job-start toasts must stay unmuted for Undo.
|
||
**Residual risk:** prefs are browser-local only (lost on new device/clear storage); no email for sync/AI/export failures until SMTP ops + this backlog ship.
|
||
**Re-open when:** SMTP/Resend live-proven **and** a tenant requires cross-device or email alerts. Track as post-cutover P1.
|
||
|
||
#### P0-8 notes (2026-08-04)
|
||
|
||
**Shipped (incremental, no proposal API):**
|
||
- Pipeline upserts processed products as `needs_review` (legacy `processed` still listed via filter alias).
|
||
- Needs Review tab + bulk **Accept enrichment** / **Reject (reset)**; edit panel **Review** tab with original vs enriched side-by-side; Accept / Reject / Save.
|
||
- Completed jobs on Processing link to `/products?status=needs_review`.
|
||
- Accept = PATCH `status=completed`; Reject = existing `/api/products/reset` (admin).
|
||
- **Wave 7:** field-level Accept name/description (copy `processed_*` → live fields, stay `needs_review`); Discard resets `processed_*` when original non-empty; keyboard A/R/Alt+1/Alt+2/Ctrl+Enter; Undo toasts on field actions.
|
||
|
||
**Deferred (full proposal API; see signed waiver):**
|
||
- Dedicated enrich-proposal endpoints (pending proposals, confidence bands).
|
||
- Per-job product ID list / job-scoped review queue (jobs do not expose product diffs today).
|
||
- Soft undo of whole-product Accept beyond admin bulk Accept→reset (restore previous enriched values without reset) — related to P1-8 / research Undo theme.
|
||
|
||
##### Signed waiver — P0-8 remainder (2026-08-08)
|
||
|
||
**WAIVER ID:** `UX-P0-8-PROPOSAL-API-2026-08-08`
|
||
**Decision:** Accept cutover / staging GO with the **shipped** Needs Review MVP; do **not** block on a dedicated enrich-proposal API, job-scoped review queue, or soft whole-product Accept undo.
|
||
**Accepted by:** product cutover gate (per `docs/go-live-checklist.md` § “signed waiver for tenants that do not need those paths”).
|
||
**Why deferred (not small/safe now):**
|
||
- Proposal API + confidence bands imply new persistence, list/get/accept contracts, and OpenAPI drift — medium blast radius on catalog/processing.
|
||
- Job-scoped queues need processing-job → product-diff linkage the job model does not expose today.
|
||
- Soft undo of whole-product Accept overlaps P1-8 / research Undo and risks incorrect field restoration without prior-value snapshots.
|
||
**Residual risk:** operators review via status filter + field-level accept/discard, not proposal confidence bands or per-job queues; whole-product Accept undo remains admin reset only.
|
||
**Re-open when:** a paying tenant requires confidence-gated proposals or job-scoped review, or Undo theme (P1-8) lands snapshots. Track as post-cutover P1.
|
||
|
||
### New P1 (research)
|
||
|
||
| Status | ID | Item | Targets |
|
||
|--------|----|------|---------|
|
||
| [x] | **P1-10** | ⌘K/Ctrl+K command palette (nav + common actions: sync, process, map, jobs) | new `CommandPalette.svelte`, `+layout.svelte`, `Nav.svelte` |
|
||
| [~] | **P1-11** | Inline field help (glossary tips on mapping landed; export + blank=keep/overwrite still open) | mapping page, `standard-fields`, export-feed builder |
|
||
| [~] | **P1-12** | Soft undo via toast `onClick` (job cancel + bulk Accept Undo for admins; bulk reset/delete still open) | `toast-state.ts`, `Toaster.svelte`, product bulk handlers |
|
||
|
||
---
|
||
|
||
## Cutover / production-readiness UX (2026-08-04)
|
||
|
||
Sources: FileFeed/Spiderhunts SaaS migration + reconciliation; Rework account setup (RBAC/SSO blockers); Gigabit ERP cutover + hypercare; YuSMP/StarterPick/Jimo B2B onboarding (activation event, invite+role, stuck accounts); Auth0 migrated password invite UX; Stripe Billing go-live (webhooks as SoT, past_due grace, Customer Portal); Bitsfolio/SautiKit invite email-mismatch recovery; Helply/Whatfix hypercare exit criteria.
|
||
|
||
Mapped to Descrybe cutover blockers in `docs/cutover.md` / `docs/migration-readiness.md` (synthetic emails, all-memberships-as-`member`, skipped `company_plans`, set-password after `-skip-post-import`).
|
||
|
||
### Theme → already covered vs gap
|
||
|
||
| Theme | Already in backlog / product | Still missing (this addendum) |
|
||
|-------|------------------------------|-------------------------------|
|
||
| Greenfield activation checklist | P0-1 (shipped) | **P1-13 [x]** Migrated-cohort track (platform cutover + company dashboard gate) |
|
||
| Role-based chrome | P1-5 (shipped); **P0-11 role repair [x]** | — |
|
||
| Set-password accept flow | `/accept-invite` + login CTA + admin re-issue (P0-10 [x] code) | SMTP/login smoke still operator |
|
||
| Billing page / portal | `/billing` + Manage subscription | **P0-12 [x]** missing-plan + past_due Portal CTA |
|
||
| Team invites | Settings invite + role at invite time; member role change (P0-11) | Session email ≠ invite email recovery (**P1-14 [x]**) |
|
||
| Ops cutover runbook | `docs/cutover.md` (ops); maintenance/read-only banner + platform-admin readiness strip (P1-15) | — |
|
||
|
||
### New P0 (cutover)
|
||
|
||
| Status | ID | Item | Targets |
|
||
|--------|----|------|--------|
|
||
| [x] | **P0-10** | Migrated set-password first-run: login `password_not_set` + CTA → `/accept-invite`; expired-invite / admin re-issue copy (no public self-serve resend); `mode=set-password` → sign-in + skip greenfield tour; **admin re-issue hardened** (rate limits, skip `@legacy.local`, durable invites, Admin Users UI) — SMTP/login smoke still operator | `login/+page.svelte`, `accept-invite/+page.svelte`, `auth` Login / handleLogin, admin set-password send / Users UI |
|
||
| [x] | **P0-11** | Membership **role repair** (promote/demote admin): Settings team control + API — required because migrator imports all as `member`; block demoting last admin — landed: `PATCH /api/team/{userID}` + Settings Team Make admin/member | `settings/+page.svelte` team table, `apps/api` team/membership handlers |
|
||
| [x] | **P0-12** | Billing go-live / entitlement recovery: banner when plan missing or Free fallback after skipped `company_plans`; admin Checkout CTA + member “ask admin”; `past_due` sticky banner → Customer Portal (grace copy, don’t hard-lock day 1) | `billing/+page.svelte`, `billing-display.ts`, `+layout.svelte` / dashboard banner; `cmd/migrator` `-assign-missing-plans` |
|
||
|
||
#### P0-12 notes (2026-08-04)
|
||
|
||
**Shipped:**
|
||
- API `has_active_plan` on CreditsOverview — missing/skipped `company_plans` no longer looks like intentional Free / Unlimited.
|
||
- Stripe `subscription_status` on status + webhook-managed `stripe_status:*` note; `past_due` grace copy (no day-1 hard lock).
|
||
- Billing + sticky layout + dashboard recovery banners: admin → Plans / Customer Portal; member → ask admin.
|
||
- `formatSkuUsage` / display helpers no longer say Unlimited when no plan is assigned.
|
||
- Migrator plan-skip tooling: `-list-companies-without-plans`, `-assign-missing-plans` (never overwrites active plans), ETL `-fallback-plan-name` (see `docs/cutover.md`).
|
||
|
||
**Deferred:** dedicated `stripe_subscription_status` column (status currently cached in managed `company_plans.notes` prefix).
|
||
|
||
#### P0-10 notes (2026-08-04)
|
||
|
||
**Shipped (code):**
|
||
- Login returns `403` + `code=password_not_set` for `must_set_password` users; login page CTA → `/accept-invite` + admin re-issue guidance (no public self-serve resend API).
|
||
- Accept-invite: expired/invalid copy with admin re-issue path; `mode=set-password` success skips greenfield activation then sign-in → workspace.
|
||
- Rate-limited admin set-password send; skips `@legacy.local`; durable invites (`ReissueSetPasswordInvite`); shareable links when SMTP off; Admin Users UI.
|
||
|
||
**Still open (ops):** SMTP + mailhooks + login smoke remain **operator-owned**. Production cutover remains **NO-GO** (`docs/cutover.md`, `docs/migration-readiness.md`).
|
||
|
||
### New P1 (cutover)
|
||
|
||
| Status | ID | Item | Targets |
|
||
|--------|----|------|--------|
|
||
| [x] | **P1-13** | Migrated-cohort onboarding track (≠ P0-1): platform cutover checklist (verify email → promote admin → set-password → confirm plan → SMTP smoke) on Admin home/Settings; company track on dashboard when gated (set-password accept / `must_set_password`) — skippable, advances from evidence | `MigratedCohortChecklist`, `lib/migrated-cohort/*`, `admin/+page.svelte`, `admin/settings`, `dashboard/+page.svelte`, `accept-invite` |
|
||
| [x] | **P1-14** | Invite / set-password **email mismatch** recovery: if session email ≠ invite email, explicit sign-out + switch account (no silent fail); login `password_not_set` copy + admin re-issue path — landed: `POST /api/auth/invite-preview`, accept/complete mismatch `code=email_mismatch`, accept-invite + login UX | `accept-invite/+page.svelte`, `login/+page.svelte`, auth handlers |
|
||
| [x] | **P1-15** | Cutover hypercare chrome: sticky maintenance / read-only banner from `/healthz` (**landed** `SystemModeBanner` + client mutate block); platform-admin readiness strip (counts: `must_set_password`, companies without admin, companies without plan) with deep links to Users / Settings (roles) / Billing | `SystemModeBanner.svelte`, `CutoverReadinessBanner.svelte`, `cutover-readiness.svelte.ts`, `+layout.svelte`, `GET /api/admin/readiness` |
|
||
|
||
---
|
||
|
||
## Cutover UX gaps addendum (integrations / known ETL skips) — 2026-08-04
|
||
|
||
Sources: FileFeed SaaS migration (re-establish integrations + post-migration verification); Truto / Paragon reconnect cliff (`needs_reauth` in-app banner, deep-link re-auth, batch reconnect); knowledgelib ERP cutover (credential provisioning lead time); STOA / Refgrow cutover consumer FAQ + support channel; StarterPick stuck-account inspect; Helply hypercare exit criteria. Mapped to explicit Gaps in `docs/cutover.md` / `docs/migration-readiness.md`: `api_keys`, Woo configs, file blobs, jobs/history, full `company_settings` not migrated.
|
||
|
||
### Theme → already covered vs gap
|
||
|
||
| Theme | Already in backlog / product | Still missing (this addendum) |
|
||
|-------|------------------------------|-------------------------------|
|
||
| Channel sync / SoT conflict UX | P1-4 [~]; **P0-13 [x]** reconnect cliff | — |
|
||
| Set-password / role / billing go-live | P0-10…P0-12, P1-13…P1-15 | — |
|
||
| API keys (greenfield create) | Settings integrations | **P0-14 [x]** cutover empty honesty + Stores/docs deep links (revoke-all deferred) |
|
||
| Hypercare admin strip / maintenance | **P1-15 [x]** readiness strip; **P1-16 [x]** known-gap honesty; **P1-17 [x]** report-missing CTA | — |
|
||
| Empty jobs / files | Honest empties elsewhere; **P1-16 [x]** migrated-cohort gaps panel | — |
|
||
|
||
### New P0
|
||
|
||
| Status | ID | Item | Targets |
|
||
|--------|----|------|--------|
|
||
| [x] | **P0-13** | Store / connector **reconnect cliff** after cutover: detect missing Woo (and Shopify) credentials/`has_credentials=false` post-migration; sticky admin banner + deep-link to reconnect (not generic Settings); Test Connection before first sync; batch list if multiple stores need reauth — migrator does **not** import usable Woo secrets | `woocommerce/+page.svelte`, `stores/shopify/+page.svelte`, `stores/+page.svelte`, dashboard banner, `StoreReconnectBanner.svelte`, `store-reconnect.ts` |
|
||
| [x] | **P0-14** | **API key reissue** for migrated tenants: honest empty + “legacy keys were not migrated” copy; create/rotate with one-time plaintext reveal; optional revoke-all; link from Integrations — `api_keys` not in ETL — **landed:** Settings empty Alert + EmptyState CTA; create dialog one-time reveal; Stores hub + docs/export-feeds deep links to `?tab=api-keys`; revoke-all deferred | Settings API keys UI, `stores/+page.svelte`, docs/export-feeds links |
|
||
|
||
#### P0-13 notes (2026-08-04)
|
||
|
||
**Shipped:** `needsStoreReconnect` when config identity exists but `has_credentials=false`; `StoreReconnectBanner` on Woo/Shopify pages, stores hub (batch list), and dashboard; sync CTAs gated until credentials saved; sync error copy reframed as reconnect (not mystery broken sync); deep links to `#store-reconnect` / connection tab.
|
||
|
||
### New P1
|
||
|
||
| Status | ID | Item | Targets |
|
||
|--------|----|------|--------|
|
||
| [x] | **P1-16** | **Known ETL gap honesty** (migrated cohort): dismissible dashboard panel listing what did **not** move (API keys, Woo secrets, file blobs, job/history, partial `company_settings`) with deep links to recreate/reconnect; distinct from P1-13 activation steps — **landed:** `MigratedEtlGapsPanel` + `etl-gaps.ts` (dismiss localStorage); gated on migrated cohort (Legacy/A1 name) or hypercare + admin; links to API keys / stores / files / processing / settings; **admin inventory:** diagnostics `migration_inventory` cheap COUNTs (metadata-only files / migrated jobs / tasks) + Files metadata-only notice — no fake import | Dashboard cutover panel; gate on migrated/session heuristic; `/admin/diagnostics` |
|
||
| [x] | **P1-17** | Hypercare **report missing / wrong data** CTA (tenant): reuses support ticket create (`/support/new?category=migration…`) while `HYPERCARE_MODE` is on; pairs with P1-15 admin strip + triage `q=Hypercare`; exit when env cleared — **landed:** `HypercareReportBanner`, `hypercare-report.ts`, healthz `hypercare` | Layout CTA, `/support/new` prefills, admin queue link |
|
||
| [x] | **P1-18** | **Self-serve forgot-password** — dedicated reset tokens + opaque `POST /api/auth/forgot-password` + `POST /api/auth/reset-password` + `/forgot-password`/`/reset-password` UI; reuses SMTP/`mail.Send` + `EMAIL_DRY_RUN`. Design: [forgot-password.md](forgot-password.md). Admin set-password re-issue remains for migration cohort | `auth` service/handlers, `internal/mail`, login + forgot/reset routes |
|