.planning/ documentava in dettaglio cio che era vecchio e per niente cio
che e in produzione: le fasi 11-22 (v2.1 e v2.2, chiuse a giugno) erano
ancora in phases/ mentre v1.0 e v2.0 stavano gia in milestones/, e il
lavoro degli ultimi due mesi - gate OTP e ciclo di vita dei retainer, cioe
quello che gira su hub.iamcavalli.net - non aveva nessuna cartella.
- phases/{11,12,14} -> milestones/v2.1-phases/, phases/{18..22} ->
milestones/v2.2-phases/. Ora phases/ contiene solo la milestone in
corso, che e quello che state.cjs conta per il progresso
- v2.1-ROADMAP.md ricostruito: era l'unica milestone senza archivio,
interrotta dal reset del 19/06 e mai chiusa formalmente
- v2.3-ROADMAP.md + v2.3-REQUIREMENTS.md: v2.3 e stata eseguita fuori dal
ciclo GSD, non esistono PLAN/SUMMARY per fase. L'archivio E la doc
- REQUIREMENTS.md riscritto per v2.4 con il backlog reale
- phases/13 e phases/26: SUMMARY ricostruiti da commit, migration e
STATUS.md. 26 e il primo numero libero
- research/: cancellate 4 varianti dello stesso PITFALLS e FEATURES/
SUMMARY, superati da PROJECT.md. Diverse anti-feature erano ormai
contraddette dai fatti (il Kanban e stato costruito in Phase 19,
l'email in v2.3, il time tracking esiste)
- cancellati UI-RULES.md e DESIGN-SYSTEM.md (CLAUDE.md li dichiara
superseded: impongono l'inverso della regola attuale) e HANDOFF.md,
fermo al 13/06
- SECURITY-*.md -> security/: audit chiuso, ma i report restano la doc di
cosa e stato ruotato e perche
- PROJECT.md/MILESTONES.md/ROADMAP.md allineati: milestone corrente v2.4,
sessione OTP 90gg non 30, migrazioni fino alla 0016
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.9 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 11-catalog-database-view-ux-legacy-consolidation | 02 | api |
|
|
|
|
|
|
|
|
|
12min | 2026-06-13 |
Phase 11 Plan 2: Catalog Query Layer + Inline-Edit/Tag/Quick-Add Server Actions Summary
getAllServices() now returns each service's assigned tag names via a left-join on the new tags table, and four new admin-gated server actions (updateServiceField, addTagToService, removeTagFromService, quickAddService) provide the inline-edit, tag-assignment, and quick-add primitives for the database-view UX.
Performance
- Duration: ~12 min
- Started: 2026-06-13T13:36:00Z
- Completed: 2026-06-13T13:40:07Z
- Tasks: 2 of 2
- Files modified: 2
Accomplishments
getAllServices()rewritten toPromise<ServiceWithTags[]>: left-joinstags(scoped toentity_type="services"viaeq+and), groups rows in-memory into{ ...service, tags: string[] }, ordered byservices.name asc, tags.name asc. Services with zero tags returntags: [](left-join nulls filtered out).getClientFullDetailandgetProjectFullDetail(and theiractiveServices: Service[]fields) verified byte-for-byte unchanged — confirmed viagit diff.- Added 4 new server actions to
src/app/admin/catalog/actions.ts, all callingrequireAdmin()first andrevalidatePath("/admin/catalog")last:updateServiceField(serviceId, fieldName, value)— generic single-field inline edit forname | description | category | unit_price | active, with a closedEDITABLE_FIELDSunion + runtime whitelist check, per-field validation (required name, non-negative price stored with 2 decimals, boolean coercion foractive).addTagToService(serviceId, tagName)/removeTagFromService(serviceId, tagName)— tag add/remove hardcoded toentity_type="services", idempotent insert viaonConflictDoNothing().quickAddService(name)— creates a newservicesrow withunit_price="0.00",active=true, from just a trimmed name (D-12).
npx tsc --noEmitpasses with zero errors across the full project.npx eslinton both modified files: 0 new warnings/errors (6 pre-existing unused-import warnings inadmin-queries.ts, unrelated to this plan's changes, confirmed present before this plan too).
Task Commits
Each task was committed atomically:
- Task 1: Extend getAllServices() with tags join (ServiceWithTags) -
f743410(feat) - Task 2: Add inline-edit, tag, and quick-add server actions -
445de85(feat)
Plan metadata: (this commit, following SUMMARY)
Files Created/Modified
src/lib/admin-queries.ts- Addedtagsto schema import; addedServiceWithTagstype (Service & { tags: string[] }); rewrotegetAllServices()to left-jointags(scopedentity_type="services") and aggregate per-service tag arrayssrc/app/admin/catalog/actions.ts- Addedtags+andimports; appendedupdateServiceField,addTagToService,removeTagFromService,quickAddServiceserver actions; existingcreateService/updateService/toggleServiceActiveunchanged
Decisions Made
onConflictDoNothing()(no explicittarget) was used as written in the plan — it compiled cleanly under the project's Drizzle version and is correct given the single unique index (tags_entity_name_unique) on thetagstable. No change to the plan's suggested fallback was needed.
Deviations from Plan
None - plan executed exactly as written.
Issues Encountered
None.
DB-state note (carried from Plan 01, non-blocking for this plan)
The tags table exists only in src/db/schema.ts (committed in Plan 01) — it has not yet been physically created in the live dev/prod Postgres database (firewalled, pending manual SSH+docker exec migration apply by the user). This plan is code-only and verified via TypeScript types (npx tsc --noEmit passes against the Drizzle-inferred tags/services schema types). No live-DB queries were attempted or required for this plan's verification — getAllServices(), addTagToService, removeTagFromService etc. will function correctly once the Plan 01 migration (scripts/push-11-tags-migration.ts) is applied to the live DB. This is the same pending checkpoint documented in 11-01-SUMMARY.md and STATE.md Blockers — not a new issue introduced here.
Known Stubs
None - no UI or data-rendering stubs introduced by this plan (query layer + server actions only, consumed by Plans 03/04).
Threat Flags
None - this plan's new surface (updateServiceField, addTagToService, removeTagFromService, quickAddService) is fully covered by the threat model already documented in 11-02-PLAN.md (T-11-06 through T-11-10), all mitigated/accepted as designed:
- T-11-06 (Elevation of Privilege): every new action calls
await requireAdmin()first. - T-11-07 (Tampering via field whitelist):
EDITABLE_FIELDSclosed union + runtime.includes()check prevents arbitrary column writes. - T-11-08 (Tampering via entity_type):
entity_typehardcoded to"services"literal in both tag actions, never client-supplied. - T-11-09 (SQL injection): all values pass through Drizzle's parameterized query builder.
- T-11-10 (DoS via duplicate tags):
onConflictDoNothing()on the(entity_type, entity_id, name)unique index makesaddTagToServiceidempotent.
No new endpoints, auth paths, or trust-boundary changes beyond what was already reviewed in the plan's threat model.
User Setup Required
None - no new environment variables or external service configuration needed. (The pending tags table migration apply is tracked from Plan 01, not new to this plan.)
Next Phase Readiness
- Query layer ready:
ServiceWithTagstype +getAllServices()are implemented and typecheck cleanly — Plan 03 (EditableCell/TagMultiSelectcomponents) and Plan 04 (ServiceTablerewrite) can importServiceWithTagsdirectly with no further query-layer changes needed. - Server actions ready:
updateServiceField,addTagToService,removeTagFromService,quickAddServiceare implemented, admin-gated, and exported — Plans 03/04 can wire these into UI components immediately. - NOT ready for live runtime verification: as with Plan 01, any runtime/integration test that queries the live
tagstable (e.g., confirmingaddTagToServiceactually persists a row) will fail until the Plan 01 migration is applied to the database. This does not block Plan 02's code-level completion (typecheck is the success bar per the DB-state note above). - Recommendation: Resolve the Plan 01 DB-execution checkpoint (apply
scripts/push-11-tags-migration.tsvia SSH+docker exec) before or in parallel with Plans 03/04, so that UI built against these actions can be verified end-to-end once ready.
Phase: 11-catalog-database-view-ux-legacy-consolidation Completed: 2026-06-13