# Recovery Helio — Application Documentation & Deployment Runbook ## What This App Is Star / theme: **Recovery Helios**. Churn copilot for tiny subscription paywalls. Watches each subscription sign its trial-end or renewal-peak window and runs fastest-recovering nudges *before* money bleeds into silent churn nobody noticed: a friendly re-engagement ping → then a discount-only retrial. Flags ~at-risk MRR near loss time and recovers programmatically (discount-only retrial only — NO unverified auto-charges). Agent-native UI. Metering settles over Bitcoin / BTCPay (**store_id: startapp** = 10.30.20.140). Works PAST Shopify (competitors locked platform-native here). Core promise vs competitors (captured raw in raw-research-20260920.md Phase-1): one flat $19 Flask copilot for <500 subs that BOTH flags at-risk AND fires fastest-recovering nudge/offer out of the box (vs two-week Stripe/Braintree wiring + weekly friction). ### Free tier boundary (must not leak payment keys on free; retries need explicit opt-in) Free tier must not leak payment keys nor enable unverified auto-charges. All paid-tier retries require explicit customer opt-in (e.g. Continue-with-Google flow for IG/FB-like signups). BTC settlement ONLY via BTCPay; no gray-area token-driven charges beyond legit Stripe parallel option approved as policy. ## Pricing $19/mo up to 500 tracked subscriptions · $49/mo unlimited (free tier for <150 subs — gated). ## Tech Stack — Local (dev) | | Spec | Notes | |---|---|---| | Language | Python 3.8+ | `requirements.txt` declares deps; never `pip install -r requirements.txt --break-system-packages --force-reinstall` | | WSGI server | Werkzeug dev server (`python recovery_helio.py` / `Werkzeug.serving.run_simple`) | Debuggers only behind trusted env var; production gates disabled except tests | | Test framework | pytest (or `unittest` stdlib fallback) under `tests/` | `pytest --db-path=/tmp/reh_db.sqlite` example | | Config loader | `config.py` reads from disk, no inline flag soup | keep creds OUT of git / `.gitignore` lists them | | Git init tool | any GIT client version ≥ x.y.z installed system-wide (PATH lookup first, else home tools dir), NOT an inline `--`/`-e` bash heredoc piped straight into bash `-c` | prefer absolute local paths & `git` CLI commits, not `git add/commit/push` inline edits by LLM (policy rule) | Runtime repo layout after this session's self-heal: ``` ~/RecoveryHelio/README.md . git init -> bare clone at /home/ubuntu/repos/recovery-helio-app.git/.git ~/RecoveryHelio/src/ app source files -> staging commit -> push to Gitea @ drjones@10.30.20.149:3000 (SSH) then deploy copy ~/RecoveryHelio/tests/ runtime test suite (independent of web layer) ~/RecoveryHelio/config.py ~/RecoveryHelio/analytics.py ~/RecoveryHelio/models.py ~/RecoveryHelio/rules.py # validation rules (retrial/thresholds, thresholds for churn signals like trial-end/renewal-time-left) ``` ## Deployment (Production) Environment - Container image name: Docker registry `ghcr.io/drgn/recoveryhelios:vX.Y.Z`. Build with explicit `FROM`, pin pinned version tags (never latest/main). - Container id pattern: `recovery_helio_app_XXX` (XXX short uuid suffix for uniqueness per host). - Internal port: **9652**. Public: Cloudflare tunnel mapped to `.startapp.thetempleofdoom.com` → forwarded to CT internal IP + :9652. - Docker entrypoint CMD: docker-entrypoint shell script `/usr/local/bin/docker-entryposhyft.sh`? No — real entry cmd runs the containerized `src/recovery_helios` service on port 9652 and stays up until container stop/start via systemd unit **helios-retryal.service** or Docker compose (docker-compose.yml) with a fixed named volume (NOT anonymous volumes). - Container resource limits enforced in resources: max memory 1G, CPU share capped to avoid starving neighbors; healthcheck probe = HTTP call to local :9652 (no user interaction required for retryal flow). - Persistence: SQLite at `/data/.db` inside anonymous-vol-free persistent data dir (bind-mount from local storage path); never write DB secrets or credentials there. Never store plaintext PII. - Secrets management: env vars only (`GET_ENV_FROM_SECRETSTORE=true` style), no hardcoded password/token defaults in committed config. ### Health checks (self-service, no operator babysitting) Probe endpoints used by systemd/Docker HEALTHCHECK every so often: | Method+Path | Purpose | Auth expected | Allowed origin | Rate/IP | Max bytes | |---|---|---|---|---|---| | GET /api/v1/health | Service-level liveness probe (DB connected, last reconcile ≤ Nmin) | None | Public | generous but sane | minimal JSON | | POST /register | Register subscriber/trial window into store DB | session cookie ONLY | logged-in subscribers | one-per-subscriber | small | | GET /login | Return HTML login form | session cookie | subscribers | n/a | moderate | | GET /createinvoice | Fetch/create invoice for given plan | session cookie | subscribers | one-per-order-intent | moderate | | POST /webhook/btcpay | Accept BTCPay webhook (store :80), update subscription payment state | BTCPay server internal auth (server-side secret; NOT shared with public API clients) | private BTCPay servers only | throttled per webhook client | large allowed (full webhook payload) | **Critical rule:** Always run a full end-to-end payment-purchase test after any change before claiming it works (invoice→payment→webhook→order complete→code delivered), not just invoice creation alone. ## Key Endpoints (HTTP) | Path | Notes | |------|-------| | `/api/v1/health` | Liveness | | `/register` | Session-only, register trial window | | `/login` | Returns HTML form | | `/createinvoice` | Invoice fetch/create (session) | | `/webhook/btcpay` | BTCPay → app payment-state sync (server-side) |