Files
gurixandClaude 05e201f1fc Add implementation planning artifacts for anonymous feedback platform
Complete Phase 0 (Research) and Phase 1 (Design) of implementation planning workflow:

- plan.md: Technical context, constitution check, and project structure
- research.md: Technology decisions for AI integration, file storage, authentication, security
- data-model.md: Domain entities with validation rules and state transitions
- contracts/: API specifications for submission, dashboard, and admin endpoints
- quickstart.md: Developer setup guide with test-first workflow
- CLAUDE.md: Updated agent context with tech stack

All constitutional requirements validated. Ready for task generation phase.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 22:31:26 +02:00

15 KiB

Data Model: Anonymous Feedback Platform (Reklamator)

Branch: 001-build-an-application | Date: 2025-10-15

This document defines the domain entities, their attributes, relationships, validation rules, and state transitions for the Reklamator application.

Entity Overview

Product (1) ----< (N) Feedback
   |                     |
   |                     |---< (N) Attachment
   |                     |
   |                     |---- (1) AnalysisResult
   |
   |----< (N) ProductOwner

Administrator (manages all entities)

Entity Definitions

1. Feedback Submission

Description: Represents a single feedback item submitted by an anonymous user.

Storage Location: data/products/{product_id}/feedback/{feedback_id}/

Attributes

Field Type Required Validation Description
id UUID v4 Yes Auto-generated Unique identifier
product_id String Yes Must reference existing product Associated product identifier
original_text String Yes* 1-10,000 characters Original feedback text (*empty if file-only submission)
original_language String (ISO 639-1) No 2-char code Detected language (e.g., "en", "de", "ja")
submission_timestamp ISO 8601 DateTime Yes Auto-generated When feedback was submitted (UTC)
status Enum Yes See Status enum below Current processing/review status
category Enum No See Category enum below AI-assigned category (null if analysis pending/failed)
attachment_count Integer Yes 0-3 Number of attached files

Status Enum

  • submitted - Initial state after successful submission
  • analyzing - AI analysis in progress
  • analysis_failed - AI analysis encountered error
  • analyzed - AI analysis completed successfully
  • reviewed - Product owner has reviewed
  • in_progress - Product owner marked as being worked on
  • resolved - Product owner marked as resolved
  • rejected - Product owner marked as not actionable

Category Enum (AI-assigned)

  • idea - New concept or suggestion
  • feature_request - Request for specific functionality
  • bug - Problem or defect report
  • complaint - Negative feedback about existing functionality

Validation Rules

  • FR-002: original_text max length 10,000 characters
  • FR-011: At least one of (original_text, attachment_count > 0) must be true
  • FR-012: Cannot be empty (no text AND no attachments)
  • FR-027: submission_timestamp immutable after creation

State Transitions

submitted → analyzing → analyzed → {reviewed, in_progress, resolved, rejected}
                ↓
           analysis_failed (terminal state until manual retry)

File Representation (metadata.yaml)

id: "a3f2c1d5-8b4e-4f1a-9c2d-7e6f5a4b3c2d"
product_id: "001-acme-app"
original_language: "en"
submission_timestamp: "2025-10-15T14:32:10Z"
status: "analyzed"
category: "bug"
attachment_count: 2
attachments:
  - filename: "screenshot.png"
    size_bytes: 245678
    mime_type: "image/png"
  - filename: "error_log.txt"
    size_bytes: 1234
    mime_type: "text/plain"

2. Product/Service

Description: Represents a product or service for which feedback can be collected.

Storage Location: data/products/{product_id}/config.yaml

Attributes

Field Type Required Validation Description
id String Yes Unique, URL-safe slug Product identifier (e.g., "001-acme-app")
name String Yes 1-100 characters Display name
description String No Max 500 characters Product description
target_language String (ISO 639-1) Yes 2-char code Preferred language for AI translations
submission_url_slug String Yes URL-safe, unique URL path for submission form (e.g., "/submit/acme-app")
created_date ISO 8601 Date Yes Auto-generated When product was registered
status Enum Yes "active" or "archived" Current status
assigned_owner_ids List[String] No Must reference existing users Product owner user IDs

Validation Rules

  • FR-046: id must be unique across all products
  • FR-047: target_language must be valid ISO 639-1 code
  • FR-049: submission_url_slug must be unique and URL-safe (alphanumeric + hyphens)
  • FR-053: Cannot accept new feedback if status is "archived"

State Transitions

active ⇄ archived (bidirectional, admin only)

File Representation (config.yaml)

id: "001-acme-app"
name: "Acme Mobile App"
description: "Customer feedback for Acme's flagship mobile application"
target_language: "en"
submission_url_slug: "acme-app"
created_date: "2025-10-01"
status: "active"
assigned_owner_ids:
  - "owner-001"
  - "owner-002"
