Files
Reklamator/specs/001-build-an-application/contracts/submission_routes.md
T

221 lines
5.3 KiB
Markdown
Raw Normal View History

# Submission Routes Contract
**Scope**: Anonymous feedback submission web routes (User Story P1)
**Authentication**: None (anonymous access)
**Response Type**: Server-rendered HTML (no JavaScript required)
---
## GET /submit/{product_slug}
Display the feedback submission form for a specific product.
### Request
**Path Parameters**:
- `product_slug` (string, required): Product's URL-safe identifier
**Headers**: None required
**Query Parameters**: None
### Response
**Success (200 OK)**:
```html
Content-Type: text/html
<!DOCTYPE html>
<html>
<head><title>Submit Feedback - {Product Name}</title></head>
<body>
<h1>Submit Feedback for {Product Name}</h1>
<form method="POST" action="/submit/{product_slug}" enctype="multipart/form-data">
<textarea name="feedback_text" maxlength="10000"></textarea>
<input type="file" name="attachments" multiple accept=".pdf,.docx,.txt,.jpg,.png,.gif,.webp">
<button type="submit">Submit Feedback</button>
</form>
</body>
</html>
```
**Error (404 Not Found)**: Product does not exist or is archived
```html
Content-Type: text/html
<!DOCTYPE html>
<html>
<body>
<h1>Product Not Found</h1>
<p>The product you're looking for does not exist or is no longer accepting feedback.</p>
</body>
</html>
```
### Functional Requirements Covered
- FR-001: Public, unauthenticated submission form
- FR-002: Text input up to 10,000 characters
- FR-004: Up to 3 file attachments
---
## POST /submit/{product_slug}
Submit anonymous feedback for a specific product.
### Request
**Path Parameters**:
- `product_slug` (string, required): Product's URL-safe identifier
**Headers**:
- `Content-Type: multipart/form-data`
**Form Data**:
- `feedback_text` (string, optional): Feedback text (0-10,000 characters)
- `attachments` (file[], optional): Up to 3 files, max 10MB each
**Example**:
```http
POST /submit/acme-app HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="feedback_text"
The app crashes when uploading files over 5MB.
------WebKitFormBoundary
Content-Disposition: form-data; name="attachments"; filename="screenshot.png"
Content-Type: image/png
[binary data]
------WebKitFormBoundary--
```
### Response
**Success (200 OK)**:
```html
Content-Type: text/html
<!DOCTYPE html>
<html>
<body>
<h1>Thank You!</h1>
<p>Your feedback has been submitted successfully.</p>
<p>Your feedback ID: {feedback_id}</p>
</body>
</html>
```
**Error (400 Bad Request)**: Validation failure
```html
Content-Type: text/html
<!DOCTYPE html>
<html>
<body>
<h1>Submission Error</h1>
<ul>
<li>Feedback must contain text or at least one attachment</li>
<li>Maximum 3 attachments allowed</li>
<li>Text cannot exceed 10,000 characters</li>
<li>File size cannot exceed 10MB per file</li>
<li>Unsupported file type: {filename}</li>
</ul>
</body>
</html>
```
**Error (413 Payload Too Large)**: File size exceeds limit
```html
Content-Type: text/html
HTTP/1.1 413 Payload Too Large
<!DOCTYPE html>
<html>
<body>
<h1>File Too Large</h1>
<p>One or more files exceed the 10MB limit.</p>
</body>
</html>
```
**Error (429 Too Many Requests)**: Rate limit exceeded
```html
Content-Type: text/html
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1697456789
<!DOCTYPE html>
<html>
<body>
<h1>Too Many Submissions</h1>
<p>You have exceeded the submission limit of 10 per hour. Please try again later.</p>
</body>
</html>
```
**Error (451 Unavailable For Legal Reasons)**: Malware detected
```html
Content-Type: text/html
<!DOCTYPE html>
<html>
<body>
<h1>Security Error</h1>
<p>One or more files failed security scanning. Please ensure your files are safe and try again.</p>
</body>
</html>
```
### Validation Rules
1. **Text Validation** (FR-002, FR-003):
- Length: 0-10,000 characters
- Encoding: UTF-8, any language accepted
- Empty allowed if attachments present
2. **Attachment Validation** (FR-004, FR-005, FR-006):
- Count: 0-3 files
- Size: Max 10MB per file
- Types: PDF, DOCX, TXT, JPG, PNG, GIF, WebP
- MIME type validation (server-side)
3. **Submission Validation** (FR-011, FR-012):
- Must have text OR attachments (not both empty)
4. **Security** (FR-059, FR-060):
- ClamAV virus scan before storage
- Filename sanitization (remove path traversal)
- MIME type validation
5. **Rate Limiting** (FR-061):
- 10 submissions per hour per IP address
### Functional Requirements Covered
- FR-001 to FR-012: Complete submission flow
- FR-055: No IP/session tracking stored
- FR-059, FR-060: File security
- FR-061: Rate limiting
### Side Effects
1. **File System**:
- Creates `data/products/{product_id}/feedback/{feedback_id}/`
- Writes `metadata.yaml`, `content.txt`
- Writes `attachments/{filename}` if files uploaded
2. **Async Processing**:
- Triggers AI analysis background job
- Updates feedback status: `submitted``analyzing`
---
## POST /submit/{product_slug}/status/{feedback_id}
**Note**: This endpoint is OUT OF SCOPE for MVP. Feedback submission is fire-and-forget. Users cannot track submission status anonymously.
Future consideration: Anonymous status check via feedback ID (requires balancing anonymity with user experience).