# Task: Diagnose and fix project deletion ## Identity - Task ID: 20260813-project-delete-fix-d3633d68 - Mode: Feature - Branch: main - Worktree: D:\Datas\PythonProjects\XQKqueue - Base commit: 1eb36645e41dfd479799470df65d5cb8a8ac077e - Owner: codex - Status: Complete; ready for integration ## Scope - Diagnose the missing administrator project-deletion workflow across the React admin client and Go HTTP service. - Add a safe deletion contract for projects that have no retained operational history. - Preserve queue sessions and their ticket, call-batch, and simulation history by rejecting deletion when retained operational data exists; preserve audit rows by detaching the project foreign key. - Cover the administrator UI/API request and the server deletion boundary with regression tests. ## Intent And Constraints - The user's confirmed symptom is that a project cannot be deleted; the repository currently exposes no project-delete UI action, web API method, HTTP route, or handler. - PostgreSQL remains the sole write authority. The client must not infer deletion eligibility. - Existing `ON DELETE RESTRICT` history relationships must not be replaced with broad cascading deletion. - The working product assumption is that deletion means removing an unused/accidentally-created project; projects with retained operational history must be rejected with an explicit conflict response, while audit history must remain available without retaining a project foreign key. - Keep the change surgical and reuse the existing admin authentication, transaction, API-error, polling-refresh, and feedback patterns. ## Outcome - Confirmed the reported behavior was a missing capability rather than a failing existing request: the admin UI had no delete action, the web API client had no delete method, and the Go server had no DELETE route or handler. - Added an administrator-only `DELETE /api/admin/projects/{id}` endpoint and registered it as an important structured-log route. - Implemented guarded deletion in one transaction: lock the project row, reject projects with any queue session using `409 PROJECT_HAS_HISTORY`, detach retained project-scoped audits, write an unscoped `PROJECT_DELETED` snapshot audit, and delete the otherwise-unused project. - Preserved the existing database ownership of ephemeral cascades (`user_projects` and `idempotency_keys`) and did not add broad cascades or delete queue, ticket, call-batch, device, or audit history. - Added a two-step destructive action to the project maintenance page, including in-flight duplicate prevention, server error feedback, refresh, and replace-navigation to the project list after success. - Added a danger-color button variant so deletion is visually distinct from ordinary project maintenance. - Added web API/component regression coverage and full-handler PostgreSQL integration coverage for authentication, successful unused-project deletion, retained audit history, and atomic rejection of a project with queue history. ## Verification - Red signal: before implementation, the new web deletion tests failed because `api.deleteProject` and the delete controls did not exist; the new Go DELETE route test returned 405 instead of reaching admin authentication. - Focused web: `pnpm exec vitest run src/api.test.ts src/pages/AdminPage.test.tsx` passed, 2 files / 22 tests. - The web API regression uses the server's actual empty `204 No Content` response contract rather than a JSON success fixture. - Full web: `pnpm test:run` passed, 18 files / 69 tests. - Web type/build: `pnpm typecheck` and `pnpm build` passed. - Focused real PostgreSQL: `go test ./internal/httpapi -run '^TestDeleteProject(PostgresIntegration|RouteRequiresAdminAuthentication)$' -count=1 -v` passed against a fresh isolated PostgreSQL 17 database. - Full server: `go test ./... -count=1` passed against a second fresh isolated PostgreSQL 17 database. - The integration test exercises the complete admin login-cookie and routed-handler chain. It verifies 204 with an empty body, project/grant removal, retained old audit rows with a null project foreign key, a deletion snapshot audit, and a 409 path with no partial mutation. - `git diff --check` passed with only existing Windows line-ending notices. - Server static checks: `go vet ./...` and `go build ./...` passed. - Independent read-only Sol review: PASS; no P0/P1 or unresolved P2/P3 findings. It verified PostgreSQL parent/FK lock compatibility, transactional rollback, 204 handling, audit detachment/snapshot semantics, schema-owned cascades, UI confirmation/in-flight/error/navigation behavior, logging, and task-document ownership. ## Follow-ups - Promote the guarded deletion rule and admin DELETE interface into canonical business-rule/data-flow documentation through a later Integration Gate. - If product policy later requires archived projects, deleted-code reservation, or deleted-project filtering in audit/history screens, treat that as a separate schema and cross-query design task rather than broadening this hard-delete endpoint. ## Promotion Candidates - Target: `.project-docs/40-domain/business-rules.md`. Proposal: an administrator may permanently delete only a project with no queue session; any retained queue history blocks deletion with `PROJECT_HAS_HISTORY`. Deletion of an eligible unused project preserves audit entries and records a `PROJECT_DELETED` snapshot while removing the project and ephemeral grants/idempotency state. Evidence: `server/internal/httpapi/admin.go`, `server/internal/httpapi/project_delete_integration_test.go`, and the PostgreSQL verification recorded above. Future impact: future project relationships must either be classified as retained deletion blockers or explicitly ephemeral; clients must not decide eligibility locally or introduce broad history cascades. Semantic conflicts: none with current retention rules; the prior documents did not define project deletion. Human confirmation: the user requested that projects become deletable; the guarded empty-only interpretation was selected to preserve existing history and audit contracts. - Target: `.project-docs/20-architecture/data-flow.md`. Proposal: add `DELETE /api/admin/projects/{id}` to the admin interface list and record that the service transaction locks the project, enforces the queue-history guard, preserves detached audits, and owns deletion. Evidence: the registered server route, transaction handler, web client call, and full-handler integration test. Future impact: administrator clients should surface the service's 409 reason and must not emulate or bypass deletion rules. Semantic conflicts: none known. Human confirmation: no additional confirmation required for documenting the implemented interface.