diff --git a/alchemy.run.ts b/alchemy.run.ts index 4d8b3c9..1732c6d 100644 --- a/alchemy.run.ts +++ b/alchemy.run.ts @@ -9,14 +9,15 @@ // deployment that apps/scout/.env.local selects. // // Each deployment has a client of the identity hub at https://auth.samebase.com, for Google -// sign-in (RFC 134). IdentityHub.Client asks `POST /hub-clients` with the GitHub OIDC token of -// the run (`id-token: write` in alchemy.yml), or on a laptop with the app's initial access token -// that the production registration saved. The hub first reads /samebase-verification.json on the -// callback's site (convex/http.ts), so the code with that route is pushed before the client -// registers, and the client's variables are written after it. Each variable stays on the row that -// owned it before: a Convex.Deployment removes a name that leaves its own `env`, after its push -// when it has one. The push runs apps/scout/scripts/ensure-convex-auth.ts, which sets the off values -// of the client's variables when they are missing, so the code loads before "Site" writes them. +// sign-in (RFC 134). IdentityHub.Client registers with `POST /register` (RFC 7591), sending +// the GitHub OIDC token of the run (`id-token: write` in alchemy.yml), or on a laptop the app's +// initial access token that the production registration saved. The hub first reads +// /samebase-verification.json on the callback's site (convex/http.ts), so the code with that +// route is pushed before the client registers, and the client's variables are written after it. +// Each variable stays on the row that owned it before: a Convex.Deployment removes a name that +// leaves its own `env`, after its push when it has one. The push runs +// apps/scout/scripts/ensure-convex-auth.ts, which sets the off values of the client's variables +// when they are missing, so the code loads before "Site" writes them. import { execFileSync } from "node:child_process"; import { existsSync, readFileSync } from "node:fs"; import { parseEnv } from "node:util"; diff --git a/docs/deploy.md b/docs/deploy.md index ea7a24d..246454e 100644 --- a/docs/deploy.md +++ b/docs/deploy.md @@ -42,11 +42,12 @@ Convex. Stage `prod` mints the account API token `scout production email sending`, with only Email Sending Write, and retains it when the stack is destroyed. See `EMAIL_SETUP.md`. -Google sign-in runs through the identity hub at `https://auth.samebase.com`. Each deployment asks -`POST /hub-clients` for its client with the GitHub OIDC token of the run (`id-token: write`), so -sign-in needs no secret of its own. The hub first reads `/samebase-verification.json` on the -callback's site (`convex/http.ts`). So the stack pushes first (`Push` in production, `Preview` on a -pull request), then registers the client on the Convex site URL plus `/auth/hub/callback`, then +Google sign-in runs through the identity hub at `https://auth.samebase.com`. Each deployment +registers its client with `POST /register`, the client registration request of RFC 7591. It +sends the GitHub OIDC token of the run (`id-token: write`), so sign-in needs no secret of its +own. The hub first reads `/samebase-verification.json` on the callback's site +(`convex/http.ts`). So the stack pushes first (`Push` in production, `Preview` on a pull +request), then registers the client on the Convex site URL plus `/auth/hub/callback`, then `Site` writes `IDENTITY_HUB_ISSUER`, `IDENTITY_HUB_CLIENT_ID`, and `IDENTITY_HUB_CLIENT_SECRET` with no push. Before each push, `apps/scout/scripts/ensure-convex-auth.ts` sets the off value of each of the three that is missing, so the code loads before `Site` writes the client. A deploy fails diff --git a/package.json b/package.json index 68a761e..536d9c9 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@alchemy.run/cloudflare": "2.0.0-beta.85", "@alchemy.run/github": "2.0.0-beta.85", "@effect/platform-node": "4.1.2", - "@samebase/alchemy-convex": "0.39.1", + "@samebase/alchemy-convex": "0.40.0", "@types/node": "^24.19.2", "alchemy": "2.0.0-beta.85", "effect": "4.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b4286ac..2f51582 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -217,8 +217,8 @@ importers: specifier: 4.1.2 version: 4.1.2(effect@4.1.2)(redis@6.3.0) '@samebase/alchemy-convex': - specifier: 0.39.1 - version: 0.39.1(@effect/platform-node@4.1.2(effect@4.1.2)(redis@6.3.0))(alchemy@2.0.0-beta.85(@effect/platform-node@4.1.2(effect@4.1.2)(redis@6.3.0))(@types/react@19.3.0)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(effect@4.1.2)(ws@8.22.0))(convex@1.48.0(react@19.3.1))(effect@4.1.2) + specifier: 0.40.0 + version: 0.40.0(@effect/platform-node@4.1.2(effect@4.1.2)(redis@6.3.0))(alchemy@2.0.0-beta.85(@effect/platform-node@4.1.2(effect@4.1.2)(redis@6.3.0))(@types/react@19.3.0)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(effect@4.1.2)(ws@8.22.0))(convex@1.48.0(react@19.3.1))(effect@4.1.2) '@types/node': specifier: ^24.19.2 version: 24.19.2 @@ -2625,8 +2625,8 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@samebase/alchemy-convex@0.39.1': - resolution: {integrity: sha512-KpCa1mMjO7I/K9kKvJS3Ftg3fPMn9XGU1NFU0mUdCfB+UojD0WpHL1/lSQC7zUYE8oO5TCYAcHyKTvzLr+91hg==} + '@samebase/alchemy-convex@0.40.0': + resolution: {integrity: sha512-pNqA0ePSFi88DM6BiG2bAdwgzpdowOL4XN6VqbnH8UTdd1HP/JuLCY+uKFn0IGBynUAqADfc/bVXdWmADFZ3vw==} engines: {node: '>=22'} hasBin: true peerDependencies: @@ -4097,8 +4097,8 @@ packages: fast-xml-builder@1.3.1: resolution: {integrity: sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==} - fast-xml-parser@5.11.2: - resolution: {integrity: sha512-R9iDuNrQYeQut46cn2r2wHKn4HYzVDvDm5J1wW+koZewykv0yuO2HChTYeZtrULyHIDM9cj9TUXloCsueCQUog==} + fast-xml-parser@5.12.0: + resolution: {integrity: sha512-/pXxRBtwxY9w8z7YbgsvIPPcPvFDsTbIkWwTQJhzNJPokj+TbN6ftmcv4j/pEQDvOCNnKGDzuk5Bo2oogIOiFg==} hasBin: true fastq@1.20.3: @@ -4421,8 +4421,8 @@ packages: resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} engines: {node: '>=18'} - is-unsafe@2.0.2: - resolution: {integrity: sha512-HgbIHPBH0KHHCcjLfGsCvhtPTVxjaAZlXjwdz7/GQC40SjSe4sfQsar8J5VFo8JOSbarkpV0OLG95bbaNd9aAQ==} + is-unsafe@2.0.3: + resolution: {integrity: sha512-ZBllczCCO267vgdFb6Tq3pv+LhHaCiGMdr+ZsuL+OopruAg7S+3ZDs1vD0RPC0uSrkjzbraxaGjtX1YBxjPeFQ==} is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} @@ -8221,7 +8221,7 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} - '@samebase/alchemy-convex@0.39.1(@effect/platform-node@4.1.2(effect@4.1.2)(redis@6.3.0))(alchemy@2.0.0-beta.85(@effect/platform-node@4.1.2(effect@4.1.2)(redis@6.3.0))(@types/react@19.3.0)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(effect@4.1.2)(ws@8.22.0))(convex@1.48.0(react@19.3.1))(effect@4.1.2)': + '@samebase/alchemy-convex@0.40.0(@effect/platform-node@4.1.2(effect@4.1.2)(redis@6.3.0))(alchemy@2.0.0-beta.85(@effect/platform-node@4.1.2(effect@4.1.2)(redis@6.3.0))(@types/react@19.3.0)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(effect@4.1.2)(ws@8.22.0))(convex@1.48.0(react@19.3.1))(effect@4.1.2)': dependencies: '@convex-dev/platform': 0.1.11 '@effect/platform-node': 4.1.2(effect@4.1.2)(redis@6.3.0) @@ -9584,11 +9584,11 @@ snapshots: path-expression-matcher: 1.6.2 xml-naming: 0.3.0 - fast-xml-parser@5.11.2: + fast-xml-parser@5.12.0: dependencies: '@nodable/entities': 3.1.0 fast-xml-builder: 1.3.1 - is-unsafe: 2.0.2 + is-unsafe: 2.0.3 path-expression-matcher: 1.6.2 strnum: 2.5.1 xml-naming: 0.3.0 @@ -9890,7 +9890,7 @@ snapshots: is-unicode-supported@2.1.0: {} - is-unsafe@2.0.2: {} + is-unsafe@2.0.3: {} is-wsl@2.2.0: dependencies: @@ -9939,7 +9939,7 @@ snapshots: just-bash@3.6.0: dependencies: diff: 8.0.4 - fast-xml-parser: 5.11.2 + fast-xml-parser: 5.12.0 file-type: 21.3.4 guarded-fetch: 0.1.3 ini: 6.0.0