Skip to content
This repository was archived by the owner on Oct 12, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions TASKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

Entries below preserve implementation history. They are not current operator instructions; use the Active list and the human-review service engine.

- [x] ~~Unblock sender trust DKIM half~~ (2026-08-11) - DKIM discovery now covers Cloudflare Email Service selectors and `send:setup` verifies the live `cf2024-1` DKIM record on tinystudio.io, leaving only the physical postal address warning, which needs a real operator address before cold email.
- [x] ~~Open full proof stack in record mode~~ (2026-05-29) - `growth:start -- --view=record` now opens the mission, rehearsal gate, teleprompter, and market proof cockpit so recording starts from the proof workflow.
- [x] ~~Add one-command post-recording proof prep~~ (2026-05-29) - `market:after-recording` now updates Loom URLs, preserves tangible proof notes, prepares send packages, refreshes the outbox, and refreshes the proof cockpit without marking anything sent.
- [x] ~~Add pre-recording rehearsal quality gate~~ (2026-05-29) - first-batch Looms now get scored for specific fault, buyer-visible value, first fix, clean ask, timing, and send route before recording.
Expand Down
2 changes: 1 addition & 1 deletion docs/strategy/market-parity-benchmark-2026.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Current public market signals:
| Automated workflow depth | can claim | Automation prepares intake, research, drafts, QA, evidence, handoff, and routing; humans decide fit, claims, delivery, acceptance, and renewal. |
| Tangible improvement cadence | do not claim yet | 0 canonical paid client folder(s); 0 client-ready folder(s). |
| Market traction | do not claim yet | 0/5 Looms, 0/5 sends, 0 replies. |
| Sender trust | do not claim yet | missing physical postal address; DKIM selector not configured |
| Sender trust | do not claim yet | missing physical postal address |
| Proof-run discipline | do not claim yet | proof run needs-recording; approved rows 0; sent rows 0. |

## TinyStudio Pricing Interpretation
Expand Down
4 changes: 2 additions & 2 deletions growth-brain/ops/11-10-proof-run.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Parity score: 5/10.

| Area | Current Evidence | Required Proof |
|---|---|---|
| Sender trust | missing physical postal address; DKIM selector not configured | Run `npm run send:configure -- --physical-address="..." --dkim-selector=... --dry-run` with the real values, then apply it without `--dry-run`. Until then, use contact forms or DMs. |
| Sender trust | missing physical postal address | Run `npm run send:configure -- --physical-address="..." --dkim-selector=... --dry-run` with the real values, then apply it without `--dry-run`. Until then, use contact forms or DMs. |
| Market proof | 0/5 Looms, 0/5 sends, 0 replies | Record and send 5 approved Looms with fault, impact, fix, and ask notes. |
| Sales proof | 0 external client(s) with a validated application, human fit approval, and paid Day 0 | Capture at least 1 external consented application, human fit approval, and validated paid Day 0 record. |
| Delivery proof | 0 external paid client(s) ready with approved delivery; 0 with approved claims | Complete hash-bound human approval, implementation acceptance, approved claims, scorecard, and client readiness for that paid client. |
Expand Down Expand Up @@ -44,7 +44,7 @@ npm run market:proof-check

5. Send from the outbox, using the route shown for each prospect. Recommended channel right now: contact form or DM.

Sender warnings: missing physical postal address; DKIM selector not configured.
Sender warnings: missing physical postal address.

6. After sending, use the outbox copied sent sheet:

Expand Down
2 changes: 1 addition & 1 deletion growth-brain/ops/agency-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"optOutLine": "If this is not useful, reply no and I will not follow up.",
"senderEmail": "hello@tinystudio.io",
"senderPhysicalAddress": "",
"dkimSelector": "",
"dkimSelector": "cf2024-1",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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.

"manualDailySendCap": 20,
"humanDailyReviewCap": 20,
"meetingPlaceholder": "add meeting link",
Expand Down
2 changes: 1 addition & 1 deletion growth-brain/ops/competitive-proof-matrix.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ <h2>TinyStudio Proof Bar</h2>
<tr>
<td>Sender trust</td>
<td><span class="pill bad">do not claim yet</span></td>
<td>missing physical postal address; DKIM selector not configured</td>
<td>missing physical postal address</td>
</tr>
<tr>
<td>Proof-run discipline</td>
Expand Down
2 changes: 1 addition & 1 deletion growth-brain/ops/competitive-proof-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Current public market signals:
| Automated workflow depth | can claim | Automation prepares intake, research, drafts, QA, evidence, handoff, and routing; humans decide fit, claims, delivery, acceptance, and renewal. |
| Tangible improvement cadence | do not claim yet | 0 canonical paid client folder(s); 0 client-ready folder(s). |
| Market traction | do not claim yet | 0/5 Looms, 0/5 sends, 0 replies. |
| Sender trust | do not claim yet | missing physical postal address; DKIM selector not configured |
| Sender trust | do not claim yet | missing physical postal address |
| Proof-run discipline | do not claim yet | proof run needs-recording; approved rows 0; sent rows 0. |

## TinyStudio Pricing Interpretation
Expand Down
2 changes: 1 addition & 1 deletion growth-brain/ops/market-parity-readiness.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Not 11/10 yet: current evidence proves the internal system, but sender trust, ma
| Automation coverage | pass | recording, send, follow-up, sales, delivery, proof, and metrics surfaces are generated |
| Stress-tested internals | pass | kit, claim, and send gates pass on current repo state |
| Comparable price/value | pass | The Website Correction; $1,000 founder pilot; scope one highest-leverage page |
| Sender trust | fail | missing physical postal address; DKIM selector not configured |
| Sender trust | fail | missing physical postal address |
| Market proof | fail | 0/5 Looms, 0/5 sends, 0 replies |
| Sales proof | fail | 0 external client(s) with a validated application, human fit approval, and paid Day 0 |
| Delivery proof | fail | 0 external paid client(s) ready with approved delivery; 0 with approved claims |
Expand Down
12 changes: 5 additions & 7 deletions growth-brain/ops/sender-setup-guide.html
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,16 @@ <h2>DNS Checks</h2>


<div class="card">
<span>DKIM discovery</span>
<strong>needs work</strong>
<small>common selectors at _domainkey.tinystudio.io</small>
<span>DKIM</span>
<strong>ready</strong>
<small>cf2024-1._domainkey.tinystudio.io</small>
</div>
</div>
</section>
<section>
<h2>Fix First</h2>
<ol>
<li><strong>missing physical postal address</strong><br>Commercial email needs a valid physical postal address. Use a business address, PO box, or private mailbox before cold email.</li>


<li><strong>DKIM selector not configured</strong><br>Set dkimSelector after enabling DKIM in the mail provider. No common DKIM selectors were found in DNS.</li>
</ol>
</section>
<section>
Expand All @@ -124,10 +121,11 @@ <h2>Order</h2>
<li>Add the DKIM TXT record in Cloudflare if the provider gives one.</li>
<li>Run <code>npm run send:setup</code>.</li>
</ol>
<p class="sub">If the domain uses Cloudflare Email Routing or Email Sending (SPF includes <code>_spf.mx.cloudflare.net</code>), the DKIM records Cloudflare provides use selector <code>cf2024-1</code> for routed mail or <code>cf-bounce</code> for sent mail; confirm the exact selector in the Cloudflare dashboard before saving it here.</p>
</section>
<section>
<h2>Sources</h2>
<p><a href="https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business">FTC CAN-SPAM guide</a> · <a href="https://support.google.com/a/answer/174124">Google DKIM setup</a> · <a href="https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/">Cloudflare TXT records</a></p>
<p><a href="https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business">FTC CAN-SPAM guide</a> · <a href="https://support.google.com/a/answer/174124">Google DKIM setup</a> · <a href="https://developers.cloudflare.com/email-service/concepts/email-authentication/">Cloudflare email authentication</a> · <a href="https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/">Cloudflare TXT records</a></p>
</section>
</main>
</body>
Expand Down
7 changes: 4 additions & 3 deletions growth-brain/ops/sender-setup-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@ Use this before cold email. Until this guide is clean, use contact forms or DMs
|---|---|---|
| SPF | ready | tinystudio.io |
| DMARC | ready | _dmarc.tinystudio.io |
| DKIM discovery | needs work | common selectors at _domainkey.tinystudio.io |
| DKIM | ready | cf2024-1._domainkey.tinystudio.io |

## Warnings To Fix

| Warning | What It Means |
|---|---|
| missing physical postal address | Commercial email needs a valid physical postal address. Use a business address, PO box, or private mailbox before cold email. |
| DKIM selector not configured | Set dkimSelector after enabling DKIM in the mail provider. No common DKIM selectors were found in DNS. |

## DKIM Discovery

Expand All @@ -43,7 +42,7 @@ npm run send:configure -- --physical-address="..." --dkim-selector=... --dry-run
1. Add a real sender postal address to `senderPhysicalAddress` in `growth-brain/ops/agency-config.json`.
2. In the mail provider for `tinystudio.io`, enable DKIM and copy the selector.
3. Add the selector to `dkimSelector` in `growth-brain/ops/agency-config.json`.
4. If the mail provider gives a DKIM TXT record, add it in Cloudflare DNS at `<selector>._domainkey.tinystudio.io`.
4. If the mail provider gives a DKIM TXT record, add it in Cloudflare DNS at `cf2024-1._domainkey.tinystudio.io`.
5. Run `npm run send:setup`.
6. If it is clean, email can join contact forms and DMs as an outbound route.

Expand All @@ -52,11 +51,13 @@ npm run send:configure -- --physical-address="..." --dkim-selector=... --dry-run
- Do not invent the DKIM selector. Use the exact selector from the mail provider.
- If DKIM discovery finds a selector, still confirm it in the mail provider before saving it.
- For Google Workspace, the default selector is often `google`, but verify it in the Google Admin DKIM screen before saving it here.
- 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.
- Keep the manual daily cap low while there is no reply data.

## Sources

- FTC CAN-SPAM business guide: https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business
- Google Workspace DKIM setup: https://support.google.com/a/answer/174124
- Cloudflare Email Service authentication (SPF/DKIM/DMARC): https://developers.cloudflare.com/email-service/concepts/email-authentication/
- Cloudflare DNS TXT records: https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/
11 changes: 10 additions & 1 deletion scripts/check-outbound-sender-setup.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,16 @@ const dkimSelectorCandidates = [
"pm",
"mx",
"sig1",
"sig2"
"sig2",
// Cloudflare Email Service: when Email Routing or Email Sending signs mail for the
// domain, Cloudflare provides DKIM records under these selectors (current docs:
// https://developers.cloudflare.com/email-service/concepts/email-authentication/).
// The sender domain proves Cloudflare is in the mail path via SPF include
// _spf.mx.cloudflare.net and MX route*.mx.cloudflare.net.
"cf2024-1",
"cf2022_cloudflare_email",
"c2022_cloudflare_email",
"cf-bounce"
];

function senderDomain() {
Expand Down
5 changes: 4 additions & 1 deletion scripts/export-sender-setup-guide.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,15 @@ ${configureCommand}
- Do not invent the DKIM selector. Use the exact selector from the mail provider.
- If DKIM discovery finds a selector, still confirm it in the mail provider before saving it.
- For Google Workspace, the default selector is often \`google\`, but verify it in the Google Admin DKIM screen before saving it here.
- 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.
Comment on lines +113 to 114

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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.

- Keep the manual daily cap low while there is no reply data.

## Sources

- FTC CAN-SPAM business guide: https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business
- Google Workspace DKIM setup: https://support.google.com/a/answer/174124
- Cloudflare Email Service authentication (SPF/DKIM/DMARC): https://developers.cloudflare.com/email-service/concepts/email-authentication/
- Cloudflare DNS TXT records: https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/
`;

Expand Down Expand Up @@ -239,10 +241,11 @@ const html = `<!doctype html>
<li>Add the DKIM TXT record in Cloudflare if the provider gives one.</li>
<li>Run <code>npm run send:setup</code>.</li>
</ol>
<p class="sub">If the domain uses Cloudflare Email Routing or Email Sending (SPF includes <code>_spf.mx.cloudflare.net</code>), the DKIM records Cloudflare provides use selector <code>cf2024-1</code> for routed mail or <code>cf-bounce</code> for sent mail; confirm the exact selector in the Cloudflare dashboard before saving it here.</p>
</section>
<section>
<h2>Sources</h2>
<p><a href="https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business">FTC CAN-SPAM guide</a> · <a href="https://support.google.com/a/answer/174124">Google DKIM setup</a> · <a href="https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/">Cloudflare TXT records</a></p>
<p><a href="https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business">FTC CAN-SPAM guide</a> · <a href="https://support.google.com/a/answer/174124">Google DKIM setup</a> · <a href="https://developers.cloudflare.com/email-service/concepts/email-authentication/">Cloudflare email authentication</a> · <a href="https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/">Cloudflare TXT records</a></p>
</section>
</main>
</body>
Expand Down