diff --git a/.gitignore b/.gitignore index f1a90a0..3285e14 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ lerna-debug.log* report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Runtime data +data/ pids *.pid *.seed diff --git a/README.md b/README.md index f8e971d..53177b6 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ Copy `src/env.example` to a file named `.env` and fill it in. dotenv reads `.env | `GROUP_NAMES` | No | Only include requests in these support groups, e.g. `Customer Support`. Leave it empty for all groups. | | `UNASSIGNED_EXCLUDED_STATUSES` | No | Statuses the Unassigned requests counter leaves out. Defaults to `STATUS_NAMES`. | | `WORKLOAD_MINUTES` | No | How often the status table and unassigned count refresh, in minutes. Defaults to 5. | +| `ADMIN_KEY` | No | Key needed for **Connect** and **Refresh now**. Enter it with the page's **Admin** button; it's remembered in that browser. Without a key, only browsers on the server's own machine can use those buttons. Set one before hosting. | +| `TOKEN_FILE` | No | Where the Zoho sign-in is saved. Defaults to `data/token.json`, which git ignores. | | `OWM_API_KEY`, `OWM_ZIP_CODE` | No | OpenWeatherMap key and zip code for the weather card. Leave either one empty to hide the card. A free key from is enough. New keys can take a couple of hours to start working. | Spaces around commas are fine in every list. @@ -48,9 +50,9 @@ npm run app ## Connecting to Zoho -The token is kept in memory only, so you connect each time the server starts. +An admin connects once. The sign-in is saved to `data/token.json` and renewed automatically every hour, so the board keeps running and picks up again after a restart. You only connect again if Zoho revokes the sign-in; the page then shows the Connect button again. Treat `data/token.json` like a password. -1. Click **Connect**. +1. Click **Connect**. If `ADMIN_KEY` is set, click **Admin** and enter it first. ![Connect screen](images/1.png) @@ -84,7 +86,8 @@ If a query fails, a red error box shows what SDP returned, and the other section | --- | --- | | `src/server.js` | Reads `.env`, then starts Express and the services. | | `src/auth.js` | Zoho device-code sign-in. | -| `src/boardService.js` | Holds the token and state, and runs the refresh timers. | +| `src/boardService.js` | Holds the token and state, renews the token, and runs the refresh timers. | +| `src/tokenStore.js` | Saves the Zoho sign-in to disk so it survives restarts. | | `src/tickets.js` | SDP API queries for the closed feed, the status table, closed today and unassigned requests. | | `src/weather.js` | OpenWeatherMap current weather and forecast, cached for 10 minutes. | | `src/routes.js` | `/api/state`, `/api/connect`, `/api/check` and `/api/weather`. | diff --git a/SESSION.md b/SESSION.md index df0afae..b33d79f 100644 --- a/SESSION.md +++ b/SESSION.md @@ -31,23 +31,26 @@ The dashboard is running and working against live SDP data for the central regio ## Known issues -- **The Zoho token expires after about an hour and is lost on restart.** `auth.js` throws away the `refresh_token`. This is the first thing to fix before hosting. - On a typical screen the status table scrolls sideways ("Need Info" gets cut off), because the page is capped at 1,320px. -- Anyone who can reach the URL can see the data and click Connect or Refresh. That's fine locally, not when hosted. +- Anyone who can reach the URL can still *see* the data (Connect and Refresh are admin-only now). That's for the auth rebuild to solve. + +## Phase 1 done (later the same day) + +- `auth.js` keeps the `refresh_token` and adds `refreshAccessToken()`. `boardService.js` renews the access token 5 minutes before it expires (once, even when checks overlap), and `resume()` restarts from `data/token.json` at boot (`src/tokenStore.js`; `TOKEN_FILE` to move it). A revoked sign-in drops back to the Connect screen. +- `/api/connect` and `/api/check` are admin-only: `ADMIN_KEY` via the page's Admin button, or localhost only when no key is set. `/api/state` hides the device code from non-admins and reports `isAdmin`. +- Verified with stubbed axios and a stubbed page DOM, not yet against live Zoho. **To check live:** connect, restart the server, and confirm it comes back live without Connect. Then wait more than an hour and confirm "Access token renewed" appears in the log. + +## Plan change + +Phases 2 to 5 are dropped. The whole auth process is being rebuilt to run on a server instead of locally, and the roadmap will be redrawn around it. Don't start any of the old phases. Phase 1 (token renewal, saved sign-in, `ADMIN_KEY`) still works today, but the rebuild may replace it. See `docs/ROADMAP.md`. ## Next steps -Planned direction: hosted, multi-region, per-user. See `docs/ROADMAP.md`. - -1. **Phase 1:** store and auto-renew the refresh token, save it so it survives restarts, and make Connect and Refresh admin-only. -2. **Phase 2:** regions as configuration in SQLite, with the current `.env` settings as the first region, "Central", plus a region switcher. -3. Then user sign-in, admin pages and Docker. - -**Answer these before phase 3:** -- Are regions a security boundary or a convenience? -- Microsoft or Zoho sign-in for staff? -- Does SDP restrict technicians to certain sites? +1. **Check phase 1 against live Zoho** (steps above), then commit it so the board keeps running in the meantime. +2. **Plan the server-based auth rebuild** and rewrite the phases in `docs/ROADMAP.md` around it. ## To pick up -Start a Claude Code session in this repo and say something like: *"Read SESSION.md and docs/ROADMAP.md, then start phase 1."* +Start a Claude Code session in this repo and say something like: + +*"Read SESSION.md and docs/ROADMAP.md. The old phases 2 to 5 are dropped, and I'm rebuilding auth to run on a server instead of locally. Help me plan that rebuild and redraw the roadmap around it."* diff --git a/docs/NOTES.md b/docs/NOTES.md index 8bde04d..2cddb3a 100644 --- a/docs/NOTES.md +++ b/docs/NOTES.md @@ -11,7 +11,8 @@ Docs: