An AT Protocol PDS
1import crypto from 'node:crypto'
2import { IdResolver } from '@atproto/identity'
3import type { MoonstoneConfig } from '@ewanc26/moonstone-config'
4import type { Db } from './db/index.js'
5import { AccountManager } from './account-manager/index.js'
6import { AuthVerifier, makeJwtKey } from './auth/index.js'
7import { KeyStore } from './key-store.js'
8import { Mailer } from './mailer.js'
9
10export type AppContext = {
11 cfg: MoonstoneConfig & {
12 jwtSecret: string
13 adminPassword: string
14 }
15 db: Db
16 accountManager: AccountManager
17 authVerifier: AuthVerifier
18 keyStore: KeyStore
19 idResolver: IdResolver
20 mailer: Mailer | null
21 plcRotationKey: crypto.KeyObject
22}
23
24export function buildAppContext(
25 cfg: MoonstoneConfig & { jwtSecret: string; adminPassword: string },
26 db: Db,
27): AppContext {
28 const accountManager = new AccountManager(
29 db,
30 cfg.jwtSecret,
31 cfg.service.did,
32 cfg.identity.serviceHandleDomains,
33 )
34
35 const jwtKey = makeJwtKey(cfg.jwtSecret)
36
37 const authVerifier = new AuthVerifier(
38 jwtKey,
39 cfg.service.did,
40 cfg.adminPassword,
41 accountManager,
42 )
43
44 const keyStore = new KeyStore(db)
45
46 const idResolver = new IdResolver({
47 plcUrl: cfg.identity.plcUrl,
48 })
49
50 const mailer = cfg.email
51 ? new Mailer(cfg.email.smtpUrl, cfg.email.fromAddress, cfg.service.hostname)
52 : null
53
54 // PLC rotation key is derived from the JWT secret for simplicity.
55 // In production this should be a dedicated env var.
56 const plcRotationKey = jwtKey
57
58 return { cfg, db, accountManager, authVerifier, keyStore, idResolver, mailer, plcRotationKey }
59}