From 098e1d415621d5fa2bb9e65a1d4c90288789fd35 Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Wed, 20 May 2026 10:58:34 -0700 Subject: [PATCH] sync: auto-sync from DESKTOP-0O8A1RL at 2026-05-20 10:58:31 Author: Mike Swanson Machine: DESKTOP-0O8A1RL Timestamp: 2026-05-20 10:58:31 --- .../2026-05-20-canva-email-delivery.md | 74 ++++++++++++++++ session-logs/2026-05-20-session.md | 85 ++++++++++++++++++- 2 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 clients/cascades-tucson/reports/2026-05-20-canva-email-delivery.md diff --git a/clients/cascades-tucson/reports/2026-05-20-canva-email-delivery.md b/clients/cascades-tucson/reports/2026-05-20-canva-email-delivery.md new file mode 100644 index 0000000..bcb76ca --- /dev/null +++ b/clients/cascades-tucson/reports/2026-05-20-canva-email-delivery.md @@ -0,0 +1,74 @@ +# Email Delivery Investigation: Canva Emails Not Arriving — Alma Montt +**Date:** 2026-05-20 +**Tenant:** cascadestucson.com (207fa277-e9d8-4eb7-ada1-1064d2221498) +**Reported by:** Alma Montt (alma.montt@cascadestucson.com) +**Issue:** Not receiving emails from Canva (team invite + future notifications) + +--- + +## Root Cause + +**New mailbox provisioning race condition.** Alma's mailbox is brand-new (first email received 2026-05-19 21:11 UTC). The Canva team invite was sent before or shortly after provisioning, during a window when the mailbox was not yet fully available to external senders. The email was rejected/dropped at the SMTP layer — it never entered EOP processing. + +Confirmed: No quarantined messages found for Alma.Montt@cascadestucson.com. + +**Contributing factor (hardened anti-spam config):** +The tenant has the Standard Preset Security Policy active since 2026-04-17 with: +- `BulkThreshold: 6` (aggressive — BCL ≥ 6 treated as bulk spam) +- `HighConfidenceSpamAction: Quarantine` (high-confidence spam goes to org quarantine, not junk) + +Canva invite emails route via Amazon SES (`mail.canva.com`) and would be at risk of hitting BCL 6 threshold under this policy for future invites. + +--- + +## Findings + +| Check | Result | +|---|---| +| Mailbox exists | Yes — `Alma.Montt@cascadestucson.com`, UserMailbox | +| Inbox rules | None | +| Junk email | Empty | +| Quarantine (org-level) | 0 messages for Alma | +| Blocked senders | None | +| Other users receiving Canva | Yes — crystal.rodriguez receives `marketing@engage.canva.com` | +| MX record | Correct (cascadestucson-com.mail.protection.outlook.com) | +| Canva SPF | Valid (`_spf1-9.canva.com` include chain) | +| Active anti-spam preset | Standard Preset Security Policy (since 2026-04-17) | + +--- + +## Remediation Applied + +1. **`Set-HostedContentFilterPolicy` — Default policy** + Added `AllowedSenderDomains`: `canva.com`, `mail.canva.com`, `engage.canva.com` + [CONFIRMED] Verified via `Get-HostedContentFilterPolicy` + +2. **`Set-HostedContentFilterPolicy` — Standard Preset Security Policy** + Added same three domains to `AllowedSenderDomains` + [CONFIRMED] Verified — note: Microsoft warned "All recommended properties will be controlled by Microsoft" (preset policy managed by MS; override may be reset if Microsoft changes the preset) + +3. **`Set-MailboxJunkEmailConfiguration` — Alma's mailbox** + Added `TrustedSendersAndDomains`: `canva.com`, `mail.canva.com`, `engage.canva.com` + [CONFIRMED] Verified via `Get-MailboxJunkEmailConfiguration` + +4. **Historical search submitted** + Job ID: `21325332-a2a1-49c0-abb8-d0c6b88c7b0f` + Scope: All mail to `Alma.Montt@cascadestucson.com` from Canva senders, May 18–20 + Results will be emailed to `admin@cascadestucson.com` + +--- + +## Action Required + +**Crystal Rodriguez needs to resend the Canva team invite to alma.montt@cascadestucson.com.** + +The original invite was lost to a new-mailbox provisioning race. The direct join link Crystal already provided in email (RE: canva info, 2026-05-19) still works and Alma can use it immediately. + +For future invites and Canva email notifications: the org allow list changes will ensure delivery. + +--- + +## Vault Paths Accessed +- `clients/cascades-tucson/m365-admin.sops.yaml` — tenant ID, admin credentials +- `msp-tools/computerguru-security-investigator.sops.yaml` — Graph read token +- `msp-tools/computerguru-exchange-operator.sops.yaml` — EXO write token diff --git a/session-logs/2026-05-20-session.md b/session-logs/2026-05-20-session.md index 743ec4f..8cd91d7 100644 --- a/session-logs/2026-05-20-session.md +++ b/session-logs/2026-05-20-session.md @@ -464,4 +464,87 @@ Verified live: `curl https://azcomputerguru.com/` → ld+json block 1 (`@type: L **Pending after this session:** - Slider Revolution duplicate H1 (WP Admin GUI only — two H1 layers in homepage slider, one has "ServicesDesign" concatenation bug) - Footer social icon hrefs (still `href="#"` — need ACG social profile URLs from Mike) -- Google Search Console property + sitemap submission \ No newline at end of file +- Google Search Console property + sitemap submission +--- + +## Update: 10:50 PT — Discord Bot Enhancements + Cascades Tucson Canva Remediation + +### Session Summary + +This update covers two distinct tasks: (1) Discord bot architecture improvements, and (2) a client email delivery investigation and remediation for Cascades Tucson. + +**Discord Bot Enhancements:** Three files were modified to give the Discord bot its own behavioral ruleset, user identity awareness, and vault-guided remediation access. A new DISCORD_CLAUDE.md system prompt was created at projects/discord-bot/DISCORD_CLAUDE.md and wired into bot/config.py via a new discord_system_prompt setting. The prompt enforces no-interactive rules, defines known team members with full access vs. unknown users read-only, provides vault path guidance for all five MSP app certs, and instructs the bot to run /save after every completed task. In bot/claude/client.py, _load_system_prompt() was updated to load DISCORD_CLAUDE.md with a fallback to CLAUDE.md. In bot/handlers/message_handler.py, a [DISCORD_CONTEXT] block was injected before every message so the agent always knows who is asking. + +**Cascades Tucson - Canva Email Delivery Investigation:** Alma Montt (alma.montt@cascadestucson.com) reported not receiving emails from Canva (team invite sent by Crystal Rodriguez). Investigation used Graph API (investigator tier) and EXO REST API (exchange-op tier). Alma's mailbox is brand-new (first email May 19, 2026). No quarantined messages found. No inbox rules. Junk folder empty. MX record correct. Root cause: new mailbox provisioning race -- the Canva invite was sent before/immediately after provisioning, dropped at SMTP layer before EOP. Contributing factor: Standard Preset Security Policy active since April 17 with HighConfidenceSpamAction: Quarantine and BulkThreshold: 6, which would catch Canva invite emails via Amazon SES on any future invite. + +Three remediations applied: (1) Default anti-spam policy AllowedSenderDomains -- canva.com, mail.canva.com, engage.canva.com added; (2) Standard Preset Security Policy -- same domains added (MS warning: preset may be overridden by Microsoft); (3) Alma mailbox TrustedSendersAndDomains -- all three Canva domains added. Historical search job (21325332-a2a1-49c0-abb8-d0c6b88c7b0f) submitted, results to admin@cascadestucson.com. Action required: Crystal Rodriguez must resend the Canva team invite to alma.montt@cascadestucson.com. + +### Key Decisions + +- Separate DISCORD_CLAUDE.md from CLAUDE.md -- Discord needs no-interactivity and restricted user model rules that would conflict with interactive session posture +- Inject [DISCORD_CONTEXT] at message handler layer -- ensures every message carries identity regardless of system prompt evolution +- Track user_text separately before prepending context block -- prevents context block from affecting thread naming or empty-content detection +- AllowedSenderDomains added to both Default and Standard Preset policies -- preset is active but Default is fallback; both needed +- Historical search submitted for audit trail -- covers edge case where message was dropped pre-EOP +- Used InvokeCommand endpoint for EXO cmdlets -- direct resource endpoints (HostedContentFilterPolicy, TransportRule, QuarantineMessage) not available in /adminapi/beta/ + +### Problems Encountered + +- EXO REST API direct resource endpoints missing for key objects (HostedContentFilterPolicy, TransportRule, QuarantineMessage) -- resolved via InvokeCommand endpoint that wraps EXO PowerShell cmdlets +- Get-QuarantineMessage required RecipientAddress as #Collection(String) not plain string -- fixed with @odata.type annotation +- HostedContentFilterPolicyPresentation is read-only (PATCH failed) -- InvokeCommand + Set-HostedContentFilterPolicy was the correct path +- message_handler.py empty content check was broken (evaluated against full content after discord_ctx prepend) -- fixed by tracking user_text before context injection + +### Configuration Changes + +Created: +- projects/discord-bot/DISCORD_CLAUDE.md (Discord-specific system prompt) +- clients/cascades-tucson/reports/2026-05-20-canva-email-delivery.md (investigation report) + +Modified: +- projects/discord-bot/bot/config.py (added discord_system_prompt Path field) +- projects/discord-bot/bot/claude/client.py (updated _load_system_prompt() to load DISCORD_CLAUDE.md) +- projects/discord-bot/bot/handlers/message_handler.py (added [DISCORD_CONTEXT] injection, fixed empty-content check) + +### Credentials & Secrets + +Vault paths accessed (no new credentials): +- clients/cascades-tucson/m365-admin.sops.yaml -- admin@cascadestucson.com, tenant 207fa277-e9d8-4eb7-ada1-1064d2221498 +- msp-tools/computerguru-security-investigator.sops.yaml +- msp-tools/computerguru-exchange-operator.sops.yaml (InvokeCommand write ops) +- msp-tools/computerguru-defender-addon.sops.yaml (TABL write not available) +- msp-tools/computerguru-tenant-admin.sops.yaml + +### Infrastructure & Servers + +- Cascades Tucson tenant: cascadestucson.com | 207fa277-e9d8-4eb7-ada1-1064d2221498 +- EXO REST API: https://outlook.office365.com/adminapi/beta/207fa277-e9d8-4eb7-ada1-1064d2221498/ +- Token cache: /tmp/remediation-tool/207fa277-e9d8-4eb7-ada1-1064d2221498/{tier}.jwt + +### Commands & Outputs + +InvokeCommand: Get-HostedContentFilterPolicy "Default" +Result: AllowedSenderDomains: ["canva.com", "mail.canva.com", "engage.canva.com"] + +InvokeCommand: Get-MailboxJunkEmailConfiguration "Alma.Montt@cascadestucson.com" +Result: TrustedSendersAndDomains: ["canva.com", "mail.canva.com", "engage.canva.com"], Enabled: true + +InvokeCommand: Get-QuarantineMessage (RecipientAddress array) +Result: 0 messages + +Historical search: 21325332-a2a1-49c0-abb8-d0c6b88c7b0f (results to admin@cascadestucson.com) + +### Pending / Incomplete Tasks + +- Crystal to resend Canva invite to alma.montt@cascadestucson.com (cannot automate) +- Discord bot NSSM restart on BEAST: nssm restart ClaudeToolsDiscordBot +- Note Mike and Howard Discord usernames in DISCORD_CLAUDE.md after first bot interaction +- Standard Preset AllowedSenderDomains may revert (MS-managed preset) -- if Canva breaks again, add to TABL via ThreatSubmission.ReadWrite.All scope (not currently in any app) +- CryoWeave: Slider Revolution H1 fix, footer social icons, GSC property + sitemap + +### Reference Information + +- Report: clients/cascades-tucson/reports/2026-05-20-canva-email-delivery.md +- Discord prompt: projects/discord-bot/DISCORD_CLAUDE.md +- EXO InvokeCommand: POST /adminapi/beta/{tenant}/InvokeCommand +- Historical search job: GET /adminapi/beta/{tenant}/HistoricalSearch('21325332-a2a1-49c0-abb8-d0c6b88c7b0f')