From 3b8fdf207271b7907fb37f5d37f75cca0ebda384 Mon Sep 17 00:00:00 2001 From: Florian <45694132+flo-bit@users.noreply.github.com> Date: Sat, 23 May 2026 22:08:51 +0200 Subject: [PATCH] commit --- apps/example-sender/package.json | 107 ++++++------- apps/example-sender/src/lib/server/relay.ts | 3 + .../src/lib/server/subscribers.ts | 19 +++ .../example-sender/src/routes/+page.server.ts | 5 +- apps/example-sender/src/routes/+page.svelte | 18 +++ .../src/routes/xrpc/[method]/+server.ts | 65 ++++++++ apps/example-sender/wrangler.jsonc | 10 +- apps/homepage/src/routes/docs/+page.server.ts | 31 +++- apps/homepage/src/routes/docs/+page.svelte | 28 +++- apps/relay/package.json | 3 +- apps/relay/scripts/generate-relay-key.js | 18 +++ apps/relay/src/auth/relay-signer.ts | 48 ++++++ apps/relay/src/delivery/dispatcher.ts | 55 +++++++ apps/relay/src/env.ts | 13 ++ apps/relay/src/lib/apps.ts | 52 +++++++ apps/relay/src/lib/trusted.ts | 11 -- apps/relay/src/rpc/entrypoint.ts | 4 + apps/relay/src/rpc/ops.ts | 34 ++++ apps/relay/src/well-known.ts | 28 +++- apps/relay/src/xrpc/requestPermission.ts | 2 +- apps/relay/test/subscriberChanged.test.ts | 147 ++++++++++++++++++ apps/web/src/lib/server/relay.ts | 1 + .../web/src/routes/(app)/apps/+page.server.ts | 17 +- apps/web/src/routes/(app)/apps/+page.svelte | 45 ++++++ .../pub/atmo/notify/subscriberChanged.json | 42 +++++ packages/lexicons/src/rpc.ts | 16 ++ pnpm-lock.yaml | 9 +- 27 files changed, 747 insertions(+), 84 deletions(-) create mode 100644 apps/example-sender/src/lib/server/subscribers.ts create mode 100644 apps/example-sender/src/routes/xrpc/[method]/+server.ts create mode 100644 apps/relay/scripts/generate-relay-key.js create mode 100644 apps/relay/src/auth/relay-signer.ts create mode 100644 apps/relay/src/lib/apps.ts delete mode 100644 apps/relay/src/lib/trusted.ts create mode 100644 apps/relay/test/subscriberChanged.test.ts create mode 100644 packages/lexicons/lexicons/pub/atmo/notify/subscriberChanged.json diff --git a/apps/example-sender/package.json b/apps/example-sender/package.json index 61b8c4c..c27292e 100644 --- a/apps/example-sender/package.json +++ b/apps/example-sender/package.json @@ -1,55 +1,56 @@ { - "name": "example", - "private": true, - "version": "0.0.1", - "type": "module", - "scripts": { - "atproto:setup": "atproto-oauth setup", - "atproto:keygen": "atproto-oauth keygen", - "atproto:secret": "atproto-oauth secret", - "sender:keygen": "node scripts/generate-keys.js", - "dev": "vite dev", - "build": "vite build", - "preview": "vite preview", - "deploy": "vite build && wrangler deploy", - "prepare": "svelte-kit sync || echo ''", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "prettier --check . && eslint .", - "format": "prettier --write ." - }, - "devDependencies": { - "@eslint/compat": "^2.0.4", - "@eslint/js": "^10.0.1", - "@sveltejs/adapter-cloudflare": "^7.2.8", - "@sveltejs/kit": "^2.57.0", - "@sveltejs/vite-plugin-svelte": "^7.0.0", - "@tailwindcss/forms": "^0.5.11", - "@tailwindcss/typography": "^0.5.19", - "@tailwindcss/vite": "^4.2.2", - "@types/node": "^22", - "eslint": "^10.2.0", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-svelte": "^3.17.0", - "globals": "^17.4.0", - "prettier": "^3.8.1", - "prettier-plugin-svelte": "^3.5.1", - "prettier-plugin-tailwindcss": "^0.7.2", - "svelte": "^5.55.2", - "svelte-check": "^4.4.6", - "tailwindcss": "^4.2.2", - "typescript": "^6.0.2", - "typescript-eslint": "^8.58.1", - "vite": "^8.0.7" - }, - "dependencies": { - "@atcute/atproto": "^4.0.0", - "@atcute/client": "^5.0.0", - "@atcute/crypto": "^2.4.1", - "@atcute/lexicons": "^2.0.0", - "@atcute/uint8array": "^1.1.2", - "@atcute/xrpc-server": "^2.0.0", - "@svelte-atproto/oauth": "^0.3.0", - "valibot": "^1.0.0" - } + "name": "example", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "atproto:setup": "atproto-oauth setup", + "atproto:keygen": "atproto-oauth keygen", + "atproto:secret": "atproto-oauth secret", + "sender:keygen": "node scripts/generate-keys.js", + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "deploy": "vite build && wrangler deploy", + "prepare": "svelte-kit sync || echo ''", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --check . && eslint .", + "format": "prettier --write ." + }, + "devDependencies": { + "@eslint/compat": "^2.0.4", + "@eslint/js": "^10.0.1", + "@sveltejs/adapter-cloudflare": "^7.2.8", + "@sveltejs/kit": "^2.57.0", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tailwindcss/forms": "^0.5.11", + "@tailwindcss/typography": "^0.5.19", + "@tailwindcss/vite": "^4.2.2", + "@types/node": "^22", + "eslint": "^10.2.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-svelte": "^3.17.0", + "globals": "^17.4.0", + "prettier": "^3.8.1", + "prettier-plugin-svelte": "^3.5.1", + "prettier-plugin-tailwindcss": "^0.7.2", + "svelte": "^5.55.2", + "svelte-check": "^4.4.6", + "tailwindcss": "^4.2.2", + "typescript": "^6.0.2", + "typescript-eslint": "^8.58.1", + "vite": "^8.0.7" + }, + "dependencies": { + "@atcute/atproto": "^4.0.0", + "@atcute/client": "^5.0.0", + "@atcute/crypto": "^2.4.1", + "@atcute/identity-resolver": "^2.0.0", + "@atcute/lexicons": "^2.0.0", + "@atcute/uint8array": "^1.1.2", + "@atcute/xrpc-server": "^2.0.0", + "@svelte-atproto/oauth": "^0.3.0", + "valibot": "^1.0.0" + } } diff --git a/apps/example-sender/src/lib/server/relay.ts b/apps/example-sender/src/lib/server/relay.ts index ffe6f37..98e642f 100644 --- a/apps/example-sender/src/lib/server/relay.ts +++ b/apps/example-sender/src/lib/server/relay.ts @@ -35,6 +35,9 @@ async function postRelay(jwt: string, lxm: string, body: object): Promise(); + +export function recordSubscriber(did: string, enabled: boolean): void { + if (enabled) { + subscribers.add(did); + } else { + subscribers.delete(did); + } +} + +export function listSubscribers(): string[] { + return [...subscribers]; +} diff --git a/apps/example-sender/src/routes/+page.server.ts b/apps/example-sender/src/routes/+page.server.ts index ef6ba2f..b06418e 100644 --- a/apps/example-sender/src/routes/+page.server.ts +++ b/apps/example-sender/src/routes/+page.server.ts @@ -1,6 +1,8 @@ import { loadHandle } from '@svelte-atproto/oauth/helper'; import { memory } from '@svelte-atproto/oauth/server/stores/memory'; +import { listSubscribers } from '$lib/server/subscribers'; + import type { PageServerLoad } from './$types'; // Tiny in-memory cache for handle lookups (fine for a demo). @@ -8,5 +10,6 @@ const handleCache = memory(); export const load: PageServerLoad = async ({ locals }) => { const handle = locals.did ? await loadHandle(locals.did, { cache: handleCache }) : null; - return { did: locals.did, handle }; + // Users the relay told us enabled us via atmo.pub's "enable apps" flow. + return { did: locals.did, handle, subscribers: listSubscribers() }; }; diff --git a/apps/example-sender/src/routes/+page.svelte b/apps/example-sender/src/routes/+page.svelte index dc2ba24..f265fb9 100644 --- a/apps/example-sender/src/routes/+page.svelte +++ b/apps/example-sender/src/routes/+page.svelte @@ -370,6 +370,24 @@ {/if} +
+

Subscribers from atmo.pub

+

+ Users who enabled this app from inside atmo.pub. The relay tells us via a signed + subscriberChanged callback (we verify it's really the + relay), and a real app would start sending them notifications. Demo store is in-memory. +

+ {#if data.subscribers.length === 0} +

None yet — enable this app from atmo.pub's Apps screen.

+ {:else} + + {/if} +
+