Initial Commit
This commit is contained in:
713
IMPLEMENTATION_PLAN.md
Normal file
713
IMPLEMENTATION_PLAN.md
Normal file
@@ -0,0 +1,713 @@
|
||||
# Privacy Policy Analyzer - Implementation Plan
|
||||
|
||||
## Overview
|
||||
A self-hosted web application that analyzes privacy policies using AI (ChatGPT) and provides easy-to-understand ratings and summaries.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Runtime**: Bun (JavaScript)
|
||||
- **Database**: PostgreSQL
|
||||
- **Search**: Meilisearch
|
||||
- **Cache**: Redis
|
||||
- **Templating**: EJS
|
||||
- **AI**: OpenAI API (GPT-4o/GPT-4-turbo)
|
||||
- **Containerization**: Docker Compose
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
privacy-policy-analyzer/
|
||||
├── docker-compose.yml # Multi-service orchestration
|
||||
├── Dockerfile # Bun app container
|
||||
├── .env.example # Environment variables template
|
||||
├── .env # Actual environment variables (gitignored)
|
||||
├── package.json # Bun dependencies
|
||||
├── src/
|
||||
│ ├── app.js # Main application entry
|
||||
│ ├── config/
|
||||
│ │ ├── database.js # PostgreSQL connection
|
||||
│ │ ├── redis.js # Redis connection
|
||||
│ │ ├── meilisearch.js # Meilisearch client
|
||||
│ │ └── openai.js # OpenAI client
|
||||
│ ├── models/
|
||||
│ │ ├── Service.js # Service/site model
|
||||
│ │ ├── PolicyVersion.js # Policy version model
|
||||
│ │ └── Analysis.js # Analysis results model
|
||||
│ ├── routes/
|
||||
│ │ ├── public.js # Public-facing routes
|
||||
│ │ └── admin.js # Admin panel routes
|
||||
│ ├── controllers/
|
||||
│ │ ├── publicController.js
|
||||
│ │ └── adminController.js
|
||||
│ ├── services/
|
||||
│ │ ├── aiAnalyzer.js # OpenAI analysis logic
|
||||
│ │ ├── policyFetcher.js # Fetch policy from URL
|
||||
│ │ ├── scheduler.js # Cron jobs
|
||||
│ │ └── searchIndexer.js # Meilisearch indexing
|
||||
│ ├── middleware/
|
||||
│ │ ├── auth.js # Admin authentication
|
||||
│ │ └── errorHandler.js # Global error handling
|
||||
│ ├── views/
|
||||
│ │ ├── layouts/
|
||||
│ │ │ └── main.ejs
|
||||
│ │ ├── public/
|
||||
│ │ │ ├── index.ejs # Service listing
|
||||
│ │ │ └── service.ejs # Service detail page
|
||||
│ │ └── admin/
|
||||
│ │ ├── login.ejs
|
||||
│ │ ├── dashboard.ejs
|
||||
│ │ ├── add-service.ejs
|
||||
│ │ └── edit-service.ejs
|
||||
│ └── utils/
|
||||
│ ├── logger.js
|
||||
│ └── validators.js
|
||||
└── migrations/
|
||||
└── 001_initial.sql # Database schema
|
||||
```
|
||||
|
||||
## Database Schema
|
||||
|
||||
### Services Table
|
||||
```sql
|
||||
CREATE TABLE services (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
url VARCHAR(500) NOT NULL,
|
||||
logo_url VARCHAR(500),
|
||||
policy_url VARCHAR(500),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
### Policy Versions Table
|
||||
```sql
|
||||
CREATE TABLE policy_versions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
service_id INTEGER REFERENCES services(id) ON DELETE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
content_hash VARCHAR(64) NOT NULL, -- SHA-256 hash for change detection
|
||||
fetched_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
### Analyses Table
|
||||
```sql
|
||||
CREATE TABLE analyses (
|
||||
id SERIAL PRIMARY KEY,
|
||||
service_id INTEGER REFERENCES services(id) ON DELETE CASCADE,
|
||||
policy_version_id INTEGER REFERENCES policy_versions(id) ON DELETE CASCADE,
|
||||
overall_score VARCHAR(1) NOT NULL, -- A, B, C, D, or E
|
||||
findings JSONB NOT NULL, -- Structured analysis results
|
||||
raw_analysis TEXT, -- Full AI response for debugging
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- When this analysis was created (used as "last analyzed" date)
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
**Note**: The `created_at` field in the analyses table represents when the policy was last analyzed. This date must be displayed prominently on every service page so users know the freshness of the analysis.
|
||||
|
||||
### Admin Sessions Table
|
||||
```sql
|
||||
CREATE TABLE admin_sessions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
session_token VARCHAR(255) UNIQUE NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
## AI Analysis Structure
|
||||
|
||||
### Scoring Parameters
|
||||
|
||||
The AI will analyze privacy policies based on these weighted categories:
|
||||
|
||||
1. **Data Collection (25%)**
|
||||
- What personal data is collected
|
||||
- Scope of collection (minimal vs excessive)
|
||||
- Collection methods (active vs passive)
|
||||
|
||||
2. **Data Sharing (25%)**
|
||||
- Third-party sharing practices
|
||||
- Purposes for sharing
|
||||
- Sale of personal data
|
||||
|
||||
3. **User Rights (20%)**
|
||||
- Data access rights
|
||||
- Deletion rights
|
||||
- Portability rights
|
||||
- Opt-out mechanisms
|
||||
|
||||
4. **Data Retention (15%)**
|
||||
- Retention periods
|
||||
- Deletion policies
|
||||
- Post-account deletion handling
|
||||
|
||||
5. **Tracking & Security (15%)**
|
||||
- Tracking technologies used
|
||||
- Security measures mentioned
|
||||
- Encryption practices
|
||||
|
||||
### AI Output Schema (JSON)
|
||||
|
||||
```json
|
||||
{
|
||||
"overall_score": "A|B|C|D|E",
|
||||
"score_breakdown": {
|
||||
"data_collection": "A|B|C|D|E",
|
||||
"data_sharing": "A|B|C|D|E",
|
||||
"user_rights": "A|B|C|D|E",
|
||||
"data_retention": "A|B|C|D|E",
|
||||
"tracking_security": "A|B|C|D|E"
|
||||
},
|
||||
"findings": {
|
||||
"positive": [
|
||||
{
|
||||
"category": "user_rights",
|
||||
"title": "Clear deletion process",
|
||||
"description": "Users can delete their account and data easily",
|
||||
"severity": "good"
|
||||
}
|
||||
],
|
||||
"negative": [
|
||||
{
|
||||
"category": "data_sharing",
|
||||
"title": "Data sold to third parties",
|
||||
"description": "Personal data is sold to advertisers and partners",
|
||||
"severity": "blocker"
|
||||
}
|
||||
],
|
||||
"neutral": [
|
||||
{
|
||||
"category": "general",
|
||||
"title": "Policy updated regularly",
|
||||
"description": "Privacy policy is reviewed and updated annually",
|
||||
"severity": "neutral"
|
||||
}
|
||||
]
|
||||
},
|
||||
"data_types_collected": [
|
||||
"name",
|
||||
"email",
|
||||
"location",
|
||||
"device_info"
|
||||
],
|
||||
"third_parties": [
|
||||
{
|
||||
"name": "Google Analytics",
|
||||
"purpose": "analytics",
|
||||
"data_shared": ["usage_data", "device_info"]
|
||||
}
|
||||
],
|
||||
"summary": "Brief 2-3 sentence summary of the privacy policy"
|
||||
}
|
||||
```
|
||||
|
||||
### Severity Levels
|
||||
|
||||
- **blocker**: Critical privacy concerns (red icon)
|
||||
- **bad**: Significant issues (orange icon)
|
||||
- **neutral**: Informational (gray icon)
|
||||
- **good**: Positive privacy practices (green icon)
|
||||
|
||||
## Features
|
||||
|
||||
### Phase 1: Foundation
|
||||
|
||||
1. **Docker Setup**
|
||||
- Bun application container
|
||||
- PostgreSQL container with persistent volume
|
||||
- Meilisearch container
|
||||
- Redis container
|
||||
- Docker network for inter-service communication
|
||||
|
||||
2. **Database Layer**
|
||||
- Migration system
|
||||
- Connection pooling
|
||||
- Basic CRUD operations for all models
|
||||
|
||||
3. **Basic Web Server**
|
||||
- Bun HTTP server or lightweight framework
|
||||
- EJS templating engine setup
|
||||
- Static file serving
|
||||
- Request logging
|
||||
|
||||
### Phase 2: Core Features
|
||||
|
||||
1. **Admin Authentication**
|
||||
- Simple login form
|
||||
- Session-based authentication (stored in Redis)
|
||||
- Single admin user (credentials in .env)
|
||||
- Protected admin routes
|
||||
|
||||
2. **Service Management**
|
||||
- Add new service (name, URL, policy URL)
|
||||
- Edit service details
|
||||
- Delete service
|
||||
- List all services in admin panel
|
||||
|
||||
3. **Policy Fetching**
|
||||
- Fetch policy from URL (with timeout and error handling)
|
||||
- Support for pasting policy text directly
|
||||
- Content hash generation for change detection
|
||||
- Store full policy text in database
|
||||
|
||||
4. **AI Analysis**
|
||||
- Manual trigger from admin panel
|
||||
- Structured prompt engineering
|
||||
- JSON mode for consistent output
|
||||
- Error handling and retry logic
|
||||
- Store analysis results in database
|
||||
|
||||
5. **Public Pages**
|
||||
- Homepage with service listing (A-E grades displayed, last analyzed dates shown)
|
||||
- Search functionality via Meilisearch
|
||||
- Individual service detail page with prominent "last analyzed" date display
|
||||
- Filter by grade
|
||||
|
||||
### Phase 3: Enhancements
|
||||
|
||||
1. **Automated Policy Updates**
|
||||
- Daily cron job to check all policy URLs
|
||||
- Compare content hash with latest version
|
||||
- Flag services with changed policies
|
||||
- Admin notification of pending re-analysis
|
||||
|
||||
2. **Re-analysis Workflow**
|
||||
- Bulk re-analysis of updated policies
|
||||
- Historical analysis comparison
|
||||
- Show policy change history on service page
|
||||
|
||||
3. **Search & Discovery**
|
||||
- Full-text search via Meilisearch
|
||||
- Filter by data types collected
|
||||
- Filter by third parties
|
||||
- Sort by grade, name, last analyzed
|
||||
|
||||
4. **Caching**
|
||||
- Redis caching for public pages
|
||||
- Cache analysis results
|
||||
- Cache search results
|
||||
- TTL-based cache invalidation
|
||||
|
||||
### Phase 4: Polish
|
||||
|
||||
1. **Error Handling**
|
||||
- Global error handler middleware
|
||||
- User-friendly error pages
|
||||
- Graceful degradation when AI is unavailable
|
||||
|
||||
2. **Rate Limiting**
|
||||
- Rate limit on AI analysis endpoint
|
||||
- Rate limit on policy fetching
|
||||
- Prevent abuse
|
||||
|
||||
3. **UI/UX**
|
||||
- Clean, simple design
|
||||
- Responsive layout
|
||||
- Grade badges with colors
|
||||
- Expandable finding details
|
||||
|
||||
4. **Monitoring**
|
||||
- Basic logging
|
||||
- Health check endpoint
|
||||
- Analysis success/failure metrics
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Public Routes
|
||||
|
||||
- `GET /` - Homepage with service listing
|
||||
- `GET /search?q=query` - Search services
|
||||
- `GET /service/:id` - Service detail page
|
||||
- `GET /api/health` - Health check
|
||||
|
||||
### Admin Routes
|
||||
|
||||
- `GET /admin/login` - Login page
|
||||
- `POST /admin/login` - Authenticate
|
||||
- `GET /admin/logout` - Logout
|
||||
- `GET /admin/dashboard` - Admin dashboard
|
||||
- `GET /admin/services/new` - Add service form
|
||||
- `POST /admin/services` - Create service
|
||||
- `GET /admin/services/:id/edit` - Edit service form
|
||||
- `POST /admin/services/:id` - Update service
|
||||
- `POST /admin/services/:id/delete` - Delete service
|
||||
- `POST /admin/services/:id/analyze` - Trigger analysis
|
||||
- `GET /admin/pending-updates` - Services with policy changes
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```env
|
||||
# Database
|
||||
DATABASE_URL=postgresql://user:password@postgres:5432/privacy_analyzer
|
||||
|
||||
# Redis
|
||||
REDIS_URL=redis://redis:6379
|
||||
|
||||
# Meilisearch
|
||||
MEILISEARCH_URL=http://meilisearch:7700
|
||||
MEILISEARCH_API_KEY=your_master_key
|
||||
|
||||
# OpenAI
|
||||
OPENAI_API_KEY=sk-your-api-key
|
||||
OPENAI_MODEL=gpt-4o
|
||||
|
||||
# Admin
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_PASSWORD=secure_password_here
|
||||
SESSION_SECRET=random_session_secret
|
||||
|
||||
# App
|
||||
PORT=3000
|
||||
NODE_ENV=production
|
||||
```
|
||||
|
||||
## Docker Compose Configuration
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://postgres:password@postgres:5432/privacy_analyzer
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- MEILISEARCH_URL=http://meilisearch:7700
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- meilisearch
|
||||
volumes:
|
||||
- ./src:/app/src
|
||||
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=password
|
||||
- POSTGRES_DB=privacy_analyzer
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.6
|
||||
environment:
|
||||
- MEILI_MASTER_KEY=your_master_key
|
||||
volumes:
|
||||
- meilisearch_data:/meili_data
|
||||
ports:
|
||||
- "7700:7700"
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
meilisearch_data:
|
||||
```
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
### 1. Search Engine Optimization (SEO)
|
||||
|
||||
#### In-Page SEO
|
||||
- **Title Tags**: Dynamic `<title>` for each page
|
||||
- Homepage: "Privacy Policy Analyzer | Compare Website Privacy Practices"
|
||||
- Service page: "{Service Name} Privacy Policy Analysis | Grade {A-E}"
|
||||
- Search results: "Search Results for '{query}' | Privacy Policy Analyzer"
|
||||
- **Meta Descriptions**: 150-160 character descriptions for each page
|
||||
- **Open Graph Tags**: og:title, og:description, og:image, og:url for social sharing
|
||||
- **Twitter Cards**: Summary cards with large images
|
||||
- **Canonical URLs**: Prevent duplicate content issues
|
||||
- **Structured Data (Schema.org)**:
|
||||
- Organization schema for the site
|
||||
- Review/Rating schema for service pages
|
||||
- BreadcrumbList for navigation
|
||||
|
||||
#### Technical SEO
|
||||
- **Sitemap.xml**: Auto-generated daily, includes all public service pages
|
||||
- Lastmod timestamps from analysis `created_at` dates
|
||||
- Priority levels (homepage: 1.0, service pages: 0.8, search: 0.5)
|
||||
- **Robots.txt**: Allow public pages, disallow admin routes
|
||||
- **URL Structure**: Clean, descriptive URLs
|
||||
- `/service/facebook`
|
||||
- `/search?q=google`
|
||||
- `/grade/A` (filter by grade)
|
||||
- **Performance**: Fast page load times (affects SEO rankings)
|
||||
- **Mobile-First**: Responsive design is crawled as mobile
|
||||
|
||||
#### Last Updated Display
|
||||
- **Required on all service pages**: Display the `created_at` date from the latest analysis
|
||||
- **Format**: "Last analyzed: January 27, 2026" or relative time ("Last analyzed: 3 days ago")
|
||||
- **Location**: Prominently displayed near the service name/grade
|
||||
- **Purpose**: Users must know when the analysis was performed to assess freshness
|
||||
- **Example placement**:
|
||||
```html
|
||||
<div class="service-header">
|
||||
<h1>Facebook Privacy Policy Analysis</h1>
|
||||
<span class="grade grade-e">Grade E</span>
|
||||
<p class="last-updated">Last analyzed: January 27, 2026</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### Content SEO
|
||||
- **Semantic HTML5**: Proper use of `<header>`, `<nav>`, `<main>`, `<article>`, `<footer>`
|
||||
- **Heading Hierarchy**: Single H1 per page, logical H2-H6 structure
|
||||
- **Alt Text**: Descriptive alt text for all images (logo, grade badges)
|
||||
- **Internal Linking**: Link between related services
|
||||
- **Keywords**: Focus on "privacy policy analyzer", "{service} privacy", "privacy grade"
|
||||
|
||||
### 2. Performance Benchmarking
|
||||
|
||||
#### Target Metrics
|
||||
| Metric | Target | Maximum |
|
||||
|--------|--------|---------|
|
||||
| First Contentful Paint (FCP) | < 1.0s | 1.8s |
|
||||
| Largest Contentful Paint (LCP) | < 2.5s | 4.0s |
|
||||
| Time to Interactive (TTI) | < 3.8s | 7.3s |
|
||||
| Cumulative Layout Shift (CLS) | < 0.1 | 0.25 |
|
||||
| Total Blocking Time (TBT) | < 200ms | 600ms |
|
||||
| First Input Delay (FID) | < 100ms | 300ms |
|
||||
|
||||
#### Optimization Strategies
|
||||
- **Redis Caching**:
|
||||
- Public pages: 1 hour TTL
|
||||
- Analysis results: 24 hour TTL
|
||||
- API responses: 5 minute TTL
|
||||
- Meilisearch queries: 10 minute TTL
|
||||
- **Compression**: Brotli + Gzip for all text responses
|
||||
- **CDN**: Serve static assets (CSS, JS, images) via CDN
|
||||
- **Lazy Loading**: Load images and heavy content on-demand
|
||||
- **Database Optimization**:
|
||||
- Indexed columns: service.name, analysis.overall_score, policy_versions.service_id
|
||||
- Query optimization with EXPLAIN ANALYZE
|
||||
- Connection pooling (max 20 connections)
|
||||
- **Asset Optimization**:
|
||||
- Minified CSS/JS
|
||||
- Optimized images (WebP format)
|
||||
- Critical CSS inline
|
||||
- Async/defer for non-critical scripts
|
||||
|
||||
#### Monitoring
|
||||
- **Lighthouse CI**: Automated testing in CI/CD pipeline
|
||||
- **Real User Monitoring (RUM)**: Track actual user performance
|
||||
- **Uptime Monitoring**: Pingdom or similar for availability
|
||||
- **Alerting**: Notify when response time > 2s or error rate > 1%
|
||||
|
||||
### 3. Security Standards
|
||||
|
||||
#### OWASP Top 10 Mitigation
|
||||
1. **Injection**: Parameterized queries for all database operations
|
||||
2. **Broken Authentication**:
|
||||
- bcrypt for password hashing (cost factor 12)
|
||||
- Secure session tokens (128-bit random)
|
||||
- Session expiration (24 hours)
|
||||
- Rate limiting on login (5 attempts per 15 minutes)
|
||||
3. **Sensitive Data Exposure**:
|
||||
- HTTPS only (HSTS header)
|
||||
- Secure cookies (HttpOnly, Secure, SameSite=Strict)
|
||||
- No sensitive data in URLs
|
||||
- Encrypted env vars
|
||||
4. **XML External Entities (XXE)**: Not applicable (no XML parsing)
|
||||
5. **Broken Access Control**:
|
||||
- Authentication middleware on all admin routes
|
||||
- Principle of least privilege
|
||||
- No directory traversal
|
||||
6. **Security Misconfiguration**:
|
||||
- Remove default passwords
|
||||
- Disable unnecessary features
|
||||
- Security headers (see below)
|
||||
7. **Cross-Site Scripting (XSS)**:
|
||||
- EJS auto-escaping enabled
|
||||
- Content Security Policy (CSP)
|
||||
- Input validation and sanitization
|
||||
8. **Insecure Deserialization**: Not applicable
|
||||
9. **Using Components with Known Vulnerabilities**:
|
||||
- Regular dependency audits (`bun audit`)
|
||||
- Automated security updates
|
||||
- Container image scanning
|
||||
10. **Insufficient Logging and Monitoring**:
|
||||
- Log all authentication attempts
|
||||
- Log all AI analysis requests
|
||||
- Log errors with context
|
||||
- Never log sensitive data
|
||||
|
||||
#### Security Headers
|
||||
```javascript
|
||||
// Middleware to add security headers
|
||||
app.use((req, res, next) => {
|
||||
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
|
||||
res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'");
|
||||
res.setHeader('X-Content-Type-Options', 'nosniff');
|
||||
res.setHeader('X-Frame-Options', 'DENY');
|
||||
res.setHeader('X-XSS-Protection', '1; mode=block');
|
||||
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
|
||||
res.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');
|
||||
next();
|
||||
});
|
||||
```
|
||||
|
||||
#### Additional Security Measures
|
||||
- **Rate Limiting**:
|
||||
- Public API: 100 requests per 15 minutes per IP
|
||||
- Admin endpoints: 30 requests per 15 minutes per IP
|
||||
- AI analysis: 10 requests per hour per admin session
|
||||
- **Input Validation**:
|
||||
- Validate all user inputs with Joi or Zod
|
||||
- Sanitize HTML if allowing rich text
|
||||
- Max length limits on all text fields
|
||||
- **CORS**: Restrict to specific origins
|
||||
- **Dependency Scanning**: Run `bun audit` before each deploy
|
||||
- **Container Security**:
|
||||
- Non-root user in Docker
|
||||
- Read-only filesystem where possible
|
||||
- Minimal base image (distroless or alpine)
|
||||
|
||||
### 4. WCAG 2.1 AA Compliance
|
||||
|
||||
#### Perceivable (1)
|
||||
- **1.1 Text Alternatives**:
|
||||
- Alt text for all images (service logos, grade badges, icons)
|
||||
- Decorative images have empty alt (alt="")
|
||||
|
||||
- **1.2 Time-based Media**: Not applicable (no video/audio)
|
||||
|
||||
- **1.3 Adaptable**:
|
||||
- Semantic HTML structure
|
||||
- Proper heading hierarchy (H1 → H2 → H3)
|
||||
- ARIA labels where needed
|
||||
- Table headers with proper scope attributes
|
||||
- Form labels associated with inputs
|
||||
|
||||
- **1.4 Distinguishable**:
|
||||
- Color contrast ratio ≥ 4.5:1 for normal text
|
||||
- Color contrast ratio ≥ 3:1 for large text (18pt+) and UI components
|
||||
- Text resizing up to 200% without loss of content
|
||||
- No images of text (use actual text)
|
||||
- Focus indicators visible (2px solid outline)
|
||||
|
||||
#### Operable (2)
|
||||
- **2.1 Keyboard Accessible**:
|
||||
- All functionality available via keyboard
|
||||
- Logical tab order
|
||||
- No keyboard traps
|
||||
- Skip to main content link
|
||||
|
||||
- **2.2 Enough Time**: Not applicable (no time limits)
|
||||
|
||||
- **2.3 Seizures and Physical Reactions**:
|
||||
- No flashing content (>3 flashes per second)
|
||||
|
||||
- **2.4 Navigable**:
|
||||
- Descriptive page titles
|
||||
- Breadcrumb navigation
|
||||
- Multiple ways to find pages (search, browse by grade)
|
||||
- Focus order matches visual order
|
||||
- Link text describes destination (no "click here")
|
||||
|
||||
- **2.5 Input Modalities**:
|
||||
- Touch targets minimum 44x44px
|
||||
- No motion-based interactions required
|
||||
|
||||
#### Understandable (3)
|
||||
- **3.1 Readable**:
|
||||
- Primary language declared (lang="en")
|
||||
- Simple, clear language
|
||||
- Abbreviations explained on first use
|
||||
|
||||
- **3.2 Predictable**:
|
||||
- Consistent navigation across pages
|
||||
- No unexpected changes on focus/input
|
||||
- Error prevention for destructive actions
|
||||
|
||||
- **3.3 Input Assistance**:
|
||||
- Form labels and instructions
|
||||
- Error messages identify field and suggest fix
|
||||
- Confirmation for important actions (delete)
|
||||
|
||||
#### Robust (4)
|
||||
- **4.1 Compatible**:
|
||||
- Valid HTML5
|
||||
- ARIA roles, states, and properties used correctly
|
||||
- Status messages announced to screen readers
|
||||
|
||||
#### Implementation Checklist
|
||||
- [ ] All images have alt text
|
||||
- [ ] Color contrast verified (use WebAIM Contrast Checker)
|
||||
- [ ] Keyboard navigation tested
|
||||
- [ ] Screen reader tested (NVDA, VoiceOver, JAWS)
|
||||
- [ ] Focus indicators visible
|
||||
- [ ] Forms have labels and error handling
|
||||
- [ ] Page titles are descriptive
|
||||
- [ ] Semantic HTML5 structure
|
||||
- [ ] ARIA landmarks (banner, main, navigation, contentinfo)
|
||||
- [ ] Skip link implemented
|
||||
|
||||
#### Accessibility Testing Tools
|
||||
- **Automated**: axe-core, Lighthouse, WAVE
|
||||
- **Manual**: Keyboard-only navigation, screen reader testing
|
||||
- **Browser**: Firefox Accessibility Inspector, Chrome DevTools
|
||||
|
||||
## Implementation Order
|
||||
|
||||
### Phase 1: Foundation
|
||||
1. Create project structure and Docker Compose setup
|
||||
2. Set up database and migrations
|
||||
3. Create models and basic CRUD
|
||||
4. Implement admin authentication with bcrypt
|
||||
5. Add security headers middleware
|
||||
|
||||
### Phase 2: Core Features
|
||||
6. Build admin panel UI (add/edit services)
|
||||
7. Implement policy fetching with validation
|
||||
8. Integrate OpenAI analysis with rate limiting
|
||||
9. Build public pages (listing and detail) with SEO tags
|
||||
10. Add sitemap.xml generation
|
||||
|
||||
### Phase 3: Enhancements
|
||||
11. Add Meilisearch indexing
|
||||
12. Implement Redis caching layer
|
||||
13. Add cron jobs for policy updates
|
||||
14. Optimize assets (minification, compression)
|
||||
|
||||
### Phase 4: Non-Functional Requirements
|
||||
15. Implement accessibility features (WCAG 2.1 AA)
|
||||
16. Add structured data (Schema.org)
|
||||
17. Performance testing and optimization
|
||||
18. Security audit and penetration testing
|
||||
19. Final accessibility audit
|
||||
20. Documentation
|
||||
|
||||
## Future Enhancements (Post-MVP)
|
||||
|
||||
- GDPR/CCPA compliance badges
|
||||
- Browser extension for quick checks
|
||||
- Policy comparison tool
|
||||
- RSS feed for policy changes
|
||||
- API for third-party integrations
|
||||
- Multi-language support
|
||||
- Export reports as PDF
|
||||
- Email notifications for policy changes
|
||||
|
||||
## Notes
|
||||
|
||||
- Keep AI prompts versioned for reproducibility
|
||||
- Log all AI analysis attempts (success and failure)
|
||||
- Consider rate limiting on OpenAI API calls
|
||||
- Store raw AI responses for debugging
|
||||
- Implement graceful degradation if AI service is down
|
||||
- Regular backups of PostgreSQL database
|
||||
- Monitor Meilisearch disk usage
|
||||
Reference in New Issue
Block a user