Files
greeneclipse 8580c996c3 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.
2026-08-09 22:47:43 +02:00

24 KiB
Raw Permalink Blame History

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; earlier -race green). Soft Undo PASS; readiness 200. Bare /settings re-smoke PASS (tabs; no replaceState error; Alerts 6 switches; fix ddad0c89). 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 (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 XY” (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 XY” 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 ≤56 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
  2. P0-7 → P0-8 → P0-9 (research) → 6. P1-10 → P1-11 → P1-12
  3. P0-10 → P0-11 → P0-12 (cutover) → 8. P1-13 → P1-14 → P1-15
  4. P0-13 → P0-14 (integration/API cutover) → 10. P1-16 → P1-17

Research addendum (20242026 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, dont 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. Admin set-password re-issue remains for migration cohort auth service/handlers, internal/mail, login + forgot/reset routes