From 92982a22924bdc6594b9269ef1ab1b256ae35e62 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Mon, 13 Jul 2026 02:54:24 -0700 Subject: [PATCH] feat(loopover): flip PUBLIC_API_ORIGIN to api.loopover.ai Closes #4765. Completes the domain flip started in the earlier PUBLIC_SITE_ORIGIN change: this was deliberately deferred pending confirmation that the GitHub OAuth callback URL was updated on GitHub's side, since flipping this changes the redirect_uri sent during login. Confirmed and executed: the classic OAuth App behind GITHUB_OAUTH_CLIENT_ID (used for dashboard web login and the MCP CLI's device-flow login) only supports a single registered callback URL (unlike a GitHub App's up-to-10), so this had to be a hard cutover -- the OAuth App's callback URL was updated directly to https://api.loopover.ai/v1/auth/github/callback on GitHub's side in lockstep with this change. The old gittensory-api.aethereal.dev domain stays live and routed to the same Worker (both routes already present in wrangler.jsonc's routes array from the earlier Step 1 domain-wiring work) and stays in the CORS allowlist -- added it to DEFAULT_CORS_ORIGINS statically, since PUBLIC_API_ORIGIN's dynamic CORS addition now only covers the new domain. No redirect, no sunset date; only which domain this instance treats as canonical for outbound URL construction (redirect_uri, ORB_BROKER_URL default, etc.) has flipped. ## Test plan - [x] Full local gate (`npm run test:ci` + `npm audit --audit-level=moderate`) green. - [x] Fixed the one real assertion depending on the old default: the redirect_uri built during startGitHubWebOAuth in test/unit/auth.test.ts (env.PUBLIC_API_ORIGIN always wins over the requestUrl argument passed to that function, so every other gittensory-api.aethereal.dev mention in that file is arbitrary fixture input, unaffected). - [x] Fixed a CORS preflight test that exercised exactly the static-list gap this PR closes. --- docker-compose.yml | 2 +- src/api/routes.ts | 4 ++++ test/helpers/d1.ts | 2 +- test/unit/auth.test.ts | 2 +- worker-configuration.d.ts | 4 ++-- wrangler.jsonc | 9 ++++++++- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index d3cb984346..e446b6c439 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -139,7 +139,7 @@ services: # BROKERED mode — use the central Gittensory Orb App instead of creating your own GitHub App. Install the # Orb App on your repos + set ORB_ENROLLMENT_SECRET in .env (loaded above); the engine then brokers # short-lived GitHub tokens from the Orb on demand (no own App private key). See .env.example. - # ORB_BROKER_URL: https://gittensory-api.aethereal.dev # override only for a private Orb deployment + # ORB_BROKER_URL: https://api.loopover.ai # override only for a private Orb deployment volumes: - loopover-data:/data # Container-private per-repo config dir (read-only). Create ./gittensory-config/{owner}__{repo}/.gittensory.yml diff --git a/src/api/routes.ts b/src/api/routes.ts index a8ef612eef..dbc436c534 100644 --- a/src/api/routes.ts +++ b/src/api/routes.ts @@ -5702,6 +5702,10 @@ function requiresApiToken(path: string): boolean { const DEFAULT_CORS_ORIGINS = [ "https://loopover.ai", "https://gittensory.aethereal.dev", + // LoopOver rebrand (#4765): PUBLIC_API_ORIGIN's dynamic addition below now only covers api.loopover.ai + // (the new default), so the old API domain needs to stay allowed here statically for backward compat, + // same as the site origin above. + "https://gittensory-api.aethereal.dev", "http://localhost:3000", "http://localhost:4173", "http://localhost:5173", diff --git a/test/helpers/d1.ts b/test/helpers/d1.ts index 49facb83b8..9d7f3dbfc7 100644 --- a/test/helpers/d1.ts +++ b/test/helpers/d1.ts @@ -88,7 +88,7 @@ export function createTestEnv(overrides: Partial = {}): Env { GITTENSOR_REGISTRY_URL: "https://raw.githubusercontent.com/entrius/gittensor/test/gittensor/validator/weights/master_repositories.json", GITTENSORY_AUTO_FILE_DRIFT_ISSUES: "false", GITTENSORY_DRIFT_ISSUE_REPO: "JSONbored/gittensory", - PUBLIC_API_ORIGIN: "https://gittensory-api.aethereal.dev", + PUBLIC_API_ORIGIN: "https://api.loopover.ai", PUBLIC_SITE_ORIGIN: "https://loopover.ai", INTERNAL_JOB_TOKEN: "dev-internal-token", GITTENSORY_API_TOKEN: "test-api-token", diff --git a/test/unit/auth.test.ts b/test/unit/auth.test.ts index abe6e40705..673bf94f16 100644 --- a/test/unit/auth.test.ts +++ b/test/unit/auth.test.ts @@ -637,7 +637,7 @@ describe("private-beta auth and rate limiting", () => { expect(started.returnTo).toBe("https://loopover.ai/app/workbench"); expect(started.authorizationUrl).toContain("https://github.com/login/oauth/authorize"); expect(started.authorizationUrl).toContain("client_id=client-id"); - expect(started.authorizationUrl).toContain("redirect_uri=https%3A%2F%2Fgittensory-api.aethereal.dev%2Fv1%2Fauth%2Fgithub%2Fcallback"); + expect(started.authorizationUrl).toContain("redirect_uri=https%3A%2F%2Fapi.loopover.ai%2Fv1%2Fauth%2Fgithub%2Fcallback"); await expect( startGitHubWebOAuth(createTestEnv({ GITHUB_OAUTH_CLIENT_ID: "client-id" }), "https://gittensory-api.aethereal.dev/v1/auth/github/start", undefined), diff --git a/worker-configuration.d.ts b/worker-configuration.d.ts index f02444525f..cc6a761707 100644 --- a/worker-configuration.d.ts +++ b/worker-configuration.d.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types` (hash: eaba2a08cc6397ed08020b695340552a) +// Generated by Wrangler by running `wrangler types` (hash: 9896bc2c8e8ee38acb14d18a753667a1) // Runtime types generated with workerd@1.20260701.1 2026-05-28 nodejs_compat interface __BaseEnv_Env { REVIEW_AUDIT: R2Bucket; @@ -14,7 +14,7 @@ interface __BaseEnv_Env { SCORING_TIME_DECAY_ENABLED: "true"; GITTENSORY_AUTO_FILE_DRIFT_ISSUES: "false"; GITTENSORY_DRIFT_ISSUE_REPO: "JSONbored/gittensory"; - PUBLIC_API_ORIGIN: "https://gittensory-api.aethereal.dev"; + PUBLIC_API_ORIGIN: "https://api.loopover.ai"; PUBLIC_SITE_ORIGIN: "https://loopover.ai"; PUBLIC_SITE_ORIGIN_ALIASES: "https://gittensory.aethereal.dev"; ADMIN_GITHUB_LOGINS: "JSONbored"; diff --git a/wrangler.jsonc b/wrangler.jsonc index 4ca8b437cc..f1ea24a845 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -38,11 +38,18 @@ "SCORING_TIME_DECAY_ENABLED": "true", "GITTENSORY_AUTO_FILE_DRIFT_ISSUES": "false", "GITTENSORY_DRIFT_ISSUE_REPO": "JSONbored/gittensory", - "PUBLIC_API_ORIGIN": "https://gittensory-api.aethereal.dev", // LoopOver rebrand (issue #4765, domain flip): loopover.ai is now the canonical site origin. The old // gittensory.aethereal.dev domain stays live (still resolves, still valid as a post-OAuth-login redirect // target via PUBLIC_SITE_ORIGIN_ALIASES below) -- no redirect rule, no sunset date, both domains keep // working side by side; only which one this instance treats as canonical has flipped. + // + // PUBLIC_API_ORIGIN flipped here too (previously deferred): it builds this Worker's own GitHub OAuth + // redirect_uri (githubOAuthCallbackUrl, src/auth/github-oauth.ts). The classic OAuth App behind + // GITHUB_OAUTH_CLIENT_ID only supports ONE registered callback URL (unlike a GitHub App's up-to-10), so + // this had to be a hard cutover in lockstep with updating that OAuth App's callback URL to + // https://api.loopover.ai/v1/auth/github/callback on GitHub's side -- no dual-domain transition window + // was possible for this one value the way PUBLIC_SITE_ORIGIN got above. + "PUBLIC_API_ORIGIN": "https://api.loopover.ai", "PUBLIC_SITE_ORIGIN": "https://loopover.ai", "PUBLIC_SITE_ORIGIN_ALIASES": "https://gittensory.aethereal.dev", "ADMIN_GITHUB_LOGINS": "JSONbored",