## User
- **User:** Mike Swanson (mike)
- **Machine:** DESKTOP-0O8A1RL
- **Role:** admin
- **Session:** 2026-05-20 ~14:40 PT

## Session Summary

Investigated and resolved a website contact form email delivery failure for Cascades of Tucson. The client reported that no contact form submissions had been reaching staff since approximately 4/19/2026 -- coinciding with the M365 mail migration. Investigation confirmed the root cause was an SPF misconfiguration: the cascadestucson.com website is hosted on GoDaddy, and GoDaddy's PHP mail relay (spf-0.secureserver.net IPs) was not authorized in the domain SPF record. With DMARC set to p=quarantine/pct=100, every form submission was being silently quarantined as phishing before reaching staff mailboxes.

The fix was applied directly to the cascadestucson.com DNS zone on the ACG IX nameservers (ns1/ns2.azcomputerguru.com). The SPF record was updated to add GoDaddy's relay include. Additionally, the Cascades M365 tenant was onboarded to the ComputerGuru Security Investigator app suite (previously on old deprecated app only), which enabled quarantine API access. 32 quarantined contact form emails spanning May 5-20 were released to crystal.rodriguez and megan.hiatt. A permanent Exchange transport rule was created to bypass spam/phish filtering for wordpress@cascadestucson.com as a backstop.

A Syncro ticket was created (#32304), billed at 1hr remote labor against the Cascades prepaid block (38.5 hrs available, 37.5 remaining), invoiced, and marked Invoiced. During billing, discovered the Syncro skill rate table has Labor - Remote Business at $150/hr but the correct standard rate is $175/hr. Cascades block rate is distinct from the standard rate -- $175 confirmed as the non-block rate, actual Cascades block rate still TBD.

## Key Decisions

- **cpapi2 for DNS update**: IX nameservers run WHM/cPanel. Used cpapi2 ZoneEdit edit_zone_record API (line 19 in zone) to update the SPF TXT record -- handles serial number bump and BIND reload automatically.
- **GoDaddy relay include**: Added include:spf-0.secureserver.net (not include:secureserver.net -- the spf-0 subdomain is what GoDaddy's own SPF record references). Confirmed by checking TXT record on secureserver.net directly.
- **Transport rule as permanent backstop**: SPF fix is correct but external relay scenarios (GoDaddy infrastructure changes, plugin SMTP overrides) could re-break delivery. SetSCL=-1 rule provides a permanent bypass layer.
- **Security Investigator onboarding**: Done programmatically via onboard-tenant.sh after Cascades admin consented the app. Script assigned Exchange Administrator role to the SP automatically.

## Problems Encountered

- **investigator-exo token had [INFO] prefix in file**: get-token.sh outputs "[INFO] auth=cert" to stdout before the token. Token cached to file included the prefix, causing 400 Bad Request on EXO API calls. Fix: pipe through `grep -v '^\['` to strip info lines.
- **Get-QuarantineMessage SenderAddress must be array**: Passing as string caused ParameterTransformationException. Fix: wrapped in JSON array.
- **Release-QuarantineMessage Identity rejects array**: Unlike Get-, Release- requires one Identity at a time (QuarantineMessageIdentity type). Fix: looped 32 individual API calls.
- **Identity backslashes in JSON**: Quarantine GUIDs contain backslashes (e.g. guid1\guid2). Bash heredoc passed them unescaped. Fix: used `jq -n --arg id` to construct payload with correct escaping.
- **$0 invoice misread**: Invoice posted at $0.00. Confirmed correct -- Cascades has prepaid block, Syncro deducted 1hr by quantity, annotated line "Applied 1.0 Prepay Hours".
- **Labor Remote Business rate wrong in skill**: Skill table shows $150/hr for product 1190473. Correct standard rate is $175/hr. Initial billing used $150, corrected via update_line_item. Cascades block rate still TBD.

## Configuration Changes

- **Modified:** cascadestucson.com DNS zone on IX (line 19, TXT SPF) -- added include:spf-0.secureserver.net. New serial: 2026052000.
- **Created:** M365 Exchange transport rule "Allow WordPress contact form - cascadestucson.com" (SetSCL=-1, Enabled) in Cascades tenant.
- **Onboarded:** Cascades tenant to Security Investigator + Exchange Operator + User Manager + Defender apps via onboard-tenant.sh. All directory roles assigned.
- **Created:** Syncro ticket #32304 -- Initial Issue + Resolution comments, 1hr timer entry (product 1190473), line item id 42525181 @ $175, invoice #67632. Status: Invoiced.

## Credentials & Secrets

- **Cascades M365 tenant ID:** 207fa277-e9d8-4eb7-ada1-1064d2221498
- **IX root SSH password:** t4qygLl7{1zJcUj#022W^FBQ>}qYp-Od -- vault: infrastructure/ix-server.sops.yaml credentials.password

## Infrastructure & Servers

- **IX server:** 172.16.3.10 (internal) / 72.194.62.5 (external / ns1.azcomputerguru.com)
- **cascadestucson.com DNS:** WHM/cPanel on IX. Zone: /var/named/cascadestucson.com.db
- **cascadestucson.com web hosting:** GoDaddy (A: 198.12.239.76). PHP mail through GoDaddy relay (spf-0.secureserver.net).
- **Cascades M365:** MX = cascadestucson-com.mail.protection.outlook.com. DMARC p=quarantine/pct=100.
- **Security Investigator SP (Cascades tenant):** c64ee5c1-a607-46cb-81b8-42de3de98d48
- **Exchange Operator SP (Cascades tenant):** 1c3bcfe9-6b4b-4273-852c-09d90f9ad146

## Commands & Outputs

```bash
# SPF record update on IX via cpapi2
/usr/local/cpanel/bin/cpapi2 --user=cascades ZoneEdit edit_zone_record \
  domain=cascadestucson.com Line=19 type=TXT name=cascadestucson.com. ttl=300 \
  txtdata='v=spf1 +a +mx +ip4:72.194.62.5 +include:spf.protection.outlook.com +include:spf-0.secureserver.net -all'
# newserial=2026052000, status=1

# Tenant onboarding
bash D:/claudetools/.claude/skills/remediation-tool/scripts/onboard-tenant.sh cascadestucson.com
# All 5 apps consented, all directory roles assigned [OK]

# Quarantine: 32 messages found from wordpress@cascadestucson.com (May 5-20)
# All QuarantineTypes: Phish, Released: false
# Released all 32 via loop -- Released: 32 / Failed: 0

# Transport rule created
# Name: Allow WordPress contact form - cascadestucson.com, State: Enabled, SetSCL=-1
```

## Pending / Incomplete Tasks

- **Cascades block rate:** $175/hr is the standard non-block rate. Actual Cascades prepaid block rate not yet confirmed. Required before next billing.
- **Syncro skill rate table:** Labor - Remote Business (product 1190473) shows $150/hr in .claude/commands/syncro.md -- needs correction to $175/hr (standard) and block-rate note added.

## Reference Information

- Syncro ticket #32304: https://computerguru.syncromsp.com/tickets/110680368
- Syncro invoice #67632
- Cascades M365 quarantine portal: https://security.microsoft.com/quarantine
- Cascades Entra admin: https://entra.microsoft.com/#@cascadestucson.com
- Live SPF: v=spf1 a mx ip4:72.194.62.5 include:spf.protection.outlook.com include:spf-0.secureserver.net -all
