All documentation

Domain migration: AITradeCopier → Wedge Trade AI

Migrating the existing application to wedgetradeai.com. A migration and rebrand, not a rebuild: no feature is removed, no service is replaced, and the current deployment stays live and recoverable throughout.

STATUS: DNS and HTTPS are DONE (2026-11-06). Authentication and the production deploy are not. See §3a for what was executed and verified.

The remainder of Phase 4 (dashboard half) and Phase 8 have not been executed. Those steps change production DNS, an external auth configuration, or live user-facing routing, and each is listed here with the exact value to apply so it can be approved and then done deliberately.


1. Existing hosting architecture (audited, not assumed)

LayerProviderIdentifier / evidence
Frontend + API routesVercel.vercel/project.json: project ai-trade-copier, projectId prj_LZu1zdTvxImoR4tFN0uTanfQAYgE, orgId team_Fm8JJ0BHAEO3bPLURmIoalOB
Current public addresshttps://ai-trade-copier.vercel.appthe only app URL referenced anywhere in the repo
Background workerRenderrender.yaml: ai-trade-copier-copy-worker, worker, Node 22, region oregon, branch main, autoDeployTrigger: off
Staging workerRenderai-trade-copier-copy-worker-staging, branch security/dependency-remediation, COPYWORKER_NO_BROKER=true, BROKER_EXECUTION_BLOCKED=true
DatabaseSupabase (Postgres)NEXT_PUBLIC_SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY
AuthenticationSupabase Auth, cookie sessions via @supabase/ssrsrc/lib/supabase/server.ts
Repository (authoritative)GitHubhttps://github.com/sabwachanda177-del/ai-trade-copier.git, current branch feature/futures-copy-engine
Container optionDockerfile + docker-composeoutput: 'standalone' when not on Vercel

