64 lines
6.7 KiB
Markdown
64 lines
6.7 KiB
Markdown
# Task: Resolve ended project deletion semantics
|
|
|
|
## Identity
|
|
|
|
- Task ID: 20260813-ended-project-delete-6a714b5b
|
|
- Mode: Feature
|
|
- Branch: main
|
|
- Worktree: D:\Datas\PythonProjects\XQKqueue
|
|
- Base commit: cb88a6901219c5a489eced946c8fe87427f3dedb
|
|
- Owner: codex
|
|
- Status: Complete; ready for integration
|
|
|
|
## Scope
|
|
|
|
- Replace the contradictory `PROJECT_HAS_HISTORY` outcome for ended projects with guarded archival while retaining hard deletion for projects without queue history.
|
|
- Hide archived projects from every ordinary administrator, staff, visitor, browser-display, and Android-display project list or direct operational entry.
|
|
- Preserve archived projects and their sessions, tickets, batches, simulations, and audit/history joins so administrators can still inspect retained history.
|
|
- Add an explicit schema state, server transaction/query guards, accurate administrator UI wording, and regression coverage at the real PostgreSQL/HTTP seams.
|
|
|
|
## Intent And Constraints
|
|
|
|
- User-confirmed product semantics: an ended project with history is archived, retains history, and must not appear in any ordinary project list.
|
|
- Projects with no queue history remain eligible for irreversible hard deletion; projects with history must be `ENDED` before archival.
|
|
- Use an explicit nullable `archived_at` field rather than implicit GORM soft-delete scopes; every ordinary project query must make visibility intentional, while history joins intentionally retain archived projects.
|
|
- Archived projects cannot be operated, edited, granted to staff, resolved by public code/token, or restored through this task.
|
|
- Project code and display-token uniqueness remain global after archival; this task does not add code reuse, restoration, a purge flow, or an archived-project management list.
|
|
- PostgreSQL remains the authority for the archival transaction and state constraint. Preserve existing queue-history and personal-data retention rules.
|
|
- Concurrent write ownership is split by file: archival core, ordinary query visibility, and web wording/tests. The root task owns integration, task documentation, any explicitly coordinated history authorization seam, and final verification.
|
|
|
|
## Outcome
|
|
|
|
- Added migration `000015_project_archival` and `Project.ArchivedAt`. PostgreSQL enforces that only `ENDED` projects may carry an archive timestamp; project codes and display tokens remain globally unique.
|
|
- Changed the existing project removal transaction so an unused project is still hard-deleted, an operational project that is not ended returns `PROJECT_MUST_BE_ENDED`, and an ended project with queue history is archived atomically. Archival removes staff grants, writes `PROJECT_ARCHIVED`, and retains the project row, sessions, tickets, batches, simulations, and project-scoped audit entries.
|
|
- Hid archived projects from administrator overview data, account grant lists, staff project/queue entry points, visitor project and active-phone lookup results, browser/Android display overview, and direct display code/token resolution. Direct administrator maintenance and operational write paths also reject archived projects.
|
|
- Kept administrator history joins and private terminal-ticket lookups intentionally able to resolve the retained project. These are historical records, not ordinary project directories.
|
|
- Prevented account create/update calls from granting archived projects, including a row-lock protocol that serializes grant creation against archival.
|
|
- Updated the administrator action to the accurate neutral wording “移除项目” and made the confirmation copy distinguish archival from permanent deletion. When a staff user's final project disappears, the web client now clears the cached selection, stops polling the archived project, and hides stale queue data.
|
|
- Prevented the demo seed reset from matching and erasing an archived project's retained history.
|
|
|
|
## Verification
|
|
|
|
- TDD red evidence:
|
|
- The initial PostgreSQL deletion integration test did not compile because `Project.ArchivedAt` was absent.
|
|
- Administrator deletion-flow tests failed against the former delete-only wording.
|
|
- The staff-page regression test showed that an archived final project remained in `sessionStorage` and stale queue content remained visible.
|
|
- PostgreSQL 17, disposable fresh database: `go test -p 1 ./internal/database ./internal/httpapi -count=1` passed, including migration shape, hard deletion, ended-project archival, history/audit retention, grant removal, visibility, and rejection cases.
|
|
- Server: `go test ./... -count=1`, `go vet ./...`, and `go build ./...` passed.
|
|
- Web: `vitest run` passed 18 files / 70 tests; both application and Node TypeScript configurations passed `tsc --noEmit`; `vite build` passed.
|
|
- Repository: `git diff --check` passed; line-ending notices are informational working-copy warnings.
|
|
- Independent Sol High read-only final review: `PASS`, with no P0/P1 findings. The initial review found the ambiguous “归档项目” action label because unused projects are hard-deleted; it was corrected to “移除项目”, retested, and passed re-review.
|
|
|
|
## Follow-ups
|
|
|
|
- Deploy migration 15 before the archive-aware server/application. After the first project is archived, rolling back to an older binary or dropping `archived_at` would expose that project in ordinary lists again; such a rollback requires a compatibility filter or a deliberate data migration.
|
|
- Pre-existing display event streams are not proactively disconnected at the instant of archival. All new display resolution and operational writes are rejected, so no new project activity is produced; add project-level stream invalidation later if instantaneous connection termination becomes a requirement.
|
|
- Add a dedicated PostgreSQL concurrency regression for the grant-write versus archive interleaving if this area receives further authorization changes. The current sorted `FOR KEY SHARE` grant locks and project `FOR UPDATE` archive lock were independently reviewed as correct.
|
|
- Restoration, code reuse, permanent history purge, and a separate archive-management screen remain intentionally out of scope and require explicit retention/product decisions.
|
|
|
|
## Promotion Candidates
|
|
|
|
- Target: `.project-docs/40-domain/business-rules.md`. Record the confirmed removal rule: unused projects may be hard-deleted; projects with retained queue history must be ended and are then archived with history preserved.
|
|
- Target: `.project-docs/20-architecture/data-flow.md`. Record the visibility split between ordinary active-project queries, which must filter `archived_at`, and historical joins, which intentionally retain archived project identity.
|
|
- Target: `.project-docs/20-architecture/decisions/`. Consider an accepted decision for explicit archival state instead of implicit ORM soft-delete behavior, including the global code/token uniqueness and rollback constraints.
|