Files
XQKqueue/.project-docs/30-worklog/tasks/20260813-project-delete-fix-d3633d68.md

6.6 KiB

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: 1eb36645e4
  • 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.