- BUG-056: Fix sitemap namespace sitemapns.org -> sitemaps.org
- BUG-062: Extend <main> to wrap all page content (hero+features+pricing+EU section)
- BUG-064: Add sr-only <label> elements to all modal form inputs (signup, recovery, change-email)
- BUG-051/052: Remove duplicate X-Content-Type-Options headers from nginx (let helmet handle)
- BUG-057: Fix JSON-LD and pricing card: Pro plan is 2,500 PDFs/month not 5,000
- BUG-059: Add meta description, canonical URL, og: tags to /docs page
- BUG-063: Change eu-hosting h3 to h2 (correct heading hierarchy)
- BUG-065/066: Add aria-modal=true, role=dialog to modals; aria-label=Close to close buttons
- BUG-068: Add hash-based modal open for #change-email on page load
- Add .sr-only CSS utility class to base and index styles
- Created build-time templating system using existing build-html.cjs
- Extracted index.html into source template with partials:
_styles_index.html, _nav_index.html, _modals.html
- All 4 templated pages (index, impressum, privacy, terms) use partials
- docs.html excluded (Swagger UI, completely different structure)
- Added HTML build step to Dockerfile
- Built output is byte-identical to original files
- Set Pro tier limit to 2,500 PDFs/month (was unlimited/5000)
- Added Pro limit enforcement in usage middleware
- Updated landing page, JSON-LD, and Stripe product description
- Created build-time HTML templating (partials for nav/footer/styles)
- Source files in public/src/, partials in public/partials/
- Build script: node scripts/build-html.cjs
- Deleted stale backup file
- Fixed index.html nav logo to use <a> tag for consistency
BUG-046 (CRITICAL): getUsageStats() now accepts apiKey param and returns
only that key usage instead of all users. Route passes req.apiKeyInfo.key.
BUG-047: Added visible Copy button to Pro key success page in billing.ts.
BUG-048: Added class="open-email-change" to Change Email links in all
HTML pages so the JS modal opener can find them.
- Add footer links for Impressum, Privacy Policy, Terms of Service
- Create legal pages: /impressum, /privacy, /terms (Austrian/EU compliant)
- Add EU hosting badge highlighting GDPR compliance and EU data residency
- Add Express routes for legal pages with caching headers
- All pages use consistent dark theme design matching landing page
- Docker healthcheck: Use Node.js instead of curl (not installed in slim image)
- Pricing: Change from USD ($) to EUR (€) in frontend and backend Stripe integration
- Static assets: Add Cache-Control headers (1 day) for /public and /docs files
- Remove duplicate text/html from nginx gzip_types (fixes nginx -t warning)
- Update hardcoded API version from 0.2.0 to 0.2.1 to match package.json
- Update logrotate config: daily rotation, 7 days retention, improved postrotate
- Add Docker logging configuration with size/file limits
- Add fe80::/10 (IPv6 link-local) detection to isPrivateIP()
- Update error message to match specification: 'URL resolves to a private/internal IP address'
- Existing protections already covered all required IPv4 ranges and IPv6 localhost
- Update sitemap.xml to include /v1/health endpoint
- Add proper 404 handling (JSON for API paths, HTML for browser paths)
- Create optimized nginx config with gzip, cache headers, specific locations
- Add logrotate configuration for DocFast logs
- Add security headers and static asset caching
- Full backup of PostgreSQL, Docker volumes, nginx config, SSL certs, crontabs, OpenDKIM
- Daily backups at 03:00 UTC with 7d/4w/3m retention
- Local storage at /opt/borg-backups/docfast
- Restore testing verified
- Documentation for disaster recovery procedures
- Add .forgejo/workflows/deploy.yml for automated deployment
- Include rollback mechanism with image tagging
- Add health check verification (http://127.0.0.1:3100/health)
- Create manual rollback script for emergency use
- Add deployment documentation and setup instructions
- Supports auto-rollback on deployment failure
- Replace JSON file storage with PostgreSQL (pg package)
- Add db.ts service for connection pool and schema init
- Rewrite keys.ts, verification.ts, usage.ts for async PostgreSQL
- Update all routes for async function signatures
- Add migration script (scripts/migrate-to-postgres.mjs)
- Update docker-compose.yml with DATABASE_* env vars
- Change SLA from 99.9% to 99.5% in landing page
Safety net: provisions pro API key on successful checkout via webhook,
in case user doesn't reach the success page. Idempotent with existing
createProKey logic. Gracefully handles missing STRIPE_WEBHOOK_SECRET.
- Extract customer email from session.customer_details?.email
- Check if Pro key already exists for that email (idempotent)
- Create Pro key only if one does not exist
- Add comprehensive logging for debugging
- Ensures webhook and success page work together without duplicates
Fix BUG-032: Add 375px mobile breakpoint for terminal gap issues
- Reduced container padding to 12px on smallest screens
- Optimized code-section margins and padding
- Improved terminal header and code-block spacing
- Enhanced hero section padding for mobile