{"slug":"george-gmail","total":70,"limit":100,"offset":0,"since":null,"commits":[{"hash":"bc88ec5","date":"2026-07-28 08:28:42 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-28T08:28:39 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"b05223a","date":"2026-07-27 14:21:16 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-27T14:21:14 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"82cb9b3","date":"2026-07-27 08:19:06 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-27T08:19:05 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"5aad99c","date":"2026-07-26 14:13:56 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-26T14:13:54 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"569e097","date":"2026-07-26 08:11:42 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-26T08:11:40 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"a782058","date":"2026-07-25 14:06:45 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-25T14:06:43 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"4beb2bc","date":"2026-07-25 08:04:54 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-25T08:04:52 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"2435de6","date":"2026-07-24 14:28:10 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-24T14:28:09 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"59af615","date":"2026-07-24 08:26:44 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-24T08:26:42 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"bb6e047","date":"2026-07-23 14:21:56 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-23T14:21:54 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"742a6a4","date":"2026-07-23 08:19:37 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-23T08:19:35 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"3d4e782","date":"2026-07-22 14:14:45 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-22T14:14:43 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"7af8d23","date":"2026-07-22 08:12:33 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-22T08:12:31 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"cc6d073","date":"2026-07-21 14:07:56 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-21T14:07:54 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"f40bafb","date":"2026-07-21 08:06:28 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-21T08:06:27 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"1720459","date":"2026-07-20 14:02:33 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-20T14:02:31 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"bf346cb","date":"2026-07-20 08:00:48 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-20T08:00:46 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"7357bd8","date":"2026-07-19 14:26:44 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-19T14:26:43 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"fd852cb","date":"2026-07-19 08:25:32 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-19T08:25:31 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"9d08c5a","date":"2026-07-18 14:21:40 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-18T14:21:38 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"f9948ba","date":"2026-07-18 08:20:27 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-18T08:20:26 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"5f87f20","date":"2026-07-17 14:16:48 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-17T14:16:47 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"373e7d4","date":"2026-07-17 08:15:51 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-17T08:15:49 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"0432323","date":"2026-07-16 08:12:05 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-16T08:12:03 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"a078db7","date":"2026-07-15 12:36:36 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-15T12:36:34 (1 files) — data/bridge-alert-state.json","body":""},{"hash":"c4c9ba4","date":"2026-07-15 12:17:27 -0700","author":"Steve","subject":"bridge: every-6-day 1-click renewal email to steve-office for the 2 consumer accounts (CADENCE mode) + dead-token safety net stays on 8/2/8","body":""},{"hash":"a2eaa2d","date":"2026-07-15 12:14:32 -0700","author":"Steve","subject":"bridge: nudge to renew at day 5 (2-day runway before the 7-day expiry)","body":""},{"hash":"bb1ae3a","date":"2026-07-15 12:06:26 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-15T12:06:24 (1 files) — data/","body":""},{"hash":"7b49e78","date":"2026-07-15 11:58:02 -0700","author":"Steve","subject":"feat(bridge): painless George token renewal — WARN/CRIT accounts get a one-click re-consent email (DTD verdict B, 2026-07-15)","body":"token-age-warn.mjs computed WARN/CRIT but never alerted. token-bridge.mjs reads its latest.json and emails Steve a \"Renew now\" button (George /auth/<account>) for each aging/dead token, throttled 1/20h per account, +CNCP card. 3x/day launchd plist runs monitor then bridge. Verified: emailed 4 accounts (steve-personal dead, calendar dead, steve@/info@ aging)."},{"hash":"76f3426","date":"2026-07-15 11:33:55 -0700","author":"Steve","subject":"docs: lead the OAuth runbook with the Internal-flip fast path + consumer-account fork","body":""},{"hash":"fbeffde","date":"2026-07-15 11:18:57 -0700","author":"Steve","subject":"docs: service-account + domain-delegation runbook — permanent zero-expiry fix for steve@/info@ Workspace accounts","body":""},{"hash":"2c2c36d","date":"2026-07-13 11:28:16 -0700","author":"Steve Abrams","subject":"chore: version v1.1.1 (session close)","body":""},{"hash":"a9140cb","date":"2026-07-13 11:04:03 -0700","author":"Steve Abrams","subject":"auth: unify both middlewares on resolved GEORGE_BASIC_AUTH cred + fail-closed on empty password (rotation completed 2026-07-13)","body":""},{"hash":"b6e91b3","date":"2026-07-10 11:07:58 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-10T11:07:57 (1 files) — server.js","body":""},{"hash":"e86cb67","date":"2026-07-07 14:08:15 -0700","author":"Steve","subject":"feat(api): add /api/attachment-local — fetch a Gmail attachment by filename to /tmp (normal auth, /tmp-only)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"ee22604","date":"2026-07-03 08:08:02 -0700","author":"Steve","subject":"chore: macstudio3 migration — reconcile from mac2 + repoint paths (stevestudio2→macstudio3, node/npm/npx→/opt/homebrew)","body":""},{"hash":"89b542a","date":"2026-07-01 10:56:35 -0700","author":"Steve Abrams","subject":"chore: v1.1.0 (session close — dormant SA/DWD path)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"769c500","date":"2026-07-01 10:47:25 -0700","author":"Steve Abrams","subject":"george-gmail: pre-write dormant SA/DWD (domain-wide delegation) auth path for Workspace accounts","body":"Adds a service-account/JWT impersonation path alongside the existing OAuth refresh-token\npath so the Workspace pair (steve@ + info@) can drop off the ~7-day Testing-mode token\ntreadmill. Fully DORMANT by default: with no GOOGLE_SA_KEYFILE set, saAuthFor() returns\nnull and the SA-override block is a no-op — every account keeps its refresh-token client\nbyte-for-byte. Arm via GOOGLE_SA_KEYFILE + GEORGE_SA_ACCOUNTS=steve-office,info (Workspace\nonly; consumer gmail keys can never be SA-backed). resolveAccount() reads the module-level\nservice-client vars per request, so it transparently picks up the SA clients when armed.\n\nVerified by boot tests: dormant -> 0 SA lines + all accounts on refresh tokens; armed w/\nmissing or bogus keyfile -> clear warn + safe fallback + still boots. Live JWT impersonation\nawaits Steve's gated console work (SA creation + domain-wide delegation authorization).\nArming checklist + rollback in PLAN-OAUTH-DURABILITY.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"9e11f3d","date":"2026-07-01 09:54:40 -0700","author":"Steve Abrams","subject":"george: pre-emptive OAuth token-age monitor + durable-migration decision memo","body":"Council #3 — end the weekly-token treadmill. Read-only token-age-warn.mjs probes each\nrefresh token against Google's token endpoint (idempotent refresh, never writes creds) and\ncombines validity with a hash-tracked age; WARNs ~1d before the 7d Testing-mode expiry,\nCRIT on invalid_grant. Alerts on worsening transition only (CNCP + George email via run.sh).\nFirst run surfaced a live finding: GOOGLE_CALENDAR_REFRESH_TOKEN is DEAD (appointments push\nsilently broken). Migration paths (service-account/DWD or Internal user-type) in\nPLAN-OAUTH-DURABLE-TOKENS.md — those steps are Steve-gated.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>"},{"hash":"3608276","date":"2026-07-01 09:43:25 -0700","author":"Steve Abrams","subject":"Add OAuth durability decision memo — retire the weekly-token treadmill (SA/DWD for Workspace, fold/WARN for consumer)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"0ff8bf3","date":"2026-06-26 16:04:31 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-26T16:04:29 (1 files) — server.js","body":""},{"hash":"23d49a6","date":"2026-06-24 14:46:45 -0700","author":"Steve","subject":"send-with-attachment: resolve any account (steve-personal/agentabrams), not just office/info","body":""},{"hash":"2626a50","date":"2026-06-24 11:42:15 -0700","author":"Steve","subject":"Add DELETE /api/drafts/:id route + make GET /api/drafts account-aware (was always steve-office)","body":""},{"hash":"a42bc74","date":"2026-06-17 15:02:25 -0700","author":"Steve Abrams","subject":"George external-send guard: block outbound sends to non-Steve recipients unless human-approval token present (X-Send-Approval / send_approval_token); fail-closed. Born from autonomous-worker auto-send incident 2026-06-17. NOTE: must also deploy to the Kamatera george (the instance MCP actually uses).","body":""},{"hash":"918647c","date":"2026-06-17 11:56:15 -0700","author":"Steve Abrams","subject":"Add launchd KeepAlive supervisor for george-gmail :9850 (durable fix for the unsupervised-death outage)","body":"Tracked plist + install note. Not bootstrapped here — Steve runs the bootstrap\n(starts the email service + touches launchd). RunAtLoad+KeepAlive so the :9850\nsend service self-respawns; daily-overnight-skus + idea-loop-digest were only\nfailing because this send path died.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>"},{"hash":"8c22e56","date":"2026-06-12 13:01:46 -0700","author":"Steve Abrams","subject":"secret-strip george-gmail: env-first the hardcoded George basic-auth cred (server) + remove browser-embedded copy (client)","body":""},{"hash":"cf27272","date":"2026-06-12 07:36:39 -0700","author":"Steve Abrams","subject":"Add scoped one-shot trash for benign cron-drift alert flood in info@","body":""},{"hash":"8599fb2","date":"2026-05-31 16:56:03 -0700","author":"Steve Abrams","subject":"Link favicon.svg in head (use branded SVG, not .ico fallback)","body":""},{"hash":"0d55d20","date":"2026-05-31 16:32:32 -0700","author":"Steve Abrams","subject":"Add per-site favicon (kills /favicon.ico 404)","body":""},{"hash":"ac33e88","date":"2026-05-26 10:54:55 -0700","author":"Steve","subject":"george-gmail: recover prod hand-patches (basic-auth env migration) into source + preserve Mac2 static-snapshot 404 guard","body":""},{"hash":"630eea8","date":"2026-05-19 21:54:43 -0700","author":"Steve Abrams","subject":"fix(public/index.html): wrap xfetch helper in <script> tags","body":"xfetch was sitting OUTSIDE any <script> tag, wedged between the\nreact.production.min.js and react-dom.production.min.js script tags.\nBrowsers parsed it as text content → xfetch was undefined → every\napi()/apiPost() call (lines 67-74, 88, 96, 105, 113) threw ReferenceError\non page load. George admin inbox UI was unusable in any browser.\n\nPure positional fix — wrapped the existing one-line function in\n<script>...</script>. The inline basic-auth credential\n(\"admin:DWSecure2024!\") was already in this file at lines 60 + 66 before\nthis commit and is unchanged by it. Credential rotation across the fleet\nis tracked separately (cred is also in dozens of sibling repos per MEMORY).\n\nSurfaced by tick 169 session #102 Teal mechanical refactor pass; that\npass deferred the fix because the diff touches the cred line, but the\nLIVE-BROKEN production UI takes precedence — fixing now, rotation later.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"941feb1","date":"2026-05-19 21:16:16 -0700","author":"Steve Abrams","subject":"Snapshot-files cleanup: untrack server.js.bak-*, broaden .gitignore, add 404 guard","body":"- Untrack the 7-month-old server.js.bak-20260421-094351 snapshot that was\n  tracked in the repo (still present on disk, now ignored).\n- Broaden .gitignore to cover *.bak.*, *.bak-*, *.pre-*, *.orig, *.rej,\n  *.swp, *~ so future snapshots don't slip back in.\n- Add a static-snapshot 404 guard middleware that runs before\n  express.static('public'); any URL matching .bak, .bak-*, .pre-*, .orig,\n  .rej, .swp, or trailing ~ returns 404 regardless of disk state.\n  Defense-in-depth on top of the existing basic-auth gate.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"c2bdfca","date":"2026-05-19 11:34:57 -0700","author":"Steve Abrams","subject":"add trash-fleet-mailtests.js — one-off cleanup of 89 fleet delivery-test emails (modeled on trash-redfin-zillow.js)","body":""},{"hash":"ab70d2e","date":"2026-05-19 10:38:59 -0700","author":"Steve Abrams","subject":"George: make the 'From job:' provenance banner opt-out (no_source_tag flag / x-george-no-tag header) so customer-facing sends can be banner-free","body":"Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"fd1481e","date":"2026-05-19 10:36:10 -0700","author":"Steve Abrams","subject":"Fleet auto-responder: stop logging non-fleet mail to UI run-log (run-log tracks fleet inquiries only)","body":""},{"hash":"8f310af","date":"2026-05-19 10:32:53 -0700","author":"Steve Abrams","subject":"Fleet auto-responder: update usage docstring (daemon/force flags, HTML reply, UI)","body":""},{"hash":"2f343b5","date":"2026-05-19 10:31:20 -0700","author":"Steve Abrams","subject":"Fleet auto-responder: fix scan query (bare deliveredto:steve+ never matches in Gmail) + probe-subject safety guard (RETEST/FLEETMAILTEST/DTEST/PMRCV)","body":""},{"hash":"e9fdf0f","date":"2026-05-19 10:27:55 -0700","author":"Steve Abrams","subject":"Fleet auto-responder: --daemon self-scheduling mode (pm2-managed, 3-min interval); UI on port 9768","body":""},{"hash":"9c7a470","date":"2026-05-19 10:27:16 -0700","author":"Steve Abrams","subject":"fleet-autoresponder UI: move port 9766→9768 (9766 reserved for agent-architect mindmap viewer)","body":""},{"hash":"d6e30ce","date":"2026-05-19 10:26:19 -0700","author":"Steve Abrams","subject":"Fleet auto-responder: pm2 ecosystem config — 3-min cron schedule + UI process","body":""},{"hash":"fb57ee9","date":"2026-05-19 10:14:36 -0700","author":"Steve Abrams","subject":"Fleet auto-responder admin UI dashboard (Express viewer, port 9766, pm2-managed)","body":""},{"hash":"13d4e3b","date":"2026-05-19 10:13:06 -0700","author":"Steve Abrams","subject":"Fleet auto-responder: multipart/alternative HTML+plain reply, structured run-log + state","body":""},{"hash":"7d77cad","date":"2026-05-19 10:08:50 -0700","author":"Steve Abrams","subject":"Fleet auto-responder: deliveredto query fix + --only-ids scoped-test flag","body":"Tested live on barwallpaper.com + grassclothwallcovering.com (2-domain test):\n- Gmail does not match plus-tags via to:; switched candidate query to\n  deliveredto: and rely on Delivered-To header parsing for domain recovery.\n- Added --only-ids flag so a scoped test does not touch the inbox backlog\n  of unrelated probe mail.\n- Verified: reply sent from info@designerwallcoverings.com landed in the\n  recipient INBOX (not Spam), correct per-domain sign-off, no loop, label\n  + 7-day ledger dedup both idempotent on re-run.\n\nLedger (data/fleet-autoresponder-ledger.json) gitignored — runtime state.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"d135118","date":"2026-05-19 10:03:30 -0700","author":"Steve Abrams","subject":"Add fleet auto-responder for the 44 dw-domain-fleet domains","body":"Sends one warm acknowledgment from info@designerwallcoverings.com to genuine\nnew customer inquiries arriving at info@<fleet-domain> (forwarded into the\nsteve-office Gmail via Purelymail catch-all + plus-tag). Reply-To is set to\ninfo@<fleet-domain> so customer replies route back to the right site.\n\nSpam-safety: skips Spam, no-reply/bounce senders, bulk/auto/list mail, and any\nmail from designerwallcoverings.com or a fleet domain (loop guard). One reply\nper sender per rolling 7-day window (persisted ledger). Marks every processed\nmessage with the 'fleet-autoreplied' Gmail label — idempotent on re-run.\n\nReuses George's DW-MCP/.env OAuth credentials; no prod deploy needed.\nNot yet scheduled — run manually with: node fleet-autoresponder.js\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"02ef28b","date":"2026-05-18 14:34:30 -0700","author":"Steve Abrams","subject":"Make /api/profile honor ?account= param like the other 31 routes","body":""},{"hash":"2cbc311","date":"2026-05-18 14:33:51 -0700","author":"Steve Abrams","subject":"remove bogus stevesclaude account from George — theagentabrams@gmail.com (agentabrams) is the real AI account; also exempt /auth/agentabrams from basic auth","body":""},{"hash":"23979b0","date":"2026-05-18 14:21:06 -0700","author":"Steve Abrams","subject":"Add agentabrams (theagentabrams@gmail.com) as 5th george account slot","body":""},{"hash":"ec801aa","date":"2026-05-18 13:11:38 -0700","author":"Steve Abrams","subject":"george /auth honors ?account= — dispatches to per-account re-auth routes","body":""},{"hash":"a4d0448","date":"2026-05-12 08:47:06 -0700","author":"Steve Abrams","subject":"fix(george): ENV_PATH portable across Mac2/Kamatera","body":"ENV_PATH was hardcoded to /root/Projects/Designer-Wallcoverings/DW-MCP/.env\nwhich only exists on Kamatera. On Mac2 the same .env lives at\n~/Projects/Designer-Wallcoverings/DW-MCP/.env. The readFileSync would\nquietly fail in the try/catch upstream, INFO_REFRESH_TOKEN stayed empty,\nand the boot log said 'Info@ not configured' even though the token IS\nin the Mac2 .env.\n\nFix: try $DW_MCP_ENV then $HOME/Projects/.../DW-MCP/.env then the\nlegacy /root/ path. First readable wins.\n\nSymptom that exposed this: GET /api/search?account=info returned\n'unknown account: info' because infoGmail was never built. After\nrestart with the fix, log says 'Info@ account initialized (full\nWorkspace)' and /api/search returns the real DW inbox (201 messages\nfor a Shopify-orders query, including 'New Order on the New DW')."},{"hash":"facbb3b","date":"2026-05-06 10:25:18 -0700","author":"Steve Abrams","subject":"initial scaffold (gitify-all 2026-05-06)","body":""}]}