- Move cross-cutting docs (personas, design system, implementation phases, Ideen.md) to .specify/memory/ - Move cross-cutting research and plans to .specify/memory/research/ and .specify/memory/plans/ - Extract 5 setup tasks from spec/setup-tasks.md into individual specs/001-005/spec.md files with spec-kit template format - Extract 20 user stories from spec/userstories.md into individual specs/006-026/spec.md files with spec-kit template format - Relocate feature-specific research and plan docs into specs/[feature]/ - Add spec-kit constitution, templates, scripts, and slash commands - Slim down CLAUDE.md to Claude-Code-specific config, delegate principles to .specify/memory/constitution.md - Update ralph.sh with stream-json output and per-iteration logging - Delete old spec/ and docs/agents/ directories - Gitignore Ralph iteration JSONL logs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.9 KiB
Feature Specification: Automatic Data Deletion After Expiry Date
Feature: 018-data-deletion
Created: 2026-03-06
Status: Draft
Source: Migrated from spec/userstories.md
User Scenarios & Testing
User Story 1 - Automatic cleanup of expired event data (Priority: P1)
As a guest, I want all event data — including my RSVP and any other stored personal information — to be automatically and permanently deleted after the event's expiry date, so that I can trust that data I submitted is not retained on the server longer than necessary.
Why this priority: This is a privacy guarantee, not merely a housekeeping task. The mandatory expiry date in US-1 is only meaningful if the server actually enforces deletion. Without this story, the expiry date is a lie.
Independent Test: Can be tested by creating an event with a near-future expiry date, submitting an RSVP, waiting for expiry, and verifying that the event's public URL returns "event not found" and no data remains accessible.
Acceptance Scenarios:
- Given an event whose expiry date has passed, When the cleanup process runs, Then the event record and all associated data (RSVPs, update messages, field-change metadata, header images, cancellation state) are permanently deleted from the server.
- Given an event that has been deleted by the cleanup process, When a guest navigates to the event's public URL, Then the server returns a clear "event not found" response with no partial data or error traces.
- Given a deletion event, When the cleanup process deletes data, Then no log entry records the names, RSVPs, or any personal data of the deleted event's guests — the deletion is silent from a logging perspective.
- Given the cleanup process, When it runs, Then it runs automatically without manual operator intervention (e.g. via a scheduled job or on-request lazy cleanup triggered by access attempts).
User Story 2 - Expiry date extension delays deletion (Priority: P2)
As an event organizer, I want to be able to extend the expiry date of my event (via US-5) and have the deletion be deferred accordingly, so that I can keep my event data available for longer when needed.
Why this priority: Ensures US-5 (edit expiry date) and US-12 (deletion) work together correctly — the cleanup must always use the current stored expiry date, not the original one.
Independent Test: Can be tested by creating an event, extending its expiry date before expiry passes, and verifying that the event data is not deleted until the new expiry date.
Acceptance Scenarios:
- Given an event whose expiry date was extended via US-5 before the original expiry passed, When the cleanup process runs after the original date but before the new date, Then the event data is not deleted.
- Given an event whose expiry date was extended, When the new expiry date passes and the cleanup process runs, Then the event and all associated data are deleted.
User Story 3 - Cleanup does not trigger early (Priority: P2)
As a guest, I want my event data to be retained until the expiry date has fully passed, so that I can access the event page right up until expiry without unexpected data loss.
Why this priority: Ensures correctness — data must not be deleted prematurely.
Independent Test: Can be tested by verifying that an event with an expiry date set to tomorrow remains fully accessible today.
Acceptance Scenarios:
- Given an event whose expiry date is today but has not yet passed, When a guest accesses the event page, Then the event data is still served normally.
- Given an event whose expiry date passed yesterday, When the cleanup process runs, Then the event and all associated data are deleted.
Edge Cases
- What happens if the cleanup process fails mid-run (e.g. server crash)? The next run must safely re-attempt deletion without corrupting partial state.
- What happens if multiple cleanup runs overlap? The process must be idempotent — deleting an already-deleted event must not cause errors.
- LocalStorage entries on guests' devices are unaffected by server-side deletion — this is intentional. The app handles the "event not found" response gracefully (US-2, US-7).
- If a stored header image file is missing on disk at deletion time (e.g. corrupted storage), the cleanup must still complete and delete the database record.
Requirements
Functional Requirements
- FR-001: The server MUST run a periodic cleanup process that automatically deletes all data associated with events whose expiry date has passed.
- FR-002: The cleanup MUST delete the event record along with all associated data: RSVPs, update messages (US-10a), field-change metadata (US-9), stored header images (US-16) [deferred until US-16 is implemented], and cancellation state (US-18 if applicable).
- FR-003: After deletion, the event's public URL MUST return a clear "event not found" response — no partial data is ever served.
- FR-004: The cleanup process MUST run automatically without manual operator intervention (e.g. a scheduled job, Spring
@Scheduled, or on-request lazy cleanup triggered by access attempts). - FR-005: The cleanup MUST NOT log the names, RSVPs, or any personal data of deleted events — deletion is silent from a logging perspective.
- FR-006: The cleanup MUST always use the current stored expiry date when determining whether an event is eligible for deletion — extending the expiry date via US-5 before expiry passes delays deletion accordingly.
- FR-007: The cleanup MUST NOT be triggered early — data is retained until the expiry date has passed, not before.
- FR-008: The cleanup process MUST be idempotent — re-running it against already-deleted events must not cause errors.
Key Entities
- Event (expiry_date): The
expiry_datefield on the Event entity determines when the event becomes eligible for deletion. It is updated by US-5 (edit event details). - Cleanup Job: A background process (not a user-facing entity) responsible for identifying and deleting expired events and all their associated data.
Success Criteria
Measurable Outcomes
- SC-001: An event with a passed expiry date returns "event not found" from the server within one cleanup cycle of the expiry.
- SC-002: All associated data (RSVPs, update messages, metadata, images) is deleted atomically with the event record — no orphaned records remain after a successful cleanup run.
- SC-003: No PII (names, RSVP choices) appears in server logs during or after the deletion process.
- SC-004: Extending an event's expiry date via US-5 correctly defers deletion — verified by querying the database after the original expiry would have triggered cleanup.
- SC-005: The cleanup process completes successfully even if a stored header image file is missing on disk (resilient to partial storage failures).