← back to Dw Activation Calendar
Document Google Calendar layer: README + updated server header comment
c3c31accf039a6900efeb9246b12c69d0e376979 · 2026-06-24 13:43:28 -0700 · Steve
Files touched
Diff
commit c3c31accf039a6900efeb9246b12c69d0e376979
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Jun 24 13:43:28 2026 -0700
Document Google Calendar layer: README + updated server header comment
---
README.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
server.js | 18 +++++++++++-------
2 files changed, 71 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5ccfde8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,60 @@
+# 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
+```
diff --git a/server.js b/server.js
index 401a0d9..b0c6a1e 100644
--- a/server.js
+++ b/server.js
@@ -1,13 +1,17 @@
'use strict';
/*
- * DW Activation Calendar — projects the go-active rollout of every SKU staged
- * for activation, at the publish cadence (18/hr = 432/day) with a per-vendor
- * daily cap (10/vendor/day), in date order, until the staged list is exhausted.
- * Renders a 1-month calendar; each SKU is a chip with its vendor name + product
- * image. Read-only projection (no Shopify/PG writes).
+ * DW Calendar — TWO surfaces in one app (DTD verdict AX, 2026-06-24):
*
- * Source = dw_unified.bulk_fivefield_worklist (the staged-for-active list),
- * joined to shopify_products for the product image.
+ * 1) Google Calendar tab (EDITABLE): live read + CRUD against a real shared
+ * DW Google Calendar via google-cal.js (OAuth + events.list/insert/patch/
+ * delete). The modal creates/edits/deletes real events. Degrades gracefully
+ * to a "not connected" state when no OAuth credential is present (never 500s).
+ * Credential + consent are Steve-gated (see README + pending-approval memo).
+ *
+ * 2) SKU Activation tab (read-only): projects the go-active rollout of every
+ * SKU staged for activation, at the publish cadence, in date order, until
+ * the staged list is exhausted. Each SKU is a chip with vendor + image.
+ * Source = dw_unified.bulk_fivefield_worklist joined to shopify_products.
*/
const express = require('express');
const path = require('path');
← 5498582 Add two-tab DW Calendar UI: editable Google Calendar modal (
·
back to Dw Activation Calendar
·
Restyle DW Calendar to luxe Figma spec (Cormorant/Inter, plu 73ec16d →