docs(auth): correct the claim that QA could never run Google sign-in
Linting / lint (pull_request) Successful in 3m44s
SonarQube Analysis / sonarqube (pull_request) Failing after 28m29s

It can, and it does. Registering the QA callback under Authorized redirect URIs was all it took.

The claim was that qa-redefined-designs.bermudalamb.synology.me could never be registered, because Google requires a redirect URI's host to sit under a domain whose ownership has been proved by DNS, and Synology owns the domain above that one. It was inferred from #285, where Cloudflare's free tier genuinely cannot be applied to that hostname, and asserted with far more confidence than the inference supported. What was actually established is narrower: localhost is exempt from the authorized-domain rules, and a domain listed as an authorized domain has to be verified in Search Console. Whether either applied here was never checked.

It was not a harmless error. On the strength of it, QA testing of this feature was documented as blocked behind #313, the QA compose file hardcoded its credentials to empty rather than reading the stack, #345 recorded it as a constraint, and #332 closed with it written into the summary. A QA deploy was spent on it.

So the correction is left in place rather than the wrong sentences quietly deleted. A document that silently stops saying something teaches nobody why it said it, and this is the second time in this feature that a confident inference about somebody else's platform has cost a day — the first being the assumption that a passing local build said anything about another machine.

What replaces it is the thing that was always true and never written down plainly: every environment sends a redirect URI derived from its own PUBLIC_URL, and each one has to exist verbatim in the console. There is now one table listing all four, including the localhost:5173 entry that local development needs and that Phase 0 originally omitted — the omission that cost an hour of redirect_uri_mismatch before any of this.

The QA compose comment now says which URL to register rather than why it cannot be. The ops document gains the steps QA actually took, in order, with a note on why registering before setting the variables is the order that matters: a button that appears before its callback exists fails at Google, where nothing in the storefront logs explains it.

Verified: backend tsc clean, the QA compose file still parses, and no file in the tree still claims the hostname is unusable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
synAdmin
2026-09-11 14:48:46 -05:00
co-authored by Claude Opus 5
parent c9dccfe4a2
commit f5a29127fb
3 changed files with 92 additions and 60 deletions
+52 -28
View File
@@ -18,33 +18,42 @@ screen, so what appears there is the production identity even while testing.
| Data Access | Exactly `openid`, `email`, `profile` |
| Verification Center | Nothing to submit, and it should stay that way |
## The constraint that shapes everything
## Redirect URIs, one per environment
**Google refuses a redirect URI whose host is not under an authorized domain,
and a domain can only be authorized after ownership is proved by DNS in Search
Console.** `localhost` is the only exemption.
Every environment sends a redirect URI derived from its own `PUBLIC_URL`, and
each one has to exist verbatim under **Authorized redirect URIs** on the client
this app uses. Google compares them as strings and answers a mismatch with
`redirect_uri_mismatch`, which is accurate and says nothing about which half is
wrong.
`qa-redefined-designs.bermudalamb.synology.me` therefore cannot ever be used:
Synology owns the registrable domain above it, so there is no record to add and
nothing to prove. This is the same wall #285 hit with Cloudflare.
The consequence, stated plainly because it changes how the feature is worked on:
| Environment | Google sign-in |
| Environment | Redirect URI |
| --- | --- |
| Local, on `localhost` | Works, by exemption |
| QA on the Synology hostname | **Impossible**, not merely unconfigured |
| QA on `qa.redefined-designs.com` | Works, after the cutover |
| Production on `redefined-designs.com` | Works, after the cutover |
| Local, Vite dev server | `http://localhost:5173/api/auth/google/callback` |
| Local, backend serving a build | `http://localhost:3000/api/auth/google/callback` |
| QA | `https://qa-redefined-designs.bermudalamb.synology.me/api/auth/google/callback` |
| Production | `https://redefined-designs.com/api/auth/google/callback` |
So this feature is built and exercised locally, and QA cannot see it at all
until QA moves onto a subdomain of the real domain. The Search Console property
for `redefined-designs.com` already covers `qa.redefined-designs.com`, because
a Domain property covers every subdomain.
Local development needs the 5173 entry, because that is where the dev server
serves the app. The 3000 one applies only when the backend serves a built
frontend, which local development does not produce.
`docker-compose.qa.yml` sets both credentials to empty deliberately, with a
comment saying so, and the storefront then offers no button rather than one that
fails at Google.
### A correction
An earlier version of this document said the QA hostname **could never be
registered**, because it sits under a domain Synology owns rather than one we
do. That was wrong. Adding the URI works.
The claim is recorded here rather than quietly removed, because of what it
cost. It was inferred from #285, where Cloudflare genuinely cannot be applied to
that hostname, and asserted with far more confidence than the inference
supported. On the strength of it, QA testing of Google sign-in was documented as
blocked behind #313, the QA compose file hardcoded its credentials to empty, and
two issues recorded it as fact.
What is true, and is all that was ever established: `localhost` is exempt from
the authorized-domain rules, and a domain listed as an authorized domain has to
be verified in Search Console. Whether either of those actually applied to this
hostname, and how, was never checked.
## Scopes, and why publishing needs no review
@@ -60,20 +69,35 @@ walkthrough and a wait measured in weeks.** Nothing in this feature needs one.
Uploading an app logo also triggers a brand review, which is why Branding has
none.
## Turning it on in QA
Already done, and recorded here because the order matters.
1. Register the QA callback under **Clients**, Authorized redirect URIs:
`https://qa-redefined-designs.bermudalamb.synology.me/api/auth/google/callback`
2. Set `QA_GOOGLE_CLIENT_ID` and `QA_GOOGLE_CLIENT_SECRET` on the QA stack. Both
or neither — the backend refuses to start on one without the other, because
the failure would otherwise arrive the moment a customer presses the button.
3. Redeploy.
Registering first is the point. Setting the variables makes the button appear,
and a button that appears before its callback exists fails at Google rather than
in the storefront, where nothing in the logs explains it.
## The cutover checklist, for #313
1. Point QA at `qa.redefined-designs.com` and set its `PUBLIC_URL` to match.
2. Set `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` in the QA stack. Both or
neither — the backend refuses to start on one without the other, because the
failure would otherwise arrive the moment a customer presses the button.
3. In **Clients**, add the QA callback:
2. In **Clients**, add the new QA callback:
`https://qa.redefined-designs.com/api/auth/google/callback`
4. Confirm the production callback is registered:
3. Confirm the production callback is registered:
`https://redefined-designs.com/api/auth/google/callback`
5. In **Audience**, move the publishing status from Testing to **In production**.
4. In **Audience**, move the publishing status from Testing to **In production**.
Do it once the domain resolves, so the home page and privacy links Google
shows actually answer.
The old QA callback can be left registered until the hostname is retired. An
extra entry costs nothing and removing it early breaks QA for no gain.
No code changes at any step. The redirect URI is derived from `PUBLIC_URL`, so
the environment variable and the console entry are the whole of it.