From 3dfd44aa02bbcd31d01065c8fab42e623c91782f Mon Sep 17 00:00:00 2001 From: Chris Amow Date: Tue, 11 Aug 2026 00:28:15 -0500 Subject: [PATCH] Document how the live feed reaches production MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Production shows yahoo with a ten minute delay because LIVE_SOURCE=schwab lives in .env, which is gitignored and so has never been deployed. Nothing in the repo can carry it, and that is deliberate — but it means the switch is invisible until someone looks at the status line and wonders. Written down: the three Coolify variables, the token file that has to land on the persistent volume, and two things easy to get wrong. The local token needs no new login because it was minted against the production callback and Schwab binds tokens to the app rather than the machine. And the dev stream has to stop first, because one refresh token means one streaming connection and the two installs will fight over it. Co-Authored-By: Claude Opus 5 --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/README.md b/README.md index acc8b03..3927c02 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,50 @@ curl -X POST -H "Authorization: Bearer $(cat ~/.coolify-token)" \ ``` +## Putting the live feed on production + +Production runs the default `LIVE_SOURCE=yahoo` and therefore shows "yahoo" with +a ~10 minute delay. `LIVE_SOURCE=schwab` and the credentials live in `.env`, +which is gitignored — so the switch has never crossed the deploy boundary. It +cannot: nothing in the repo carries it. + +Four things are needed, and all of them are set on the VPS rather than here. + +**1. Environment, in Coolify:** + +``` +LIVE_SOURCE=schwab +SCHWAB_API_KEY=... # same values as the local .env +SCHWAB_APP_SECRET=... +``` + +`SCHWAB_CALLBACK_URL` already defaults to `https://chart.amow.com/api/qt`, which +is what the Schwab app is registered with. Do not change it — a registered +callback edit can send the app back through approval. + +**2. The OAuth token, at `data/.schwab_token.json` on the persistent volume.** +No new login is required: the local token was minted against the production +callback, and Schwab tokens are bound to the app rather than the machine. Copy +the file's contents into that path on the volume. If the path is not persistent, +the next deploy erases it and production falls silently back to Yahoo. + +**3. Stop the dev stream first.** One refresh token means one Schwab streaming +connection. Dev and production both streaming will fight for it — see the risk +register on duplicate connections. Set `LIVE_SOURCE=yahoo` in the local `.env`, +or stop the local stack, before production goes live. + +**4. Plan for expiry.** The Schwab refresh token lasts about seven days. When it +lapses, production drops back to Yahoo and needs a fresh token by the same +route: run the flow locally, paste the callback URL from `/api/qt` into the +waiting prompt, then copy the new token onto the volume. + +Verify from anywhere: + +```bash +curl -s -H "X-Chart-Token: $TOKEN" https://chart.amow.com/api/status +# want: "source":"schwab","delay_minutes":0 +``` + ## Access token `CHART_AUTH_TOKEN` guards everything under `/api` plus the `/ws` stream. Leave