5.7 KiB
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 explicitFROM, 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 containerizedsrc/recovery_heliosservice 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/.dbinside 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=truestyle), 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) |