fix(ops): unblock sender trust DKIM half with live Cloudflare selector - #60
fix(ops): unblock sender trust DKIM half with live Cloudflare selector#60nish3451 wants to merge 16 commits into
Conversation
DKIM discovery now covers Cloudflare Email Service selectors (cf2024-1, cf2022_cloudflare_email, c2022_cloudflare_email, cf-bounce) and agency-config applies the live DKIM record published at cf2024-1._domainkey.tinystudio.io. send:setup now verifies SPF, DMARC, and DKIM; the only remaining sender warning is the physical postal address, which needs a real operator address before cold email.
sender-setup-guide, 11-10-proof-run, market-parity-readiness, competitive-proof-matrix, and market-parity-benchmark now reflect send:setup verifying SPF, DMARC, and DKIM; the only remaining sender warning is the physical postal address.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe sender setup now recognizes Cloudflare selectors, configures ChangesSender trust
Estimated code review effort: 2 (Simple) | ~10 minutes Mergeability Score: ⚪ Minimal · up to The PR updates DKIM selector discovery and configuration while preserving the physical-address safety gate; no actionable merge-blocking risk remains after normal checks and review. Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
The fleet keeps dispatching the same finding to multiple lanes, producing duplicate same-fix PR pairs: #36/#44 and #55/#56 are byte-identical or near-identical patches of the operator export --help fix, #39/#49 the offername article fix, #40/#52 the recording exporter --help fix, plus #38/#48/#51, #30/#61/#72, #45/#64, #42/#60, #43/#54 and #46/#74. Add a PR Duplicate Guard: - scripts/check-pr-duplicates.mjs compares a PR's diff against every other open PR (shared changed-file coverage >= 0.8 and patch similarity >= 0.5). Calibrated on all 79 open PRs on 2026-08-11: every pair above the thresholds was a genuine duplicate-cluster member, zero false positives. - .github/workflows/pr-duplicate-guard.yml runs it on every PR event and posts one marker comment naming the duplicate(s) and the canonical PR; the check fails loudly when a duplicate is found. Informational, not required. - scripts/test-pr-duplicates.mjs covers parsing, similarity, detection, and comment upsert with an injected API; wired into npm ci and npm test.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@growth-brain/ops/agency-config.json`:
- Line 35: Confirm which Cloudflare service sends outbound email and update the
dkimSelector configuration to that service’s selector; use cf-bounce for Email
Sending rather than cf2024-1. If both Email Routing and Email Sending are used,
define separate routing and sending selector settings and ensure the outbound
sender-trust check uses the sending selector.
In `@scripts/export-sender-setup-guide.mjs`:
- Around line 111-112: Update the DKIM discovery and fix-order generation in the
relevant setup-guide functions so they consume the same verified DKIM result
used by checkRows, ensuring all outputs consistently show readiness and omit
completed DKIM steps. Preserve postal-address warnings independently, then
regenerate both tracked Markdown and HTML artifacts from the corrected
generator.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 5498571c-f38f-4957-b238-bb04ee0c3f19
📒 Files selected for processing (11)
TASKS.mddocs/strategy/market-parity-benchmark-2026.mdgrowth-brain/ops/11-10-proof-run.mdgrowth-brain/ops/agency-config.jsongrowth-brain/ops/competitive-proof-matrix.htmlgrowth-brain/ops/competitive-proof-matrix.mdgrowth-brain/ops/market-parity-readiness.mdgrowth-brain/ops/sender-setup-guide.htmlgrowth-brain/ops/sender-setup-guide.mdscripts/check-outbound-sender-setup.mjsscripts/export-sender-setup-guide.mjs
| "senderEmail": "hello@tinystudio.io", | ||
| "senderPhysicalAddress": "", | ||
| "dkimSelector": "", | ||
| "dkimSelector": "cf2024-1", |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
Use the selector for the actual outbound service.
dkimSelector feeds the outbound sender-trust check. Cloudflare documents cf2024-1 for Email Routing and cf-bounce for Email Sending. If Cloudflare Email Sending sends the cold email, this value can validate the routing record and clear the outbound gate incorrectly. Confirm the real sending path before merge. Store separate routing and sending selectors if both services are used. (developers.cloudflare.com)
Verification
#!/usr/bin/env bash
set -euo pipefail
rg -n -C 5 \
'dkimSelector|senderEmail|cf2024-1|cf-bounce|Email Routing|Email Sending|SMTP|Cloudflare' \
growth-brain/ops scripts package.json🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@growth-brain/ops/agency-config.json` at line 35, Confirm which Cloudflare
service sends outbound email and update the dkimSelector configuration to that
service’s selector; use cf-bounce for Email Sending rather than cf2024-1. If
both Email Routing and Email Sending are used, define separate routing and
sending selector settings and ensure the outbound sender-trust check uses the
sending selector.
| - If the domain runs Cloudflare Email Routing or Email Sending (SPF includes \`_spf.mx.cloudflare.net\`), the DKIM records Cloudflare provides use selector \`cf2024-1\` for routed mail or \`cf-bounce\` for sent mail; confirm the exact selector in the Cloudflare dashboard before saving it here. | ||
| - Cloudflare TXT records are the normal DNS record type for DKIM, SPF, and DMARC values. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Derive all DKIM guidance from one verified state.
The generated Markdown and HTML show DKIM ready while their discovery sections still say No common DKIM selector found in DNS yet. They also keep DKIM setup steps even though the only warning is the postal address. This output can cause the operator to repeat or overwrite completed DKIM setup. Make the discovery table and fix order consume the same verified result as checkRows, then regenerate both tracked artifacts.
Also applies to: 244-245
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/export-sender-setup-guide.mjs` around lines 111 - 112, Update the
DKIM discovery and fix-order generation in the relevant setup-guide functions so
they consume the same verified DKIM result used by checkRows, ensuring all
outputs consistently show readiness and omit completed DKIM steps. Preserve
postal-address warnings independently, then regenerate both tracked Markdown and
HTML artifacts from the corrected generator.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
Leaving this one open deliberately — it needs a call I should not make on my own, because it changes outbound email signing. The conflict is a factual disagreement about the DKIM selector. This branch sets I checked live DNS, and both records genuinely exist:
So "the selector resolves" does not settle it. What matters is which service actually sends the cold email, because that is the one whose selector signs it. On that reading this PR is stale and would regress the sender config to a selector that is not on the sending path. I have not closed it, because getting this wrong silently breaks DKIM on the sales channel and I cannot confirm from here which provider is actually wired up for sending. Nish's call: if outbound goes through Resend, close this PR — |
|
Closing as superseded. This PR was opened when dkimSelector was empty, but PR #141 later merged and deliberately set it to |
Nish's direct decision 2026-08-20: all outbound email runs on Cloudflare, not Resend. Flips dkimSelector from resend to cf2024-1 and regenerates the sender setup guide under the tracked-artifact pinned clock. Live send:setup confirms the cf2024-1 DKIM record on tinystudio.io; the only remaining sender-trust warning is the physical postal address. Reverses #141's provider choice; supersedes closed #60.
Closes the sender-trust blocker tracked as "Outbound email stays blocked on sender trust: empty physical postal address and empty dkimSel".
What changed
scripts/check-outbound-sender-setup.mjsnow probes Cloudflare Email Service selectors (cf2024-1,cf2022_cloudflare_email,c2022_cloudflare_email,cf-bounce) alongside the common selectors. The sender domain's SPF (include:_spf.mx.cloudflare.net) and MX (route*.mx.cloudflare.net) prove Cloudflare is the mail path.growth-brain/ops/agency-config.json:dkimSelectorset tocf2024-1— the selector whosev=DKIM1TXT record is live in DNS atcf2024-1._domainkey.tinystudio.io(verified via authoritative Cloudflare DNS:dig TXT cf2024-1._domainkey.tinystudio.ioreturns a valid DKIM record).export-sender-setup-guide.mjsdocuments the Cloudflare selector convention and source link;send:guideartifacts regenerated.2026-08-06,SERVICE_TEST_NOW,TZ=Asia/Kolkata) sotest-active-operator-surfaces.mjsbyte-compares cleanly:sender-setup-guide.{md,html},11-10-proof-run.md,market-parity-readiness.md,competitive-proof-matrix.{md,html},docs/strategy/market-parity-benchmark-2026.md.Result of
npm run send:setupOnly the physical postal address warning remains.
What remains: physical postal address
The other half of the item (empty
senderPhysicalAddress) cannot be closed from the repo without a real address:Inventing an address would violate the repo's claim-safety/product-truth discipline. The operator supplies the real address once via
npm run send:configure -- --physical-address="..."(or by editingagency-config.json); until then,send:setupstill warns and channel guidance keeps recommending contact forms/DMs, which is the intended fail-safe.Verification
npm run cipasses (full suite;test-service-engine.mjsflaked once on the acquireLock timing test and passed on re-run — pre-existing, unrelated to this change).Note
This supersedes the stale open PR #42 (same fix, rebased onto current main with the fixed-clock regeneration).
Summary by CodeRabbit
Bug Fixes
cf2024-1selector.Documentation