statistics:
  total_feedback_count: 127
  last_submission: "2025-10-15T14:32:10Z"

3. Analysis Result

Description: Represents the AI-generated analysis of a feedback submission.

Storage Location: data/products/{product_id}/feedback/{feedback_id}/analysis.md Additional Storage: Original text stored in content.txt for reference

Attributes (Markdown Format)

Field Type Required Description
translated_text Markdown Yes* Feedback translated to target language (*if different from original)
summary Markdown Yes Concise 2-3 sentence summary in target language
detected_category Enum Yes Category assigned by AI (idea/feature_request/bug/complaint)
confidence_score Float (0.0-1.0) Yes AI confidence in categorization
analysis_timestamp ISO 8601 DateTime Yes When analysis completed
model_used String Yes AI model identifier (e.g., "claude-3-haiku-20240307")
error_message String No Error details if analysis failed

Validation Rules

  • FR-014: summary should be 2-3 sentences maximum
  • FR-015: translated_text required unless original language = target language
  • FR-016: Original text preserved in content.txt alongside analysis
  • FR-017: Detected language stored in feedback metadata.yaml original_language

File Representation (analysis.md)

# Feedback Analysis

**Analyzed**: 2025-10-15T14:35:22Z
**Model**: claude-3-haiku-20240307
**Category**: bug (confidence: 0.92)
**Original Language**: de → **Target Language**: en

## Summary

User reports that the app crashes when uploading large files. This appears to be a bug affecting the file upload module, preventing users from submitting documents over 5MB.

## Translation

**Original (German):**
> Die App stürzt ab, wenn ich versuche, große Dateien hochzuladen. Jedes Mal wenn ich eine PDF über 5MB hochlade, friert die App ein und schließt sich.

**Translated (English):**
The app crashes when I try to upload large files. Every time I upload a PDF over 5MB, the app freezes and closes.

## Attachments

- screenshot.png (245 KB)
- error_log.txt (1 KB)

4. Attachment

Description: Represents a file (document or image) uploaded with feedback.

Storage Location: data/products/{product_id}/feedback/{feedback_id}/attachments/{filename}

Attributes (stored in feedback metadata.yaml)

Field Type Required Validation Description
filename String Yes Sanitized, max 255 chars Original filename (sanitized for safety)
size_bytes Integer Yes Max 10,485,760 (10MB) File size in bytes
mime_type String Yes See allowed types Validated MIME type
upload_timestamp ISO 8601 DateTime Yes Auto-generated When file was uploaded
virus_scan_status Enum Yes "clean" or "infected" ClamAV scan result

Allowed MIME Types

  • Documents: application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document (DOCX), text/plain
  • Images: image/jpeg, image/png, image/gif, image/webp

Validation Rules

  • FR-004: Maximum 3 attachments per feedback
  • FR-006: Maximum 10MB per file
  • FR-026: Preserve original filename (sanitized)
  • FR-059: Sanitize filename to prevent directory traversal
  • FR-060: Must pass ClamAV virus scan before storage

Security Sanitization

  • Remove directory traversal patterns: ../, ..\\, absolute paths
  • Replace unsafe characters: <>:"|?*
  • Limit filename length to 255 characters
  • If duplicate filename, append counter: file.pdffile_2.pdf

5. Product Owner

Description: Represents an authenticated user responsible for reviewing feedback for one or more products.

Storage Location: data/users.yaml

Attributes

Field Type Required Validation Description
id String Yes Unique User identifier (e.g., "owner-001")
email String Yes Valid email, unique Login email address
password_hash String (bcrypt) Yes bcrypt format Hashed password (never store plaintext)
name String Yes 1-100 characters Display name
role Enum Yes "product_owner" User role (always "product_owner" for this entity)
assigned_product_ids List[String] Yes Must reference existing products Products this owner can access
created_date ISO 8601 Date Yes Auto-generated Account creation date
last_login ISO 8601 DateTime No Auto-updated Last successful login

Validation Rules

  • FR-048: Can be assigned to multiple products
  • FR-056: Must authenticate to access dashboard
  • FR-063: Passwords hashed with bcrypt (cost factor 12)
  • FR-033: Can only view feedback for assigned_product_ids

File Representation (users.yaml entry)

users:
  - id: "owner-001"
    email: "jane.smith@example.com"
    password_hash: "$2b$12$KIXxBt5H4vE2zT9vN8FqOe9Jx..."
    name: "Jane Smith"
    role: "product_owner"
    assigned_product_ids:
      - "001-acme-app"
      - "002-beta-service"
    created_date: "2025-09-15"
    last_login: "2025-10-15T09:23:11Z"

