2025-10-15 22:31:26 +02:00
|
|
|
# Quickstart Guide: Reklamator Development
|
|
|
|
|
|
|
|
|
|
**Branch**: `001-build-an-application` | **Date**: 2025-10-15
|
|
|
|
|
|
|
|
|
|
This guide helps developers set up the Reklamator development environment and understand the project structure.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Prerequisites
|
|
|
|
|
|
|
|
|
|
- Python 3.11 or higher
|
|
|
|
|
- ClamAV daemon (`clamd`) for malware scanning
|
|
|
|
|
- Git
|
|
|
|
|
- Virtual environment tool (venv)
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Initial Setup
|
|
|
|
|
|
|
|
|
|
### 1. Clone Repository
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
git clone <repository-url>
|
|
|
|
|
cd reklamator
|
|
|
|
|
git checkout 001-build-an-application
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 2. Create Virtual Environment
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
python3 -m venv venv
|
|
|
|
|
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 3. Install Dependencies
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
pip install -r requirements.txt
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Expected Core Dependencies**:
|
|
|
|
|
- Flask 3.0+
|
|
|
|
|
- Flask-Login (session management)
|
|
|
|
|
- Flask-Limiter (rate limiting)
|
|
|
|
|
- Flask-WTF (CSRF protection)
|
|
|
|
|
- anthropic (Claude API client)
|
|
|
|
|
- clamd (ClamAV integration)
|
|
|
|
|
- bcrypt (password hashing)
|
|
|
|
|
- PyYAML (configuration files)
|
|
|
|
|
- pytest, pytest-flask (testing)
|
|
|
|
|
|
|
|
|
|
### 4. Install and Configure ClamAV
|
|
|
|
|
|
|
|
|
|
**Ubuntu/Debian**:
|
|
|
|
|
```bash
|
|
|
|
|
sudo apt-get update
|
|
|
|
|
sudo apt-get install clamav clamav-daemon
|
|
|
|
|
sudo systemctl start clamav-daemon
|
|
|
|
|
sudo systemctl enable clamav-daemon
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**macOS**:
|
|
|
|
|
```bash
|
|
|
|
|
brew install clamav
|
|
|
|
|
brew services start clamav
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Verify ClamAV is running**:
|
|
|
|
|
```bash
|
|
|
|
|
clamdscan --version
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 5. Set Up Environment Variables
|
|
|
|
|
|
|
|
|
|
Create `.env` file in project root:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Flask Configuration
|
|
|
|
|
FLASK_APP=run.py
|
|
|
|
|
FLASK_ENV=development
|
|
|
|
|
SECRET_KEY=your-secret-key-here-change-in-production
|
|
|
|
|
|
|
|
|
|
# Claude API
|
|
|
|
|
ANTHROPIC_API_KEY=your-claude-api-key-here
|
|
|
|
|
|
|
|
|
|
# ClamAV
|
|
|
|
|
CLAMD_SOCKET=/var/run/clamav/clamd.ctl # Adjust path for your system
|
|
|
|
|
|
|
|
|
|
# File Storage
|
|
|
|
|
DATA_DIR=./data
|
|
|
|
|
|
|
|
|
|
# Rate Limiting
|
|
|
|
|
RATE_LIMIT_ENABLED=true
|
|
|
|
|
RATE_LIMIT_PER_HOUR=10
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Get Claude API Key**:
|
|
|
|
|
1. Sign up at https://console.anthropic.com/
|
|
|
|
|
2. Create an API key
|
|
|
|
|
3. Add to `.env` file
|
|
|
|
|
|
|
|
|
|
### 6. Initialize Data Directory
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
mkdir -p data/products
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 7. Create Initial Admin User
|
|
|
|
|
|
|
|
|
|
Create `data/users.yaml`:
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
users:
|
|
|
|
|
- id: "admin-001"
|
|
|
|
|
email: "admin@localhost"
|
|
|
|
|
password_hash: "$2b$12$KIXxBt5H4vE2zT9vN8FqOe9JxwLxPqz0q5kYv2Z3j4RQvN8FqOe9J" # Password: "admin123"
|
|
|
|
|
name: "Admin User"
|
|
|
|
|
role: "admin"
|
|
|
|
|
assigned_product_ids: []
|
|
|
|
|
created_date: "2025-10-15"
|
|
|
|
|
last_login: null
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Security Note**: Change the password immediately after first login!
|
|
|
|
|
|
|
|
|
|
To generate a new password hash:
|
|
|
|
|
```python
|
|
|
|
|
import bcrypt
|
|
|
|
|
password = "your-password-here"
|
|
|
|
|
hash = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(rounds=12))
|
|
|
|
|
print(hash.decode('utf-8'))
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Running the Application
|
|
|
|
|
|
|
|
|
|
### Development Server
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
python run.py
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Application will be available at: http://localhost:5000
|
|
|
|
|
|
|
|
|
|
### Production Server (Gunicorn)
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
gunicorn -w 4 -b 0.0.0.0:8000 "app:create_app()"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Project Structure Overview
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
reklamator/
|
|
|
|
|
├── app/ # Application code
|
|
|
|
|
│ ├── __init__.py # Flask app factory
|
|
|
|
|
│ ├── routes/ # HTTP endpoints
|
|
|
|
|
│ │ ├── submission.py # Anonymous feedback submission
|
|
|
|
|
│ │ ├── dashboard.py # Product owner dashboard
|
|
|
|
|
│ │ └── admin.py # Admin interface
|
|
|
|
|
│ ├── services/ # Business logic
|
|
|
|
|
│ │ ├── feedback_storage.py # File-based storage operations
|
|
|
|
|
│ │ ├── ai_analyzer.py # AI analysis/translation
|
|
|
|
|
│ │ └── auth.py # Authentication
|
|
|
|
|
│ ├── models/ # Domain models
|
|
|
|
|
│ │ ├── feedback.py # Feedback entity
|
|
|
|
|
│ │ ├── product.py # Product entity
|
|
|
|
|
│ │ └── user.py # User entity
|
|
|
|
|
│ ├── templates/ # HTML templates (Jinja2)
|
|
|
|
|
│ └── utils/ # Utilities
|
|
|
|
|
│ ├── file_validator.py # File upload validation
|
|
|
|
|
│ └── rate_limiter.py # Rate limiting
|
|
|
|
|
│
|
|
|
|
|
├── data/ # File-based storage
|
|
|
|
|
│ ├── users.yaml # User accounts
|
|
|
|
|
│ └── products/ # Product-specific data
|
|
|
|
|
│ └── {product-id}/
|
|
|
|
|
│ ├── config.yaml # Product metadata
|
|
|
|
|
│ └── feedback/
|
|
|
|
|
│ └── {feedback-id}/
|
|
|
|
|
│ ├── metadata.yaml
|
|
|
|
|
│ ├── content.txt
|
|
|
|
|
│ ├── analysis.md
|
|
|
|
|
│ └── attachments/
|
|
|
|
|
│
|
|
|
|
|
├── tests/ # Test suite
|
|
|
|
|
│ ├── contract/ # API contract tests
|
|
|
|
|
│ ├── integration/ # User journey tests
|
|
|
|
|
│ └── unit/ # Unit tests
|
|
|
|
|
│
|
|
|
|
|
├── config/ # Configuration files
|
|
|
|
|
│ ├── development.py
|
|
|
|
|
│ ├── production.py
|
|
|
|
|
│ └── testing.py
|
|
|
|
|
│
|
|
|
|
|
├── specs/ # Feature specifications (this directory)
|
|
|
|
|
├── requirements.txt
|
|
|
|
|
├── pytest.ini
|
|
|
|
|
├── .env # Environment variables (not in git)
|
|
|
|
|
└── run.py # Application entry point
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Common Development Tasks
|
|
|
|
|
|
|
|
|
|
### Creating a Test Product
|
|
|
|
|
|
|
|
|
|
1. Log in as admin: http://localhost:5000/login
|
|
|
|
|
- Email: `admin@localhost`
|
|
|
|
|
- Password: `admin123`
|
|
|
|
|
|
|
|
|
|
2. Navigate to: http://localhost:5000/admin/products
|
|
|
|
|
|
|
|
|
|
3. Click "Create New Product" and fill in:
|
|
|
|
|
- ID: `001-test-product`
|
|
|
|
|
- Name: `Test Product`
|
|
|
|
|
- Target Language: `en`
|
|
|
|
|
- Submission URL Slug: `test-product`
|
|
|
|
|
- Assign yourself as product owner
|
|
|
|
|
|
|
|
|
|
4. Access submission form: http://localhost:5000/submit/test-product
|
|
|
|
|
|
|
|
|
|
### Submitting Test Feedback
|
|
|
|
|
|
|
|
|
|
1. Visit: http://localhost:5000/submit/test-product
|
|
|
|
|
2. Enter feedback text
|
|
|
|
|
3. Optionally attach files (max 3, max 10MB each)
|
|
|
|
|
4. Submit
|
|
|
|
|
|
|
|
|
|
Feedback will be processed asynchronously. Check the dashboard to view analysis results.
|
|
|
|
|
|
|
|
|
|
### Viewing Feedback in Dashboard
|
|
|
|
|
|
|
|
|
|
1. Log in: http://localhost:5000/login
|
|
|
|
|
2. Dashboard: http://localhost:5000/dashboard
|
|
|
|
|
3. Click on feedback item to view details
|
|
|
|
|
|
|
|
|
|
### Running Tests
|
|
|
|
|
|
|
|
|
|
**All tests**:
|
|
|
|
|
```bash
|
|
|
|
|
pytest
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Contract tests only**:
|
|
|
|
|
```bash
|
|
|
|
|
pytest tests/contract/
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Integration tests only**:
|
|
|
|
|
```bash
|
|
|
|
|
pytest tests/integration/
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**With coverage**:
|
|
|
|
|
```bash
|
|
|
|
|
pytest --cov=app --cov-report=html
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Test-first workflow** (per constitution):
|
|
|
|
|
1. Write test for new feature (should fail)
|
|
|
|
|
2. Run test to verify failure
|
|
|
|
|
3. Implement feature
|
|
|
|
|
4. Run test to verify success
|
|
|
|
|
5. Refactor if needed
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-10-16 13:47:40 +02:00
|
|
|
## Web Routes Reference
|
2025-10-15 22:31:26 +02:00
|
|
|
|
|
|
|
|
### Anonymous Submission
|
|
|
|
|
- `GET /submit/{product_slug}` - Submission form
|
|
|
|
|
- `POST /submit/{product_slug}` - Submit feedback
|
|
|
|
|
|
|
|
|
|
### Authentication
|
|
|
|
|
- `GET /login` - Login form
|
|
|
|
|
- `POST /login` - Authenticate
|
|
|
|
|
- `GET /logout` - Log out
|
|
|
|
|
|
|
|
|
|
### Dashboard (Product Owners)
|
|
|
|
|
- `GET /dashboard` - Feedback list (with filters)
|
|
|
|
|
- `GET /feedback/{feedback_id}` - Feedback detail
|
|
|
|
|
- `POST /feedback/{feedback_id}/status` - Update status
|
|
|
|
|
- `GET /feedback/{feedback_id}/attachment/{filename}` - Download attachment
|
|
|
|
|
|
|
|
|
|
### Admin
|
|
|
|
|
- `GET /admin/products` - List products
|
|
|
|
|
- `GET /admin/products/new` - Create product form
|
|
|
|
|
- `POST /admin/products` - Create product
|
|
|
|
|
- `GET /admin/products/{id}/edit` - Edit product form
|
|
|
|
|
- `POST /admin/products/{id}` - Update product
|
|
|
|
|
- `POST /admin/products/{id}/archive` - Archive product
|
|
|
|
|
- `GET /admin/users` - List users
|
|
|
|
|
- `POST /admin/users` - Create user
|
|
|
|
|
- `POST /admin/users/{id}` - Update user
|
|
|
|
|
|
|
|
|
|
Full API contracts: See `/specs/001-build-an-application/contracts/`
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Configuration
|
|
|
|
|
|
|
|
|
|
### Development Configuration (`config/development.py`)
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
DEBUG = True
|
|
|
|
|
TESTING = False
|
|
|
|
|
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-secret-key')
|
|
|
|
|
DATA_DIR = os.environ.get('DATA_DIR', './data')
|
|
|
|
|
ANTHROPIC_API_KEY = os.environ.get('ANTHROPIC_API_KEY')
|
|
|
|
|
CLAMD_SOCKET = os.environ.get('CLAMD_SOCKET', '/var/run/clamav/clamd.ctl')
|
|
|
|
|
MAX_CONTENT_LENGTH = 10 * 1024 * 1024 # 10MB max upload
|
|
|
|
|
RATE_LIMIT_ENABLED = True
|
|
|
|
|
RATE_LIMIT_PER_HOUR = 10
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Production Configuration (`config/production.py`)
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
DEBUG = False
|
|
|
|
|
TESTING = False
|
|
|
|
|
SECRET_KEY = os.environ.get('SECRET_KEY') # Required, no default
|
|
|
|
|
DATA_DIR = os.environ.get('DATA_DIR', '/var/lib/reklamator/data')
|
|
|
|
|
ANTHROPIC_API_KEY = os.environ.get('ANTHROPIC_API_KEY') # Required
|
|
|
|
|
CLAMD_SOCKET = os.environ.get('CLAMD_SOCKET', '/var/run/clamav/clamd.ctl')
|
|
|
|
|
MAX_CONTENT_LENGTH = 10 * 1024 * 1024
|
|
|
|
|
RATE_LIMIT_ENABLED = True
|
|
|
|
|
RATE_LIMIT_PER_HOUR = 10
|
|
|
|
|
SESSION_COOKIE_SECURE = True # HTTPS only
|
|
|
|
|
SESSION_COOKIE_HTTPONLY = True
|
|
|
|
|
SESSION_COOKIE_SAMESITE = 'Lax'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Troubleshooting
|
|
|
|
|
|
|
|
|
|
### ClamAV Connection Error
|
|
|
|
|
|
|
|
|
|
**Error**: `pyclamd.ConnectionError: Could not connect to clamd`
|
|
|
|
|
|
|
|
|
|
**Solution**:
|
|
|
|
|
1. Verify ClamAV is running: `sudo systemctl status clamav-daemon`
|
|
|
|
|
2. Check socket path: `ls /var/run/clamav/clamd.ctl`
|
|
|
|
|
3. Update `CLAMD_SOCKET` in `.env` if needed
|
|
|
|
|
4. Restart ClamAV: `sudo systemctl restart clamav-daemon`
|
|
|
|
|
|
|
|
|
|
### Claude API Error
|
|
|
|
|
|
|
|
|
|
**Error**: `anthropic.APIError: Invalid API key`
|
|
|
|
|
|
|
|
|
|
**Solution**:
|
|
|
|
|
1. Verify API key in `.env` file
|
|
|
|
|
2. Check key is active at https://console.anthropic.com/
|
|
|
|
|
3. Ensure no extra whitespace in key
|
|
|
|
|
|
|
|
|
|
### File Upload Fails
|
|
|
|
|
|
|
|
|
|
**Error**: `413 Payload Too Large`
|
|
|
|
|
|
|
|
|
|
**Solution**:
|
|
|
|
|
- Check file size (max 10MB per file)
|
|
|
|
|
- Check total payload size (3 files + form data)
|
|
|
|
|
- Verify `MAX_CONTENT_LENGTH` in config
|
|
|
|
|
|
|
|
|
|
**Error**: `Unsupported file type`
|
|
|
|
|
|
|
|
|
|
**Solution**:
|
|
|
|
|
- Verify file extension: `.pdf`, `.docx`, `.txt`, `.jpg`, `.png`, `.gif`, `.webp`
|
|
|
|
|
- Check MIME type matches extension
|
|
|
|
|
|
|
|
|
|
### Rate Limit Exceeded
|
|
|
|
|
|
|
|
|
|
**Error**: `429 Too Many Requests`
|
|
|
|
|
|
|
|
|
|
**Solution**:
|
|
|
|
|
- Wait 1 hour before retrying
|
|
|
|
|
- For development, disable rate limiting: `RATE_LIMIT_ENABLED=false` in `.env`
|
|
|
|
|
- Or increase limit: `RATE_LIMIT_PER_HOUR=100`
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Development Guidelines
|
|
|
|
|
|
|
|
|
|
### Test-First Discipline (Constitutional Requirement)
|
|
|
|
|
|
|
|
|
|
1. **Before implementing any feature**:
|
|
|
|
|
- Write contract/integration test
|
|
|
|
|
- Run test to verify it fails
|
|
|
|
|
- Implement feature
|
|
|
|
|
- Run test to verify success
|
|
|
|
|
|
|
|
|
|
2. **Test organization**:
|
|
|
|
|
- Contract tests: Test API endpoints (HTTP requests/responses)
|
|
|
|
|
- Integration tests: Test user journeys (multi-step workflows)
|
|
|
|
|
- Unit tests: Test complex business logic in isolation
|
|
|
|
|
|
|
|
|
|
3. **Example test-first workflow**:
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
# Step 1: Write test (tests/contract/test_submission_api.py)
|
|
|
|
|
def test_submit_feedback_with_text_only(client):
|
|
|
|
|
response = client.post('/submit/test-product', data={
|
|
|
|
|
'feedback_text': 'This is test feedback'
|
|
|
|
|
})
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
assert b'Thank You!' in response.data
|
|
|
|
|
|
|
|
|
|
# Step 2: Run test (should FAIL - endpoint not implemented)
|
|
|
|
|
# pytest tests/contract/test_submission_api.py::test_submit_feedback_with_text_only
|
|
|
|
|
|
|
|
|
|
# Step 3: Implement feature (app/routes/submission.py)
|
|
|
|
|
@bp.route('/submit/<product_slug>', methods=['POST'])
|
|
|
|
|
def submit_feedback(product_slug):
|
|
|
|
|
# Implementation here
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# Step 4: Run test again (should PASS)
|
|
|
|
|
# pytest tests/contract/test_submission_api.py::test_submit_feedback_with_text_only
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Code Style
|
|
|
|
|
|
|
|
|
|
- Follow PEP 8
|
|
|
|
|
- Use type hints where helpful
|
|
|
|
|
- Keep functions small and focused
|
|
|
|
|
- Prefer clear names over comments
|
|
|
|
|
- Run linting: `flake8 app/`
|
|
|
|
|
- Run formatting: `black app/`
|
|
|
|
|
|
|
|
|
|
### Git Workflow
|
|
|
|
|
|
|
|
|
|
- Feature branch: `001-build-an-application` (already created)
|
|
|
|
|
- Commit messages: Descriptive, imperative mood
|
|
|
|
|
- Test before committing
|
|
|
|
|
- Regular integration to main branch
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Next Steps
|
|
|
|
|
|
|
|
|
|
1. **Set up environment** following steps above
|
|
|
|
|
2. **Run tests** to verify setup: `pytest`
|
|
|
|
|
3. **Start development server**: `python run.py`
|
|
|
|
|
4. **Create test product** via admin interface
|
|
|
|
|
5. **Submit test feedback** via submission form
|
|
|
|
|
6. **Review implementation plan**: `/specs/001-build-an-application/plan.md`
|
|
|
|
|
7. **Begin task implementation**: Wait for `/specs/001-build-an-application/tasks.md` (generated by `/speckit.tasks`)
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Resources
|
|
|
|
|
|
|
|
|
|
- **Feature Specification**: `/specs/001-build-an-application/spec.md`
|
|
|
|
|
- **Implementation Plan**: `/specs/001-build-an-application/plan.md`
|
|
|
|
|
- **Research**: `/specs/001-build-an-application/research.md`
|
|
|
|
|
- **Data Model**: `/specs/001-build-an-application/data-model.md`
|
|
|
|
|
- **API Contracts**: `/specs/001-build-an-application/contracts/`
|
|
|
|
|
- **Flask Documentation**: https://flask.palletsprojects.com/
|
|
|
|
|
- **Claude API Documentation**: https://docs.anthropic.com/
|
|
|
|
|
- **Pytest Documentation**: https://docs.pytest.org/
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
**Questions?** Refer to the specification documents or implementation plan for detailed requirements and design decisions.
|