Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a7eaf4d
add managed relay tunnels and standards-based auth
juliusmarminge Jun 1, 2026
d0342f8
refactor relay/
juliusmarminge Jun 1, 2026
8737199
Update relay for Alchemy beta.48 and Cloudflare bindings
juliusmarminge Jun 1, 2026
e59b54c
Refactor relay bindings for Alchemy Cloudflare integration
juliusmarminge Jun 1, 2026
188c763
Flatten relay worker layer graph and managed endpoint bindings
juliusmarminge Jun 1, 2026
34d558e
Simplify Cloudflare zone resource mapping
juliusmarminge Jun 1, 2026
3036815
fmt
juliusmarminge Jun 1, 2026
6ed8c21
renames
juliusmarminge Jun 1, 2026
04b1ee0
chore: update alchemy package to version 2.0.0-beta.49
juliusmarminge Jun 1, 2026
5e89744
rename
juliusmarminge Jun 1, 2026
23f72f2
feat(cloud): integrate relay environments and notification settings
juliusmarminge Jun 1, 2026
7660374
refactor(cloud): retain relay queries with atoms
juliusmarminge Jun 2, 2026
7411bfb
fix(mobile): refresh cloud environment credentials on reconnect
juliusmarminge Jun 2, 2026
c88daad
chore(cloud): clarify private beta settings copy
juliusmarminge Jun 2, 2026
86e10ec
fix(mobile): reconnect saved environments after resume
juliusmarminge Jun 2, 2026
bb9a222
fix(mobile): keep live activity layout self-contained
juliusmarminge Jun 2, 2026
13326ed
feat(web): add desktop Clerk-compatible cloud auth UI
juliusmarminge Jun 2, 2026
9a13b86
chore: add alchemy reference repo
juliusmarminge Jun 2, 2026
2d4d269
Squashed '.repos/alchemy-effect/' content from commit afc2585ae
juliusmarminge Jun 2, 2026
437e8aa
Merge commit '2d4d26936de8bec3af554db29b81364ffda7be0d' as '.repos/al…
juliusmarminge Jun 2, 2026
547bee6
feat(cloud): manage cloudflared installation and relay defaults
juliusmarminge Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Optional root-level overrides for the checked-in public client configuration.
# Server-side secrets must never be committed here.
#
# T3CODE_CLERK_PUBLISHABLE_KEY=pk_test_...
# T3_RELAY_URL=https://relay.example.com
6 changes: 6 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ permissions:
contents: read
id-token: none

env:
T3CODE_CLERK_PUBLISHABLE_KEY: ${{ vars.T3CODE_CLERK_PUBLISHABLE_KEY }}
T3_RELAY_URL: ${{ vars.T3_RELAY_URL }}

