--- status: human_needed phase: 11-catalog-database-view-ux-legacy-consolidation verified: 2026-06-13 verifier: orchestrator-inline reason: verifier-agent socket failure; code verified directly by orchestrator. DB-data must_haves blocked by firewall (user-owned manual migration). requirements_code_verified: [OFFER-07, OFFER-08, OFFER-09, OFFER-10] requirements_pending_db: [OFFER-13] --- # Phase 11 Verification — Catalog Database-View UX & Legacy Consolidation ## Goal Deliver a Notion/Airtable-style catalog database-view UX (inline-edit cells, tags, instant search, quick-add, active/inactive split) on the unified `services` table, AND complete the additive legacy consolidation of `service_catalog`/`offer_services` into `services` (OFFER-13). ## Verdict: HUMAN_NEEDED All **code** must-haves are verified and build-clean. The **data**-level guarantee (OFFER-13 + physical existence of the `tags` table and consolidated rows) cannot be verified in this environment — the dev/staging DB (`178.104.27.55:54321`) is firewalled and unreachable. Applying the additive migration + consolidation scripts is a deliberate, user-accepted manual step (SSH+docker exec). This is the only thing standing between this phase and `passed`. ## Code Must-Haves — VERIFIED ✓ | Requirement | Evidence | Status | |-------------|----------|--------| | OFFER-07 (inline-edit catalog table) | `ServiceTable.tsx` rewritten; every field is `EditableCell`; `updateServiceField` action gated by `requireAdmin()` | ✓ | | OFFER-08 (multi-select tags + create-on-the-fly) | `tags` pgTable + `Tag`/`NewTag` types in `schema.ts`; `tags_entity_name_unique` index; `TagMultiSelect` component; `addTagToService`/`removeTagFromService` actions | ✓ | | OFFER-09 (quick-add row, name+Enter) | `QuickAddRow` in `ServiceTable.tsx` → `quickAddService` action | ✓ | | OFFER-10 (instant client-side search) | `CatalogSearch.tsx` (`useMemo` filter, no reload); `page.tsx` renders it; `ServiceForm.tsx` deleted | ✓ | | Query layer | `getAllServices()` left-joins `tags` scoped to `entity_type="services"`, aggregates per-service via Map (null-guarded); `ServiceWithTags` type exported | ✓ | | Security | All 4 new server actions call `requireAdmin()` (8 occurrences); `entity_type` hardcoded to `"services"` (no injection path) — confirmed by code review (0 Critical) | ✓ | | Migration additive-only (LOCKED data-safety) | `0006_add_tags_table.sql` + `push-11-tags-migration.ts` contain only `CREATE TABLE IF NOT EXISTS` / `CREATE INDEX IF NOT EXISTS`; no DROP/TRUNCATE/DELETE/ALTER-DROP against any protected table | ✓ | | Integration build | `npx tsc --noEmit` → exit 0, zero errors; `next build` clean (Wave 4) | ✓ | ## Data Must-Haves — PENDING DB MIGRATION (human action required) These require the migration + consolidation scripts to run against the live DB. They are NOT failures — they are blocked on firewall access the user owns. ### 1. Apply the additive `tags` table migration expected: `tags` table physically exists in the DB with the `tags_entity_name_unique` unique index on `(entity_type, entity_id, name)`. command: `npx tsx --env-file=.env.local scripts/push-11-tags-migration.ts` (prints "✓ tags table created successfully" or "✓ already exists") result: [pending] ### 2. Run legacy consolidation (OFFER-13) expected: `service_catalog` + `offer_services` rows fully present in `services` (`migrated_from`/`migrated_id` populated), zero data loss. command: `npx tsx --env-file=.env.local scripts/migrate-services.ts` then `npx tsx --env-file=.env.local scripts/validate-services-migration.ts` → must print `ALL CHECKS PASSED`. result: [pending] ### 3. Assign "Offerta" tag to migrated offer rows (D-02) expected: every `services` row with `migrated_from='offer_services'` carries the "Offerta" tag; count matches. command: `npx tsx --env-file=.env.local scripts/migrate-tags.ts` then `npx tsx --env-file=.env.local scripts/validate-tags-migration.ts` → must print `ALL CHECKS PASSED`. result: [pending] ### 4. Mark OFFER-13 complete expected: After steps 1-3 validate clean, set OFFER-13 to `Complete` in `.planning/REQUIREMENTS.md` (currently `Pending`). result: [pending] ### 5. Runtime smoke test of /admin/catalog expected: page loads, inline-edit saves, tag add/remove works, quick-add creates a service, search filters instantly, inactive services sink below the divider. result: [pending] ## Code Review `11-REVIEW.md`: 0 Critical, 4 Warning, 5 Info. Security clean. Warnings are inline-edit robustness bugs (WR-01 double `onSave` on toggle, WR-02/03 blur committing unchanged/invalid values, WR-04 price locale-parse truncation). Non-blocking; address via `/gsd-code-review 11 --fix` or in a follow-up. WR-04 (price truncation) is the most data-relevant. ## Production deploy note Per CLAUDE.md Data Safety + project memory (Gitea→Coolify, prod Postgres via SSH+docker exec): the same additive migration MUST be applied to **production** before the Phase 11 schema-dependent code is deployed.