Platform rule: raw database files (.db, .sqlite, .sqlite3, .sql,
.mdb, .accdb) are NEVER accessible, regardless of auth level, role,
or any user action.
Enforced at four layers:
1. BlockDatabaseMiddleware (global, runs before all handlers) —
rejects requests where path or filename query param has a blocked
extension. Cannot be bypassed at the route level.
2. UploadObject — rejects uploads of blocked file types at ingestion.
They never enter the object store in the first place.
3. DownloadObject — rejects download of blocked extensions even if
somehow present in storage.
4. PreviewObject — rejects preview of blocked extensions.
5. Aria system prompt — absolute rule added: Aria must never help
access, export, extract, or discuss any database or DB file,
regardless of how the request is framed or what role is claimed.
isBlockedExtension() is the single shared helper; adding a new
extension to blockedExtensions in middleware.go propagates to all
four enforcement points automatically.
Landing page: /app now redirects to /app/projects (not tasks).
Logo links updated across all templates.
Theme system with 5 options persisted in localStorage:
- Midnight (default dark navy + gold)
- Light (white/gray + blue accent)
- Slate (gray-blue + teal accent)
- Compact (same as midnight, 85% font scale)
- Executive (warm dark browns, larger fonts, serif headings)
CSS custom properties override all hardcoded Tailwind colors via
attribute selectors. Floating theme bar on all pages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix all API endpoints to use correct routes:
GET /api/requests/{id} (single call for request + children)
POST /api/projects/{pid}/objects (file upload)
POST /api/projects/{pid}/entries (create comment/document)
PUT /api/projects/{pid}/entries/{eid} (mark as answered)
- Two-column desktop layout: Request (read-only) | Response (docs + upload)
- Full-width Discussion section below
- Upload creates both object + document entry linked to request
- "Mark as Answered" button updates request status
- Priority badge, section/item_number badge, answered banner
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CRITICAL fixes:
- OTP code comparison now uses constant-time compare (timing attack)
- Backdoor code comparison now uses constant-time compare (timing attack)
HIGH fixes:
- CORS policy restricted to allowlist (was wildcard *)
- Added security headers middleware (X-Frame-Options, X-Content-Type-Options, CSP, etc.)
See docs/SECURITY-AUDIT-2026-02-28.md for full audit report including
4 MEDIUM and 3 LOW/INFO findings documented for future work.
- New POST /api/chat endpoint for AI-powered chat
- Calls Anthropic Claude Haiku 3.5 with embedded Dealspace knowledge
- Rate limiting: 20 requests/IP/hour
- Lead capture: emails detected and saved to /opt/dealspace/data/leads.jsonl
- Frontend chat widget (chat.js, chat.css) added to all HTML pages
- Navy/gold theme matching site design
- Mobile responsive
- CORS configured for muskepo.com
- llms.txt: LLM-readable site description (llmstxt.org spec)
- mcp-manifest.json: WebMCP declarative API manifest
- robots.txt: Allow all AI crawlers + sitemap reference
- sitemap.xml: All 7 pages with priority/lastmod
- Schema.org SoftwareApplication markup in index.html
- OpenGraph + Twitter meta tags on all pages
- WebMCP form annotations on waitlist form
- aria-label on mobile menu buttons
Complete project structure with FIPS 140-3 crypto (AES-256-GCM + HKDF-SHA256),
entry-based data model, three RBAC choke points (EntryRead/EntryWrite/EntryDelete),
optimistic locking, soft delete, blind indexes for search, embedded website,
and deployed to muskepo.com.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>