Skip to content

Move the apex to yellowpine.com and make .dev the redirect - #1

Merged
cansin merged 3 commits into
mainfrom
worktree-yellowpine-com-apex
Sep 9, 2026
Merged

cansin merged 3 commits into
mainfrom
worktree-yellowpine-com-apex

Conversation

@cansin

@cansin cansin commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

yellowpine.com is finally in the Porkbun account. This moves the site onto it and turns yellowpine.dev into the redirect domain, reversing the topology chosen on 2026-09-08 (which parked the site on .dev precisely because .com was not ours to point anywhere).

The defect this closes

The page has advertised hello@yellowpine.com since 2026-09-08, in the masthead and again under Get in touch. .com was not ours then, and when it arrived it came carrying the previous owner's Mailgun MX records and zero forwards of ours.

Every message sent to the address on the homepage went to servers we do not control. Nothing in the suite caught it, because no test related the contact address to the domain the site is served from.

tests/site.test.mjs now asserts that relationship. It was written against the live page first, where it failed:

AssertionError: contact address is not on yellowpine.dev: hello@yellowpine.com

and only then was the domain flipped.

What changed

File Change
CNAME yellowpine.dev → yellowpine.com
index.html canonical, og:url, og:site_name. The two mailto: links already said .com and are untouched.
tests/site.test.mjs DOMAIN flipped; new invariant tying every mailto: to DOMAIN; header renumbered.
README.md Title, links, inverted topology line, rewritten Deploying.
package.json Description.
docs/.../2026-09-10-yellowpine-com-apex-design.md New. The 2026-09-08 spec is left as written.

Deploying is rewritten rather than retitled: its reasoning rested on .dev being HSTS-preloaded, which made HTTPS free. .com is not, so Enforce HTTPS is now something to set rather than assume. The ordering footgun is written down there too — DNS must point at GitHub before the domain lands in CNAME, or validation fails and GitHub never retries.

Merge order

DNS for yellowpine.com is being pointed at GitHub Pages before this merges, so Pages does not register a custom domain whose DNS still resolves elsewhere. .dev stays fully live until the moment this lands.

Known transitional risk, accepted: Pages serves exactly one custom domain, so between this merge and Porkbun issuing a certificate for yellowpine.dev, .dev is dark — and being HSTS-preloaded at the TLD level it hard-fails rather than degrading. The sequence puts that gap on the domain being retired, never on the live one.

Tests

npm test — 20/20 with network checks enabled.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q5nJ8eKEb1wm5tCzxipXHS

yellowpine.com is finally in the Porkbun account, so the site takes the name
people actually guess. yellowpine.dev becomes the redirect domain.

This also closes a live defect. The page has advertised hello@yellowpine.com
since 2026-09-08, but .com was not ours then, and when it arrived it came with
the previous owner's Mailgun MX records and none of our forwards. Every message
sent to the address on the homepage went to servers we do not control. No test
related the contact address to the domain the site is served from, so nothing
caught it.

tests/site.test.mjs now asserts that relationship. It was written against the
live page first, where it failed with "contact address is not on yellowpine.dev:
hello@yellowpine.com", and only then was the domain flipped.

The Deploying section is rewritten rather than retitled: its reasoning rested on
.dev being HSTS-preloaded, which made HTTPS free. .com is not, so Enforce HTTPS
is now something to set rather than assume. The ordering footgun that cost a
morning last time -- DNS must point at GitHub before the domain lands in CNAME,
or validation fails and GitHub never retries -- is written down there too.

The 2026-09-08 spec is left as written; the new one supersedes it rather than
editing what was true then.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5nJ8eKEb1wm5tCzxipXHS

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Four moderate findings remain in the migration documentation, metadata checks, and contact-address validation.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Moves the GitHub Pages site apex from yellowpine.dev to yellowpine.com and documents .dev as the redirect domain.

Changes:

  • Updates CNAME, metadata, README, and package description.
  • Adds contact-domain validation tests.
  • Adds DNS migration and deployment documentation.
File summaries
File Summary Final review comments
tests/site.test.mjs Updates domain assertions and validates mailto: links. Moderate (1 vote): Strip query parameters before validating mailto: addresses. Moderate (1 vote): Reject malformed addresses containing multiple @ characters.
README.md Documents the new domain topology and deployment process. No final comments.
package.json Updates the project description. No final comments.
index.html Updates canonical and Open Graph metadata. Moderate (3 votes): Assert og:url and og:site_name against DOMAIN, rather than only checking tag existence.
docs/superpowers/specs/2026-09-10-yellowpine-com-apex-design.md Records migration sequencing and DNS decisions. Moderate (2 votes): Resolve the conflict between deleting .dev mail records and preserving the hosted inbox.
CNAME Sets yellowpine.com as the custom domain. No final comments.
Review details

Suppressed comments (2)

tests/site.test.mjs:96

  • RFC 6068 permits query parameters on a mailto: URI, such as mailto:hello@yellowpine.com?subject=Hello. Including that query in address makes this assertion reject an otherwise valid contact link because the parsed domain becomes yellowpine.com?subject=Hello; strip the query before validating the address.
    const address = href.slice('mailto:'.length);