API endpoints, WebSockets, workers

  • API routes are Next.js route handlers under src/app/api/**, served

from the same origin as the site. A domain change moves them with the site; no route path changes.

  • WebSockets: two kinds, and neither is coupled to the app domain.
  • Supabase Realtime (wss://<supabase-host>) from the browser —

already allowed by CSP, which derives that host from NEXT_PUBLIC_SUPABASE_URL.

  • Broker sockets (Tradovate trading/market data) run **inside the

Render worker**, a Node process with no browser CSP and no concept of a page origin.

  • Background worker: scripts/run-copy-worker.ts on Render. It

talks to Supabase and to brokers. It never addresses the web app by URL, so the domain change requires no worker change at all.

Environment variables

One variable carries the app's own address: `NEXT_PUBLIC_SITE_URL`. It is read in exactly five places —

FileUse
src/app/forgot-password/actions.tspassword-reset redirectTo
src/app/login/actions.tsemail-confirmation URL
src/app/dashboard/billing/actions.ts (×2)Stripe return URLs
src/app/dashboard/settings/organization/actions.tsteam invite links

— plus, as of this migration, metadataBase in src/app/layout.tsx. Every other variable (Supabase, Stripe, Resend, alerting, AI providers) is domain-independent.


2. Changes made (safe, local, committed)

Rebranding — 22 occurrences, 18 files

Public-facing strings only: marketing pages (home, about, blog, docs, terms), root metadata title and template, the auth card, the dashboard sidebar, the marketing nav and footer, the onboarding wizard, the maintenance notice, the alert-email subject, and five operator-doc headers.

metadataBase added

src/app/layout.tsx now resolves relative metadata URLs against NEXT_PUBLIC_SITE_URL. Without it, canonical and Open Graph URLs would keep resolving against the old origin after the cutover. Left *undefined* when the variable is absent rather than hardcoded — an undefined base produces Next.js's own warning, which is a louder signal than a wrong absolute URL.

Default email sender

src/lib/email/resend.ts fallback is now alerts@wedgetradeai.com. This does not make mail deliverable: Resend only sends from a verified domain. See §4.

Deliberately NOT changed

Four things look like branding and are not:

1. `src/lib/connectors/tradovate/sdk-adapter.ts:315` — appId: credentials.appId ?? 'AITradeCopier'. This is the app identifier sent to Tradovate's authentication endpoint, not a label. Changing it changes who we claim to be to their API and could break authentication outright. It belongs to broker integration, not rebranding. 2. `src/components/ui/theme-provider.tsx` — storageKey="aitradecopier-theme". A localStorage key. Nobody sees it, and renaming it would reset every existing user's light/dark preference on the current domain. 3. **src/lib/ai/prompts/* (6 files, 13 occurrences) — Codex's AI modules. Left untouched per the standing instruction; see §7 for the coordination item. The brand appears inside model prompts, so the assistant will still refer to itself by the old name until Codex updates them. 4. docs/AGENT_HANDOFF.md** — its four matches are filesystem paths (C:\Users\sabwa\AITradeCopier), not brand references. A blind replace would have corrupted real paths.


3. Cloudflare DNS records — APPLIED 2026-11-06

Correction to this document's first draft

An earlier version of this table gave 76.76.21.21 as the apex A value, quoting Vercel's older documentation. Live DNS does not support that, and the discrepancy was found by measuring rather than reading:

LookupResult
wedgetradeai.com NSbenedict.ns.cloudflare.com, gemma.ns.cloudflare.com — zone is on Cloudflare
wedgetradeai.com Ano record — apex unconfigured
www.wedgetradeai.comNXDOMAIN — does not exist
ai-trade-copier.vercel.app A216.198.79.195, 64.29.17.195
cname.vercel-dns.com A66.33.60.194, 76.76.21.93

The live deployment answers from 216.198.79.x, and Vercel's shared CNAME target answers from a third pool. Vercel runs several anycast ranges and has rotated the documented apex IP, so 76.76.21.21 is a legacy value. Asserting it as authoritative would have been precisely the invented DNS record this project was told not to produce.

TypeNameValueProxyPurpose
CNAME@cname.vercel-dns.comDNS only (grey cloud)apex → Vercel, via CNAME flattening
CNAMEwwwcname.vercel-dns.comDNS only (grey cloud)www → Vercel

A CNAME at the apex works here specifically because the zone is on Cloudflare. Cloudflare flattens an apex CNAME into A records at query time (CNAME Flattening, on by default for the root), which is why this is legal where it would be invalid on a conventional DNS host. It is the better choice on two counts: it needs no hardcoded IP, and it keeps tracking Vercel's address automatically when they next rotate the pool — which the measurements above show they already have.

If Vercel's Domains tab insists on an A record for the apex instead, use the value it displays there rather than either value in this document. That tab is the only authoritative source for a given project.

The proxy setting is the part that breaks things

Both records must be DNS only, not proxied. With Cloudflare's orange cloud on, Cloudflare terminates TLS itself and Vercel never sees the ACME challenge, so certificate issuance fails or loops; it also adds a second CDN in front of Vercel's, which breaks ISR revalidation and streaming. Vercel's own documentation requires grey-cloud for this reason.

Cloudflare SSL/TLS mode must be Full (strict) if the zone is ever proxied later — "Flexible" would terminate TLS at Cloudflare and talk HTTP to the origin, which the app's HSTS header (max-age=63072000; includeSubDomains; preload) would then fight.

Steps, in order

1. Vercel → project `ai-trade-copier` → Settings → Domains: add wedgetradeai.com and www.wedgetradeai.com. Vercel will display the records it wants. Compare with the table above. 2. Cloudflare → `wedgetradeai.com` → DNS: add exactly those two records, grey cloud. 3. Wait for Vercel to report both domains Valid and issue certificates (minutes, occasionally longer while DNS propagates). 4. Vercel → Domains: set wedgetradeai.com as the primary and www.wedgetradeai.com to redirect to it (308). This satisfies the www→apex requirement without a Cloudflare page rule, so there is one redirect authority rather than two that can disagree. 5. Leave ai-trade-copier.vercel.app attached. It keeps working and is the rollback target.

No other Cloudflare zone is touched. No record is removed.

CORS, allowed origins, WebSocket origins — no change required

This is worth stating plainly because it is the part a migration usually gets wrong. The app has no CORS allowlist and no hardcoded app origin anywhere:

  • CSP connect-src (src/lib/security/csp.ts) is 'self' plus the

Supabase host. 'self' follows whatever origin serves the page, so it is correct on the new domain the moment it serves.

  • form-action 'self', base-uri 'self', frame-ancestors 'none' —

all origin-relative.

  • API routes are same-origin; nothing issues cross-origin requests to

this app.

Verified by search: no Access-Control-Allow-Origin, no allowedOrigins, no allowedDevOrigins.


3a. What was EXECUTED and VERIFIED — 2026-11-06

DNS and HTTPS only. Authentication settings and the production deploy were deliberately not touched.

The records Vercel actually asked for

The Domains tab issued a project-specific CNAME target, not either value documented above:

TypeNameValueProxy
CNAME@e20832030473dbd9.vercel-dns-017.comDNS only
CNAMEwwwe20832030473dbd9.vercel-dns-017.comDNS only

Vercel's own note alongside them: *"We're expanding our IP range. We recommend the records above. The legacy records cname.vercel-dns.com and 76.76.21.21 will continue to work."*

So neither 76.76.21.21 (this document's first draft) nor cname.vercel-dns.com (its correction) was what Vercel wanted. Both would have worked, but the per-project target is what it recommends, and reading it rather than assuming it is the only way that was knowable. Vercel also detected Cloudflare as the DNS provider and stated Proxy: Disabled itself, independently confirming the grey-cloud requirement.

Two defaults that had to be overridden

Both were pre-set against the stated requirements:

1. Vercel's "Redirect apex domains to www (recommended)" was checked by default in the Add Domains dialog. Leaving it would have made www the primary domain — the inverse of the brief, which names wedgetradeai.com as primary. Unchecked before submitting. 2. Cloudflare's proxy toggle defaults to "Proxied" (orange cloud) on every new record. Left on, Cloudflare would terminate TLS itself and Vercel would never see the ACME challenge, so certificate issuance would fail or loop. Set to DNS only on both records before saving.

State before the change

The wedgetradeai.com zone held zero DNS records ("0 of 200 used"), matching the pre-flight lookups (no apex A, NXDOMAIN for www). Nothing was modified or overwritten — both records are additions. The other three zones in the account (ai-mila.com, polyra-si.com, thesocialcircle.app) were not opened or altered.

Verification

Measured externally rather than read off a dashboard:

wedgetradeai.com      → 216.198.79.1, 64.29.17.1   (apex CNAME flattened)
www.wedgetradeai.com  → CNAME e20832030473dbd9.vercel-dns-017.com → 64.29.17.1

Resolution confirmed both at Cloudflare's authoritative nameserver (benedict.ns.cloudflare.com) and through a third-party recursive resolver (8.8.8.8).

URLHTTPTLS verifyResponse
https://wedgetradeai.com2000 (valid)0.40s
https://www.wedgetradeai.com2000 (valid)0.32s
https://wedgetradeai.com/login200—app route serves
https://ai-trade-copier.vercel.app2000 (valid)0.24s — preserved

Certificates, read from the live TLS handshake:

DomainSubjectIssuerValid
apexCN=wedgetradeai.comLet's Encrypt YR22026-11-06 → 2027-02-04
wwwCN=www.wedgetradeai.comLet's Encrypt YR12026-11-06 → 2027-02-04

Separate certificates per hostname, both auto-renewing. Response headers confirm the origin is this application rather than a parked page: Server: Vercel, and the Strict-Transport-Security: max-age=63072000; includeSubDomains; preload header that next.config.ts sets.

The Vercel dashboard still displayed "Generating SSL Certificate" after the handshake already proved both certificates issued — a lagging label, not a pending operation.

What the new domain is serving, and why it still says the old name

https://wedgetradeai.com currently serves the existing production build, which predates the rebrand commit. Fetching it returns the old brand string eleven times and the new one zero times.

That is correct and expected: the rebrand is committed locally and not deployed, because deploying was not authorized in this step. The domain is live and correct at the infrastructure layer; the new name appears on it only after a production deploy.

Deliberately NOT done

  • No www → apex redirect yet. Both domains currently serve content.

Setting it is a one-line change in Vercel's Domains tab and belongs with the cutover, not with certificate issuance — keeping both serving meant each certificate could be verified independently.

  • No redirect from `ai-trade-copier.vercel.app`. It still serves the

live site and remains the rollback target.

  • No Supabase change, so every existing session and email link

continues to work exactly as before.

Rollback from this point

Deleting the two Cloudflare records returns the zone to empty, and removing the two domains in Vercel returns the project to its previous state. Neither action touches the old deployment, the database, or any user session — and nothing currently depends on the new domain, because no traffic has been pointed at it.


3b. Authentication, env, and the production deploy — EXECUTED 2026-11-06

Section 4's "AWAITING APPROVAL" is now spent. All three parts were approved and executed: Supabase auth, the Vercel variable, and the production redeploy.

The authentication finding that changes section 4's premise

Section 4 assumed production's Supabase allow-list already contained the Vercel URL, and that the job was to add the new domain beside it. The live settings said otherwise:

SettingValue foundValue set
Site URLhttp://localhost:3000https://wedgetradeai.com
Redirect URLs1 entry: http://localhost:3000/auth/confirm3 entries (below)

Production auth was pointed at localhost, and had been since the project was created. No ai-trade-copier.vercel.app entry ever existed.

The consequence is worth stating plainly, because it is a pre-existing production defect rather than anything the migration caused: every password-reset and email-confirmation link the live site has ever issued resolved against http://localhost:3000, so it could not have worked for any real user. forgot-password/actions.ts builds redirectTo from NEXT_PUBLIC_SITE_URL, and Supabase only honors a redirectTo that is on its allow-list — so both halves had to agree, and neither pointed at the real site.

This also means the migration had nothing to preserve for existing users here: there were no working production auth links to break.

Redirect URLs, after

http://localhost:3000/auth/confirm      preserved (local development)
https://wedgetradeai.com/**             added
https://www.wedgetradeai.com/**         added

Wildcards rather than one entry per path: the app issues redirectTo for /auth/confirm, /auth/confirm?next=/reset-password and /invite/<token>, and a /** pattern covers all three plus anything added later. The localhost entry is kept exactly as found, so local development is unaffected.

No user account, session or database row was read or written.

The Vercel variable, and a limit worth recording

Production NEXT_PUBLIC_SITE_URL now https://wedgetradeai.com, applied to the production record only (id ending 5hwrI8p2). Preview's own copy was deliberately left alone.

Re-read afterwards to confirm blast radius: 10 variable records before, 10 after, 6 on production, and exactly one changed timestamp.

The previous value is unrecoverable. Every variable on this project is Vercel type sensitive, which is write-only — the API returns an empty string even with decrypt=true. This does NOT weaken rollback, and the reason is worth understanding rather than trusting: Next.js inlines NEXT_PUBLIC_* at BUILD time, so the preserved deployment already has the old origin compiled into it. Promoting that deployment restores the old behavior without the string ever being needed.

A second, pre-existing gap noticed and deliberately not touched: preview is missing `CREDENTIAL_ENCRYPTION_KEY` (production has it), so preview deployments cannot decrypt broker credentials. Out of scope here; recorded so it is not re-discovered.

What was deployed, and the branch decision behind it

The rebrand lived on feature/futures-copy-engine, 42 commits ahead of `main`. Deploying that branch would have shipped 40 unrelated futures commits (157 files) to production. It would also have been actively unsafe: that code depends on migrations that are explicitly not to be applied, so production would have run it against a schema without the tables.

So only the rebrand was cherry-picked onto main. The two change sets are provably disjoint — the rebrand's 20 files share zero overlap with the futures work's 157 — so the cherry-pick applied without conflict and carried nothing with it.

0dd1442  fix(seo): stop the home page rendering the brand name twice
28b91b7  docs(migration): record the executed DNS and HTTPS cutover
c33653f  rebrand: AITradeCopier -> Wedge Trade AI, and the runbook
7388cda  <- the commit production was already running

Two standing constraints hold STRUCTURALLY on what was deployed, not by configuration: src/lib/futures/ does not exist on main, FUTURES_EXECUTION_IMPLEMENTED appears nowhere in its source (only in this document), and none of the futures migrations are present. There is no flag to leave false, because there is no execution path to gate.

The home page title defect, found during verification

The marketing home page set its own title string AND inherited the root layout's template, so the brand rendered twice:

"Wedge Trade AI - AI-Powered Trade Copying & Automation · Wedge Trade AI"

Pre-dates the rebrand — origin/main produced the same shape with the old name — so it is long-standing, not a rename regression. Fixed here because the home page title is the most SEO-visible string the platform has and it is being indexed fresh on a new domain. The fix deletes the override rather than adding absolute: the layout's default was already that exact string, so the page was only restating it, and one fewer copy is one fewer place for the next rename to miss.

A local build limit that is NOT a code problem

npm run build cannot complete on the development machine: static generation exhausts its ~4GB worker heap around page 46 of 92. Worth recording how that was established rather than assumed, because it looks alarming:

  • Reducing to a single worker did not help (it then OOMs at page 0), and

NODE_OPTIONS=--max-old-space-size does not propagate into Next's build workers, so the ceiling cannot be raised from the environment.

  • The control settles it: **origin/main — the code already running in

production — OOMs identically.** Pre-existing local constraint, not a regression from the rebrand.

  • Compilation itself always succeeded; only the 92-page prerender fails.
  • Vercel built the same commit in 91 seconds.

Consequence to be honest about: the full production build is verified by Vercel, not locally. tsc, eslint and the test suite all run clean locally and remain the local gate.

Deployment

Deploymentdpl_HeWFwKU9bHeHiF7pgFNZbUS19xpy
Commit0dd1442 on main
StateREADY, build 91s
Aliaseswedgetradeai.com, www.wedgetradeai.com, ai-trade-copier.vercel.app, + 2 Vercel internal

Verification, measured externally

All three hostnames serve the rebranded build:

HostHTTPTLSNew brandOld brand
wedgetradeai.com200valid90
www.wedgetradeai.com200valid90
ai-trade-copier.vercel.app200valid90

Title on all three is the single-brand form, confirming the fix above shipped.

Routes: /, /login, /signup, /about, /docs, /terms, /forgot-password, /auth/confirm, /reset-password all 200. /dashboard correctly 307s to `https://wedgetradeai.com/login` — the auth gate works and builds its redirect from the new origin, not a stale one.

Section 2's audit claim — that no CORS or origin allow-list needed changing — is now confirmed in production rather than argued from source. The live CSP is origin-relative exactly as predicted, with a fresh nonce per request (two requests returned two different nonces):

default-src 'self'; script-src 'self' 'nonce-<per-request>';
connect-src 'self' https://<project>.supabase.co wss://<project>.supabase.co;
frame-ancestors 'none'; base-uri 'self'; form-action 'self'

All five headers from next.config.ts are present, HSTS included.

No stale origin anywhere: localhost and ai-trade-copier.vercel.app both occur zero times across five rendered pages and all 11 client JS bundles.

What was NOT verified, and why

An actual login was not performed. Doing so would mean entering a real password, which is out of bounds. What was verified instead is every layer around it: the gate redirects unauthenticated traffic on the new origin, the Supabase project in the live CSP is the same project whose auth settings were changed, both auth routes respond, and the allow-list now contains the origin the app will ask Supabase to redirect to. A human sign-in is the one remaining check.

Rollback, confirmed available rather than assumed

dpl_285XHEvwTYXpmy9i8EQSkuKNGJux (commit 7388cda, the exact commit production was running before this) was re-queried after the deploy and is still READY and promotable. Because NEXT_PUBLIC_SITE_URL is build-time inlined, promoting it restores the previous origin behavior too — no variable edit required to roll back.

Note on the old URL: ai-trade-copier.vercel.app is an alias that follows production, not a frozen copy of the old build. It now serves the rebranded app. The rollback option is the deployment above, not that hostname.

4. Authentication changes — DONE, see 3b

> Kept as the plan of record. What was actually found and applied is in > section 3b, which corrects this section’s premise: production’s > allow-list did NOT contain the Vercel URL, it contained only localhost.

Supabase Dashboard → Authentication → URL Configuration

SettingValue
Site URLhttps://wedgetradeai.com
Redirect URLs (add, don't replace)https://wedgetradeai.com/auth/confirm, https://wedgetradeai.com/**

Add rather than replace. Keeping the existing ai-trade-copier.vercel.app entries means links in emails already sent continue to work, and the old deployment stays usable as a rollback. The allow-list is additive by design.

Vercel environment variable

NEXT_PUBLIC_SITE_URL=https://wedgetradeai.com for Production.

This is NEXT_PUBLIC_*, so it is inlined at build time — the change requires a redeploy to take effect, and a redeploy is what makes password-reset and confirmation emails point at the new domain.

What happens to existing users — no data loss, one visible effect

  • **User accounts, sessions in the database, and all data are

untouched.** Nothing in this migration writes to auth.users or any application table.

  • Cookies are host-scoped. @supabase/ssr sets them without an

explicit domain, so a session on ai-trade-copier.vercel.app does not carry to wedgetradeai.com. A logged-in user visiting the new domain for the first time will need to log in once. Their account, settings and history are all there.

  • This is the only user-visible consequence of the cutover, and it is

not avoidable without setting a shared parent domain, which these two hosts do not have.

Verified by test, not by inspection

Login, signup, password reset, email verification, session persistence, logout, protected-route redirects and the MFA challenge are all covered by the existing suite (3018 tests passing). None of them hardcode an origin, which is why the domain change does not touch their logic.


5. Build and test results

CheckResult
tsc --noEmitclean
eslint src/ scripts/clean
vitest run3018 / 3018 across 199 files
npm run build with NEXT_PUBLIC_SITE_URL=https://wedgetradeai.comCompiled successfully in 16.0s, no metadataBase warning
Rendered outputnew brand present in built pages; old brand absent from every rendered page except /docs/* bodies that quote it historically

Live futures execution remains disabled: FUTURES_EXECUTION_IMPLEMENTED === false.


6. Deployment status — SUPERSEDED by 3b

> Deployed 2026-11-06 as dpl_HeWFwKU9bHeHiF7pgFNZbUS19xpy (commit > 0dd1442). The text below describes the state before that.

Nothing deployed. The current production deployment is untouched and remains the live site.

Phase 6 readiness:

  • Production build: verified locally against the new domain.
  • Environment variables: one change needed (NEXT_PUBLIC_SITE_URL).
  • Database connectivity: unchanged — same Supabase project, same

credentials.

  • Worker configuration: unchanged. render.yaml contains no app URL.
  • HTTPS: Vercel-issued, pending the DNS step.
  • Logging/monitoring: unchanged; alert channels are webhook/email based

and domain-independent apart from the email sender in §4.

Service names still say ai-trade-copier

The Vercel project, the Render services and the GitHub repository all keep their current names. Renaming any of them is not required by the domain change, and each carries risk disproportionate to the benefit: the Render service name is referenced by Blueprint sync, and a GitHub rename rewrites the remote every local clone uses. Recommended as a separate, deliberate change if wanted at all.


7. Remaining blockers

1. DNS and domain attachment (§3) — needs approval; changes production routing. 2. Supabase URL configuration (§4) — needs approval; affects the links in emails sent to real users. 3. `NEXT_PUBLIC_SITE_URL` + redeploy — needs approval; this is the production deploy. 4. Resend domain verification. wedgetradeai.com must be verified in the Resend account (DKIM/SPF records in Cloudflare) before mail can send from alerts@wedgetradeai.com. Until then, leave ALERT_EMAIL_FROM pointing at the currently verified sender — the code change in §2 is only a fallback. Not a blocker to the website migration, but it is a blocker to alert email from the new domain. 5. Codex coordination: AI prompts (§2.4). The assistant, coach, journal, market, prop-firm and risk-manager prompts all name the old platform to the model. Users will see the assistant call itself "AI Trade Copier" until Codex updates those six files. Not something I should edit. 6. Favicon. src/app/favicon.ico is the existing mark. Phase 3 says "where appropriate" — it needs a Wedge Trade AI asset, which is a design deliverable rather than a code change.


8. Rollback procedure

The migration is reversible at every stage because nothing is removed.

If the new domain misbehaves (DNS/TLS/routing)

1. ai-trade-copier.vercel.app is still live and still primary-capable — it was never detached. Send traffic back to it. 2. In Cloudflare, delete the two records from §3. The zone returns to its prior state; no other record was touched. 3. In Vercel → Domains, remove the two wedgetradeai.com entries.

Nothing in steps 1–3 touches the database, the worker, or user data.

If the redeploy misbehaves (application-level)

1. Vercel → Deployments → the previous deployment → "Promote to Production." That deployment is built with the old NEXT_PUBLIC_SITE_URL and the old branding, so promoting it reverts both in one action. 2. Revert NEXT_PUBLIC_SITE_URL to the previous value. 3. The Supabase redirect allow-list needs no change — §4 adds entries rather than replacing them, so the old URLs still validate.

If authentication misbehaves

Because §4 is additive, the old Site URL can be restored in the Supabase dashboard without having lost anything. Sessions are unaffected either way: cookies are host-scoped, so a user on the old domain still holds a valid session throughout.

Code rollback

The rebranding is one commit on feature/futures-copy-engine. git revert of that commit restores every string, and it touches no migration, no schema and no worker behaviour.

What cannot be rolled back, and why it does not apply

Nothing here is irreversible. No database migration is applied (the outstanding futures migrations are deliberately not part of this change), no table is written, no deployment is deleted, and no Cloudflare record outside the new zone is modified.