Some checks failed
CI / Tests / 🧪 Test (push) Has been cancelled
Production /join on the broker (from feat 18c) rejects every invite
with invite_bad_signature because the web UI was emitting unsigned
payloads. This fixes that.
createMyMesh now generates ed25519 owner keypair + 32-byte root key
and stores all three on the mesh row. createMyInvite loads them,
signs the canonical invite bytes via crypto_sign_detached, and
emits a fully-signed payload matching what the broker expects:
payload = {v, mesh_id, mesh_slug, broker_url, expires_at,
mesh_root_key, role, owner_pubkey, signature}
canonical = same fields minus signature, "|"-delimited
signature = ed25519_sign(canonical, mesh.owner_secret_key)
token = base64url(JSON(payload)) ← stored as invite.token
The base64url(JSON) token IS the DB lookup key — broker's /join
does `WHERE invite.token = <that string>`, then re-verifies the
signature it extracts from the decoded payload.
Also drops the sha256 derivePlaceholderRootKey() helper and the
encodeInviteLink helper, both replaced by inline logic.
backfill extended: the one-off script now populates owner_pubkey
AND owner_secret_key AND root_key together in a single pass. Query
condition is `WHERE any of the three IS NULL`, so running it
post-migration catches every row regardless of partial prior fills.
requires packages/api to depend on libsodium-wrappers + types
(added). 64/64 broker tests still green.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
50 lines
1.5 KiB
JSON
50 lines
1.5 KiB
JSON
{
|
|
"name": "@turbostarter/api",
|
|
"version": "0.1.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"exports": {
|
|
".": "./src/index.ts",
|
|
"./env": "./src/env.ts",
|
|
"./utils": "./src/utils/index.ts",
|
|
"./schema": "./src/schema/index.ts"
|
|
},
|
|
"scripts": {
|
|
"clean": "git clean -xdf .cache .turbo dist node_modules",
|
|
"format": "prettier --check . --ignore-path ../../.gitignore",
|
|
"lint": "eslint",
|
|
"test": "vitest run",
|
|
"typecheck": "tsc --noEmit"
|
|
},
|
|
"prettier": "@turbostarter/prettier-config",
|
|
"dependencies": {
|
|
"@ai-sdk/openai": "2.0.68",
|
|
"@anthropic-ai/sdk": "0.71.2",
|
|
"@hono/zod-validator": "0.7.4",
|
|
"@turbostarter/auth": "workspace:*",
|
|
"@turbostarter/billing": "workspace:*",
|
|
"@turbostarter/db": "workspace:*",
|
|
"@turbostarter/email": "workspace:*",
|
|
"@turbostarter/i18n": "workspace:*",
|
|
"@turbostarter/monitoring-web": "workspace:*",
|
|
"@turbostarter/shared": "workspace:*",
|
|
"@turbostarter/storage": "workspace:*",
|
|
"ai": "catalog:",
|
|
"envin": "catalog:",
|
|
"hono": "4.10.4",
|
|
"libsodium-wrappers": "0.7.15",
|
|
"zod": "catalog:"
|
|
},
|
|
"devDependencies": {
|
|
"@turbostarter/eslint-config": "workspace:*",
|
|
"@turbostarter/prettier-config": "workspace:*",
|
|
"@turbostarter/tsconfig": "workspace:*",
|
|
"@turbostarter/vitest-config": "workspace:*",
|
|
"@types/libsodium-wrappers": "0.7.14",
|
|
"eslint": "catalog:",
|
|
"prettier": "catalog:",
|
|
"typescript": "catalog:",
|
|
"vitest": "catalog:"
|
|
}
|
|
}
|