tests/site.test.mjs:98

  • The new invariant does not actually reject every off-domain address: address.split('@')[1] is still yellowpine.com for a malformed value such as hello@yellowpine.com@attacker.example, so that link would pass despite not being a valid address on this domain. Validate that there is exactly one @ (and compare the part after it) before asserting the domain.
      address.split('@')[1],
  • Files reviewed: 6/6 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

domain whose DNS still points elsewhere fails validation, and GitHub never retries.
5. Merge -> Pages re-registers on `.com`. Verify the certificate reaches `approved`, then
enable `https_enforced` in its own call.
6. Immediately after: `.dev` A records, `www`, MX, SPF and forwards deleted; URL forward added.
Comment thread index.html
Comment on lines +12 to +13
<meta property="og:site_name" content="yellowpine.com">
<meta property="og:url" content="https://yellowpine.com/">
cansin and others added 2 commits September 10, 2026 00:23
mailto: hrefs may carry ?subject= or ?body=, and splitting on @ alone folds
that tail into the host: "yellowpine.com?subject=Hello" never equals DOMAIN,
so the invariant would fail on a link that is perfectly correct.

Found reviewing the diff, not in the wild -- neither address on the page
carries a query today. Fixing it now keeps the next person from hitting a
false failure and "fixing" it by loosening the assertion.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5nJ8eKEb1wm5tCzxipXHS
Five findings, all real:

The domain guard missed og:url and og:site_name entirely. hrefsIn() matches
only href=/src=, so the og:* tags never reached the mailto or canonical checks,
and the metadata test asserted those tags EXIST without ever reading what they
say. A future move could update CNAME and canonical, miss og:*, and go green
while every shared link advertised the old domain. Proven by reverting og:url
alone: CNAME and canonical both still passed, and only the new guard failed.

The address is also visible anchor text, not just an href. Editing one without
the other left the suite green while anyone copying the address by eye got the
dead domain. Also proven by mutation.

README documented `-f cname=""` as the certificate recovery. The Pages API
removes a custom domain only on a JSON null, and gh's -f sends raw strings, so
the one command written down for the emergency would fail at the moment it was
needed. Now `-F cname=null`, with the reason next to it.

The spec claimed `npm test` was the gate for four things it cannot check: the
apex is excluded from the liveness test by isSelf, and nothing fetches .dev or
tests mail. A certificate that never issued would have kept CI green forever.
The verification section now says plainly that those checks are manual.

The spec's non-goal about the .dev trial inbox contradicted step 6, which
deletes the MX and SPF that inbox would need. Reworded: it is neither set up
nor cancelled, it lapses on 2026-09-22, and nothing reaches it meanwhile --
which is what redirect-only means.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5nJ8eKEb1wm5tCzxipXHS
@cansin

cansin commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Review findings — all five addressed

Reviewed at high effort against the full branch diff. Every finding was real; none were dismissed.

# Finding Severity Resolution
1 Domain guard missed og:url / og:site_name medium Fixed — new guard, proven by mutation
2 Spec claimed npm test gates checks it cannot perform medium Fixed — verification section rewritten
3 -f cname="" cannot clear the Pages domain medium Fixed — now -F cname=null
4 Spec non-goal contradicted step 6 low Fixed — reworded
5 Anchor text not checked against mailto: href low Fixed — new guard, proven by mutation

1 — the guard had a hole exactly where the PR claimed to close one

hrefsIn() matches only href=/src=, so <meta property="og:url"> never entered allHrefs, and page has the metadata a shared link needs asserted those tags exist without ever reading their values. Reverting og:url alone demonstrates it:

✔ CNAME pins the custom domain
✔ page declares the canonical URL and matches CNAME
✖ the social metadata points at the same domain

CNAME and canonical both stay green. Without the new guard, that mutation ships.

5 — same class, second instance

The address is a link target and visible text. Reverting only the text:

✔ the contact address is on the domain the site serves
✖ the contact address reads the same as it links

3 — the emergency command didn't work

The Pages API removes a custom domain only on a JSON null; gh's -f sends raw strings. The one command written down for a failed certificate would have errored at the moment it was needed. Now -F cname=null, with the reason recorded beside it.

2 — the spec overstated its own gate

The apex is excluded from the liveness test by isSelf, nothing fetches .dev, and nothing tests mail delivery. A certificate that never issued would have kept CI green forever. The verification section now states plainly that those four checks are manual, and that they — not CI — are the real gate for this change.

4 — self-contradiction in the spec

The non-goal said the .dev trial inbox was untouched; step 6 deletes the MX and SPF it would need. Reworded: neither set up nor cancelled, lapses 2026-09-22, and nothing reaches it meanwhile — which is what redirect-only means.

npm test — 22/22 with network checks enabled.

@cansin
cansin merged commit d150f28 into main Sep 9, 2026
2 checks passed
@cansin
cansin deleted the worktree-yellowpine-com-apex branch September 9, 2026 22:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants