Unified · Split
| @@ -29,9 +29,9 @@ jobs: · 28 unmodified lines | ||
| 29 | 29 | PLANETSCALE_ORGANIZATION: ${{ vars.PLANETSCALE_ORGANIZATION }} |
| 30 | 30 | AXIOM_TOKEN: ${{ secrets.AXIOM_TOKEN }} |
| 31 | 31 | AXIOM_ORG_ID: ${{ vars.AXIOM_ORG_ID }} |
| 32 | − T3CODE_RELAY_DOMAIN: ${{ vars.T3CODE_RELAY_DOMAIN }} | |
| 33 | − T3CODE_RELAY_ZONE_NAME: ${{ vars.T3CODE_RELAY_ZONE_NAME }} | |
| 34 | − T3CODE_CLERK_PUBLISHABLE_KEY: ${{ vars.T3CODE_CLERK_PUBLISHABLE_KEY }} | |
| 32 | + RELAY_DOMAIN: ${{ vars.RELAY_DOMAIN }} | |
| 33 | + RELAY_ZONE_NAME: ${{ vars.RELAY_ZONE_NAME }} | |
| 34 | + CLERK_PUBLISHABLE_KEY: ${{ vars.CLERK_PUBLISHABLE_KEY }} | |
| 35 | 35 | CLERK_SECRET_KEY: ${{ secrets.CLERK_SECRET_KEY }} |
| 36 | 36 | APNS_ENVIRONMENT: ${{ vars.APNS_ENVIRONMENT }} |
| 37 | 37 | APNS_TEAM_ID: ${{ vars.APNS_TEAM_ID }} |
| @@ -178,8 +178,8 @@ jobs: · 177 unmodified lines | ||
| 178 | 178 | clerk_publishable_key: ${{ steps.public_config.outputs.clerk_publishable_key }} |
| 179 | 179 | relay_url: ${{ steps.public_config.outputs.relay_url }} |
| 180 | 180 | env: |
| 181 | − T3CODE_RELAY_DOMAIN: ${{ vars.T3CODE_RELAY_DOMAIN }} | |
| 182 | − T3CODE_CLERK_PUBLISHABLE_KEY: ${{ vars.T3CODE_CLERK_PUBLISHABLE_KEY }} | |
| 181 | + RELAY_DOMAIN: ${{ vars.RELAY_DOMAIN }} | |
| 182 | + CLERK_PUBLISHABLE_KEY: ${{ vars.CLERK_PUBLISHABLE_KEY }} | |
| 183 | 183 | steps: |
| 184 | 184 | - id: public_config |
| 185 | 185 | name: Resolve production relay public config |
| @@ -188,8 +188,8 @@ jobs: · 2 unmodified lines | ||
| 188 | 188 | set -euo pipefail |
| 189 | 189 | |
| 190 | 190 | required=( |
| 191 | − T3CODE_RELAY_DOMAIN | |
| 192 | − T3CODE_CLERK_PUBLISHABLE_KEY | |
| 191 | + RELAY_DOMAIN | |
| 192 | + CLERK_PUBLISHABLE_KEY | |
| 193 | 193 | ) |
| 194 | 194 | missing=() |
| 195 | 195 | for name in "${required[@]}"; do |
| @@ -202,8 +202,8 @@ jobs: · 6 unmodified lines | ||
| 202 | 202 | exit 1 |
| 203 | 203 | fi |
| 204 | 204 | |
| 205 | − echo "clerk_publishable_key=$T3CODE_CLERK_PUBLISHABLE_KEY" >> "$GITHUB_OUTPUT" | |
| 206 | − echo "relay_url=https://$T3CODE_RELAY_DOMAIN" >> "$GITHUB_OUTPUT" | |
| 205 | + echo "clerk_publishable_key=$CLERK_PUBLISHABLE_KEY" >> "$GITHUB_OUTPUT" | |
| 206 | + echo "relay_url=https://$RELAY_DOMAIN" >> "$GITHUB_OUTPUT" | |
| 207 | 207 | |
| 208 | 208 | build: |
| 209 | 209 | name: Build ${{ matrix.label }} |
| @@ -56,10 +56,10 @@ Required repository secrets shared by relay deployments: · 55 unmodified lines | ||
| 56 | 56 | |
| 57 | 57 | Required `production` environment variables: |
| 58 | 58 | |
| 59 | −- `T3CODE_RELAY_DOMAIN` | |
| 60 | −- `T3CODE_RELAY_ZONE_NAME` | |
| 61 | −- `T3CODE_CLERK_PUBLISHABLE_KEY` | |
| 62 | −- `T3CODE_CLERK_CLI_OAUTH_CLIENT_ID` | |
| 59 | +- `RELAY_DOMAIN` | |
| 60 | +- `RELAY_ZONE_NAME` | |
| 61 | +- `CLERK_PUBLISHABLE_KEY` | |
| 62 | +- `CLERK_CLI_OAUTH_CLIENT_ID` | |
| 63 | 63 | - `APNS_ENVIRONMENT` |
| 64 | 64 | - `APNS_TEAM_ID` |
| 65 | 65 | - `APNS_KEY_ID` |
| @@ -34,11 +34,11 @@ client-facing values in their EAS environment. · 33 unmodified lines | ||
| 34 | 34 | When either public value is absent, cloud UI is omitted. |
| 35 | 35 | |
| 36 | 36 | For a hosted relay deployment, copy `infra/relay/.env.example` to `infra/relay/.env`. The relay |
| 37 | −deployment reads `T3CODE_RELAY_DOMAIN`, `T3CODE_RELAY_ZONE_NAME`, and | |
| 38 | −`T3CODE_CLERK_PUBLISHABLE_KEY` through Effect `Config`. There are no checked-in deployment defaults. | |
| 37 | +deployment reads `RELAY_DOMAIN`, `RELAY_ZONE_NAME`, and `CLERK_PUBLISHABLE_KEY` through Effect | |
| 38 | +`Config`. There are no checked-in deployment defaults. | |
| 39 | 39 | `bun --cwd infra/relay run deploy` invokes Alchemy from the relay directory, so Alchemy loads |
| 40 | 40 | `infra/relay/.env`. After a successful deployment, the wrapper updates the repository-root `.env` |
| 41 | −with the HTTPS relay URL derived from `T3CODE_RELAY_DOMAIN`. The relay still requires | |
| 41 | +with the HTTPS relay URL derived from `RELAY_DOMAIN`. The relay still requires | |
| 42 | 42 | `CLERK_SECRET_KEY` as an Alchemy secret. Never put `CLERK_SECRET_KEY` in a client application |
| 43 | 43 | environment or commit it to the repository. |
| 44 | 44 | |
| @@ -56,7 +56,7 @@ In **Clerk Dashboard > JWT templates**, create a template with: · 11 unmodified lines | ||
| 56 | 56 | | Claims | `{ "aud": "https://relay.example.com" }` | |
| 57 | 57 | |
| 58 | 58 | The `aud` value must be the deployed relay public URL, with no trailing slash. It must match the |
| 59 | −client-facing `T3CODE_RELAY_URL` and the HTTPS URL derived from the deployment's `T3CODE_RELAY_DOMAIN`. If | |
| 59 | +client-facing `T3CODE_RELAY_URL` and the HTTPS URL derived from the deployment's `RELAY_DOMAIN`. If | |
| 60 | 60 | the relay domain changes, update both values and the JWT template. |
| 61 | 61 | |
| 62 | 62 | ## Desktop OAuth Redirect Allowlist |
| @@ -1,15 +1,15 @@ | ||
| 1 | 1 | # Required: Relay domain |
| 2 | 2 | # Use the DNS zone managed in your Cloudflare account. Production deploys use |
| 3 | 3 | # relay.<zone>; personal stages use relay-<stage>.<zone>. |
| 4 | −T3CODE_RELAY_ZONE_NAME=example.com | |
| 4 | +RELAY_ZONE_NAME=example.com | |
| 5 | 5 | |
| 6 | 6 | # Optional: Relay domain override |
| 7 | 7 | # Set this only when the derived relay hostname should not be used. |
| 8 | −# T3CODE_RELAY_DOMAIN=relay.example.com | |
| 8 | +# RELAY_DOMAIN=relay.example.com | |
| 9 | 9 | |
| 10 | 10 | # Required: Clerk |
| 11 | 11 | # Get both values from the Clerk Dashboard under API keys. |
| 12 | −T3CODE_CLERK_PUBLISHABLE_KEY=pk_test_... | |
| 12 | +CLERK_PUBLISHABLE_KEY=pk_test_... | |
| 13 | 13 | CLERK_SECRET_KEY=sk_test_... |
| 14 | 14 | |
| 15 | 15 | # Required: Apple Push Notification service |
| @@ -100,8 +100,8 @@ bun --cwd infra/relay run deploy -- --env-file .env.local · 99 unmodified lines | ||
| 100 | 100 | |
| 101 | 101 | Alchemy defaults personal deployments to the `dev_$USER` stage. Relay custom domains apply the same |
| 102 | 102 | DNS-safe sanitization as Alchemy physical resource names, so `prod` uses |
| 103 | −`relay.<T3CODE_RELAY_ZONE_NAME>` and `dev_julius` uses `relay-dev-julius.<T3CODE_RELAY_ZONE_NAME>`. | |
| 104 | −`T3CODE_RELAY_DOMAIN` remains available as an explicit override. | |
| 103 | +`relay.<RELAY_ZONE_NAME>` and `dev_julius` uses `relay-dev-julius.<RELAY_ZONE_NAME>`. | |
| 104 | +`RELAY_DOMAIN` remains available as an explicit override. | |
| 105 | 105 | |
| 106 | 106 | After a successful deploy, the wrapper updates the repository-root `.env` file with the derived relay |
| 107 | 107 | URL. That makes subsequent source builds point at the relay that was just deployed without copying |
| @@ -130,9 +130,9 @@ The repository must define these Actions secrets shared by relay deployments: · 22 unmodified lines | ||
| 130 | 130 | |
| 131 | 131 | The `production` GitHub environment must define these Actions variables: |
| 132 | 132 | |
| 133 | −- `T3CODE_RELAY_ZONE_NAME` | |
| 134 | −- `T3CODE_RELAY_DOMAIN` if overriding the derived production relay domain | |
| 135 | −- `T3CODE_CLERK_PUBLISHABLE_KEY` | |
| 133 | +- `RELAY_ZONE_NAME` | |
| 134 | +- `RELAY_DOMAIN` if overriding the derived production relay domain | |
| 135 | +- `CLERK_PUBLISHABLE_KEY` | |
| 136 | 136 | - `APNS_ENVIRONMENT` |
| 137 | 137 | - `APNS_TEAM_ID` |
| 138 | 138 | - `APNS_KEY_ID` |
| @@ -129,7 +129,7 @@ export default class Api extends Cloudflare.Worker<Api>()( · 128 unmodified lines | ||
| 129 | 129 | const axiomTracesEndpoint = yield* observability.traces.otelTracesEndpoint; |
| 130 | 130 | |
| 131 | 131 | const clerkSecretKey = yield* Config.redacted("CLERK_SECRET_KEY"); |
| 132 | − const clerkPublishableKey = yield* Config.string("T3CODE_CLERK_PUBLISHABLE_KEY"); | |
| 132 | + const clerkPublishableKey = yield* Config.string("CLERK_PUBLISHABLE_KEY"); | |
| 133 | 133 | |
| 134 | 134 | const cloudMintPrivateKey = yield* cloudMintKeyPair.privateKey; |
| 135 | 135 | const cloudMintPublicKey = yield* cloudMintKeyPair.publicKey; |
| @@ -0,0 +1,50 @@ | ||
| 1 | +import * as Alchemy from "alchemy"; | |
| 2 | +import * as ConfigProvider from "effect/ConfigProvider"; | |
| 3 | +import * as Effect from "effect/Effect"; | |
| 4 | +import * as Layer from "effect/Layer"; | |
| 5 | +import { describe, expect, it } from "vitest"; | |
| 6 | + | |
| 7 | +import { RelayDeploymentConfig } from "./zone.ts"; | |
| 8 | + | |
| 9 | +function resolveRelayDeploymentConfig(env: Record<string, string>, stage = "prod") { | |
| 10 | + return Effect.runPromise( | |
| 11 | + RelayDeploymentConfig.pipe( | |
| 12 | + Effect.provide( | |
| 13 | + Layer.mergeAll( | |
| 14 | + Layer.succeed(Alchemy.Stage, stage), | |
| 15 | + ConfigProvider.layer(ConfigProvider.fromEnv({ env })), | |
| 16 | + ), | |
| 17 | + ), | |
| 18 | + ), | |
| 19 | + ); | |
| 20 | +} | |
| 21 | + | |
| 22 | +describe("RelayDeploymentConfig", () => { | |
| 23 | + it("derives the relay domain from the unprefixed zone name", async () => { | |
| 24 | + await expect(resolveRelayDeploymentConfig({ RELAY_ZONE_NAME: "example.com" })).resolves.toEqual( | |
| 25 | + { | |
| 26 | + stage: "prod", | |
| 27 | + relayPublicDomain: "relay.example.com", | |
| 28 | + relayPublicOrigin: "https://relay.example.com", | |
| 29 | + managedEndpointZoneName: "example.com", | |
| 30 | + }, | |
| 31 | + ); | |
| 32 | + }); | |
| 33 | + | |
| 34 | + it("uses the unprefixed relay domain override", async () => { | |
| 35 | + await expect( | |
| 36 | + resolveRelayDeploymentConfig( | |
| 37 | + { | |
| 38 | + RELAY_ZONE_NAME: "example.com", | |
| 39 | + RELAY_DOMAIN: "relay.custom.example", | |
| 40 | + }, | |
| 41 | + "dev_julius", | |
| 42 | + ), | |
| 43 | + ).resolves.toEqual({ | |
| 44 | + stage: "dev_julius", | |
| 45 | + relayPublicDomain: "relay.custom.example", | |
| 46 | + relayPublicOrigin: "https://relay.custom.example", | |
| 47 | + managedEndpointZoneName: "example.com", | |
| 48 | + }); | |
| 49 | + }); | |
| 50 | +}); | |
| @@ -9,8 +9,8 @@ import { relayPublicDomainForStage } from "./deploymentConfig.ts"; · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | export const RelayDeploymentConfig = Effect.gen(function* () { |
| 11 | 11 | const stage = yield* Alchemy.Stage; |
| 12 | − const managedEndpointZoneName = yield* Config.nonEmptyString("T3CODE_RELAY_ZONE_NAME"); | |
| 13 | − const relayPublicDomainOverride = yield* Config.nonEmptyString("T3CODE_RELAY_DOMAIN").pipe( | |
| 12 | + const managedEndpointZoneName = yield* Config.nonEmptyString("RELAY_ZONE_NAME"); | |
| 13 | + const relayPublicDomainOverride = yield* Config.nonEmptyString("RELAY_DOMAIN").pipe( | |
| 14 | 14 | Config.option, |
| 15 | 15 | ); |
| 16 | 16 | const relayPublicDomain = Option.getOrElse(relayPublicDomainOverride, () => |