Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 6 additions & 8 deletions convex/relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,18 @@
* The bootstrap token lives in `XCB_RELAY_BOOTSTRAP` on the deployment and
* admits the first owner exactly once — it dies the moment a subject
* verifies. OTP delivery defaults to `log`; `XCB_RELAY_EMAIL=resend` uses
* Resend via `XCB_RESEND_API_KEY` / `XCB_RESEND_FROM`, `sendgrid` uses the
* SendGrid v3 API via `XCB_SENDGRID_API_KEY` / `XCB_SENDGRID_FROM`, and
* `webhook` POSTs the code to `XCB_OTP_WEBHOOK_URL` with bearer
* Resend via `XCB_RESEND_API_KEY` / `XCB_RESEND_FROM`, and `webhook`
* POSTs the code to `XCB_OTP_WEBHOOK_URL` with bearer
* `XCB_OTP_WEBHOOK_TOKEN`. */

import { defineRelay } from "@hraness/relay/backend";
import type { EmailTransport } from "@hraness/relay/wire";

const email: EmailTransport = process.env.XCB_RELAY_EMAIL === "resend"
? { mode: "resend", keyEnv: "XCB_RESEND_API_KEY", fromEnv: "XCB_RESEND_FROM" }
: process.env.XCB_RELAY_EMAIL === "sendgrid"
? { mode: "sendgrid", keyEnv: "XCB_SENDGRID_API_KEY", fromEnv: "XCB_SENDGRID_FROM" }
: process.env.XCB_RELAY_EMAIL === "webhook"
? { mode: "webhook", urlEnv: "XCB_OTP_WEBHOOK_URL", tokenEnv: "XCB_OTP_WEBHOOK_TOKEN" }
: { mode: "log" };
: process.env.XCB_RELAY_EMAIL === "webhook"
? { mode: "webhook", urlEnv: "XCB_OTP_WEBHOOK_URL", tokenEnv: "XCB_OTP_WEBHOOK_TOKEN" }
: { mode: "log" };

export const relay = defineRelay({
namespace: "xcb.relay.v1",
Expand All @@ -37,4 +34,5 @@ export const relay = defineRelay({
openSignup: false,
bootstrapInviteEnv: "XCB_RELAY_BOOTSTRAP",
authProviderId: "xcb-otp-v1",
productName: "xcb",
});
12 changes: 6 additions & 6 deletions docs/relay-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ Set the relay's environment with `npx convex env set <KEY> <value>`:
forced refresh signs a new session, and the call retries.
- `XCB_RELAY_BOOTSTRAP`: a one-time invite for the first owner. It stops working
once an owner is verified; set a fresh value only when rebuilding a fleet.
- `XCB_RELAY_EMAIL`: how sign-in codes are delivered: `log`, `sendgrid`,
`resend`, or `webhook`. `sendgrid` needs `XCB_SENDGRID_API_KEY` and
`XCB_SENDGRID_FROM` (a verified sender); `resend` needs `XCB_RESEND_API_KEY`
and `XCB_RESEND_FROM`; `webhook` needs `XCB_OTP_WEBHOOK_URL` and
`XCB_OTP_WEBHOOK_TOKEN`. With `log`, codes are printed to the function log,
which you read from an authenticated Convex session with `npx convex logs`.
- `XCB_RELAY_EMAIL`: how sign-in codes are delivered: `log`, `resend`, or
`webhook`. `resend` needs `XCB_RESEND_API_KEY` and `XCB_RESEND_FROM` (a
branded sender on a verified domain, e.g. `xcb <xcb@auth.hraness.com>`);
`webhook` needs `XCB_OTP_WEBHOOK_URL` and `XCB_OTP_WEBHOOK_TOKEN`. With
`log`, codes are printed to the function log, which you read from an
authenticated Convex session with `npx convex logs`.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
},
"devDependencies": {
"@convex-dev/auth": "0.0.95",
"@hraness/relay": "github:hraness/relay#2558a0d860d35ec2537cc135380ea4bd89db1c8f",
"@hraness/relay": "github:hraness/relay#5ef01b0613ac49c4da0fcb8d2ee81e667c592992",
"@types/bun": "1.4.2",
"@types/node": "26.6.2",
"convex": "1.45.0",
Expand Down
Loading