jobs:
check_changes:
name: Check for changes since last nightly
Expand Down Expand Up @@ -660,6 +664,8 @@ jobs:
--token "$VERCEL_TOKEN" \
"${vercel_scope_args[@]}" \
--build-env "APP_VERSION=${{ needs.preflight.outputs.version }}" \
--build-env "T3CODE_CLERK_PUBLISHABLE_KEY=${T3CODE_CLERK_PUBLISHABLE_KEY:-}" \
--build-env "T3_RELAY_URL=${T3_RELAY_URL:-}" \
--build-env "VITE_HOSTED_APP_URL=$router_url" \
--build-env "VITE_HOSTED_APP_CHANNEL=$channel_name"
)"
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ node_modules
*.log
*.tsbuildinfo
apps/*/dist
infra/*/dist
.astro
packages/*/dist
.env
Expand All @@ -26,3 +27,8 @@ squashfs-root/
.gstack/
dist-electron/
.electron-runtime/
node_modules/
.alchemy/
*.log
.env*
!.env.example
1 change: 1 addition & 0 deletions .repos/alchemy-effect/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
alchemy/test/**
137 changes: 137 additions & 0 deletions .repos/alchemy-effect/.github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: Deploy Website

on:
workflow_dispatch:
push:
branches:
- main
paths:
- "website/**"
- "packages/alchemy/**"
- "bun.lock"
- ".github/workflows/deploy.yml"
pull_request:
types:
- opened
- reopened
- synchronize
- closed
paths:
- "website/**"
- "packages/alchemy/**"
- "bun.lock"
- ".github/workflows/deploy.yml"

concurrency:
group: deploy-website-${{ github.ref }}
cancel-in-progress: false

env:
STAGE: ${{ github.event_name == 'pull_request' && format('pr-{0}',
github.event.number) || (github.ref == 'refs/heads/main' && 'prod' ||
github.ref_name) }}

jobs:
deploy:
if: ${{ github.event.action != 'closed' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

# Mint a token for the alchemy-version-bot GitHub App so the PR
# preview comment (created via GitHub.Comment in alchemy.run.ts)
# posts under the bot's identity instead of `github-actions[bot]`.
# Same App as release.yml — its installation scopes already cover
# PR comments.
- name: Generate bot token
id: bot-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.ALCHEMY_VERSION_BOT_ID }}
private-key: ${{ secrets.ALCHEMY_VERSION_BOT_PRIVATE_KEY }}

- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0

- name: Install dependencies
run: bun install

# Build the website ahead of `alchemy deploy`. The
# Cloudflare.StaticSite resource declares the same `bun run build`
# in its config and runs it as part of the create lifecycle, but
# on update plans alchemy reads `dist/` during plan.diff before
# the embedded Build resource gets a chance to (re)run, causing
# a NotFound on a fresh CI checkout. Building here makes the
# workflow correct under both create and update plans.
- name: Build website
working-directory: website
run: bun run build

- name: Deploy
working-directory: website
run: bun alchemy deploy --stage ${{ env.STAGE }} --yes
env:
# Alchemy's Cloudflare auth provider accepts either a scoped
# API token (CLOUDFLARE_API_TOKEN) or the legacy global API
# key paired with email (CLOUDFLARE_API_KEY +
# CLOUDFLARE_EMAIL). We use the latter here so CI matches
# the credentials in Doppler / .env, where only the admin
# global key is provisioned.
CLOUDFLARE_API_KEY: ${{ secrets.ADMIN_CLOUDFLARE_API_KEY }}
CLOUDFLARE_EMAIL: ${{ secrets.ADMIN_CLOUDFLARE_EMAIL }}
CLOUDFLARE_ACCOUNT_ID: ${{ env.STAGE == 'prod' &&
secrets.PROD_CLOUDFLARE_ACCOUNT_ID ||
secrets.TEST_CLOUDFLARE_ACCOUNT_ID }}
PULL_REQUEST: ${{ github.event.number }}
# On `pull_request` events GitHub Actions' built-in
# `GITHUB_SHA` is the synthetic merge commit (PR head merged
# into base) — that SHA never shows up in the PR's git log.
# `GITHUB_SHA` is also a reserved env var, so a step-level
# override is silently ignored. Pass the PR head SHA under
# a non-reserved name and read it from alchemy.run.ts.
BUILD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
GITHUB_TOKEN: ${{ steps.bot-token.outputs.token }}

cleanup:
runs-on: ubuntu-latest
if:
${{ github.event_name == 'pull_request' && github.event.action == 'closed'
}}
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Generate bot token
id: bot-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.ALCHEMY_VERSION_BOT_ID }}
private-key: ${{ secrets.ALCHEMY_VERSION_BOT_PRIVATE_KEY }}

- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0

- name: Install dependencies
run: bun install

- name: Safety Check
run: |-
if [ "${{ env.STAGE }}" = "prod" ]; then
echo "ERROR: Cannot destroy prod environment in cleanup job"
exit 1
fi

- name: Destroy Preview Environment
working-directory: website
run: bun alchemy destroy --stage ${{ env.STAGE }} --yes
env:
CLOUDFLARE_API_KEY: ${{ secrets.ADMIN_CLOUDFLARE_API_KEY }}
CLOUDFLARE_EMAIL: ${{ secrets.ADMIN_CLOUDFLARE_EMAIL }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.TEST_CLOUDFLARE_ACCOUNT_ID }}
PULL_REQUEST: ${{ github.event.number }}
GITHUB_TOKEN: ${{ steps.bot-token.outputs.token }}
180 changes: 180 additions & 0 deletions .repos/alchemy-effect/.github/workflows/pr-package.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
name: pr-package

# Publishes alchemy + better-auth + pr-package tarballs to the pr-package
# service at pkg.ing on every push to main and every PR sync. On PR close,
# deletes every tag we ever assigned for that PR so the underlying tarballs
# become orphaned and the bucket cleans them up.

on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened, closed]

permissions:
contents: read
pull-requests: write

env:
PR_PACKAGE_HOST: pkg.ing
NODE_VERSION: "24"

jobs:
# ── Publish on push-to-main and PR sync. ──────────────────────────────────
publish:
if: github.event_name == 'push' || (github.event_name == 'pull_request' &&
github.event.action != 'closed')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ env.NODE_VERSION }}

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest

- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-

- run: bun install

# Build everything: tsdown bundles alchemy (bin/ + cli lib) and tsc -b
# populates lib/ for the layer packages (better-auth, pr-package).
# Their tarballs ship both src/ and lib/, and consumers in non-bun
# runtimes resolve via the `import` condition → ./lib/index.js.
- run: bun run build:packages

- name: Compute tags
id: tags
env:
EVENT: ${{ github.event_name }}
# `head_ref` for PRs (source branch), `ref_name` for push (e.g. "main").
BRANCH: ${{ github.event_name == 'pull_request' && github.head_ref ||
github.ref_name }}
PR_NUMBER: ${{ github.event.pull_request.number }}
# PR builds run on the merge commit by default; tag the actual head sha
# so consumers can pin to a specific PR commit.
SHA: ${{ github.event_name == 'pull_request' &&
github.event.pull_request.head.sha || github.sha }}
run: |
set -euo pipefail
short="${SHA:0:7}"
long="$SHA"
tags=("$short" "$long" "$BRANCH")
if [ "$EVENT" = "pull_request" ]; then
tags+=("pr-${PR_NUMBER}")
fi
json=$(printf '%s\n' "${tags[@]}" | jq -R . | jq -s -c .)
echo "tags=$json" >> "$GITHUB_OUTPUT"
echo "short=$short" >> "$GITHUB_OUTPUT"
echo "Tags: $json"

# PR builds expire after 1 week; pushes to main omit the header and
# fall back to the worker's defaultTtl (3 weeks).
- name: Publish alchemy
env:
TOKEN: ${{ secrets.PR_PACKAGE_TOKEN }}
TAGS: ${{ steps.tags.outputs.tags }}
TTL: ${{ github.event_name == 'pull_request' && '1 week' || '' }}
working-directory: packages/alchemy
run: |
set -euo pipefail
rm -f *.tgz
bun pm pack --destination .
tgz=$(ls *.tgz)
echo "Publishing $tgz with tags $TAGS ttl=${TTL:-default}"
curl -fsSL --show-error -X PUT \
"https://${PR_PACKAGE_HOST}/projects/alchemy/packages" \
-H "Authorization: Bearer ${TOKEN}" \
-H "X-Tags: ${TAGS}" \
${TTL:+-H "X-TTL: ${TTL}"} \
-H "Content-Type: application/gzip" \
--data-binary "@${tgz}"

- name: Publish better-auth
env:
TOKEN: ${{ secrets.PR_PACKAGE_TOKEN }}
TAGS: ${{ steps.tags.outputs.tags }}
TTL: ${{ github.event_name == 'pull_request' && '1 week' || '' }}
working-directory: packages/better-auth
run: |
set -euo pipefail
rm -f *.tgz
bun pm pack --destination .
tgz=$(ls *.tgz)
echo "Publishing $tgz with tags $TAGS ttl=${TTL:-default}"
curl -fsSL --show-error -X PUT \
"https://${PR_PACKAGE_HOST}/projects/@alchemy.run/better-auth/packages" \
-H "Authorization: Bearer ${TOKEN}" \
-H "X-Tags: ${TAGS}" \
${TTL:+-H "X-TTL: ${TTL}"} \
-H "Content-Type: application/gzip" \
--data-binary "@${tgz}"

- name: Publish pr-package
env:
TOKEN: ${{ secrets.PR_PACKAGE_TOKEN }}
TAGS: ${{ steps.tags.outputs.tags }}
TTL: ${{ github.event_name == 'pull_request' && '1 week' || '' }}
working-directory: packages/pr-package
run: |
set -euo pipefail
rm -f *.tgz
bun pm pack --destination .
tgz=$(ls *.tgz)
echo "Publishing $tgz with tags $TAGS ttl=${TTL:-default}"
curl -fsSL --show-error -X PUT \
"https://${PR_PACKAGE_HOST}/projects/@alchemy.run/pr-package/packages" \
-H "Authorization: Bearer ${TOKEN}" \
-H "X-Tags: ${TAGS}" \
${TTL:+-H "X-TTL: ${TTL}"} \
-H "Content-Type: application/gzip" \
--data-binary "@${tgz}"

# PR-only: leave a sticky comment with the install URLs pinned to this
# commit. Uses pkg.ing (the canonical short host), which serves both
# the pretty alias paths and the underlying /projects/:project/tags/:tag
# API directly.
- name: Generate bot token
if: github.event_name == 'pull_request'
id: bot-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.ALCHEMY_VERSION_BOT_ID }}
private-key: ${{ secrets.ALCHEMY_VERSION_BOT_PRIVATE_KEY }}

- name: Comment on PR
if: github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ steps.bot-token.outputs.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
SHORT_SHA: ${{ steps.tags.outputs.short }}
run: |
set -euo pipefail
MARKER="<!-- pr-package-comment -->"
# Use `bun add <name>@<url>` instead of `bun add <url>`. Without an
# explicit name, bun's resolver hits a DependencyLoop bug when the
# consumer already has the same package name resolved from npm
# (oven-sh/bun#5789, oven-sh/bun#17946). The aliased form bypasses
# the buggy reconciliation path and works on fresh and existing
# projects alike.
BODY=$(printf '%s\n\nInstall the packages built from this commit:\n\n**alchemy**\n```sh\nbun add alchemy@https://pkg.ing/alchemy/%s\n```\n\n**@alchemy.run/better-auth**\n```sh\nbun add @alchemy.run/better-auth@https://pkg.ing/@alchemy.run/better-auth/%s\n```\n\n**@alchemy.run/pr-package**\n```sh\nbun add @alchemy.run/pr-package@https://pkg.ing/@alchemy.run/pr-package/%s\n```\n' "$MARKER" "$SHORT_SHA" "$SHORT_SHA" "$SHORT_SHA")

existing=$(gh api --paginate \
"repos/${REPO}/issues/${PR_NUMBER}/comments" \
--jq ".[] | select(.user.login == \"alchemy-version-bot[bot]\") | select(.body | startswith(\"${MARKER}\")) | .id" \
| head -1)

if [ -n "$existing" ]; then
gh api -X PATCH "repos/${REPO}/issues/comments/${existing}" -f body="$BODY"
else
gh api -X POST "repos/${REPO}/issues/${PR_NUMBER}/comments" -f body="$BODY"
fi
Loading
Loading