← back to Dw Activation Calendar
README.md
61 lines
# DW Calendar
Two surfaces in one Express app on `:9765` (DTD verdict **AX**, 2026-06-24).
## Tabs
- **Google Calendar** — live, **editable** view of the shared DW Google Calendar.
Click any day or event → modal creates / edits / deletes real events
(`events.insert` / `patch` / `delete`). Built on a fetch-only Google Calendar
v3 client (`google-cal.js`) — **no `googleapis` SDK dependency**.
- **SKU Activation** — read-only projection of the staged-for-active SKU rollout
(`/api/schedule`, sourced from `dw_unified.bulk_fivefield_worklist`). Unchanged
from the original build.
## API
| Method | Path | Notes |
|---|---|---|
| GET | `/api/calendar/status` | `{oauth_configured, connected, calendar_id}` |
| GET | `/api/events?timeMin=&timeMax=` | events.list for a window |
| POST | `/api/events` | create — body `{summary,description?,location?,start,end,allDay?}` |
| PATCH | `/api/events/:id` | update (events.patch) |
| DELETE | `/api/events/:id` | delete |
| GET | `/api/oauth/start` | 302 → Google consent (503 if not configured) |
| GET | `/api/oauth/callback` | token exchange |
| POST | `/api/oauth/revoke` | disconnect |
| GET | `/api/schedule` | SKU-activation projection (existing) |
All event routes degrade gracefully when no credential is present: `409 not_connected`
/ `{connected:false}` — **never a 500**.
## Connecting the Google Calendar (Steve — GATED)
The OAuth credential, secrets-fan-out, and consent click are Steve-only. The full
runbook is queued at:
`~/.claude/yolo-queue/pending-approval/2026-06-24-dw-google-calendar-oauth-credential.md`
Short version:
1. Google Cloud Console → enable Calendar API → create a **Web application** OAuth
client → add redirect URI `http://127.0.0.1:9765/api/oauth/callback`.
2. Route the secret: `node ~/Projects/secrets-manager/cli.js add GOOGLE_OAUTH_CLIENT_ID '<id>'`
and `... GOOGLE_OAUTH_CLIENT_SECRET '<secret>'` (add a routes.json entry first
so it lands in `./.env`). Optionally set `GOOGLE_DW_CALENDAR_ID` to a dedicated
"DW Ops" calendar id; default is `primary`.
3. Visit `http://127.0.0.1:9765/api/oauth/start` and grant consent.
4. Verify: `curl -s http://127.0.0.1:9765/api/calendar/status` → `connected:true`.
## Env
```
PORT default 9765
GOOGLE_OAUTH_CLIENT_ID (or GOOGLE_CLIENT_ID)
GOOGLE_OAUTH_CLIENT_SECRET (or GOOGLE_CLIENT_SECRET)
GOOGLE_OAUTH_REDIRECT_URI default http://127.0.0.1:9765/api/oauth/callback
GOOGLE_DW_CALENDAR_ID default 'primary'
GOOGLE_CAL_TOKEN_FILE default ./.google-tokens.local.json (gitignored, 0600)
DATABASE_URL / PG* dw_unified (for the SKU tab)
```
## Run
```
PORT=9765 node server.js
```