aboutsummaryrefslogtreecommitdiff
path: root/working/triage-account-guard/proposed.diff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-23 23:41:24 -0500
committerCraig Jennings <c@cjennings.net>2026-07-23 23:41:24 -0500
commit392f14a83dedad96750749d46ad808f9c9bad493 (patch)
treeee06788fa3d049c00fd926fc0a6e944cc4b1700b /working/triage-account-guard/proposed.diff
parent9a8a6c7544afca5180a2f640edbfb83b27d95536 (diff)
downloadrulesets-392f14a83dedad96750749d46ad808f9c9bad493.tar.gz
rulesets-392f14a83dedad96750749d46ad808f9c9bad493.zip
chore(inbox): park the personal-gmail account-binding guard
Home hit a cross-account hazard: a triage fire reached the personal inbox through a work-bound Gmail MCP and pulled 201 DeepSat messages, which would have run every hygiene action against the wrong mailbox. The fix adds one guard to the plugin's Scan phase — verify a sample result's recipient before classifying, fall back to the local mu mirror on mismatch rather than another MCP. Parked for approval since the plugin is a synced asset. Graded [#A] on severity alone: acting on the wrong person's mailbox is a privacy exposure regardless of how rarely it happens. Diff and companion note staged under working/.
Diffstat (limited to 'working/triage-account-guard/proposed.diff')
-rw-r--r--working/triage-account-guard/proposed.diff11
1 files changed, 11 insertions, 0 deletions
diff --git a/working/triage-account-guard/proposed.diff b/working/triage-account-guard/proposed.diff
new file mode 100644
index 0000000..0eda2f6
--- /dev/null
+++ b/working/triage-account-guard/proposed.diff
@@ -0,0 +1,11 @@
+--- .ai/workflows/triage-intake.personal-gmail.org 2026-07-16 10:42:14.461682666 -0500
++++ working/triage-account-guard/triage-intake.personal-gmail.org.proposed 2026-07-23 23:38:44.358507825 -0500
+@@ -27,6 +27,8 @@
+
+ ⚠ *Do NOT add =-category:promotions -category:social=.* That filter masked 67 promo+social messages across two runs (2026-05-04, 2026-05-06), both needing a follow-up sweep. Pull the full unfiltered set; the trash-leaning bias in Classify handles promotions and social directly.
+
++⚠ *Verify the account binding before trusting the scan.* =mcp__google-docs-personal= must resolve to =craigmartinjennings@gmail.com=. Several Gmail-capable MCPs are connected and they bind to *different* accounts — =mcp__claude_ai_Gmail= is bound to the DeepSat *work* account, and its name gives no hint of that. A wrong-account scan returns a plausible mailbox that is the wrong person's, and every hygiene action in the close then fires on the wrong inbox (this happened 2026-07-23: a sweep used =claude_ai_Gmail= and pulled 201 unread *DeepSat work* messages instead of personal). Guard, every scan: confirm a sample result's =to:= is =craigmartinjennings@gmail.com= before classifying. If it isn't, or if =google-docs-personal= is unavailable, do NOT reach for another MCP — use the local mu mirror: sync first (=mbsync gmail && mu index=; the index lags), then =mu find 'maildir:/gmail/INBOX AND flag:unread AND date:<anchor>..now'=. The three accounts and their maildirs: =gmail= = craigmartinjennings@gmail.com, =cmail= = c@cjennings.net, =dmail= = craig.jennings@deepsat.com (work — out of scope from a home session, whichever tool reaches it).
++
+ ⚠ *The MCP caps at =maxResults=100= and exposes NO =pageToken= parameter.* The response carries a =nextPageToken=, but the tool can't consume it, so a pile over 100 is silently truncated — the tail below the cap never gets classified, and every later anchored sweep skips it (it predates the new anchor). This is exactly how a 300+ backlog accumulated invisibly by 2026-07-08. Two consequences:
+
+ - *Never treat a 100-row result as complete.* When a scan returns exactly 100, walk the tail in *date slices*: re-query with =before:<oldest-full-day-seen>= (day resolution), repeat until a page returns fewer than 100, dedupe by message id across slices (the day-resolution boundary overlaps).