6.6 KiB
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 RESTRICThistory 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 unscopedPROJECT_DELETEDsnapshot audit, and delete the otherwise-unused project. - Preserved the existing database ownership of ephemeral cascades (
user_projectsandidempotency_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.deleteProjectand 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.tsxpassed, 2 files / 22 tests. - The web API regression uses the server's actual empty
204 No Contentresponse contract rather than a JSON success fixture. - Full web:
pnpm test:runpassed, 18 files / 69 tests. - Web type/build:
pnpm typecheckandpnpm buildpassed. - Focused real PostgreSQL:
go test ./internal/httpapi -run '^TestDeleteProject(PostgresIntegration|RouteRequiresAdminAuthentication)$' -count=1 -vpassed against a fresh isolated PostgreSQL 17 database. - Full server:
go test ./... -count=1passed 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 --checkpassed with only existing Windows line-ending notices.- Server static checks:
go vet ./...andgo 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 withPROJECT_HAS_HISTORY. Deletion of an eligible unused project preserves audit entries and records aPROJECT_DELETEDsnapshot 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: addDELETE /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.