Replaces the dev-bearer table with PDS-backed App Password authentication
per ADR-0243 Rule 20, scoped to single-user (Joel only) for now.
packages/system-bus/src/lib/pds.ts
+ pdsCreateAppPassword — calls com.atproto.server.createAppPassword on
the caller's session; returns { name, password, did, handle }
+ pdsRevokeAppPassword — revokes by name
+ pdsValidateAppPassword — one-shot validation via createSession; used
at register time only, NOT per-request (hash lookup is cheaper +
safer, and doesn't create server-side session state at PDS)
packages/memory/src/schemas/machines.ts — NEW Typesense schema for
machines_dev collection: id, user_id, did, handle, machine_name,
app_password_name, app_password_sha256, created_at, last_seen_at,
revoked_at
apps/web/lib/memory-auth.ts — NEW auth middleware
authenticateMemoryRequest(req) → MemoryIdentity | null
Hot path: sha256(bearer) → Typesense machines_dev lookup →
{ user_id, machine_id, did, source: "app-password" }
No PDS roundtrip per request. App Password validity is established
at register time; the hash is the identity key thereafter.
Dev-bearer fallback retained during transition (MEMORY_DEV_BEARER_TOKENS
env var); effectively disappears when that var is empty in prod.
Phase 3.5 TODO: users_dev collection (DID→user_id map is hardcoded for
now).
apps/web/app/api/runs/*/route.ts — all 6 handlers now call
authenticateMemoryRequest instead of the inline DEV_BEARER_TOKENS
table + local authenticate() helper. Rule 4 privacy filtering is
unchanged (still keyed on auth.user_id from the middleware).
scripts/joelclaw-machine-register.ts — NEW provisioning CLI
Flow: load cached PDS session from ~/.joelclaw/pds-session.json →
call com.atproto.server.createAppPassword → sha256(plaintext) →
upsert machines_dev row → back up old auth.json → write new
auth.json (0600) with the plaintext bearer. Ready to register Panda
once the infra is back.
Verification status (pending Typesense reachability):
[x] pds.ts compiles; curl-tested createAppPassword directly against
PDS (returned valid password)
[x] Bun fetch works against PDS directly (ruled out fetch-lib bugs)
[x] All route handlers typecheck + biome clean
[x] Auth middleware compiles
[ ] End-to-end: register panda → POST /api/runs with new bearer →
Run indexes → search returns it — BLOCKED on Colima SSH tunnel
which is flapping (ssh 192.168.64.2:22 timing out; matches the
2026-04-17 healer-suicide-loop memory note)
When infra comes back:
TYPESENSE_API_KEY=<...> joelclaw-machine-register --name panda --user joel
then POST /api/runs with the new bearer to confirm.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This is a Next.js project bootstrapped with create-next-app.
Environment Variables
Set these in local .env.local and in Vercel project environment variables:
INNGEST_EVENT_URL: endpoint used byPOST /api/review/submitto emitcontent/review.submitted.- Production:
https://panda.tail7af24.ts.net:3111/e/local
- Production:
Getting Started
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
Open http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.tsx. The page auto-updates as you edit the file.
This project uses next/font to automatically optimize and load Inter, a custom Google Font.
Learn More
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
Deploy on Vercel
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.