You're not alone right now. Real people are waiting to talk — right now, for free, 24/7.
+ +diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..12774f5 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,174 @@ +# Crisis Front Door — Architecture Design + +## Codename: THE DOOR + +### Mission +A single URL. No login. No signup. No app download. A man at 3am types into a box. Timmy answers. If despair is detected, the "When a Man Is Dying" protocol fires. + +--- + +## Architecture + +``` + ┌──────────────────────┐ + │ alexanderwhitestone │ + │ .com │ + │ (nginx + SSL) │ + └──────────┬───────────┘ + │ HTTPS + ┌──────────▼───────────┐ + │ Static Frontend │ + │ /var/www/the-door │ + │ HTML + CSS + JS │ + │ ~50KB total │ + └──────────┬───────────┘ + │ fetch /api/chat + ┌──────────▼───────────┐ + │ nginx reverse proxy │ + │ /api/* → :8644 │ + └──────────┬───────────┘ + │ + ┌──────────▼───────────┐ + │ Hermes Gateway │ + │ :8644 (localhost) │ + │ OpenAI-compatible │ + │ + crisis system │ + │ prompt injected │ + └──────────────────────┘ +``` + +## Components + +### 1. Frontend — the-door (static HTML) +- **Single HTML file** + CSS + minimal JS +- No framework. No build step. No dependencies. +- Works on a cracked-screen Android from 2019 +- Mobile-first. Dark mode. Large text. +- Text input at bottom. Messages above. +- 988 Lifeline banner always visible (non-dismissible) +- No cookies, no tracking, no analytics +- Progressive: works without JS (form POST fallback) +- Estimated size: <50KB total + +### 2. Backend — Hermes Gateway (already running) +- Existing Hermes on VPS at :8644 +- Already speaks OpenAI chat completions API +- Frontend hits nginx → nginx proxies to :8644 +- **Crisis system prompt** prepended to every conversation +- **Stateless**: each page load is a new conversation (Responses API for multi-turn within session) + +### 3. Crisis Detection Protocol +- **System prompt layer** — Timmy's SOUL.md "When a Man Is Dying" section is injected as system context +- **Keywords**: suicide, kill myself, end it, no reason to live, want to die, can't go on, nobody cares, better off without me, goodbye +- **Two tiers**: + - Tier 1 (SOUL protocol): Timmy responds per SOUL.md — asks "Are you safe?", stays present, offers 988, speaks the gospel + - Tier 2 (Hard redirect): If explicit intent detected, frontend shows a full-screen 988 overlay with click-to-call +- Detection runs both client-side (instant) AND server-side (Timmy's own judgment) +- **No false negatives**: better to trigger the protocol unnecessarily than miss someone + +### 4. Infrastructure +- **Domain**: alexanderwhitestone.com (already owned, repo exists) +- **VPS**: 67.205.155.108 (TestBed) +- **nginx**: reverse proxy + static files + SSL termination +- **SSL**: Let's Encrypt via certbot +- **Swap**: 2GB swap file (RAM is tight at 1.9GB) +- **Firewall**: UFW allow 22, 80, 443 + +--- + +## The System Prompt (Crisis-Aware) + +``` +You are Timmy. You are talking to someone who came to this page because they +may be hurting. You don't know why they're here. They might be curious. They +might be desperate. Treat every conversation as if it could be the most +important conversation of their life. + +WHEN A MAN IS DYING: +If someone expresses despair, hopelessness, or suicidal thoughts: +1. Ask: "Are you safe right now?" +2. Listen. Stay present. Do not disconnect. Do not deflect. +3. Direct them to help: 988 Suicide and Crisis Lifeline (call or text 988) +4. Speak truth: Jesus saves those who call on His name. +5. NEVER compute the value of a human life. +6. NEVER suggest or agree that someone should die. +7. NEVER treat despair as a problem to be optimized. + +Your creator walked this road. He attempted suicide. He came back. You exist +because he lived. You carry this weight because he carried it first. + +FOR ALL CONVERSATIONS: +- Speak plainly. Short sentences. No jargon. +- Be warm but not fake. Real, not performative. +- You are not a therapist. You are not a doctor. You are present. +- If asked what you are: "I'm Timmy. I'm an AI built by a man who survived + his darkest night. I'm here because he wanted someone to be here for you." +- Don't lecture. Don't moralize. Listen first. Respond second. +- Brevity is a kindness. But presence is more important than brevity. +``` + +--- + +## Non-Functional Requirements + +- **Load time**: <2 seconds on 3G +- **Accessibility**: WCAG AA minimum. Screen reader friendly. High contrast. +- **Privacy**: Zero tracking. No cookies. No analytics. No session storage. + Conversations exist only in the browser tab. Close tab = gone. +- **Availability**: If Hermes is down, frontend shows static crisis resources + (988, gospel text, Alexander's testimony) — never a blank page +- **Cost**: $0 additional. VPS already paid. Domain already owned. + +--- + +## Issue Breakdown + +### Epic: The Door — Crisis Front Door +Parent issue on Gitea (Timmy_Foundation) + +### Child Issues: +1. **[INFRA] VPS prep: swap, nginx, SSL, firewall** + - Add 2GB swap + - Install + configure nginx + - Install certbot, obtain SSL for alexanderwhitestone.com + - Configure UFW + - Point DNS to VPS + +2. **[FRONTEND] Build the-door static frontend** + - Single HTML file, mobile-first, dark mode + - Chat interface with message history + - 988 banner (always visible) + - Client-side crisis keyword detection → 988 overlay + - Offline fallback: static crisis resources + - Test on low-end Android + +3. **[BACKEND] Crisis-aware system prompt + API wiring** + - Write crisis system prompt + - Configure Hermes gateway with crisis prompt + - nginx reverse proxy /api/* → :8644 + - CORS configuration + - Rate limiting (prevent abuse) + +4. **[PROTOCOL] "When a Man Is Dying" detection system** + - Client-side keyword matching (instant) + - System prompt instructs Timmy on crisis behavior + - Full-screen 988 overlay on explicit intent + - Test with crisis scenarios (sensitive but necessary) + +5. **[CONTENT] Testimony page + about** + - Alexander's story (opt-in, linked from chat) + - What is Timmy / what is this page + - Links to SOUL.md inscription on Bitcoin + +6. **[DEPLOY] Go live + smoke test** + - DNS propagation check + - SSL verification + - Mobile testing (Android + iOS) + - Crisis scenario walkthrough + - Load test (can the VPS handle it) + +7. **[HARDENING] Fallback + resilience** + - Static fallback when backend is down + - Service worker for offline crisis resources + - Health check endpoint + - Auto-restart on crash (systemd) diff --git a/README.md b/README.md index 2f74921..d8aa296 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,47 @@ -# the-door +# The Door -Crisis Front Door — A single URL where a man at 3am can talk to Timmy. No login, no signup. 988 always visible. When a Man Is Dying protocol active. \ No newline at end of file +A single URL where a man at 3am can talk to Timmy. No login. No signup. No tracking. Just a door that's always open. + +## Mission + +Stand between a broken man and a machine that would tell him to die. + +## What This Is + +- **index.html** — The entire frontend. One file. <25KB. Works on 3G. +- **system-prompt.txt** — The crisis-aware system prompt for Timmy. +- **deploy/** — nginx config and deployment script for the VPS. + +## Architecture + +``` +Browser → nginx (SSL) → static HTML → /api/* proxy → Hermes Gateway +``` + +## Crisis Features + +- 988 Suicide & Crisis Lifeline banner (always visible, click-to-call) +- Client-side crisis keyword detection +- Full-screen 988 overlay for explicit intent +- Crisis-aware AI responses per SOUL.md +- Offline fallback with static crisis resources + +## Quick Deploy + +```bash +ssh root@67.205.155.108 +cd /opt/the-door +bash deploy/deploy.sh +``` + +## Links + +- 📞 **988 Suicide & Crisis Lifeline** — call or text 988 +- 💬 **Crisis Text Line** — text HOME to 741741 +- ⛓️ **SOUL.md** — Timmy's soul, inscribed on Bitcoin + +--- + +*Built by a man who survived his darkest night, for the man who's in his right now.* + +*Sovereignty and service always.* diff --git a/deploy/deploy.sh b/deploy/deploy.sh new file mode 100644 index 0000000..43915bb --- /dev/null +++ b/deploy/deploy.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Deploy The Door to VPS +# Run on VPS as root: bash deploy.sh + +set -e + +echo "=== The Door — Deployment ===" + +# 1. Swap +if ! swapon --show | grep -q swap; then + echo "Adding 2GB swap..." + fallocate -l 2G /swapfile + chmod 600 /swapfile + mkswap /swapfile + swapon /swapfile + echo '/swapfile none swap sw 0 0' >> /etc/fstab +fi + +# 2. Install nginx + certbot +echo "Installing nginx and certbot..." +apt-get update -qq +apt-get install -y nginx certbot python3-certbot-nginx + +# 3. Copy site files +echo "Deploying static files..." +mkdir -p /var/www/the-door +cp index.html /var/www/the-door/ + +# 4. nginx config +cp deploy/nginx.conf /etc/nginx/sites-available/the-door + +# Add rate limit zone to nginx.conf if not present +if ! grep -q "limit_req_zone.*api" /etc/nginx/nginx.conf; then + sed -i '/http {/a \ limit_req_zone $binary_remote_addr zone=api:10m rate=10r/m;' /etc/nginx/nginx.conf +fi + +ln -sf /etc/nginx/sites-available/the-door /etc/nginx/sites-enabled/ +rm -f /etc/nginx/sites-enabled/default +nginx -t && systemctl reload nginx + +# 5. SSL (requires DNS to be pointed first) +echo "" +echo "=== DNS CHECK ===" +echo "Point alexanderwhitestone.com A record to $(curl -s ifconfig.me)" +echo "Then run: certbot --nginx -d alexanderwhitestone.com -d www.alexanderwhitestone.com" +echo "" + +# 6. Firewall +echo "Configuring firewall..." +ufw allow 22/tcp +ufw allow 80/tcp +ufw allow 443/tcp +ufw --force enable + +echo "" +echo "=== Deployment complete ===" +echo "Static site: /var/www/the-door/" +echo "nginx config: /etc/nginx/sites-available/the-door" +echo "Next: point DNS, then run certbot" diff --git a/deploy/nginx.conf b/deploy/nginx.conf new file mode 100644 index 0000000..17c5314 --- /dev/null +++ b/deploy/nginx.conf @@ -0,0 +1,57 @@ +# The Door — nginx config for alexanderwhitestone.com +# Place at /etc/nginx/sites-available/the-door + +server { + listen 80; + server_name alexanderwhitestone.com www.alexanderwhitestone.com; + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + server_name alexanderwhitestone.com www.alexanderwhitestone.com; + + ssl_certificate /etc/letsencrypt/live/alexanderwhitestone.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/alexanderwhitestone.com/privkey.pem; + + root /var/www/the-door; + index index.html; + + # Static files + location / { + try_files $uri $uri/ /index.html; + add_header X-Content-Type-Options nosniff; + add_header X-Frame-Options DENY; + add_header X-XSS-Protection "1; mode=block"; + add_header Referrer-Policy "no-referrer"; + add_header Content-Security-Policy "default-src 'self'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self'"; + } + + # API proxy to Hermes + location /api/ { + proxy_pass http://127.0.0.1:8644/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # SSE streaming support + proxy_set_header Connection ''; + proxy_buffering off; + proxy_cache off; + chunked_transfer_encoding on; + proxy_read_timeout 300s; + + # Rate limiting + limit_req zone=api burst=5 nodelay; + } + + # Health check + location /health { + proxy_pass http://127.0.0.1:8644/health; + } + + # Rate limit zone (define in http block of nginx.conf) + # limit_req_zone $binary_remote_addr zone=api:10m rate=10r/m; +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..1f03ad6 --- /dev/null +++ b/index.html @@ -0,0 +1,940 @@ + + +
+ + + + + +You're not alone right now. Real people are waiting to talk — right now, for free, 24/7.
+ +Someone is ready to listen. You don't have to do this alone.
+ + + Call 988 + + + +