6. Administrator

Description: Represents a privileged user who can register products, assign owners, and manage system configuration.

Storage Location: data/users.yaml (same file as Product Owners)

Attributes

Field Type Required Validation Description
id String Yes Unique User identifier (e.g., "admin-001")
email String Yes Valid email, unique Login email address
password_hash String (bcrypt) Yes bcrypt format Hashed password
name String Yes 1-100 characters Display name
role Enum Yes "admin" User role (always "admin" for this entity)
assigned_product_ids List[String] Yes Empty list Empty = access to all products
created_date ISO 8601 Date Yes Auto-generated Account creation date
last_login ISO 8601 DateTime No Auto-updated Last successful login

Validation Rules

  • Admin role grants full access regardless of assigned_product_ids
  • FR-045: Can create/modify/archive products
  • FR-048: Can assign/unassign product owners
  • Same authentication requirements as Product Owner (FR-056, FR-063)

File Representation (users.yaml entry)

users:
  - id: "admin-001"
    email: "admin@reklamator.local"
    password_hash: "$2b$12$vL3Fx9..."
    name: "System Administrator"
    role: "admin"
    assigned_product_ids: []  # Empty = all access
    created_date: "2025-09-01"
    last_login: "2025-10-15T10:45:33Z"

Domain Rules & Invariants

Cross-Entity Rules

  1. Product-Feedback Relationship (1:N)

    • Every Feedback must reference exactly one valid Product
    • Product can have zero or many Feedback items
    • Archived products cannot receive new feedback (FR-053)
  2. Feedback-Attachment Relationship (1:N)

    • Feedback can have 0-3 Attachments (FR-004, FR-010)
    • Attachments cannot exist without parent Feedback (cascade delete)
  3. Feedback-AnalysisResult Relationship (1:1)

    • Every analyzed Feedback has exactly one AnalysisResult
    • AnalysisResult created asynchronously after Feedback submission
    • Original content preserved even if analysis fails (FR-020)
  4. Product-Owner Relationship (N:M)

    • Product can have 1 or more assigned Product Owners (FR-048)
    • Product Owner can be assigned to multiple Products
    • Admin users bypass assignment logic (implicit access to all)
  5. Anonymity Constraint (Global)

    • No IP addresses stored in Feedback metadata (FR-055, SC-010)
    • No session tracking for anonymous submissions
    • Rate limiting uses IP for abuse prevention only (not persisted)

Deletion Rules

  • Feedback Deletion: Deletes metadata.yaml, content.txt, analysis.md, and all attachments/
  • Product Archival: Sets status to "archived", preserves all feedback (FR-052)
  • Product Owner Removal: Unassigns from products, does not delete feedback
  • Cascade Protection: Cannot delete Product with active feedback (archive instead)

Storage Implementation Notes

Directory Structure Example

data/
├── users.yaml                          # All users (admins + owners)
└── products/
    ├── 001-acme-app/
    │   ├── config.yaml                # Product metadata
    │   └── feedback/
    │       ├── a3f2c1d5-8b4e-.../
    │       │   ├── metadata.yaml      # Feedback + attachment metadata
    │       │   ├── content.txt        # Original feedback text
    │       │   ├── analysis.md        # AI analysis report
    │       │   └── attachments/
    │       │       ├── screenshot.png
    │       │       └── error_log.txt
    │       └── b7e1f3d2-4a9c-.../
    │           ├── metadata.yaml
    │           ├── content.txt
    │           └── analysis.md        # No attachments/ for this one
    └── 002-beta-service/
        ├── config.yaml
        └── feedback/
            └── ...

File Format Standards

  • YAML: UTF-8 encoding, 2-space indentation, explicit type declarations
  • Markdown: CommonMark specification, UTF-8 encoding
  • Text Files: UTF-8 encoding with BOM handling

Indexing Strategy (Performance)

For dashboard performance (SC-008, SC-014):

  • Cache product feedback counts in config.yaml statistics
  • Implement pagination (50 items per page)
  • Load metadata.yaml only, defer analysis.md loading until detail view
  • File modification times used for sorting (newest first per FR-041)

Validation Summary by Functional Requirement

FR Validation Location Rule
FR-002 Feedback.original_text Max 10,000 characters
FR-004 Feedback.attachment_count 0-3 attachments
FR-006 Attachment.size_bytes Max 10MB per file
FR-011 Feedback validation At least text OR files required
FR-012 Feedback validation Cannot be completely empty
FR-046 Product.id Must be unique
FR-048 Product.assigned_owner_ids 1+ owners required
FR-053 Product status check Reject if archived
FR-063 User.password_hash bcrypt with cost 12

Next Steps: Define API contracts in /contracts/ directory