Files
RecoveryHelio/README.md

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 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)