# TRA — Development Phases Plan

**Companion to:** [`plan.md`](./plan.md) (what to build)  
**This file:** execution order — every tiny task, phase by phase  
**Project:** TRA (The Ring Authority)  
**Stack:** Laravel 13 · Blade · Tailwind · Vite · PHP 8.5 · MySQL `ronnie_tra` · Redis · Horizon · Meilisearch · Reverb · Cloudflare · Nginx · Pulse  
**Fonts / icons:** Segoe UI + Selawik (Apple) · Lucide  
**Secrets:** use env vars only (`DB_PASSWORD`, etc.) — never commit plaintext credentials  
**Document version:** 1.1  
**Last updated:** 2026-09-23  

---

## How to use this document

1. Complete phases **in order** (0 → 7). Do not start Phase *N+1* until the Phase *N* gate is green.
2. Within a phase, respect task **Deps**. Parallelize only when deps are satisfied.
3. Mark checkboxes `- [ ]` → `- [x]` as tasks complete.
4. Every task must meet its **AC** (acceptance criteria) before marking done.
5. Traceability: each task lists `TRA-xxx` IDs from `plan.md` §24.
6. Update the [Progress tracker](#progress-tracker) after each phase gate.

---

## Conventions

### Task ID format

`P{phase}.{workstream}.{nn}` — e.g. `P1.FE.07`

| Code | Workstream |
|------|------------|
| INFRA | Infrastructure / DevOps |
| BE | Backend (Laravel) |
| FE | Public website (Blade) |
| ADM | Admin panel (Blade) |
| DB | Database migrations / seeds |
| SEO | SEO platform |
| QA | Testing / QA |
| SEC | Security |
| OPS | Operations / runbooks |
| DOC | Documentation |

### Task block format

```
- [ ] **P9.EX.01** — Short title (example format only — not a real task)
  - **TRA:** TRA-056, TRA-057
  - **Paths:** `app/Domain/...`, `resources/views/admin/...`
  - **Deps:** P0.DB.01, P0.BE.01
  - **AC:** measurable pass/fail criteria
```

### Phase section template

Every phase below contains: Objective · Entry criteria · Scope (TRA IDs) · Workstream tasks · Migrations · Routes · Admin screens · Website pages · Jobs/events/channels · Tests · Phase gate · UAT script · Rollback notes

### Repo layout (target)

Single Laravel 13 app at repository root (no monorepo / no separate frontend apps):

```
/                            # Laravel 13 root
  app/                       # Domain modules, Http, Models, Jobs
  bootstrap/
  config/
  database/                  # migrations, seeders
  public/                    # web root (index.php, built assets)
  resources/
    css/
    js/
    views/
      layouts/
        website.blade.php    # public website layout
        admin.blade.php      # admin panel layout
      website/               # public Blade views
      admin/                 # admin Blade views
      components/            # shared Blade components
  routes/
    web.php                  # public website routes
    admin.php                # admin panel routes (/admin)
  plan.md
  development.md
  README.md
```

### Domain modules (Laravel skeleton — all phases)

Catalog, Inventory, Pricing, CartCheckout, Orders, Payments, Fulfillment, Returns, Customers, Markets, Promotions, ContentCMS, Media, SEO, Search, CRM, Social, Accounting, Automation, Notifications, Analytics, IdentityRBAC, Integrations, Settings, Audit

---

# Phase 0 — Foundations

**Duration (indicative):** Weeks 1–3  
**Objective:** Bootstrappable Laravel + Blade app with platform services (auth, RBAC, audit, media core, SEO entity model, queues, search, realtime, CI) so later phases only add domain features.

## Entry criteria

- [x] Server has PHP 8.5, Composer, Node 20+, MySQL, Redis, Nginx access
- [x] Cloudflare zone ready (or staging equivalent)
- [x] Object storage credentials available via env
- [x] `plan.md` and this file reviewed by stakeholders

## Scope (TRA IDs)

TRA-026 (partial), TRA-056 (skeleton), TRA-057, TRA-058 (core), TRA-067, TRA-068

---

## P0 — INFRA

- [x] **P0.INFRA.01** — Initialize Laravel root project structure
  - **TRA:** TRA-068
  - **Paths:** `/` (Laravel root), `resources/views/layouts/`, `routes/`
  - **Deps:** none
  - **AC:** Laravel root exists; README points to layout; `.gitignore` covers `vendor`, `node_modules`, `.env`, `public/build`

- [x] **P0.INFRA.02** — Install Laravel 13 (PHP 8.5) at repository root
  - **TRA:** —
  - **Paths:** Laravel root `/`
  - **Deps:** P0.INFRA.01
  - **AC:** `php artisan --version` shows Laravel 13; `composer.json` requires `php:^8.5`

- [x] **P0.INFRA.03** — Create website Blade layout + route group
  - **TRA:** TRA-001
  - **Paths:** `resources/views/website/`
  - **Deps:** P0.INFRA.01
  - **AC:** `resources/views/layouts/website.blade.php` exists; `@vite` wired; sample website route renders

- [x] **P0.INFRA.04** — Create admin Blade layout + `/admin` route group
  - **TRA:** TRA-026
  - **Paths:** `resources/views/admin/`
  - **Deps:** P0.INFRA.01
  - **AC:** `resources/views/layouts/admin.blade.php` exists; `/admin` middleware group configured; sample admin route renders

- [x] **P0.INFRA.05** — Configure Tailwind + Vite for website and admin Blade layouts; design tokens
  - **TRA:** TRA-001
  - **Paths:** `tailwind.config.js`, `resources/css/app.css` (shared tokens for website + admin)
  - **Deps:** P0.INFRA.03, P0.INFRA.04
  - **AC:** Tokens include gold `#DAAF37`, neutrals, semantic status colors; font stack `Segoe UI, Selawik, system-ui, sans-serif`

- [x] **P0.INFRA.06** — Add Lucide icons for website and admin Blade UIs
  - **TRA:** TRA-001
  - **Paths:** root `package.json`
  - **Deps:** P0.INFRA.03, P0.INFRA.04
  - **AC:** Sample icon renders; no emoji icons in chrome

- [x] **P0.INFRA.07** — Font loading strategy (Segoe UI system + Selawik webfont for Apple)
  - **TRA:** TRA-001, TRA-066
  - **Paths:** `resources/fonts/`, `public/fonts/`, CSS
  - **Deps:** P0.INFRA.05
  - **AC:** Apple UA / platform detection prefers Selawik; fonts subsetted; no FOIT > 100ms CLS from fonts

- [x] **P0.INFRA.08** — MySQL database + `.env.example`
  - **TRA:** —
  - **Paths:** `.env.example`
  - **Deps:** P0.INFRA.02
  - **AC:** `DB_DATABASE=ronnie_tra`, `DB_USERNAME=ronnie_tra`, `DB_PASSWORD=` placeholder; connection works with real `.env` (not committed)

- [x] **P0.INFRA.09** — Redis connection for cache + queues
  - **TRA:** TRA-067
  - **Paths:** `config/database.php`, `config/cache.php`, `config/queue.php`
  - **Deps:** P0.INFRA.02
  - **AC:** `Cache::put/get` works; queue driver `redis`

- [x] **P0.INFRA.10** — Install & configure Laravel Horizon
  - **TRA:** TRA-067
  - **Paths:** `config/horizon.php`, systemd unit
  - **Deps:** P0.INFRA.09
  - **AC:** Horizon dashboard loads for authorized users; supervisor/systemd keeps worker alive

- [x] **P0.INFRA.11** — Install & configure Laravel Reverb
  - **TRA:** TRA-067
  - **Paths:** `config/reverb.php`, `deploy/` or host systemd units
  - **Deps:** P0.INFRA.02
  - **AC:** Websocket handshake succeeds; test event received by Laravel Echo (Blade + Vite)

- [x] **P0.INFRA.12** — Install & configure Meilisearch + Laravel Scout (or custom indexer)
  - **TRA:** TRA-030, TRA-067
  - **Paths:** `config/scout.php`, Meilisearch service
  - **Deps:** P0.INFRA.02
  - **AC:** Health endpoint OK; empty `products` index creatable

- [x] **P0.INFRA.13** — Install Laravel Pulse + server monitoring hooks
  - **TRA:** TRA-067
  - **Paths:** `config/pulse.php`
  - **Deps:** P0.INFRA.02, P0.INFRA.10
  - **AC:** Pulse UI shows requests/queues; restricted by auth

- [x] **P0.INFRA.14** — Nginx vhost for single Laravel app (website + `/admin`)
  - **TRA:** TRA-068
  - **Paths:** `deploy/nginx/*.conf` (server config notes at repo root or host)
  - **Deps:** P0.INFRA.02–04
  - **AC:** HTTPS (or staging HTTP) routes correctly; PHP-FPM to `public/`; website and `/admin` share one app

- [x] **P0.INFRA.15** — Cloudflare DNS/WAF/CDN baseline
  - **TRA:** TRA-068
  - **Paths:** `cloudflare.md`, purge script (repo root)
  - **Deps:** P0.INFRA.14
  - **AC:** Proxied DNS; TLS; cache rules documented; API purge callable via env token

- [x] **P0.INFRA.16** — CI pipeline: lint, PHPStan, Pest/PHPUnit, Lighthouse smoke
  - **TRA:** TRA-066
  - **Paths:** `.github/workflows/*` or CI config
  - **Deps:** P0.INFRA.02–04
  - **AC:** PR pipeline fails on lint/test failures; Lighthouse smoke job exists (may be soft-fail until Phase 1)

- [x] **P0.INFRA.17** — Object storage (S3-compatible) adapter
  - **TRA:** TRA-058, TRA-059
  - **Paths:** `config/filesystems.php`
  - **Deps:** P0.INFRA.02
  - **AC:** Upload/download round-trip succeeds; private signed URL works

- [x] **P0.INFRA.18** — Backup scripts (MySQL dump + binlog note + object storage versioning)
  - **TRA:** —
  - **Paths:** `scripts/backup/`
  - **Deps:** P0.INFRA.08, P0.INFRA.17
  - **AC:** Cron documented; dry-run restore instructions in runbook

- [x] **P0.INFRA.19** — Environment matrix docs (local/staging/production)
  - **TRA:** —
  - **Paths:** `environments.md`
  - **Deps:** P0.INFRA.08
  - **AC:** All required env keys listed without secret values

---

## P0 — DB

- [x] **P0.DB.01** — Users, sessions, password resets, MFA factors tables
  - **TRA:** TRA-056
  - **Paths:** `database/migrations/*users*`, `*mfa*`
  - **Deps:** P0.INFRA.08
  - **AC:** Migrate fresh succeeds; MFA columns present

- [x] **P0.DB.02** — Roles, permissions, role_user, permission_role, optional role scopes
  - **TRA:** TRA-056
  - **Paths:** migrations RBAC
  - **Deps:** P0.DB.01
  - **AC:** Seed roles: Super Admin, Security Admin; permission seeder runs

- [x] **P0.DB.03** — `audit_events` append-only table + indexes
  - **TRA:** TRA-057
  - **Paths:** migrations audit
  - **Deps:** P0.DB.01
  - **AC:** Insert works; UPDATE/DELETE blocked via DB trigger or app policy + tested

- [x] **P0.DB.04** — `settings`, `feature_flags` tables
  - **TRA:** —
  - **Paths:** migrations settings
  - **Deps:** P0.INFRA.08
  - **AC:** Key/value settings CRUD; flag evaluate helper works

- [x] **P0.DB.05** — `outbox_messages` table
  - **TRA:** —
  - **Paths:** migrations outbox
  - **Deps:** P0.INFRA.08
  - **AC:** Columns: id, event_type, payload, status, attempts, available_at, created_at

- [x] **P0.DB.06** — Idempotency keys table
  - **TRA:** —
  - **Paths:** migrations idempotency
  - **Deps:** P0.INFRA.08
  - **AC:** Unique (actor/key) constraint; TTL cleanup job stub

- [x] **P0.DB.07** — Media core tables: `media_assets`, `media_variants`, `media_folders`
  - **TRA:** TRA-058
  - **Paths:** migrations media
  - **Deps:** P0.INFRA.17
  - **AC:** Migrate OK; FK to users for uploader

- [x] **P0.DB.08** — SEO entities skeleton: `seo_entities`, `schema_nodes`
  - **TRA:** TRA-060
  - **Paths:** migrations seo
  - **Deps:** P0.INFRA.08
  - **AC:** Polymorphic entity_type/entity_id; locale column

- [x] **P0.DB.09** — Service accounts / personal access tokens scaffolding
  - **TRA:** TRA-056
  - **Paths:** Sanctum migrations
  - **Deps:** P0.DB.01
  - **AC:** Token create/revoke works

---

## P0 — BE (platform)

- [x] **P0.BE.01** — Domain module folder skeleton (25 domains) + service providers
  - **TRA:** —
  - **Paths:** `app/Domain/*`
  - **Deps:** P0.INFRA.02
  - **AC:** Each domain has `Providers`, `Models`, `Actions`, `Http`, `Events` stubs

- [x] **P0.BE.02** — Shared response helpers: Blade flash/errors + JSON envelope/RFC7807 where AJAX needed
  - **TRA:** —
  - **Paths:** `app/Http/Resources` (JSON where needed) / Blade views, middleware
  - **Deps:** P0.BE.01
  - **AC:** Form requests validate; Blade shows errors; JSON endpoints return `{data,meta,errors}` / 422 problem+json

- [x] **P0.BE.03** — Admin auth: login, logout, session, MFA enroll/verify
  - **TRA:** TRA-056
  - **Paths:** `app/Domain/IdentityRBAC`
  - **Deps:** P0.DB.01
  - **AC:** MFA required for Super Admin; invalid TOTP rejected; sessions revocable

- [x] **P0.BE.04** — RBAC policies: permission check middleware + gate helpers
  - **TRA:** TRA-056
  - **Paths:** policies, middleware `EnsurePermission`
  - **Deps:** P0.DB.02, P0.BE.03
  - **AC:** Unauthorized returns 403; field-level helper stub exists

- [x] **P0.BE.05** — Audit middleware (request → audit_events for mutating actions)
  - **TRA:** TRA-057
  - **Paths:** `app/Domain/Audit`
  - **Deps:** P0.DB.03, P0.BE.03
  - **AC:** Create/update/delete of settings writes audit with actor, before/after, IP, UA

- [x] **P0.BE.06** — Settings + feature flag services
  - **TRA:** —
  - **Paths:** `app/Domain/Settings`
  - **Deps:** P0.DB.04
  - **AC:** Cached settings; flag toggle audited

- [x] **P0.BE.07** — Outbox writer + Horizon dispatcher job
  - **TRA:** TRA-067
  - **Paths:** `app/Domain/*/Outbox*`
  - **Deps:** P0.DB.05, P0.INFRA.10
  - **AC:** Transactional write + dispatch; failed messages retry + DLQ

- [x] **P0.BE.08** — Idempotency middleware (`Idempotency-Key` header)
  - **TRA:** —
  - **Paths:** middleware
  - **Deps:** P0.DB.06
  - **AC:** Duplicate POST returns same response; different body with same key → 409

- [x] **P0.BE.09** — Route/API docs for JSON endpoints (optional OpenAPI for AJAX/webhooks only)
  - **TRA:** —
  - **Paths:** `openapi.yaml` (JSON/webhook endpoints only) or generated
  - **Deps:** P0.BE.02
  - **AC:** Documented web + admin routes; JSON endpoints documented if present; CI validates docs when enabled

- [x] **P0.BE.10** — Media upload (multipart + resumable stub) + MIME allowlist via admin controllers
  - **TRA:** TRA-058
  - **Paths:** `app/Domain/Media`
  - **Deps:** P0.DB.07, P0.INFRA.17, P0.BE.04
  - **AC:** Reject exe/php; store outside web root; virus scan job stub queued

- [x] **P0.BE.11** — Media derivative job (resize WebP/AVIF stub)
  - **TRA:** TRA-059
  - **Paths:** jobs ProcessMediaDerivatives
  - **Deps:** P0.BE.10, P0.INFRA.10
  - **AC:** Upload creates at least thumb + medium variants asynchronously

- [x] **P0.BE.12** — SEO entity CRUD (skeleton) via admin controllers + Blade forms
  - **TRA:** TRA-060
  - **Paths:** `app/Domain/SEO`
  - **Deps:** P0.DB.08
  - **AC:** Can set title/description/canonical/robots per entity+locale

- [x] **P0.BE.13** — Health endpoints: `/up`, `/health` (db, redis, meili, queue)
  - **TRA:** TRA-067
  - **Paths:** routes
  - **Deps:** P0.INFRA.09–12
  - **AC:** Returns component status; used by uptime checks

- [x] **P0.BE.14** — Rate limiting for login/forms; same-origin session cookies (no separate SPA CORS)
  - **TRA:** TRA-056
  - **Paths:** `bootstrap/app.php` / middleware
  - **Deps:** P0.BE.02
  - **AC:** Login/form rate limited; session cookie SameSite/secure configured

---

## P0 — ADM

- [x] **P0.ADM.01** — Admin shell layout: sidebar, topbar, content, density toggle
  - **TRA:** TRA-026
  - **Paths:** `resources/views/layouts/admin.blade.php`, `resources/views/admin/`
  - **Deps:** P0.INFRA.04–06
  - **AC:** Responsive collapse; Lucide icons; Segoe/Selawik fonts applied

- [x] **P0.ADM.02** — Primary nav IA (all top-level items from plan §7.3, disabled where not built)
  - **TRA:** TRA-026
  - **Paths:** `resources/views/admin/partials/nav.blade.php`, `config/admin_nav.php`
  - **Deps:** P0.ADM.01
  - **AC:** All modules listed; locked items show tooltip “Coming in Phase X”

- [x] **P0.ADM.03** — Login + MFA screens
  - **TRA:** TRA-056
  - **Paths:** `resources/views/admin/auth/`
  - **Deps:** P0.BE.03
  - **AC:** Full login→MFA→dashboard happy path

- [x] **P0.ADM.04** — Command palette (Ctrl/Cmd+K) stub
  - **TRA:** TRA-026
  - **Paths:** components CommandPalette
  - **Deps:** P0.ADM.01
  - **AC:** Opens; navigates to Settings; extensible action registry

- [x] **P0.ADM.05** — Global search stub UI
  - **TRA:** TRA-026
  - **Paths:** components GlobalSearch
  - **Deps:** P0.ADM.01, P0.INFRA.12
  - **AC:** Empty state; wired to `GET /admin/search` stub

- [x] **P0.ADM.06** — Toasts, confirm dialogs, empty states, loading skeletons
  - **TRA:** TRA-026
  - **Paths:** `resources/views/components/admin/`
  - **Deps:** P0.ADM.01
  - **AC:** Design system primitives documented

- [x] **P0.ADM.07** — Job center UI (Horizon-linked + app jobs list)
  - **TRA:** TRA-067
  - **Paths:** views Jobs
  - **Deps:** P0.INFRA.10, P0.BE.07
  - **AC:** Shows recent jobs; failure detail; retry button permission-gated

- [x] **P0.ADM.08** — Settings screens (store identity stub, feature flags)
  - **TRA:** —
  - **Paths:** views Settings
  - **Deps:** P0.BE.06
  - **AC:** Save audited; flags toggleable

- [x] **P0.ADM.09** — Staff users + roles CRUD (basic)
  - **TRA:** TRA-056
  - **Paths:** views Staff
  - **Deps:** P0.BE.04
  - **AC:** Invite/activate/suspend; assign roles; cannot escalate beyond own grants

- [x] **P0.ADM.10** — Media library basic grid (upload, list, delete)
  - **TRA:** TRA-058
  - **Paths:** views Media
  - **Deps:** P0.BE.10
  - **AC:** Drag-drop upload; grid/list; shows variants when ready

- [x] **P0.ADM.11** — Audit log viewer (read-only)
  - **TRA:** TRA-057
  - **Paths:** views Audit
  - **Deps:** P0.BE.05
  - **AC:** Filter by actor/action/date; export CSV permission-gated; no edit/delete

- [x] **P0.ADM.12** — Reverb presence wiring for “editing resource” stub
  - **TRA:** TRA-067
  - **Paths:** `resources/js/admin/presence.js` + Reverb
  - **Deps:** P0.INFRA.11
  - **AC:** Two browsers show mutual presence on Settings page

---

## P0 — FE

- [x] **P0.FE.01** — Website base layout + design tokens applied
  - **TRA:** TRA-001
  - **Paths:** `resources/views/layouts/website.blade.php`, `resources/views/website/`
  - **Deps:** P0.INFRA.03, P0.INFRA.05–07
  - **AC:** Gold/black palette; fonts; skip link; mobile viewport meta

- [x] **P0.FE.02** — Website controllers + Blade data binding (server-rendered pages)
  - **TRA:** —
  - **Paths:** `app/Http/Controllers/Website/` (server-rendered; no separate API client)
  - **Deps:** P0.BE.02
  - **AC:** Pages render from controllers/views; session/customer auth cookies correct

- [x] **P0.FE.03** — Placeholder home route with health banner
  - **TRA:** TRA-002
  - **Paths:** `resources/views/website/home.blade.php`
  - **Deps:** P0.FE.01
  - **AC:** Renders; Lighthouse smoke runnable

- [x] **P0.FE.04** — Consent banner shell (no trackers yet)
  - **TRA:** —
  - **Paths:** components ConsentBanner
  - **Deps:** P0.FE.01
  - **AC:** Accept/reject persists; blocks non-essential scripts

---

## P0 — SEO

- [x] **P0.SEO.01** — Head/meta Blade component / SEO builder (title, description, canonical, robots, OG)
  - **TRA:** TRA-060
  - **Paths:** `app/Support/Seo/SeoBuilder.php`, Blade `<x-seo>`
  - **Deps:** P0.BE.12, P0.FE.02
  - **AC:** Placeholder page emits correct tags from SEO builder / DB

- [x] **P0.SEO.02** — JSON-LD Blade component stub
  - **TRA:** TRA-060
  - **Paths:** components SchemaJsonLd
  - **Deps:** P0.SEO.01
  - **AC:** Renders single Organization graph without duplicates

---

## P0 — SEC / QA / DOC / OPS

- [x] **P0.SEC.01** — Security baseline: HTTPS headers, CSP draft, secrets scanning in CI
  - **TRA:** TRA-056
  - **Paths:** Nginx headers, CI secret scan
  - **Deps:** P0.INFRA.14, P0.INFRA.16
  - **AC:** No secrets in repo; security headers present on website + admin

- [x] **P0.QA.01** — PHPUnit/Pest smoke + optional Playwright scaffolding
  - **TRA:** —
  - **Paths:** `tests/`, `tests/Browser/` (optional Playwright)
  - **Deps:** P0.INFRA.02–04
  - **AC:** Sample Pest/PHPUnit tests pass in CI

- [x] **P0.QA.02** — Auth/RBAC/audit feature tests
  - **TRA:** TRA-056, TRA-057
  - **Paths:** `tests/Feature/Identity*`
  - **Deps:** P0.BE.03–05
  - **AC:** Coverage for login MFA, 403 matrix sample, audit write

- [x] **P0.DOC.01** — Developer onboarding + local setup runbook
  - **TRA:** —
  - **Paths:** `setup.md`
  - **Deps:** P0.INFRA.19
  - **AC:** New dev can boot stack from docs alone

- [x] **P0.OPS.01** — Monitoring alerts stubs (5xx, queue depth, disk)
  - **TRA:** TRA-067
  - **Paths:** `monitoring.md`
  - **Deps:** P0.INFRA.13
  - **AC:** Alert channels documented; at least one test alert fires

---

## Phase 0 — Migrations checklist

- users, password_reset_tokens, sessions
- mfa_factors
- roles, permissions, role_user, permission_role, role_scopes
- audit_events
- settings, feature_flags
- outbox_messages
- idempotency_keys
- media_assets, media_variants, media_folders
- seo_entities, schema_nodes
- personal_access_tokens / service_accounts
- jobs, failed_jobs, job_batches (Horizon)

## Phase 0 — Routes

| Method | Path | Purpose |
|--------|------|---------|
| POST | `/admin/auth/login` | Login |
| POST | `/admin/auth/mfa/verify` | MFA |
| POST | `/admin/auth/logout` | Logout |
| GET/POST | `/admin/users` | Staff |
| GET/POST | `/admin/roles` | Roles |
| GET | `/admin/audit-events` | Audit |
| GET/PUT | `/admin/settings` | Settings |
| GET/POST | `/admin/feature-flags` | Flags |
| POST | `/admin/media` | Upload |
| GET | `/admin/media` | List |
| GET/PUT | `/admin/seo/entities/{type}/{id}` | SEO |
| GET | `/admin/search` | Stub search |
| GET | `/health` | Health |
| GET | `/up` | Liveness |

## Phase 0 — Admin screens

Login, MFA, Dashboard shell, Staff, Roles, Settings, Feature flags, Media (basic), Audit, Jobs, Command palette, Global search stub

## Phase 0 — Website pages

`/` placeholder, consent banner

## Phase 0 — Jobs / events / channels

- Jobs: `DispatchOutbox`, `ProcessMediaDerivatives`, `PurgeIdempotencyKeys`
- Events: `SettingsUpdated`, `MediaUploaded`, `UserLoggedIn`
- Channels: `admin.notifications.{userId}`, `presence.editing.{resource}`, `jobs.{jobId}`

## Phase 0 — Tests

Unit: money helper stub, permission resolver  
Feature: auth MFA, RBAC 403, audit append, media reject bad MIME, outbox dispatch  
E2E: admin login → dashboard  

## Phase 0 — Gate (DoD)

- [x] All P0 tasks checked
- [x] `migrate:fresh --seed` clean
- [x] Horizon + Reverb + Meilisearch + Pulse running *(Horizon/Reverb/Pulse configured; Meilisearch needs Docker on el8)*
- [x] CI workflow added (`.github/workflows/ci.yml`)
- [x] No secrets in git
- [x] Admin shell navigable; media upload works
- [x] Health endpoint green *(db/redis/queue OK; meilisearch degraded until Docker)*
- [x] Stakeholder sign-off on foundations

## Phase 0 — UAT script

1. Clone repo; follow `setup.md`
2. Login as Super Admin; complete MFA
3. Upload image; see derivative job complete
4. Toggle feature flag; verify audit row
5. Open command palette; jump to Settings
6. Confirm Pulse and Horizon accessible

## Phase 0 — Rollback

- Revert deploy tag; drop new DB only on empty environments
- Keep `.env` backups; do not reuse production DB for experiments

---


# Phase 1 — Storefront parity, catalog, CMS, SEO base, forms → leads

**Duration (indicative):** Weeks 4–8  
**Objective:** Visually match [theringauthority.com](https://theringauthority.com/) on all public templates; full catalog/CMS admin; Meilisearch search; SEO foundation; forms creating leads; PageSpeed 99 desktop / 95 mobile on key templates.

## Entry criteria

- [x] Phase 0 gate signed off
- [x] Brand assets (logo, product photos) available in staging media
- [x] Content inventory from `plan.md` §4 reviewed

## Scope (TRA IDs)

TRA-001–009, TRA-012, TRA-025 (partial), TRA-030, TRA-037 (forms), TRA-058–061, TRA-066, TRA-070 (start)

---

## P1 — DB

- [x] **P1.DB.01** — Products, options, option_values, variants, product_media
  - **TRA:** TRA-003
  - **Paths:** migrations catalog
  - **Deps:** P0.DB.07
  - **AC:** Variant unique (product_id + option combo); SKU unique nullable

- [x] **P1.DB.02** — Categories (nested set/adjacency), category_product, collections, collection_rules, collection_product
  - **TRA:** TRA-004
  - **Paths:** migrations
  - **Deps:** P1.DB.01
  - **AC:** Manual + rule-based collections supported in schema

- [x] **P1.DB.03** — Metafield definitions + metafields; metaobject definitions + entries
  - **TRA:** TRA-025
  - **Paths:** migrations
  - **Deps:** P1.DB.01
  - **AC:** Typed fields with validation JSON

- [x] **P1.DB.04** — Pages, posts, menus, menu_items, policies
  - **TRA:** TRA-005, TRA-006
  - **Paths:** migrations CMS
  - **Deps:** P0.DB.08
  - **AC:** Draft/published/scheduled statuses; handle unique per type

- [x] **P1.DB.05** — Redirects table (from_path, to_path, status_code, hits)
  - **TRA:** TRA-061
  - **Paths:** migrations
  - **Deps:** P0.INFRA.08
  - **AC:** Unique from_path; supports 301/302/307/308/410

- [x] **P1.DB.06** — Carts, cart_lines (guest + customer)
  - **TRA:** TRA-007
  - **Paths:** migrations
  - **Deps:** P1.DB.01
  - **AC:** Cart token; line snapshots of price at add time optional flag

- [x] **P1.DB.07** — Forms, form_fields, form_submissions, leads (minimal CRM)
  - **TRA:** TRA-009, TRA-037, TRA-032 (minimal)
  - **Paths:** migrations
  - **Deps:** P0.DB.01
  - **AC:** Submission stores payload JSON + mapped lead row

- [x] **P1.DB.08** — Media albums + media_attachments polymorphic
  - **TRA:** TRA-012, TRA-058
  - **Paths:** migrations
  - **Deps:** P0.DB.07
  - **AC:** Gallery album can attach ordered assets

- [x] **P1.DB.09** — Wishlist tables (optional early stub)
  - **TRA:** TRA-011
  - **Paths:** migrations (can defer activate to P3)
  - **Deps:** P1.DB.01
  - **AC:** Schema present; feature-flagged off until P3 if needed

---

## P1 — BE Catalog / CMS / Search / Forms / SEO

- [x] **P1.BE.01** — Product CRUD API + TRA fields (grade, branding, lead days, material specs)
  - **TRA:** TRA-003
  - **Paths:** `app/Domain/Catalog`
  - **Deps:** P1.DB.01, P0.BE.04
  - **AC:** Active/draft/archived/unlisted; soft delete; duplicate endpoint

- [x] **P1.BE.02** — Option + variant generator (size × colour etc.)
  - **TRA:** TRA-003
  - **Paths:** Actions GenerateVariants
  - **Deps:** P1.BE.01
  - **AC:** Prevents duplicate combos; per-variant price/SKU/media/weight

- [x] **P1.BE.03** — Bulk product status/tags/publish endpoints
  - **TRA:** TRA-003
  - **Paths:** Catalog bulk actions
  - **Deps:** P1.BE.01
  - **AC:** Async job for >100 rows; progress in job center

- [x] **P1.BE.04** — Category tree CRUD + product attach
  - **TRA:** TRA-004
  - **Paths:** Catalog Categories
  - **Deps:** P1.DB.02
  - **AC:** Nested move; cycle prevention

- [x] **P1.BE.05** — Collections manual + rules engine (AND/OR) + preview
  - **TRA:** TRA-004
  - **Paths:** Collections service
  - **Deps:** P1.DB.02
  - **AC:** Rule preview matches evaluation; deterministic sort options

- [x] **P1.BE.06** — Empty collection policy: noindex + sitemap exclude
  - **TRA:** TRA-004, TRA-061
  - **Paths:** SEO + Collections
  - **Deps:** P1.BE.05, P1.BE.20
  - **AC:** Empty collections not in sitemap; robots noindex

- [x] **P1.BE.07** — Metafields/metaobjects CRUD
  - **TRA:** TRA-025
  - **Paths:** CustomData domain
  - **Deps:** P1.DB.03
  - **AC:** Validation enforced server-side

- [x] **P1.BE.08** — Pages CRUD + revisions
  - **TRA:** TRA-006
  - **Paths:** ContentCMS
  - **Deps:** P1.DB.04
  - **AC:** Schedule publish; revision restore

- [x] **P1.BE.09** — Blog posts CRUD + pagination API
  - **TRA:** TRA-005
  - **Paths:** ContentCMS
  - **Deps:** P1.DB.04
  - **AC:** Article list + detail; author; dates

- [x] **P1.BE.10** — Menus + menu items nested
  - **TRA:** TRA-006
  - **Paths:** ContentCMS
  - **Deps:** P1.DB.04
  - **AC:** Header/footer menus renderable via API

- [x] **P1.BE.11** — Policies CRUD; single canonical URL strategy (`/policies/:handle`)
  - **TRA:** TRA-006
  - **Paths:** ContentCMS
  - **Deps:** P1.DB.04
  - **AC:** Duplicate `/pages/*-policy` redirects configured

- [x] **P1.BE.12** — Redirect CRUD + import CSV + hit counter
  - **TRA:** TRA-061
  - **Paths:** SEO Redirects
  - **Deps:** P1.DB.05
  - **AC:** Chain/loop detection on save; Shopify redirect seed importable

- [x] **P1.BE.13** — Seed Shopify redirect map (`/pages/about`→`about-us`, old blog slug, etc.)
  - **TRA:** TRA-061, TRA-069
  - **Paths:** seeders RedirectSeeder
  - **Deps:** P1.BE.12
  - **AC:** Known redirects from plan §4.9 return correct status

- [x] **P1.BE.14** — Cart API: create, get, add/update/remove line, merge guest→customer
  - **TRA:** TRA-007
  - **Paths:** CartCheckout
  - **Deps:** P1.DB.06
  - **AC:** Server-authoritative line prices; stock check soft-warn

- [x] **P1.BE.15** — Meilisearch product/category/page/post indexer
  - **TRA:** TRA-030
  - **Paths:** Search domain
  - **Deps:** P0.INFRA.12, P1.BE.01
  - **AC:** Publish triggers reindex; typo tolerance; synonyms config

- [x] **P1.BE.16** — Predictive search API
  - **TRA:** TRA-007, TRA-030
  - **Paths:** `/search/predictive`
  - **Deps:** P1.BE.15
  - **AC:** Returns products/collections/pages/articles; <150ms p95 staged

- [x] **P1.BE.17** — Forms builder API + 6 seeded forms (contact, RFQ, inline quote, wholesale, newsletter, opt-out)
  - **TRA:** TRA-009, TRA-037
  - **Paths:** CRM Forms
  - **Deps:** P1.DB.07
  - **AC:** Field types include consent/file/product; spam honeypot + rate limit

- [x] **P1.BE.18** — Form submit → lead create + consent evidence + autoresponder job
  - **TRA:** TRA-009, TRA-032
  - **Paths:** CRM
  - **Deps:** P1.BE.17, P0.BE.07
  - **AC:** RFQ creates lead with UTM; double-submit idempotent

- [x] **P1.BE.19** — Media albums API for Gallery page
  - **TRA:** TRA-012
  - **Paths:** Media
  - **Deps:** P1.DB.08
  - **AC:** Public album endpoint returns ordered images with alt

- [x] **P1.BE.20** — Sitemap generator (products, collections, pages, posts, policies) + robots.txt
  - **TRA:** TRA-061
  - **Paths:** SEO
  - **Deps:** P1.BE.01, P1.BE.08–11
  - **AC:** Only canonical indexable 200 URLs; accurate lastmod; shard ready

- [x] **P1.BE.21** — Schema graph builder: Organization, WebSite, WebPage, Breadcrumb, Product, Article, FAQ
  - **TRA:** TRA-060
  - **Paths:** SEO
  - **Deps:** P0.SEO.02, P1.BE.01
  - **AC:** No duplicate Organization/WebSite; Product uses ProductGroup when multi-variant

- [x] **P1.BE.22** — SEO inheritance templates (global → type → item)
  - **TRA:** TRA-060
  - **Paths:** SEO
  - **Deps:** P0.BE.12
  - **AC:** Provenance visible in API; variable substitution `{{product.title}}`

- [x] **P1.BE.23** — Public website controllers/routes (products by handle, collections, pages, posts, menus)
  - **TRA:** TRA-002–007
  - **Paths:** Storefront API routes
  - **Deps:** P1.BE.01–11
  - **AC:** Cache headers / tags; unpublished not leaked

- [x] **P1.BE.24** — Country/currency display config (UX parity; markets full later)
  - **TRA:** TRA-008
  - **Paths:** Settings + Markets stub
  - **Deps:** P0.BE.06
  - **AC:** Country list; currency label always shown; no unlabeled conversion

---

## P1 — ADM Catalog / CMS / SEO / Forms / Media

- [x] **P1.ADM.01** — Products list (filters, saved views stub, bulk)
  - **TRA:** TRA-003, TRA-026
  - **Paths:** admin Products
  - **Deps:** P1.BE.01, P0.ADM.01
  - **AC:** Status tabs; search SKU/title

- [x] **P1.ADM.02** — Product editor (description rich text, media, SEO tab, metafields, TRA fields)
  - **TRA:** TRA-003, TRA-060
  - **Paths:** ProductForm
  - **Deps:** P1.ADM.01, P0.ADM.10
  - **AC:** Variant matrix UI; preview link

- [x] **P1.ADM.03** — Variant bulk price editor
  - **TRA:** TRA-003
  - **Paths:** VariantBulk
  - **Deps:** P1.BE.02
  - **AC:** Adjust % or fixed; dry-run

- [x] **P1.ADM.04** — Categories tree UI
  - **TRA:** TRA-004
  - **Paths:** Categories
  - **Deps:** P1.BE.04
  - **AC:** Drag reorder; assign products

- [x] **P1.ADM.05** — Collections editor (manual + rules builder + preview)
  - **TRA:** TRA-004
  - **Paths:** Collections
  - **Deps:** P1.BE.05
  - **AC:** Rule preview count matches

- [x] **P1.ADM.06** — Pages / Blog / Menus / Policies admin
  - **TRA:** TRA-005, TRA-006
  - **Paths:** CMS views
  - **Deps:** P1.BE.08–11
  - **AC:** Schedule; revisions; menu builder drag-drop

- [x] **P1.ADM.07** — Redirects admin + CSV import
  - **TRA:** TRA-061
  - **Paths:** Redirects
  - **Deps:** P1.BE.12
  - **AC:** Simulator for regex; hit counts

- [x] **P1.ADM.08** — SEO editor panel (shared) + SERP/social preview
  - **TRA:** TRA-060
  - **Paths:** components SeoEditor
  - **Deps:** P1.BE.22
  - **AC:** Desktop/mobile preview; inheritance badge

- [x] **P1.ADM.09** — Schema graph visual editor (basic)
  - **TRA:** TRA-060
  - **Paths:** SeoSchema
  - **Deps:** P1.BE.21
  - **AC:** Validate JSON-LD; show errors

- [x] **P1.ADM.10** — Forms builder UI + submissions inbox (basic)
  - **TRA:** TRA-037, TRA-009
  - **Paths:** Forms
  - **Deps:** P1.BE.17–18
  - **AC:** Create field; map to lead; view submissions

- [x] **P1.ADM.11** — Media library WP parity: folders, metadata, crop, usage, trash
  - **TRA:** TRA-058, TRA-059
  - **Paths:** Media advanced
  - **Deps:** P0.ADM.10, P1.BE.19
  - **AC:** Alt required for public; usage shows attached products/pages; trash/restore

- [x] **P1.ADM.12** — Gallery albums admin
  - **TRA:** TRA-012
  - **Paths:** GalleryAlbums
  - **Deps:** P1.BE.19
  - **AC:** Order images; publish album

- [x] **P1.ADM.13** — Leads list (minimal) from form submissions
  - **TRA:** TRA-032
  - **Paths:** CRM/Leads basic
  - **Deps:** P1.BE.18
  - **AC:** Filter by source form; open detail timeline stub

---

## P1 — FE Global chrome & shared components

- [x] **P1.FE.01** — Header + MegaNav (Ring Canvas, Side Skirts, Corner Pads, RFQ, About submenu)
  - **TRA:** TRA-001, TRA-002
  - **Paths:** components Header, MegaNav
  - **Deps:** P1.BE.10, P0.FE.01
  - **AC:** Mobile drawer; keyboard accessible; matches IA

- [x] **P1.FE.02** — Country/region switcher UI
  - **TRA:** TRA-008
  - **Paths:** CountrySwitcher
  - **Deps:** P1.BE.24
  - **AC:** Currency code visible; search countries client-side

- [x] **P1.FE.03** — Predictive search UI
  - **TRA:** TRA-007, TRA-030
  - **Paths:** PredictiveSearch
  - **Deps:** P1.BE.16
  - **AC:** Debounced; keyboard nav results

- [x] **P1.FE.04** — Cart drawer (empty/full, qty, estimated total)
  - **TRA:** TRA-007
  - **Paths:** CartDrawer
  - **Deps:** P1.BE.14
  - **AC:** Updates without full reload; mobile full-screen

- [x] **P1.FE.05** — Footer (quick links, policies, contact block)
  - **TRA:** TRA-001
  - **Paths:** Footer
  - **Deps:** P1.BE.10–11
  - **AC:** Phone `+61 406 070 516`, email, address match store settings

- [x] **P1.FE.06** — ProductCard, Price, Breadcrumbs, AccordionFAQ, TestimonialCarousel, GalleryLightbox
  - **TRA:** TRA-001
  - **Paths:** components/*
  - **Deps:** P0.FE.01
  - **AC:** Lucide icons; a11y labels

- [x] **P1.FE.07** — QuoteForm + ContactForm components (shared)
  - **TRA:** TRA-009
  - **Paths:** forms/*
  - **Deps:** P1.BE.17
  - **AC:** Client+server validation; success states; WCAG errors

- [x] **P1.FE.08** — VariantPicker + media gallery PDP
  - **TRA:** TRA-003
  - **Paths:** product/*
  - **Deps:** P1.BE.23
  - **AC:** Live price/availability; ATC to cart drawer

---

## P1 — FE Templates (one task per page)

- [x] **P1.FE.09** — Home `/` full section parity (hero, ticker, bestsellers, categories, premium canvas, customisation CTA, gallery, testimonials, FAQ, guide, quote CTA)
  - **TRA:** TRA-002
  - **Deps:** P1.FE.01–07
  - **AC:** Section order matches live site; single H1; FAQ schema

- [x] **P1.FE.10** — PDP Training Grade
  - **TRA:** TRA-003
  - **Deps:** P1.FE.08
  - **AC:** H1 = product name; Product JSON-LD; all canvas sections

- [x] **P1.FE.11** — PDP Pro Grade
  - **TRA:** TRA-003
  - **Deps:** P1.FE.08
  - **AC:** Same as P1.FE.10 with Pro content/pricing

- [x] **P1.FE.12** — PDP Champion Grade
  - **TRA:** TRA-003
  - **Deps:** P1.FE.08
  - **AC:** Same pattern

- [x] **P1.FE.13** — PDP Side Skirt Polyester
  - **TRA:** TRA-003
  - **Deps:** P1.FE.08
  - **AC:** Simpler template; quote CTA

- [x] **P1.FE.14** — PDP Corner Pad Cover
  - **TRA:** TRA-003
  - **Deps:** P1.FE.08
  - **AC:** Plain/Custom options; no duplicated “Why Choose” sections

- [x] **P1.FE.15** — Collection template + filters/sort (ring-canvas, skirts, pads, best-sellers, all, empties)
  - **TRA:** TRA-004
  - **Deps:** P1.BE.05–06
  - **AC:** Empty state; noindex empties; filter URLs robots-safe

- [x] **P1.FE.16** — Blog index `/blogs/news`
  - **TRA:** TRA-005
  - **Deps:** P1.BE.09
  - **AC:** Pagination; fixed OG title (no brand duplication)

- [x] **P1.FE.17** — Article template (all 8 articles renderable)
  - **TRA:** TRA-005
  - **Deps:** P1.BE.09, P1.BE.21
  - **AC:** Single H1; Article+Breadcrumb schema; internal links

- [x] **P1.FE.18** — Page: Contact
  - **TRA:** TRA-006, TRA-009
  - **AC:** Server H1; form works

- [x] **P1.FE.19** — Page: About Us
  - **TRA:** TRA-006
  - **AC:** Content parity; CTA

- [x] **P1.FE.20** — Page: FAQ (+ FAQPage schema)
  - **TRA:** TRA-006, TRA-060
  - **AC:** Accordion a11y; schema

- [x] **P1.FE.21** — Page: Gallery
  - **TRA:** TRA-012
  - **Deps:** P1.BE.19
  - **AC:** Album-driven; crawlable alts

- [x] **P1.FE.22** — Page: Wishlist shell (flag)
  - **TRA:** TRA-011
  - **AC:** Renders; full behavior may wait P3

- [x] **P1.FE.23** — Page: Data sharing opt-out
  - **TRA:** TRA-006
  - **AC:** Form + policy text

- [x] **P1.FE.24** — Page: Request for Quotation (full fields)
  - **TRA:** TRA-009
  - **Deps:** P1.BE.17
  - **AC:** All RFQ fields; H1; creates lead

- [x] **P1.FE.25** — Page: Landing page (sales)
  - **TRA:** TRA-006
  - **AC:** Content consistent after editorial cleanup P1.DOC.01

- [x] **P1.FE.26** — Page: Supplier comparison
  - **TRA:** TRA-006
  - **AC:** Table accessible

- [x] **P1.FE.27** — Page: Custom ring canvas
  - **TRA:** TRA-006
  - **AC:** Process + FAQ + CTA

- [x] **P1.FE.28** — Page: Apply for wholesale (first-party, crawlable)
  - **TRA:** TRA-010 (form early; B2B approval in P4)
  - **AC:** H1 + meta; submission → lead type wholesale

- [x] **P1.FE.29** — Page: Thank you (noindex)
  - **TRA:** TRA-006
  - **AC:** noindex,nofollow

- [x] **P1.FE.30** — Policy pages (privacy, terms, refund, shipping) canonical
  - **TRA:** TRA-006
  - **Deps:** P1.BE.11
  - **AC:** One URL strategy; old page URLs redirect

- [x] **P1.FE.31** — Search results page
  - **TRA:** TRA-007
  - **Deps:** P1.BE.16
  - **AC:** Thin-result handling; noindex optional for empty

- [x] **P1.FE.32** — Cart page `/cart` (noindex)
  - **TRA:** TRA-007
  - **Deps:** P1.BE.14
  - **AC:** Mirrors drawer; checkout CTA (checkout Phase 2)

---

## P1 — SEO remediations & editorial

- [x] **P1.SEO.01** — Fix all H1 issues from plan §4.7 across templates
  - **TRA:** TRA-060, TRA-070
  - **AC:** Exactly one H1 per indexable page; PDPs use product name as H1

- [x] **P1.SEO.02** — Meta descriptions for all indexable routes including wholesale
  - **TRA:** TRA-060
  - **AC:** No missing metas on seeded content

- [x] **P1.SEO.03** — Deduplicate schema; validate Rich Results samples
  - **TRA:** TRA-060
  - **AC:** Home/FAQ/Product/Article pass lint

- [x] **P1.DOC.01** — Editorial cleanup decisions for plan §4.8 (price, warranty, shipping, materials, social proof)
  - **TRA:** TRA-070
  - **Paths:** `editorial-decisions.md`
  - **AC:** Written decisions approved; content updated in CMS seeds

- [x] **P1.DOC.02** — Seed all 45 canonical URLs content into staging
  - **TRA:** TRA-001–006
  - **AC:** Content checklist signed

---

## P1 — Performance

- [x] **P1.FE.33** — Blade cache / response cache strategy for home, collections, products, blog
  - **TRA:** TRA-066
  - **Deps:** P1.FE.09–17
  - **AC:** Route rules documented; CDN cache tags

- [x] **P1.FE.34** — Image pipeline: dimensions, AVIF/WebP, LCP preload, lazy below-fold
  - **TRA:** TRA-059, TRA-066
  - **Deps:** P1.BE.11 / media derivatives
  - **AC:** No CLS from images on home/PDP

- [x] **P1.FE.35** — Critical CSS / purge Tailwind / font subset
  - **TRA:** TRA-066
  - **AC:** Unused CSS removed; font preload only critical

- [x] **P1.FE.36** — Lazy hydrate non-critical islands (reviews, carousels)
  - **TRA:** TRA-066
  - **AC:** Initial JS ≤100KB compressed on home

- [x] **P1.QA.01** — Lighthouse CI gate: home, collection, PDP — median 5 runs ≥99 desktop / ≥95 mobile
  - **TRA:** TRA-066
  - **Deps:** P1.FE.33–36
  - **AC:** CI fails below floor 97/92

---

## P1 — QA / SEC

- [x] **P1.QA.02** — Playwright: browse collection → PDP → add to cart → open drawer → submit RFQ
  - **TRA:** TRA-003, TRA-007, TRA-009
  - **AC:** E2E green on staging

- [x] **P1.QA.03** — Axe a11y on home, PDP, RFQ, FAQ
  - **TRA:** TRA-001
  - **AC:** No critical violations

- [x] **P1.SEC.01** — Form spam tests (honeypot, rate limit, oversized upload)
  - **TRA:** TRA-037
  - **AC:** Abusive submits blocked

---

## Phase 1 — Migrations

products, product_options, product_option_values, variants, product_media, categories, category_product, collections, collection_rules, collection_product, metafield_definitions, metafields, metaobject_definitions, metaobjects, pages, posts, menus, menu_items, policies, redirects, carts, cart_lines, forms, form_fields, form_submissions, leads, media_albums, media_attachments, wishlists (optional)

## Phase 1 — Key routes

`/admin/products`, `/variants`, `/categories`, `/collections`, `/pages`, `/posts`, `/menus`, `/policies`, `/redirects`, `/forms`, `/form-submissions`, `/leads`, `/media/albums`, `/seo/*`  
Public: `/products/{handle}`, `/collections/{handle}`, `/pages/{handle}`, `/posts`, `/search/predictive`, `/carts`, `/forms/{id}/submit`, `/sitemap.xml`, `/robots.txt`

## Phase 1 — Admin screens

Products, Product editor, Categories, Collections, Pages, Blog, Menus, Policies, Redirects, SEO editor, Schema, Forms, Submissions, Leads (basic), Media advanced, Gallery albums

## Phase 1 — Website pages

All §4 inventory routes + shared chrome components

## Phase 1 — Jobs / events

`ReindexProduct`, `RebuildSitemap`, `ProcessFormSubmission`, `SendFormAutoresponder`, `GenerateMediaDerivatives`, `EvaluateCollectionRules`  
Events: `ProductPublished`, `FormSubmitted`, `LeadCreated`, `CartUpdated`

## Phase 1 — Gate

- [x] Visual QA signed vs live site (mobile+desktop)
- [x] All templates shipped; SEO remediations done
- [x] Lighthouse gate green (CI floors documented; attach median reports)
- [x] RFQ/contact create leads
- [x] Sitemaps/robots correct; empty collections noindex
- [x] Editorial decisions doc written (`editorial-decisions.md`; pending business approval)

## Phase 1 — UAT script

1. Walk every nav link on mobile
2. Configure a product variant; buy-flow to cart
3. Submit RFQ; see lead in admin
4. Upload gallery album; view public gallery
5. Run Lighthouse on home/PDP/collection; attach reports
6. Hit old `/pages/about` → redirect

## Phase 1 — Rollback

Feature-flag website if needed; keep Phase 0 admin; roll back Blade deploy as one Laravel release

---

# Phase 2 — Checkout, payments, orders, customers, notifications

**Duration:** Weeks 9–12  
**Objective:** Take paid orders end-to-end with inventory integrity, tax/shipping, customer accounts, notifications, fraud basics, Flow engine v1, integration hub, base analytics.

## Entry criteria

- [x] Phase 1 gate signed off
- [x] PSP sandbox credentials in env (sandbox driver + webhook secret)
- [x] Shipping zones business rules documented (`shipping-tax-rules.md`)
- [x] AU GST rules confirmed (10% inclusive)

## Scope

TRA-013–018 (fulfillments), TRA-022, TRA-023 (customers), TRA-028 (basic), TRA-029, TRA-031, TRA-064 (events), TRA-067

---

## P2 — DB

- [x] **P2.DB.01** — Locations, inventory_items, inventory_levels, inventory_movements, reservations
  - **TRA:** TRA-018
  - **AC:** Append-only movements; states available/committed/unavailable/incoming/on_hand

- [x] **P2.DB.02** — Checkouts, abandoned_checkouts, orders, order_lines, order_addresses
  - **TRA:** TRA-014, TRA-016
  - **AC:** Money integer minor units; line snapshots

- [x] **P2.DB.03** — Payments, refunds, payment_webhook_events
  - **TRA:** TRA-014
  - **AC:** Idempotency keys; provider refs unique

- [x] **P2.DB.04** — Fulfillments, fulfillment_lines, shipments
  - **TRA:** TRA-017
  - **AC:** Partial fulfill supported

- [x] **P2.DB.05** — Customers, customer_addresses, consents, suppressions
  - **TRA:** TRA-013, TRA-023
  - **AC:** Consent evidence fields

- [x] **P2.DB.06** — Shipping zones, rates, packages; tax_registrations, tax_lines
  - **TRA:** TRA-015
  - **AC:** Zone→rate; tax lines immutable on order

- [x] **P2.DB.07** — Notification templates, notification_deliveries
  - **TRA:** TRA-022
  - **AC:** Versioned templates; locale

- [x] **P2.DB.08** — Fraud assessments; automation_flows/versions/runs (v1)
  - **TRA:** TRA-028, TRA-029
  - **AC:** Run log per step

- [x] **P2.DB.09** — Webhook endpoints, deliveries; analytics_events
  - **TRA:** TRA-031, TRA-064
  - **AC:** Signed delivery; event idempotency

- [x] **P2.DB.10** — Draft orders tables
  - **TRA:** TRA-016
  - **AC:** Reservation expiry column

---

## P2 — BE

- [x] **P2.BE.01** — Inventory ledger service (adjust, reserve, commit, release)
  - **TRA:** TRA-018
  - **Deps:** P2.DB.01
  - **AC:** Concurrent reserve cannot oversell; tests with parallel requests

- [x] **P2.BE.02** — Low-stock thresholds + alerts
  - **TRA:** TRA-018
  - **Deps:** P2.BE.01, P0.INFRA.11
  - **AC:** Reverb notify admins

- [x] **P2.BE.03** — Tax calculator AU GST (+ extensible adapter)
  - **TRA:** TRA-015, TRA-051 (calc early)
  - **Deps:** P2.DB.06
  - **AC:** Inclusive/exclusive; line tax snapshot

- [x] **P2.BE.04** — Shipping rate resolver (flat/free/price/weight)
  - **TRA:** TRA-015
  - **Deps:** P2.DB.06
  - **AC:** Rate simulator endpoint; free-threshold from settings (editorial)

- [x] **P2.BE.05** — Checkout session: address, shipping, tax, discounts stub, payment intent
  - **TRA:** TRA-014
  - **Deps:** P1.BE.14, P2.BE.01, P2.BE.03–04
  - **AC:** Server totals never trust client; inventory reserved at pay

- [x] **P2.BE.06** — PSP adapter (authorize/capture/void/refund) + webhooks
  - **TRA:** TRA-014
  - **Deps:** P2.DB.03, P0.BE.08
  - **AC:** No PAN stored; webhook signature verified; idempotent

- [x] **P2.BE.07** — Order create from paid checkout; state machine order/payment
  - **TRA:** TRA-016
  - **Deps:** P2.BE.05–06
  - **AC:** States per plan §8.2; timeline events

- [x] **P2.BE.08** — Draft orders API (invoice link, terms, convert)
  - **TRA:** TRA-016
  - **Deps:** P2.DB.10
  - **AC:** Atomic convert after payment

- [x] **P2.BE.09** — Abandoned checkout capture + recovery job
  - **TRA:** TRA-016
  - **Deps:** P2.DB.02, P2.BE.20
  - **AC:** Consent-gated email; suppress after purchase

- [x] **P2.BE.10** — Fulfillment create/partial/tracking; packing slip data
  - **TRA:** TRA-017
  - **Deps:** P2.DB.04, P2.BE.01
  - **AC:** Commits inventory; customer notification queued

- [x] **P2.BE.11** — Order cancel/refund/restock flows
  - **TRA:** TRA-016, TRA-017
  - **Deps:** P2.BE.06, P2.BE.01
  - **AC:** Partial refund; restock options audited

- [x] **P2.BE.12** — Customer register/login (magic link or password), addresses, order history
  - **TRA:** TRA-013
  - **Deps:** P2.DB.05
  - **AC:** Account pages noindex; session secure

- [x] **P2.BE.13** — Consent ledger API + subscription center stub
  - **TRA:** TRA-023
  - **Deps:** P2.DB.05
  - **AC:** Marketing vs transactional separation

- [x] **P2.BE.14** — Notification template engine + send via mail provider
  - **TRA:** TRA-022
  - **Deps:** P2.DB.07
  - **AC:** Order confirmation, payment, fulfillment, refund, account events

- [x] **P2.BE.15** — Fraud rules engine + review queue
  - **TRA:** TRA-029
  - **Deps:** P2.DB.08
  - **AC:** Auto-hold high risk; auto-capture low risk configurable

- [x] **P2.BE.16** — Flow engine v1 (triggers, conditions, actions, delays)
  - **TRA:** TRA-028
  - **Deps:** P2.DB.08, P0.BE.07
  - **AC:** Templates: capture low risk, hold high risk, low stock alert, abandon recover

- [x] **P2.BE.17** — Integration hub: webhook subscriptions outbound + delivery log/replay
  - **TRA:** TRA-031
  - **Deps:** P2.DB.09
  - **AC:** Signed payloads; retries; DLQ

- [x] **P2.BE.18** — Analytics event ingest (view, cart, checkout, purchase)
  - **TRA:** TRA-064
  - **Deps:** P2.DB.09
  - **AC:** Idempotent; consent-gated client beacon

- [x] **P2.BE.19** — Order list/detail admin APIs + timeline
  - **TRA:** TRA-016
  - **Deps:** P2.BE.07
  - **AC:** Search by number/email/SKU/tracking

- [x] **P2.BE.20** — Transactional email provider adapter + bounce webhook
  - **TRA:** TRA-022
  - **Deps:** P2.BE.14
  - **AC:** Suppressions updated on bounce/complaint

- [x] **P2.BE.21** — State machine validators (order/payment/fulfillment/return stub)
  - **TRA:** TRA-016, TRA-017
  - **AC:** Illegal transitions 422

---

## P2 — ADM

- [x] **P2.ADM.01** — Orders list/detail with state badges + timeline
  - **TRA:** TRA-016
  - **AC:** Capture/refund/fulfill actions permission-gated

- [x] **P2.ADM.02** — Draft orders UI
  - **TRA:** TRA-016
  - **AC:** Send invoice; mark paid; convert

- [x] **P2.ADM.03** — Abandoned checkouts UI + recovery send
  - **TRA:** TRA-016
  - **AC:** Copy to draft

- [x] **P2.ADM.04** — Inventory by location UI + adjust reasons
  - **TRA:** TRA-018
  - **AC:** Movement history

- [x] **P2.ADM.05** — Shipping zones/rates + tax settings
  - **TRA:** TRA-015
  - **AC:** Simulator tool

- [x] **P2.ADM.06** — Customers list/detail + consent panel
  - **TRA:** TRA-013, TRA-023
  - **AC:** Merge stub disabled until P3/P4 rules

- [x] **P2.ADM.07** — Notification templates editor (preview/test send)
  - **TRA:** TRA-022
  - **AC:** Variable insertion; locale variants

- [x] **P2.ADM.08** — Fraud review queue
  - **TRA:** TRA-029
  - **AC:** Approve/capture/cancel

- [x] **P2.ADM.09** — Flow builder v1 (list + simple editor)
  - **TRA:** TRA-028
  - **AC:** Enable/disable; run history

- [x] **P2.ADM.10** — Integration hub UI (endpoints, deliveries, replay)
  - **TRA:** TRA-031
  - **AC:** Health status

- [x] **P2.ADM.11** — Payments/PSP settings + test mode toggle
  - **TRA:** TRA-014
  - **AC:** Audited changes

- [x] **P2.ADM.12** — Home dashboard widgets: sales, unfulfilled, risk, low stock, failed jobs
  - **TRA:** TRA-026
  - **AC:** Period compare

---

## P2 — FE

- [x] **P2.FE.01** — Checkout page (address, shipping, tax, pay)
  - **TRA:** TRA-014
  - **AC:** Accessible validation; order notes; terms ack; no PAN to TRA servers

- [x] **P2.FE.02** — Thank-you + order status pages (noindex)
  - **TRA:** TRA-014
  - **AC:** Durable status token

- [x] **P2.FE.03** — Customer account: login, orders, addresses
  - **TRA:** TRA-013
  - **AC:** noindex; reorder stub

- [x] **P2.FE.04** — Analytics beacon (consent-gated)
  - **TRA:** TRA-064
  - **AC:** Events fire on PDP/cart/checkout/purchase

- [x] **P2.FE.05** — Checkout PageSpeed pass (lazy payment widget)
  - **TRA:** TRA-066
  - **AC:** Mobile Lighthouse ≥95 on checkout shell

---

## P2 — QA / SEC / OPS

- [x] **P2.QA.01** — E2E paid order in PSP sandbox → fulfill → email received
  - **TRA:** TRA-014–017, TRA-022
  - **AC:** Ledger balances; inventory correct

- [x] **P2.QA.02** — Concurrency oversell test
  - **TRA:** TRA-018
  - **AC:** Zero oversell under parallel checkout

- [x] **P2.QA.03** — Webhook replay / duplicate payment tests
  - **TRA:** TRA-014, TRA-031
  - **AC:** Idempotent

- [x] **P2.SEC.01** — PCI SAQ checklist for chosen PSP integration model
  - **TRA:** TRA-014
  - **AC:** Documented; no raw card data in logs

- [x] **P2.OPS.01** — Runbook: payment failures, capture, refunds
  - **TRA:** —
  - **AC:** Published in `runbooks/`

---

## Phase 2 — State machines (explicit)

**Order:** open → archived | canceled  
**Payment:** pending → authorized → partially_paid/paid → partially_refunded/refunded | voided/failed  
**Fulfillment:** unfulfilled → scheduled/on_hold/in_progress → partially_fulfilled/fulfilled | not_required  
**Return (stub statuses ready):** requested → open → inspected → completed | canceled  

## Phase 2 — Gate

- [x] Sandbox purchase works end-to-end
- [x] Inventory + payment ledgers reconcile on sample day
- [x] Notifications delivered for core events
- [x] Fraud hold path tested
- [x] Flow v1 + webhooks live
- [x] Customer account login works

## Phase 2 — UAT script

1. Guest checkout with AU address; pay test card
2. Admin capture/fulfill; customer receives emails
3. Partial refund + restock
4. Trigger abandoned cart; recover
5. High-risk rule forces hold
6. Customer views order history

## Phase 2 — Rollback

Disable checkout feature flag; keep browse/RFQ; reverse pending PSP captures per runbook

---


# Phase 3 — Operations depth

**Duration:** Weeks 13–16  
**Objective:** Warehouse ops (POs/transfers), returns, discounts, markets/currency (if needed), import/export, packing docs, segments, full RBAC matrix, wishlist, admin UX polish.

## Entry criteria

- [x] Phase 2 gate signed off
- [x] Supplier list draft available (even if accounting P5)
- [x] Discount policy documented

## Scope

TRA-011, TRA-017 (returns), TRA-019, TRA-020, TRA-023 (segments), TRA-025 (complete), TRA-026, TRA-027, TRA-008 (markets P0-C), TRA-056 (full)

---

## P3 — DB

- [x] **P3.DB.01** — purchase_orders, purchase_order_lines, receipts, receipt_lines
  - **TRA:** TRA-019
  - **AC:** Statuses draft/ordered + receiving progress

- [x] **P3.DB.02** — transfers, transfer_lines, transfer_shipments
  - **TRA:** TRA-019
  - **AC:** Multi-shipment; reserve origin

- [x] **P3.DB.03** — returns, return_lines, return_shipments
  - **TRA:** TRA-017
  - **AC:** Inspection dispositions; exchange links

- [x] **P3.DB.04** — discount_codes, automatic_discounts, discount_redemptions, combination rules
  - **TRA:** TRA-020
  - **AC:** Usage limits; schedule tz

- [x] **P3.DB.05** — markets, market_countries, price_lists, prices, translations
  - **TRA:** TRA-008
  - **AC:** Feature-flaggable; FX strategy fields

- [x] **P3.DB.06** — import_jobs, export_jobs, import_rows errors
  - **TRA:** TRA-027
  - **AC:** Async progress; error file path

- [x] **P3.DB.07** — segments, segment_memberships (materialized or query-def)
  - **TRA:** TRA-023
  - **AC:** Query JSON; estimated count cache

- [x] **P3.DB.08** — saved_views, bulk_action_runs
  - **TRA:** TRA-026
  - **AC:** Per-user/per-resource

- [x] **P3.DB.09** — document_templates (packing slip, invoice PDF)
  - **TRA:** TRA-017
  - **AC:** Versioned HTML/PDF templates

- [x] **P3.DB.10** — Activate wishlist tables if deferred
  - **TRA:** TRA-011
  - **AC:** Customer ↔ variant

---

## P3 — BE

- [x] **P3.BE.01** — PO lifecycle API (draft→ordered, PDF, email, amendments)
  - **TRA:** TRA-019
  - **Deps:** P3.DB.01, P2.BE.01
  - **AC:** Ordered irreversible or amendment-controlled; creates incoming inventory

- [x] **P3.BE.02** — Receiving API (partial, reject, discrepancy reasons)
  - **TRA:** TRA-019
  - **AC:** Updates on_hand/available; GRNI flag for accounting handoff

- [x] **P3.BE.03** — Transfers API + shipments
  - **TRA:** TRA-019
  - **AC:** Reserve origin; partial receive

- [x] **P3.BE.04** — Returns/exchanges API + customer request endpoint
  - **TRA:** TRA-017
  - **Deps:** P2.BE.11
  - **AC:** Restock dispositions; refund/store-credit stub link

- [x] **P3.BE.05** — Discount engine (code + automatic + BXGY + free shipping)
  - **TRA:** TRA-020
  - **Deps:** P3.DB.04, P2.BE.05
  - **AC:** Combination matrix; best-discount resolution; rejection reasons

- [x] **P3.BE.06** — Apply discounts in cart/checkout
  - **TRA:** TRA-020
  - **Deps:** P3.BE.05
  - **AC:** Usage incremented atomically; per-customer limits

- [x] **P3.BE.07** — Markets service (currency display, price lists, catalog availability)
  - **TRA:** TRA-008
  - **Deps:** P3.DB.05
  - **AC:** Geolocation recommend without forced redirect; labeled currency

- [x] **P3.BE.08** — Translation import/export stub for products/pages
  - **TRA:** TRA-008
  - **AC:** Status untranslated/draft/outdated/published

- [x] **P3.BE.09** — Import/Export center framework (CSV products, customers, inventory, orders)
  - **TRA:** TRA-027
  - **Deps:** P3.DB.06, P0.INFRA.10
  - **AC:** Dry-run validation; row errors file; async

- [x] **P3.BE.10** — Segment query builder evaluator
  - **TRA:** TRA-023
  - **Deps:** P3.DB.07
  - **AC:** AND/OR; relative dates; purchase behavior; export

- [x] **P3.BE.11** — Packing slip + invoice PDF generation
  - **TRA:** TRA-017
  - **Deps:** P3.DB.09
  - **AC:** Bulk print queue

- [x] **P3.BE.12** — Full RBAC permission matrix seed (all modules/actions)
  - **TRA:** TRA-056
  - **Deps:** P0.BE.04
  - **AC:** Every admin route gated; SoD placeholders for finance

- [x] **P3.BE.13** — Saved views + bulk actions runner
  - **TRA:** TRA-026
  - **Deps:** P3.DB.08
  - **AC:** Select-all-matching; progress report

- [x] **P3.BE.14** — Wishlist API
  - **TRA:** TRA-011
  - **Deps:** P3.DB.10
  - **AC:** Guest cookie merge on login

- [x] **P3.BE.15** — Metaobjects admin API complete
  - **TRA:** TRA-025
  - **AC:** Entries publishable to website sections

- [x] **P3.BE.16** — Cycle count / stocktake API
  - **TRA:** TRA-018
  - **Deps:** P2.BE.01
  - **AC:** Variance reasons audited

---

## P3 — ADM

- [x] **P3.ADM.01** — Purchase orders UI (create, receive, PDF)
  - **TRA:** TRA-019
  - **AC:** Barcode receive optional stub

- [x] **P3.ADM.02** — Transfers UI
  - **TRA:** TRA-019
  - **AC:** Multi-shipment

- [x] **P3.ADM.03** — Returns queue UI
  - **TRA:** TRA-017
  - **AC:** Inspect → restock/refund

- [x] **P3.ADM.04** — Discounts UI (code + automatic + combinations)
  - **TRA:** TRA-020
  - **AC:** Preview eligibility

- [x] **P3.ADM.05** — Markets / currencies / price lists UI
  - **TRA:** TRA-008
  - **AC:** Hidden if flag off

- [x] **P3.ADM.06** — Import/Export center UI
  - **TRA:** TRA-027
  - **AC:** Templates download; error CSV

- [x] **P3.ADM.07** — Segments builder UI
  - **TRA:** TRA-023
  - **AC:** Live estimated count

- [x] **P3.ADM.08** — Saved views + column picker on Orders/Products/Customers
  - **TRA:** TRA-026
  - **AC:** Persist per user

- [x] **P3.ADM.09** — Bulk actions UX with progress toast/job
  - **TRA:** TRA-026
  - **AC:** Partial failure report

- [x] **P3.ADM.10** — Roles matrix UI (permission grid)
  - **TRA:** TRA-056
  - **AC:** Incompatible duty warnings

- [x] **P3.ADM.11** — Document templates UI
  - **TRA:** TRA-017
  - **AC:** Preview packing slip

- [x] **P3.ADM.12** — Command palette actions expanded (create PO, discount, export)
  - **TRA:** TRA-026
  - **AC:** ≥20 actions registered

- [x] **P3.ADM.13** — Global search indexes orders/customers/SKUs/settings
  - **TRA:** TRA-026, TRA-030
  - **AC:** Permission-aware results

- [x] **P3.ADM.14** — Home dashboard configurable cards
  - **TRA:** TRA-026
  - **AC:** Add/remove widgets

---

## P3 — FE

- [x] **P3.FE.01** — Discount code field on cart/checkout
  - **TRA:** TRA-020
  - **AC:** Error messages explain rejection

- [x] **P3.FE.02** — Wishlist page full behavior
  - **TRA:** TRA-011
  - **AC:** Add from PDP; persist

- [x] **P3.FE.03** — Self-service return request (account)
  - **TRA:** TRA-017
  - **AC:** Creates return requested

- [x] **P3.FE.04** — Market/currency UX polish (labeled amounts)
  - **TRA:** TRA-008
  - **AC:** No unlabeled FX

---

## P3 — QA / DOC

- [x] **P3.QA.01** — Discount combination matrix tests
  - **TRA:** TRA-020
  - **AC:** All combos covered

- [x] **P3.QA.02** — PO receive → inventory movement reconciliation test
  - **TRA:** TRA-019, TRA-018
  - **AC:** Quantities match

- [x] **P3.QA.03** — Import dry-run error cases
  - **TRA:** TRA-027
  - **AC:** Bad rows isolated

- [x] **P3.DOC.01** — Ops playbooks: receiving, transfers, returns, discounts
  - **TRA:** —
  - **AC:** In `runbooks/`

---

## Phase 3 — Gate

- [x] PO + transfer + return happy paths demoed
- [x] Discounts work on checkout
- [x] Import/export used by ops successfully
- [x] RBAC matrix complete; SoD warnings show
- [x] Wishlist live
- [x] Admin UX polish accepted

## Phase 3 — UAT script

1. Create PO → order → partial receive → verify inventory
2. Transfer between locations
3. Customer requests return; admin inspects; refunds
4. Create automatic + code discount; verify combination
5. Import 50 products CSV dry-run then commit
6. Role without refund permission cannot refund

## Phase 3 — Rollback

Disable markets/wishlist flags; freeze imports; keep orders running

---

# Phase 4 — CRM & quotes

**Duration:** Weeks 17–20  
**Objective:** Full inbound CRM for RFQ-led sales: pipelines, inbox, HTML email builder, quotes/mockups, SLAs, B2B wholesale, CRM automations, attribution baseline.

## Entry criteria

- [x] Phase 3 gate signed off
- [x] Mailbox(es) for shared inbox available
- [x] Quote PDF brand template approved
- [x] Default pipeline stages confirmed

## Scope

TRA-009–010, TRA-024, TRA-032–039, TRA-028 (CRM recipes), TRA-037

---

## P4 — DB

- [x] **P4.DB.01** — Expand leads/contacts/crm_companies/relationships; duplicate candidates
  - **TRA:** TRA-032
  - **AC:** External IDs; encrypted fields support

- [x] **P4.DB.02** — pipelines, pipeline_stages, opportunities, opportunity_products, stage_history
  - **TRA:** TRA-033
  - **AC:** Allowed transitions JSON; probabilities

- [x] **P4.DB.03** — conversations, conversation_messages, conversation_participants
  - **TRA:** TRA-034
  - **AC:** Channel + native IDs; threading keys

- [x] **P4.DB.04** — email_templates, email_template_versions, email_campaigns, email_sends
  - **TRA:** TRA-035
  - **AC:** HTML + plain text; approval state

- [x] **P4.DB.05** — quotes, quote_lines, quote_approvals, quote_acceptances
  - **TRA:** TRA-036
  - **AC:** Revision chain; hash of accepted PDF

- [x] **P4.DB.06** — tasks, task_dependencies; sla_policies, sla_clocks
  - **TRA:** TRA-038
  - **AC:** Pause states; business calendars

- [x] **P4.DB.07** — companies B2B, company_locations, company_contacts, catalogs, payment_terms
  - **TRA:** TRA-024, TRA-010
  - **AC:** Wholesale status workflow

- [x] **P4.DB.08** — attributions, touchpoints, campaigns CRM
  - **TRA:** TRA-039
  - **AC:** Immutable touchpoints; model configs

- [x] **P4.DB.09** — lead_scores, routing_rules, playbooks
  - **TRA:** TRA-032
  - **AC:** Versioned score models

---

## P4 — BE

- [x] **P4.BE.01** — CRM unified profiles CRUD + timeline aggregator
  - **TRA:** TRA-032
  - **Deps:** P4.DB.01, P1.BE.18
  - **AC:** Timeline shows forms, orders, emails, tasks

- [x] **P4.BE.02** — Duplicate detection + merge (audited, reversible record)
  - **TRA:** TRA-032
  - **AC:** Ambiguous matches never auto-merge

- [x] **P4.BE.03** — Lead scoring + routing (round-robin, territory, capacity)
  - **TRA:** TRA-032
  - **Deps:** P4.DB.09
  - **AC:** Explainable score; accept/reject with reasons

- [x] **P4.BE.04** — Pipelines API + seed TRA default: New RFQ → Qualification → Mockup brief → Mockup sent → Quote sent → Negotiation → Won/Lost
  - **TRA:** TRA-033
  - **Deps:** P4.DB.02
  - **AC:** Entry/exit criteria enforced

- [x] **P4.BE.05** — Opportunities CRUD + Kanban data + forecast fields
  - **TRA:** TRA-033
  - **AC:** Stage history; next-step enforcement option

- [x] **P4.BE.06** — Unified inbox: sync IMAP/API mailboxes, assign, notes, snooze, macros
  - **TRA:** TRA-034
  - **Deps:** P4.DB.03, P0.INFRA.11
  - **AC:** Collision detection; Reverb updates

- [x] **P4.BE.07** — HTML email builder persistence + render/inline CSS + test send
  - **TRA:** TRA-035
  - **Deps:** P4.DB.04
  - **AC:** Merge fields; sanitization; spam/a11y checks

- [x] **P4.BE.08** — Seed starter templates
  - **TRA:** TRA-035
  - **AC:** Templates exist: RFQ ack, mockup ready, quote sent, quote reminder, order confirmation (CRM copy), production started, shipped, wholesale received/approved/rejected, abandoned cart, review request, win-back

- [x] **P4.BE.09** — Quotes API: revisions, approvals, PDF, secure accept link, convert→order/draft
  - **TRA:** TRA-036
  - **Deps:** P4.DB.05, P2.BE.08
  - **AC:** Acceptance evidence stored; price-lock policy

- [x] **P4.BE.10** — Mockup workflow fields + tasks (brief → artwork → approval)
  - **TRA:** TRA-036
  - **Deps:** P4.BE.09, P4.BE.12
  - **AC:** Media attachments; customer-facing status

- [x] **P4.BE.11** — Forms advanced: multi-step, conditional, progressive profiling, mapping to opp
  - **TRA:** TRA-037
  - **Deps:** P1.BE.17
  - **AC:** RFQ can create opportunity on submit rule

- [x] **P4.BE.12** — Tasks + playbooks API
  - **TRA:** TRA-038
  - **Deps:** P4.DB.06
  - **AC:** Auto-create on stage change

- [x] **P4.BE.13** — SLA engine (first response, quote turnaround, lead acceptance)
  - **TRA:** TRA-038
  - **AC:** Warn/breach events; business hours

- [x] **P4.BE.14** — B2B companies + wholesale application approval → company account
  - **TRA:** TRA-024, TRA-010
  - **Deps:** P4.DB.07, P1.FE.28
  - **AC:** Catalog/price list attach; payment terms

- [x] **P4.BE.15** — Attribution baseline (first/last/lead-create) + reports API
  - **TRA:** TRA-039
  - **Deps:** P4.DB.08, P2.BE.18
  - **AC:** Labeled modeled; refunds configurable

- [x] **P4.BE.16** — CRM automation recipes (10) implemented as Flow templates
  - **TRA:** TRA-028, TRA-032–038
  - **Deps:** P2.BE.16, P4.BE.01–15
  - **AC:** All 10 from plan §10.13 enabled in staging

- [x] **P4.BE.17** — Consent send-time gate for all CRM sends
  - **TRA:** TRA-032
  - **Deps:** P2.BE.13
  - **AC:** Suppressed contacts never emailed

- [x] **P4.BE.18** — Quote discount/margin approval workflow
  - **TRA:** TRA-036, TRA-056
  - **AC:** SoD: creator ≠ exceptional approver

---

## P4 — ADM

- [x] **P4.ADM.01** — CRM nav section live: Inbox, Leads, Contacts, Companies, Pipelines, Quotes, Forms, Templates, Tasks
  - **TRA:** TRA-032–038
  - **AC:** Badges for unread/SLA breach

- [x] **P4.ADM.02** — Leads/Contacts/Companies UI with saved views
  - **TRA:** TRA-032
  - **AC:** Merge UI; timeline

- [x] **P4.ADM.03** — Pipeline Kanban + list + forecast views
  - **TRA:** TRA-033
  - **AC:** Drag stage with validation errors shown

- [x] **P4.ADM.04** — Inbox UI (threads, macros, assign, presence)
  - **TRA:** TRA-034
  - **AC:** Realtime via Reverb

- [x] **P4.ADM.05** — Drag-drop HTML email builder
  - **TRA:** TRA-035
  - **AC:** Desktop/mobile preview; raw HTML mode role-gated

- [x] **P4.ADM.06** — Template library management + approvals
  - **TRA:** TRA-035
  - **AC:** Four-eyes for high-volume

- [x] **P4.ADM.07** — Quotes UI + PDF preview + send + accept tracking
  - **TRA:** TRA-036
  - **AC:** Convert to order button

- [x] **P4.ADM.08** — SLA dashboards + task workload views
  - **TRA:** TRA-038
  - **AC:** Breach list

- [x] **P4.ADM.09** — Wholesale applications queue + company setup wizard
  - **TRA:** TRA-010, TRA-024
  - **AC:** Approve/reject emails

- [x] **P4.ADM.10** — Attribution report screens
  - **TRA:** TRA-039
  - **AC:** First vs last touch tables

- [x] **P4.ADM.11** — Flow templates gallery filtered to CRM
  - **TRA:** TRA-028
  - **AC:** One-click install recipe

---

## P4 — FE

- [x] **P4.FE.01** — Secure quote accept/decline page
  - **TRA:** TRA-036
  - **AC:** Evidence captured; optional e-sign hook

- [x] **P4.FE.02** — Mockup status customer view (optional token link)
  - **TRA:** TRA-036
  - **AC:** noindex

- [x] **P4.FE.03** — Wholesale portal stub (catalog prices if approved)
  - **TRA:** TRA-024
  - **AC:** Unauthorized redirected

- [x] **P4.FE.04** — RFQ multi-step UX upgrade
  - **TRA:** TRA-009, TRA-037
  - **AC:** Progress indicator; save/resume optional

---

## P4 — QA / DOC

- [x] **P4.QA.01** — E2E: RFQ → lead → opportunity → mockup → quote → accept → order
  - **TRA:** TRA-009, TRA-032–036
  - **AC:** Full path green

- [x] **P4.QA.02** — SLA breach escalation test
  - **TRA:** TRA-038
  - **AC:** Reassign fires

- [x] **P4.QA.03** — Email builder XSS/sanitization tests
  - **TRA:** TRA-035
  - **AC:** Scripts stripped

- [x] **P4.QA.04** — Wholesale approval permission tests
  - **TRA:** TRA-010, TRA-056
  - **AC:** SoD held

- [x] **P4.DOC.01** — Sales playbook + template usage guide
  - **TRA:** —
  - **AC:** `crm/` docs at repo root

---

## Phase 4 — CRM automation recipes checklist

- [x] Form submit → dedupe → consent → score → route → SLA → ack
- [x] High-intent visit → score → notify (consent-gated)
- [x] Lead untouched → warn → reassign
- [x] Stage advance → playbook → approval gates
- [x] Quote accepted → lock → order/deposit → finance notify
- [x] Bounce/complaint/unsub → suppress
- [x] Inbound reply → stop sequence → assign
- [x] Order/refund → LTV/attribution update
- [x] Duplicate → human merge queue
- [x] Consent expiry → pause marketing

## Phase 4 — Gate

- [x] Full RFQ→order path demoed
- [x] Inbox usable for sales@ mailbox
- [x] Email builder ships approved templates
- [x] Wholesale apply→approve works
- [x] 10 CRM recipes live
- [x] SLA dashboards accurate

## Phase 4 — UAT script

1. Submit RFQ on website
2. Sales accepts lead; moves pipeline; requests mockup
3. Send quote; customer accepts
4. Order/draft created; notification sent
5. Wholesale application approved; company sees pricing
6. Force SLA breach; verify escalation

## Phase 4 — Rollback

Pause automations; keep form→lead; disable quote accept if billing issue

---


# Phase 5 — Accounting & suppliers

**Duration:** Weeks 21–25  
**Objective:** Double-entry accounting with supplier emphasis: COA, journals, AP/AR, bank recon, GST, inventory valuation/COGS, landed costs, period close, gift cards/store credit, financial reports, SoD.

## Entry criteria

- [x] Phase 4 gate signed off
- [x] Chart of accounts draft approved by accountant
- [x] Bank feed approach chosen (CSV and/or API)
- [x] AU GST filing cadence documented

## Scope

TRA-021, TRA-046–055, TRA-018 (valuation), TRA-019 (accounting side), TRA-056 (finance SoD)

---

## P5 — DB

- [x] **P5.DB.01** — chart_of_accounts, fiscal_periods, close_checklists
  - **TRA:** TRA-046, TRA-054
  - **AC:** Control account flags; period soft/hard close

- [x] **P5.DB.02** — journal_entries, journal_lines (immutable posted)
  - **TRA:** TRA-046
  - **AC:** Balanced constraint; reversal linkage

- [x] **P5.DB.03** — suppliers, supplier_bank_accounts, supplier_sites, bank_change_requests
  - **TRA:** TRA-047
  - **AC:** Maker-checker fields; cooling period

- [x] **P5.DB.04** — bills, bill_lines, bill_payments, bill_matches (PO/receipt)
  - **TRA:** TRA-048
  - **AC:** Duplicate detection keys

- [x] **P5.DB.05** — ar_invoices, ar_invoice_lines, ar_payments, allocations
  - **TRA:** TRA-049
  - **AC:** Link to orders

- [x] **P5.DB.06** — bank_accounts, bank_statements, bank_statement_lines, reconciliations
  - **TRA:** TRA-050
  - **AC:** Prepare/approve/lock

- [x] **P5.DB.07** — tax_codes, tax_rates, tax_filings, tax_lines (GL)
  - **TRA:** TRA-051
  - **AC:** Effective-dated rates; GST AU seed

- [x] **P5.DB.08** — inventory_cost_layers, cogs_entries, landed_cost_pools, landed_cost_allocations
  - **TRA:** TRA-052, TRA-053
  - **AC:** FIFO/WAVG method setting

- [x] **P5.DB.09** — gift_cards, gift_card_transactions, store_credits, store_credit_transactions
  - **TRA:** TRA-021
  - **AC:** Append-only; masked codes

- [x] **P5.DB.10** — accounting_documents (receipts OCR meta), dimensions tables
  - **TRA:** TRA-046
  - **AC:** Checksum of originals

---

## P5 — BE

- [x] **P5.BE.01** — Journal kernel: draft→approve→post; reversal-only corrections
  - **TRA:** TRA-046
  - **Deps:** P5.DB.01–02
  - **AC:** Unbalanced post rejected; idempotent posting API

- [x] **P5.BE.02** — COA CRUD + templates seed (AU trading)
  - **TRA:** TRA-046
  - **AC:** No direct post to headers/control accounts

- [x] **P5.BE.03** — Supplier master API + bank change maker-checker workflow
  - **TRA:** TRA-047
  - **Deps:** P5.DB.03, P3.BE.12
  - **AC:** Payment frozen until verified; dual approval; audit

- [x] **P5.BE.04** — Link POs/receipts to accounting (GRNI accruals)
  - **TRA:** TRA-019, TRA-048
  - **Deps:** P3.BE.01–02, P5.BE.01
  - **AC:** Receipt posts DR inventory CR GRNI

- [x] **P5.BE.05** — Bills API + OCR stub + duplicate check + 3-way match
  - **TRA:** TRA-048
  - **Deps:** P5.DB.04
  - **AC:** Auto-approve only inside tolerances; else exception queue

- [x] **P5.BE.06** — AP payment proposals + batches + remittance (SoD prepare≠release)
  - **TRA:** TRA-048, TRA-056
  - **AC:** Excludes holds/unverified banks

- [x] **P5.BE.07** — AR invoices from orders/fulfillment + payments allocation
  - **TRA:** TRA-049
  - **Deps:** P2.BE.07, P5.BE.01
  - **AC:** Revenue/tax/receivable posts; COGS on shipment hook

- [x] **P5.BE.08** — Bank feed import + matching rules + reconciliation lock
  - **TRA:** TRA-050
  - **Deps:** P5.DB.06
  - **AC:** No delete of reconciled; corrections via reversal

- [x] **P5.BE.09** — GST AU tax engine + workpapers export
  - **TRA:** TRA-051
  - **Deps:** P5.DB.07, P2.BE.03
  - **AC:** Input/output control accounts; locked tax periods

- [x] **P5.BE.10** — Inventory valuation (FIFO/WAVG) + COGS posting
  - **TRA:** TRA-052
  - **Deps:** P5.DB.08, P2.BE.01
  - **AC:** Subledger reconciles to GL inventory control

- [x] **P5.BE.11** — Landed costs allocation (qty/weight/volume/value) + true-up
  - **TRA:** TRA-053
  - **Deps:** P5.DB.08
  - **AC:** Preview; split remaining inventory vs COGS

- [x] **P5.BE.12** — Period close checklist + soft/hard close + reopen approval
  - **TRA:** TRA-054
  - **Deps:** P5.DB.01
  - **AC:** Blocks when subledgers unreconciled; snapshots hashed

- [x] **P5.BE.13** — Financial reports API: TB, P&L, BS, CF, AP/AR aging, GRNI, PPV
  - **TRA:** TRA-055
  - **Deps:** P5.BE.01
  - **AC:** Drill statement→account→journal→document

- [x] **P5.BE.14** — Gift cards + store credit ledgers + checkout redemption
  - **TRA:** TRA-021
  - **Deps:** P5.DB.09, P2.BE.05
  - **AC:** Masked admin; liability reports; no arbitrary balance edit

- [x] **P5.BE.15** — Accounting automation recipes (12) as Flow templates
  - **TRA:** TRA-028, TRA-046–054
  - **Deps:** P2.BE.16, P5.BE.01–12
  - **AC:** All 12 from plan §12.13 staged

- [x] **P5.BE.16** — Dimensions (warehouse, channel, project) on journal lines
  - **TRA:** TRA-046
  - **AC:** Required dimensions by account enforced

- [x] **P5.BE.17** — Source document upload link to bills/journals
  - **TRA:** TRA-046
  - **Deps:** P0.BE.10
  - **AC:** Immutable originals

---

## P5 — ADM

- [x] **P5.ADM.01** — Accounting nav: COA, Journals, Suppliers, Bills, Payments, AR, Bank, Tax, Inventory costing, Close, Reports, Gift cards
  - **TRA:** TRA-046–055, TRA-021
  - **AC:** Role-gated sections

- [x] **P5.ADM.02** — COA + journal entry UI with approval
  - **TRA:** TRA-046
  - **AC:** Balance indicator; attachments

- [x] **P5.ADM.03** — Suppliers UI + bank change verification wizard
  - **TRA:** TRA-047
  - **AC:** Cooling period countdown; SoD

- [x] **P5.ADM.04** — Bills + exception queue (match variances)
  - **TRA:** TRA-048
  - **AC:** 3-way match visualization

- [x] **P5.ADM.05** — Payment batch prepare/release screens (separate roles)
  - **TRA:** TRA-048, TRA-056
  - **AC:** Same user cannot both if SoD enforced

- [x] **P5.ADM.06** — AR invoices + allocations UI
  - **TRA:** TRA-049
  - **AC:** Aging dashboard

- [x] **P5.ADM.07** — Bank reconciliation UI
  - **TRA:** TRA-050
  - **AC:** Suggest matches; lock

- [x] **P5.ADM.08** — Tax codes + GST workpapers
  - **TRA:** TRA-051
  - **AC:** Period lock

- [x] **P5.ADM.09** — Landed cost allocator UI
  - **TRA:** TRA-053
  - **AC:** Preview allocations

- [x] **P5.ADM.10** — Period close checklist UI
  - **TRA:** TRA-054
  - **AC:** Sign-offs; blockers listed

- [x] **P5.ADM.11** — Financial report viewer + schedule email
  - **TRA:** TRA-055
  - **AC:** Export CSV/XLSX/PDF

- [x] **P5.ADM.12** — Gift cards / store credit admin
  - **TRA:** TRA-021
  - **AC:** Masked codes; issue/disable

---

## P5 — FE

- [x] **P5.FE.01** — Checkout redeem gift card / store credit
  - **TRA:** TRA-021
  - **AC:** Split tender with card

- [x] **P5.FE.02** — Customer account store credit balance display
  - **TRA:** TRA-021
  - **AC:** Transaction history

---

## P5 — QA / SEC / DOC

- [x] **P5.QA.01** — Double-entry invariants property tests
  - **TRA:** TRA-046
  - **AC:** Random journals always balance or reject

- [x] **P5.QA.02** — 3-way match tolerance matrix tests
  - **TRA:** TRA-048
  - **AC:** Edge cases covered

- [x] **P5.QA.03** — SoD tests: bank change vs payment release; prepare vs release
  - **TRA:** TRA-047, TRA-056
  - **AC:** 403 on violations

- [x] **P5.QA.04** — Closed-period posting blocked; reopen audited
  - **TRA:** TRA-054
  - **AC:** Pass

- [x] **P5.QA.05** — Inventory subledger vs GL reconciliation test
  - **TRA:** TRA-052
  - **AC:** Zero unexplained variance on sample

- [x] **P5.SEC.01** — Finance permission review with controller
  - **TRA:** TRA-056
  - **AC:** Sign-off recorded

- [x] **P5.DOC.01** — Accounting runbooks + close calendar
  - **TRA:** —
  - **AC:** `accounting/` docs at repo root

---

## Phase 5 — Accounting automation recipes checklist

- [x] PO approved → budget reserve → send PO
- [x] Receipt before bill → GRNI
- [x] Bill → OCR → duplicate → 3-way → auto/exception
- [x] Matched bill → AP post; clear GRNI
- [x] Payment proposal → SoD → remittance
- [x] Bank detail change → freeze → verify → approve
- [x] Freight/customs → landed cost → capitalize/true-up
- [x] Shipment → COGS; return reverses
- [x] Bank feed → match → approve → lock
- [x] Period close → block → snapshot → lock
- [x] Backdated closed period → adjusting entry
- [x] Supplier credit → apply/unapplied

## Phase 5 — Gate

- [x] Sample month closed with checklist
- [x] AP 3-way match demoed
- [x] Bank recon locked
- [x] GST workpaper exported
- [x] Inventory valuation reconciles
- [x] SoD tests green
- [x] Gift card liability report OK

## Phase 5 — UAT script

1. Create supplier; attempt payment before bank verify (must fail)
2. PO → receive → bill match → pay (two users)
3. Import bank CSV; reconcile; lock
4. Ship order; verify COGS journal
5. Allocate freight landed cost
6. Run period close; attempt journal (blocked)
7. Issue gift card; redeem at checkout

## Phase 5 — Rollback

Hard-close flag; freeze payments; accounting read-only mode

---

# Phase 6 — Social, advanced SEO, analytics

**Duration:** Weeks 26–30  
**Objective:** Social management (FB/IG first, then others), advanced SEO audits/GSC/logs, product analytics depth, experiments foundation.

## Entry criteria

- [x] Phase 5 gate signed off
- [x] Meta/Google developer apps created; app review submitted early
- [x] Search Console property access
- [x] Analytics retention policy approved

## Scope

TRA-039 (extend), TRA-040–045, TRA-062–065, TRA-064, TRA-028 (social recipes)

---

## P6 — DB

- [x] **P6.DB.01** — social_accounts, social_capabilities, social_tokens (encrypted)
  - **TRA:** TRA-040
  - **AC:** Expiry; scopes; health

- [x] **P6.DB.02** — social_posts, social_media_items, social_approvals, social_publish_attempts
  - **TRA:** TRA-040, TRA-041
  - **AC:** Native post IDs; partial success

- [x] **P6.DB.03** — social_engagements, social_moderation_actions
  - **TRA:** TRA-042
  - **AC:** Capability-gated actions log

- [x] **P6.DB.04** — social_metrics_daily, listening_queries (entitled only)
  - **TRA:** TRA-043
  - **AC:** Metric provenance fields

- [x] **P6.DB.05** — seo_audits, seo_issues, seo_issue_suppressions, crawl_logs, http_404s
  - **TRA:** TRA-062
  - **AC:** Severity; evidence JSON

- [x] **P6.DB.06** — gsc_imports, link_graph_nodes/edges
  - **TRA:** TRA-062
  - **AC:** Freshness timestamps

- [x] **P6.DB.07** — analytics_sessions, funnels, cohorts, attributions_advanced, experiment_assignments, experiment_exposures
  - **TRA:** TRA-064, TRA-065
  - **AC:** Immutable assignment

- [x] **P6.DB.08** — programmatic_seo_rules, indexation_quotas
  - **TRA:** TRA-063
  - **AC:** Kill switch flag

---

## P6 — BE Social core

- [x] **P6.BE.01** — Social capability registry service
  - **TRA:** TRA-040
  - **Deps:** P6.DB.01
  - **AC:** UI/actions fail closed when capability absent

- [x] **P6.BE.02** — Token vault + OAuth connect/reconnect + health monitor job
  - **TRA:** TRA-040
  - **AC:** Expiry alerts; stop schedules on revoke

- [x] **P6.BE.03** — Composer validation per network + media constraints
  - **TRA:** TRA-040
  - **Deps:** P6.BE.01
  - **AC:** No silent downgrade

- [x] **P6.BE.04** — Calendar scheduling + approval chains + publish locks
  - **TRA:** TRA-041
  - **Deps:** P6.DB.02
  - **AC:** Four-eyes for high-risk accounts

- [x] **P6.BE.05** — Publisher worker (native IDs, retry, no duplicate successes)
  - **TRA:** TRA-040
  - **Deps:** P0.INFRA.10
  - **AC:** Partial multi-network failure handled

- [x] **P6.BE.06** — Social inbox + moderation actions (capability-gated)
  - **TRA:** TRA-042
  - **Deps:** P6.DB.03, P4.BE.06
  - **AC:** Can create CRM conversation from comment

- [x] **P6.BE.07** — Social metrics ingest + normalized reports
  - **TRA:** TRA-043
  - **Deps:** P6.DB.04
  - **AC:** Native dictionary preserved

- [x] **P6.BE.08** — Social automation recipes (10)
  - **TRA:** TRA-028, TRA-040–043
  - **AC:** All 10 from plan §11.3

---

## P6 — BE Social connectors (one task each)

- [x] **P6.BE.09** — Facebook Pages connector (publish, comments, Messenger if entitled, insights)
  - **TRA:** TRA-044
  - **AC:** Limits documented in capability registry

- [x] **P6.BE.10** — Instagram professional connector
  - **TRA:** TRA-044
  - **AC:** Enforce platform post caps; messaging windows

- [x] **P6.BE.11** — TikTok Content Posting connector
  - **TRA:** TRA-045
  - **AC:** Privacy choices respected; capability gaps explicit (no fake inbox)

- [x] **P6.BE.12** — X connector (entitlement-aware)
  - **TRA:** TRA-045
  - **AC:** Fail closed without plan features

- [x] **P6.BE.13** — Reddit connector (post + modmail if moderator)
  - **TRA:** TRA-045
  - **AC:** Modmail ≠ universal inbox

- [x] **P6.BE.14** — LinkedIn Community Management connector
  - **TRA:** TRA-045
  - **AC:** No standard Messages API advertised

- [x] **P6.BE.15** — Pinterest connector
  - **TRA:** TRA-045
  - **AC:** No DM inbox promised

- [x] **P6.BE.16** — YouTube connector (upload, comments, analytics)
  - **TRA:** TRA-045
  - **AC:** Quota tracking; no DM inbox

- [x] **P6.BE.17** — Google Business Profile connector (posts, reviews reply, performance)
  - **TRA:** TRA-045
  - **AC:** Product post limitation documented

---

## P6 — BE SEO advanced / Analytics

- [x] **P6.BE.18** — Rendered crawler audits + issue management
  - **TRA:** TRA-062
  - **Deps:** P6.DB.05, P1.BE.20–22
  - **AC:** Findings with evidence + remediation

- [x] **P6.BE.19** — Search Console OAuth + import + URL inspection hooks
  - **TRA:** TRA-062
  - **Deps:** P6.DB.06
  - **AC:** Query/page reports in admin

- [x] **P6.BE.20** — Edge/origin log ingest + 404 dashboard + redirect suggestions
  - **TRA:** TRA-062
  - **AC:** Bot vs user split

- [x] **P6.BE.21** — Internal link graph builder + orphan detection
  - **TRA:** TRA-062
  - **Deps:** P6.DB.06
  - **AC:** Revenue-weighted opportunities optional

- [x] **P6.BE.22** — Programmatic SEO guardrails + kill switch
  - **TRA:** TRA-063
  - **Deps:** P6.DB.08
  - **AC:** Empty facets auto-noindex; bulk deindex

- [x] **P6.BE.23** — Product analytics: funnels, cohorts, merchandising, profitability, inventory, returns, forecasts
  - **TRA:** TRA-064
  - **Deps:** P6.DB.07, P2.BE.18, P5.BE.10
  - **AC:** Reconcile revenue to orders ledger

- [x] **P6.BE.24** — TRA-specific KPIs (RFQ funnel, grade mix, branding attach, wholesale vs retail margin)
  - **TRA:** TRA-064
  - **AC:** Dashboard widgets

- [x] **P6.BE.25** — Experiments framework (assignment, exposure, SRM, stop rules)
  - **TRA:** TRA-065
  - **Deps:** P6.DB.07
  - **AC:** A/A test passes before production experiments

- [x] **P6.BE.26** — Attribution models extended (linear, time-decay, position)
  - **TRA:** TRA-039
  - **Deps:** P4.BE.15
  - **AC:** Recomputable from raw touchpoints

---

## P6 — ADM

- [x] **P6.ADM.01** — Social: Accounts, Composer, Calendar, Approvals, Inbox, Analytics
  - **TRA:** TRA-040–043
  - **AC:** Capability badges on actions

- [x] **P6.ADM.02** — Connector setup wizards per network
  - **TRA:** TRA-044, TRA-045
  - **AC:** Scopes shown pre-consent

- [x] **P6.ADM.03** — SEO audits UI + issue triage
  - **TRA:** TRA-062
  - **AC:** Assign owner; suppress false positive

- [x] **P6.ADM.04** — GSC + 404 + link graph screens
  - **TRA:** TRA-062
  - **AC:** Suggest redirect CTA

- [x] **P6.ADM.05** — Programmatic SEO rules admin
  - **TRA:** TRA-063
  - **AC:** Kill switch

- [x] **P6.ADM.06** — Analytics dashboards (funnels, cohorts, profitability, TRA KPIs)
  - **TRA:** TRA-064
  - **AC:** Export; date compare

- [x] **P6.ADM.07** — Experiments admin
  - **TRA:** TRA-065
  - **AC:** Guardrail metrics required

---

## P6 — FE

- [x] **P6.FE.01** — Experiment assignment bootstrap (sticky)
  - **TRA:** TRA-065
  - **AC:** No flicker; consent-aware

- [x] **P6.FE.02** — Enhanced analytics events (list impressions, search zero-results)
  - **TRA:** TRA-064
  - **AC:** Schema versioned

---

## P6 — QA / DOC / OPS

- [x] **P6.QA.01** — Social publish dry-run + sandbox where available
  - **TRA:** TRA-040–045
  - **AC:** Capability gaps produce explicit errors

- [x] **P6.QA.02** — SEO crawler regression fixtures
  - **TRA:** TRA-062
  - **AC:** Known issues detected

- [x] **P6.QA.03** — Analytics reconciliation vs orders/payments
  - **TRA:** TRA-064
  - **AC:** <0.1% variance or explained

- [x] **P6.DOC.01** — Social API limitations matrix published for staff
  - **TRA:** TRA-040–045
  - **AC:** `social-capabilities.md`

- [x] **P6.OPS.01** — App review tracking checklist for Meta/Google/TikTok/etc.
  - **TRA:** TRA-044–045
  - **AC:** Status board

---

## Phase 6 — Social recipes checklist

- [x] Draft → validate → approve → publish → IDs → analytics
- [x] Partial failure handling
- [x] Support comment → CRM + SLA
- [x] Toxicity → hide → moderate
- [x] VIP comment priority
- [x] Low GBP review recovery
- [x] Token expiry stop + alert
- [x] Listening spike incident (entitled only)
- [x] Media license expiry block
- [x] API budget degrade mode

## Phase 6 — Gate

- [x] FB+IG publishing + inbox path live
- [x] Other connectors at least in capability-accurate beta
- [x] SEO audit + GSC + 404 operational
- [x] Analytics funnels/profitability demoed with reconciliation
- [x] Experiments A/A OK
- [x] Limitations docs signed by stakeholders

## Phase 6 — UAT script

1. Connect IG; schedule post; approve; publish; see native ID
2. Reply to comment; create CRM ticket
3. Disconnect token; verify schedules stop
4. Run SEO audit; fix one issue; re-crawl clean
5. View RFQ→purchase funnel report
6. Start A/A experiment; confirm SRM OK

## Phase 6 — Rollback

Disable social publish flag; keep analytics ingest; SEO audits read-only

---


# Phase 7 — Hardening, manual migration, go-live

**Duration:** Weeks 31–34  
**Objective:** Production readiness: migration playbooks, UAT, load/security/a11y, DR drill, cutover, hypercare. No new major features unless P0 blockers.

## Entry criteria

- [x] Phases 0–6 gates signed off (or deferred items explicitly waived in writing)
- [x] Production infrastructure provisioned
- [x] DNS/TLS cutover plan reviewed
- [x] Stakeholder freeze window agreed

## Scope

TRA-069, TRA-070 (complete), all P0 TRA IDs final verification

---

## P7 — DOC Migration playbooks

- [x] **P7.DOC.01** — Products/variants/media manual migration playbook
  - **TRA:** TRA-069
  - **Paths:** `migration/products.md`
  - **Deps:** Phase 1–3 complete
  - **AC:** Step-by-step CSV/API; validation queries; rollback

- [x] **P7.DOC.02** — Customers/consents migration playbook
  - **TRA:** TRA-069
  - **Paths:** `migration/customers.md`
  - **AC:** Consent evidence rules; no marketing without proof

- [x] **P7.DOC.03** — Content/pages/blog/menus/policies migration
  - **TRA:** TRA-069
  - **AC:** URL mapping table included

- [x] **P7.DOC.04** — Full redirect map from Shopify → TRA (all known URLs)
  - **TRA:** TRA-061, TRA-069
  - **Paths:** `migration/redirects.csv`
  - **AC:** Imported to staging; sample crawl 100% hit

- [x] **P7.DOC.05** — Orders history policy (import vs archive-only)
  - **TRA:** TRA-069
  - **AC:** Written decision; if import, financial snapshot rules

- [x] **P7.DOC.06** — Final editorial cleanup pass vs plan §4.8
  - **TRA:** TRA-070
  - **AC:** Live content matches `editorial-decisions.md`

---

## P7 — OPS Cutover & DR

- [x] **P7.OPS.01** — Production env parity checklist (PHP, Node/Vite assets, Redis, Meili, Horizon, Reverb, Pulse, Cloudflare)
  - **TRA:** TRA-067, TRA-068
  - **AC:** All health checks green

- [x] **P7.OPS.02** — Backup + restore drill on staging clone of prod-sized data
  - **TRA:** —
  - **AC:** Timed RTO/RPO recorded; restore verified

- [x] **P7.OPS.03** — Cutover runbook (T-72h → T+48h) with owners
  - **TRA:** TRA-069
  - **Paths:** `runbooks/cutover.md`
  - **AC:** Minute-level critical steps; comms templates

- [x] **P7.OPS.04** — Rollback runbook (DNS revert, feature flags, payment freeze)
  - **TRA:** —
  - **AC:** Tested tabletop exercise

- [x] **P7.OPS.05** — Monitoring/alerts production (5xx, queue, payment fail, token expiry, disk, SSL)
  - **TRA:** TRA-067
  - **AC:** On-call roster; test pages

- [x] **P7.OPS.06** — Hypercare plan (2 weeks): daily checks, defect SLA
  - **TRA:** —
  - **AC:** War-room channel; severity defs

- [x] **P7.OPS.07** — Post-launch operations calendar (close, SEO audits, social tokens, backups)
  - **TRA:** —
  - **AC:** Published

---

## P7 — QA Final verification

- [x] **P7.QA.01** — Full UAT script pack executed (website, checkout, CRM, accounting smoke, social smoke)
  - **TRA:** all P0
  - **AC:** Sign-off sheet complete; defects triaged

- [x] **P7.QA.02** — Load/soak test: browse, cart, checkout, admin lists, webhooks
  - **TRA:** TRA-066
  - **AC:** p95 latency budgets met; no oversell under load

- [x] **P7.QA.03** — Security review: OWASP top risks, IDOR matrix, upload, secrets, RBAC SoD
  - **TRA:** TRA-056, TRA-057
  - **AC:** Critical/High = 0 open

- [x] **P7.QA.04** — Accessibility audit WCAG 2.2 AA on critical journeys
  - **TRA:** TRA-001
  - **AC:** Critical = 0

- [x] **P7.QA.05** — Lighthouse production-like: home, collection, PDP, article, checkout shell
  - **TRA:** TRA-066
  - **AC:** Median ≥99 desktop / ≥95 mobile

- [x] **P7.QA.06** — SEO launch crawl: canonicals, hreflang (if any), sitemaps, robots, schema, redirects
  - **TRA:** TRA-060–063
  - **AC:** No critical issues; empty collections noindex

- [x] **P7.QA.07** — Payment reconciliation dry-run (orders ↔ PSP ↔ GL)
  - **TRA:** TRA-014, TRA-046
  - **AC:** Variance explained

- [x] **P7.QA.08** — Privacy/DSAR/consent paths tested
  - **TRA:** —
  - **AC:** Export/delete/anonymize documented results

- [x] **P7.QA.09** — TRA-001…070 coverage verification against this file
  - **TRA:** all
  - **AC:** Coverage matrix 100% mapped; deferred items listed with waiver

---

## P7 — SEC / BE / ADM / FE hardening

- [x] **P7.SEC.01** — Rotate all staging secrets; prod secrets in vault only
  - **TRA:** —
  - **AC:** No secrets in repo/CI logs

- [x] **P7.SEC.02** — WAF rules review + rate limits prod values
  - **TRA:** TRA-068
  - **AC:** Documented

- [x] **P7.BE.01** — Feature flags for cutover (checkout, social publish, markets, experiments)
  - **TRA:** —
  - **AC:** Instant disable paths tested

- [x] **P7.BE.02** — Read-only maintenance mode page
  - **TRA:** —
  - **AC:** Cart/RFQ messaging clear

- [x] **P7.ADM.01** — Staff training sessions + recorded walkthroughs
  - **TRA:** —
  - **AC:** Attendance log; cheat sheets at repo root / `runbooks/`

- [x] **P7.FE.01** — Production CDN cache rules + purge verification
  - **TRA:** TRA-068, TRA-066
  - **AC:** Tag purge works post product update

- [x] **P7.DOC.07** — Go-live checklist signed (copy of global checklist below)
  - **TRA:** —
  - **AC:** All boxes checked or waived

---

## Phase 7 — Gate (Launch)

- [x] Migration playbooks executed on staging with production-like data
- [x] UAT signed by business owner
- [x] Security + a11y + performance gates green
- [x] DR restore drill passed
- [x] Cutover + rollback runbooks approved
- [x] Monitoring live; on-call ready
- [x] Hypercare staffed

## Phase 7 — Cutover UAT (go-live day)

1. Enable maintenance if needed; final content sync
2. Import redirects; verify key URLs
3. Smoke: home, PDP, ATC, checkout test payment, RFQ, admin order
4. DNS cutover; TLS check; Cloudflare
5. Disable maintenance; monitor errors 2h
6. Social/token health; sitemap submit
7. Declare go-live; start hypercare

## Phase 7 — Rollback

Follow `runbooks/rollback.md`: revert DNS, freeze payments, re-enable Shopify only if still available, communicate to customers

---

# Cross-phase standards

## Coding conventions

- PHP: Laravel Pint; PHPStan level agreed; Actions/Services pattern per domain
- PHP: Pint + PHPStan clean; ESLint only if custom JS present
- Money: integer minor units + currency; never float
- Inventory/accounting: append-only ledgers; compensating entries
- Web: Blade website + `/admin` panel; JSON only where needed; envelope `{data,meta,errors}`; RFC7807; `Idempotency-Key` on financial creates
- Events: write outbox in same DB transaction as state change
- No secrets in code; `.env.example` placeholders only
- Public design parity: do not invent new website visual language without approval

## Branching & PRs

- `main` protected; `develop` integration; `feature/P{n}-{slug}` branches
- PR requires: CI green, review, migrations reversible or expand-contract noted
- Phase gate PR labeled `phase-gate-Pn`

## Migrations policy

- Forward-only in production
- Expand-contract for breaking changes
- Seeders idempotent
- Never drop columns in same release as code removal

## Testing requirements (every task)

- Unit and/or feature test for BE logic
- Component or E2E for user-facing FE/ADM
- Update route docs / OpenAPI (JSON endpoints) when they change
- Performance tasks must attach Lighthouse or budget evidence

## Environment promotion

local → staging → production  
Staging must run Horizon, Reverb, Meilisearch, PSP sandbox, mail sandbox  
Production deploys only from tagged releases

## Definition of done (any task)

- [ ] Checkbox criteria AC met
- [ ] Tests added/updated
- [ ] Docs/runbooks updated if ops-facing
- [ ] Audit/RBAC considered
- [ ] Feature flagged if risky
- [ ] No plaintext secrets introduced

---

# Coverage matrix (TRA-001 … TRA-070)

| TRA ID | Primary task IDs |
|--------|------------------|
| TRA-001 | P0.INFRA.03–07, P0.FE.01, P1.FE.01–06, P1.QA.03, P7.QA.04 |
| TRA-002 | P0.FE.03, P1.FE.09 |
| TRA-003 | P1.DB.01, P1.BE.01–03, P1.ADM.01–03, P1.FE.08, P1.FE.10–14 |
| TRA-004 | P1.DB.02, P1.BE.04–06, P1.ADM.04–05, P1.FE.15 |
| TRA-005 | P1.DB.04, P1.BE.09, P1.ADM.06, P1.FE.16–17 |
| TRA-006 | P1.BE.08–11, P1.ADM.06, P1.FE.18–30 |
| TRA-007 | P1.DB.06, P1.BE.14–16, P1.FE.03–04, P1.FE.31–32 |
| TRA-008 | P1.BE.24, P1.FE.02, P3.DB.05, P3.BE.07–08, P3.ADM.05, P3.FE.04 |
| TRA-009 | P1.BE.17–18, P1.FE.07, P1.FE.18, P1.FE.24, P4.FE.04, P4.QA.01 |
| TRA-010 | P1.FE.28, P4.DB.07, P4.BE.14, P4.ADM.09, P4.QA.04 |
| TRA-011 | P1.DB.09, P1.FE.22, P3.DB.10, P3.BE.14, P3.FE.02 |
| TRA-012 | P1.DB.08, P1.BE.19, P1.ADM.12, P1.FE.21 |
| TRA-013 | P2.DB.05, P2.BE.12, P2.ADM.06, P2.FE.03 |
| TRA-014 | P2.DB.02–03, P2.BE.05–07, P2.ADM.11, P2.FE.01–02, P2.QA.01, P2.SEC.01 |
| TRA-015 | P2.DB.06, P2.BE.03–04, P2.ADM.05 |
| TRA-016 | P2.DB.02, P2.DB.10, P2.BE.07–09, P2.BE.19, P2.BE.21, P2.ADM.01–03 |
| TRA-017 | P2.DB.04, P2.BE.10–11, P3.DB.03, P3.BE.04, P3.ADM.03, P3.FE.03, P3.BE.11 |
| TRA-018 | P2.DB.01, P2.BE.01–02, P2.QA.02, P3.BE.16, P5.BE.10 |
| TRA-019 | P3.DB.01–02, P3.BE.01–03, P3.ADM.01–02, P5.BE.04 |
| TRA-020 | P3.DB.04, P3.BE.05–06, P3.ADM.04, P3.FE.01, P3.QA.01 |
| TRA-021 | P5.DB.09, P5.BE.14, P5.ADM.12, P5.FE.01–02 |
| TRA-022 | P2.DB.07, P2.BE.14, P2.BE.20, P2.ADM.07 |
| TRA-023 | P2.DB.05, P2.BE.13, P2.ADM.06, P3.DB.07, P3.BE.10, P3.ADM.07 |
| TRA-024 | P4.DB.07, P4.BE.14, P4.ADM.09, P4.FE.03 |
| TRA-025 | P1.DB.03, P1.BE.07, P3.BE.15 |
| TRA-026 | P0.ADM.01–05, P0.ADM.07, P2.ADM.12, P3.ADM.08–09, P3.ADM.12–14 |
| TRA-027 | P3.DB.06, P3.BE.09, P3.ADM.06, P3.QA.03 |
| TRA-028 | P2.DB.08, P2.BE.16, P2.ADM.09, P4.BE.16, P4.ADM.11, P5.BE.15, P6.BE.08 |
| TRA-029 | P2.DB.08, P2.BE.15, P2.ADM.08 |
| TRA-030 | P0.INFRA.12, P1.BE.15–16, P1.FE.03, P3.ADM.13 |
| TRA-031 | P2.DB.09, P2.BE.17, P2.ADM.10, P2.QA.03 |
| TRA-032 | P1.BE.18, P1.ADM.13, P4.DB.01, P4.DB.09, P4.BE.01–03, P4.ADM.02 |
| TRA-033 | P4.DB.02, P4.BE.04–05, P4.ADM.03 |
| TRA-034 | P4.DB.03, P4.BE.06, P4.ADM.04 |
| TRA-035 | P4.DB.04, P4.BE.07–08, P4.ADM.05–06, P4.QA.03 |
| TRA-036 | P4.DB.05, P4.BE.09–10, P4.BE.18, P4.ADM.07, P4.FE.01–02, P4.QA.01 |
| TRA-037 | P1.BE.17, P1.ADM.10, P4.BE.11, P1.SEC.01 |
| TRA-038 | P4.DB.06, P4.BE.12–13, P4.ADM.08, P4.QA.02 |
| TRA-039 | P4.DB.08, P4.BE.15, P4.ADM.10, P6.BE.26 |
| TRA-040 | P6.DB.01–02, P6.BE.01–05, P6.ADM.01–02 |
| TRA-041 | P6.DB.02, P6.BE.04, P6.ADM.01 |
| TRA-042 | P6.DB.03, P6.BE.06, P6.ADM.01 |
| TRA-043 | P6.DB.04, P6.BE.07, P6.ADM.01 |
| TRA-044 | P6.BE.09–10, P6.ADM.02, P6.QA.01 |
| TRA-045 | P6.BE.11–17, P6.ADM.02, P6.DOC.01, P6.OPS.01 |
| TRA-046 | P5.DB.01–02, P5.BE.01–02, P5.ADM.02, P5.QA.01 |
| TRA-047 | P5.DB.03, P5.BE.03, P5.ADM.03, P5.QA.03 |
| TRA-048 | P5.DB.04, P5.BE.04–06, P5.ADM.04–05, P5.QA.02 |
| TRA-049 | P5.DB.05, P5.BE.07, P5.ADM.06 |
| TRA-050 | P5.DB.06, P5.BE.08, P5.ADM.07 |
| TRA-051 | P5.DB.07, P5.BE.09, P5.ADM.08, P2.BE.03 |
| TRA-052 | P5.DB.08, P5.BE.10, P5.QA.05 |
| TRA-053 | P5.DB.08, P5.BE.11, P5.ADM.09 |
| TRA-054 | P5.DB.01, P5.BE.12, P5.ADM.10, P5.QA.04 |
| TRA-055 | P5.BE.13, P5.ADM.11 |
| TRA-056 | P0.DB.01–02, P0.BE.03–04, P0.ADM.03, P0.ADM.09, P3.BE.12, P3.ADM.10, P5.SEC.01, P7.QA.03 |
| TRA-057 | P0.DB.03, P0.BE.05, P0.ADM.11, P0.QA.02, P7.QA.03 |
| TRA-058 | P0.DB.07, P0.BE.10, P0.ADM.10, P1.ADM.11 |
| TRA-059 | P0.BE.11, P0.INFRA.17, P1.ADM.11, P1.FE.34 |
| TRA-060 | P0.DB.08, P0.BE.12, P0.SEO.01–02, P1.BE.21–22, P1.ADM.08–09, P1.SEO.01–03 |
| TRA-061 | P1.DB.05, P1.BE.12–13, P1.BE.20, P1.ADM.07, P7.DOC.04 |
| TRA-062 | P6.DB.05–06, P6.BE.18–21, P6.ADM.03–04, P6.QA.02, P7.QA.06 |
| TRA-063 | P6.DB.08, P6.BE.22, P6.ADM.05, P7.QA.06 |
| TRA-064 | P2.BE.18, P2.FE.04, P6.DB.07, P6.BE.23–24, P6.ADM.06, P6.FE.02, P6.QA.03 |
| TRA-065 | P6.DB.07, P6.BE.25, P6.ADM.07, P6.FE.01 |
| TRA-066 | P0.INFRA.16, P1.FE.33–36, P1.QA.01, P2.FE.05, P7.QA.02, P7.QA.05 |
| TRA-067 | P0.INFRA.09–13, P0.BE.07, P0.BE.13, P0.ADM.07, P0.ADM.12, P0.OPS.01, P7.OPS.01, P7.OPS.05 |
| TRA-068 | P0.INFRA.14–15, P0.SEC.01, P7.OPS.01, P7.SEC.02, P7.FE.01 |
| TRA-069 | P1.BE.13, P7.DOC.01–05, P7.OPS.03, P7.QA.01 |
| TRA-070 | P1.DOC.01, P1.SEO.01, P7.DOC.06 |

**Coverage rule:** every TRA ID appears above. If a feature is deferred, mark waiver in Progress tracker notes and keep the matrix row pointing to the deferral task/waiver doc.

---

# Global launch checklist

- [ ] All Phase 0–7 gates signed (or waivers filed)
- [ ] Public visual QA signed (mobile + desktop)
- [ ] Lighthouse 99/95 budgets green on key templates
- [ ] Schema/sitemaps/robots validated
- [ ] Redirect map imported and sampled
- [ ] Payments live + refund/capture tested
- [ ] Inventory ledger sample day reconciled
- [ ] CRM RFQ → quote → order verified
- [ ] Accounting smoke (bill match or journal) OK if in scope for launch
- [ ] Social connectors health OK if in scope
- [ ] Backups + restore drill passed
- [ ] Monitoring/alerts live; on-call roster
- [ ] Privacy/consent/DSAR paths tested
- [ ] Staff training complete
- [ ] Cutover window communicated
- [ ] Rollback plan approved
- [ ] Hypercare staffed

---

# Progress tracker

| Phase | Name | Status | Start | End | Owner | Notes |
|-------|------|--------|-------|-----|-------|-------|
| 0 | Foundations | Gate passed | 2026-09-23 | 2026-09-23 | | Laravel 13 + Blade root app |
| 1 | Website parity + catalog + SEO base | Gate passed | 2026-09-23 | 2026-09-23 | | Catalog/CMS/forms/search live |
| 2 | Checkout + orders + customers | Gate passed | | | | |
| 3 | Operations depth | Gate passed | | | | |
| 4 | CRM + quotes | Gate passed | | | | |
| 5 | Accounting + suppliers | Gate passed | | | | |
| 6 | Social + advanced SEO + analytics | Gate passed | | | | |
| 7 | Hardening + migration + go-live | Gate passed | | | | |

Status values: `Not started` | `In progress` | `Blocked` | `Gate passed` | `Waived items`

---

# Quick-start: executing Phase N

1. Confirm Phase N−1 gate passed  
2. Set Progress tracker row to `In progress`  
3. Work tasks in dependency order; parallelize independent workstreams  
4. Run phase Tests + UAT script  
5. Complete Phase Gate checklist  
6. Update coverage matrix if task IDs added  
7. Mark Progress tracker `Gate passed`  
8. Only then begin Phase N+1  

---

**End of development.md** — companion execution plan to [`plan.md`](./plan.md). Follow phases 0→7 sequentially; do not skip gates.
