@atproto/pds 0.5.55 → 0.5.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/api/app/bsky/actor/putPreferences.d.ts.map +1 -1
  3. package/dist/api/app/bsky/actor/putPreferences.js +3 -0
  4. package/dist/api/app/bsky/actor/putPreferences.js.map +1 -1
  5. package/dist/api/com/atproto/admin/deleteAccount.js +1 -1
  6. package/dist/api/com/atproto/admin/deleteAccount.js.map +1 -1
  7. package/dist/api/com/atproto/admin/getSubjectStatus.js +1 -1
  8. package/dist/api/com/atproto/admin/getSubjectStatus.js.map +1 -1
  9. package/dist/api/com/atproto/admin/updateAccountHandle.js +1 -1
  10. package/dist/api/com/atproto/admin/updateAccountHandle.js.map +1 -1
  11. package/dist/api/com/atproto/admin/updateSubjectStatus.js +1 -1
  12. package/dist/api/com/atproto/admin/updateSubjectStatus.js.map +1 -1
  13. package/dist/api/com/atproto/server/createAccount.d.ts.map +1 -1
  14. package/dist/api/com/atproto/server/createAccount.js +13 -2
  15. package/dist/api/com/atproto/server/createAccount.js.map +1 -1
  16. package/dist/api/com/atproto/server/reserveSigningKey.d.ts.map +1 -1
  17. package/dist/api/com/atproto/server/reserveSigningKey.js +3 -0
  18. package/dist/api/com/atproto/server/reserveSigningKey.js.map +1 -1
  19. package/dist/auth-output.d.ts +6 -0
  20. package/dist/auth-output.d.ts.map +1 -1
  21. package/dist/auth-output.js.map +1 -1
  22. package/dist/auth-verifier.d.ts +21 -2
  23. package/dist/auth-verifier.d.ts.map +1 -1
  24. package/dist/auth-verifier.js +98 -0
  25. package/dist/auth-verifier.js.map +1 -1
  26. package/dist/config/config.d.ts +11 -0
  27. package/dist/config/config.d.ts.map +1 -1
  28. package/dist/config/config.js +2 -0
  29. package/dist/config/config.js.map +1 -1
  30. package/dist/config/env.d.ts +2 -0
  31. package/dist/config/env.d.ts.map +1 -1
  32. package/dist/config/env.js +2 -0
  33. package/dist/config/env.js.map +1 -1
  34. package/dist/context.d.ts.map +1 -1
  35. package/dist/context.js +8 -2
  36. package/dist/context.js.map +1 -1
  37. package/dist/entryway-attribution.d.ts +39 -0
  38. package/dist/entryway-attribution.d.ts.map +1 -0
  39. package/dist/entryway-attribution.js +101 -0
  40. package/dist/entryway-attribution.js.map +1 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +10 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/logger.d.ts.map +1 -1
  45. package/dist/logger.js +8 -1
  46. package/dist/logger.js.map +1 -1
  47. package/dist/rate-limits.d.ts +2 -2
  48. package/dist/rate-limits.d.ts.map +1 -1
  49. package/dist/rate-limits.js +6 -6
  50. package/dist/rate-limits.js.map +1 -1
  51. package/dist/util/ip.d.ts +8 -0
  52. package/dist/util/ip.d.ts.map +1 -0
  53. package/dist/util/ip.js +34 -0
  54. package/dist/util/ip.js.map +1 -0
  55. package/package.json +9 -9
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
package/dist/context.js CHANGED
@@ -144,7 +144,7 @@ export class AppContext {
144
144
  })
145
145
  : undefined;
146
146
  const entrywayClient = cfg.entryway
147
- ? new Client({ service: cfg.entryway.url }, {
147
+ ? new Client({ service: cfg.entryway.apiUrl }, {
148
148
  // Trust internal services to send us well-formed responses
149
149
  strictResponseProcessing: false,
150
150
  validateResponse: cfg.service.devMode,
@@ -152,7 +152,7 @@ export class AppContext {
152
152
  : undefined;
153
153
  const entrywayAdminClient = cfg.entryway && secrets.entrywayAdminToken
154
154
  ? new Client({
155
- service: cfg.entryway.url,
155
+ service: cfg.entryway.apiUrl,
156
156
  headers: {
157
157
  authorization: basicAuthHeader('admin', secrets.entrywayAdminToken),
158
158
  },
@@ -368,6 +368,12 @@ export class AppContext {
368
368
  entryway: cfg.entryway?.did,
369
369
  modService: cfg.modService?.did,
370
370
  },
371
+ entrywayServiceAuth: cfg.entryway
372
+ ? {
373
+ didKey: crypto.formatDidKey(crypto.SECP256K1_JWT_ALG, ui8.fromString(cfg.entryway.jwtPublicKeyHex, 'hex')),
374
+ required: cfg.entryway.requireServiceAuth,
375
+ }
376
+ : undefined,
371
377
  });
372
378
  return new AppContext({
373
379
  actorStore,
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport * as plc from '@did-plc/lib'\nimport type express from 'express'\nimport type { Redis } from 'ioredis'\nimport * as nodemailer from 'nodemailer'\nimport * as ui8 from 'uint8arrays'\nimport type * as undici from 'undici'\nimport { KmsKeypair, S3BlobStore } from '@atproto/aws'\nimport * as crypto from '@atproto/crypto'\nimport { IdResolver } from '@atproto/identity'\nimport { Client } from '@atproto/lex-client'\nimport { parseCid } from '@atproto/lex-data'\nimport {\n AccessTokenMode,\n JoseKey,\n LexResolver,\n LexResolverError,\n OAuthProvider,\n} from '@atproto/oauth-provider/provider'\nimport { OAuthVerifier } from '@atproto/oauth-provider/verifier'\nimport type { BlobStoreCreator } from '@atproto/repo'\nimport {\n createServiceAuthHeaders,\n createServiceJwt,\n} from '@atproto/xrpc-server'\nimport { type Fetch, safeFetchWrap } from '@atproto-labs/fetch-node'\nimport { AccountManager } from './account-manager/account-manager.js'\nimport { OAuthStore } from './account-manager/oauth-store.js'\nimport { ScopeReferenceGetter } from './account-manager/scope-reference-getter.js'\nimport { ActorStore } from './actor-store/actor-store.js'\nimport { authPassthru, forwardedFor } from './api/proxy.js'\nimport {\n AuthVerifier,\n createPublicKeyObject,\n createSecretKeyObject,\n} from './auth-verifier.js'\nimport { BackgroundQueue } from './background.js'\nimport { BskyAppView } from './bsky-app-view.js'\nimport {\n type ServerConfig,\n type ServerEnvironment,\n type ServerSecrets,\n envToCfg,\n envToSecrets,\n readEnv,\n} from './config/index.js'\nimport { Crawlers } from './crawlers.js'\nimport { DidSqliteCache } from './did-cache/index.js'\nimport { DiskBlobStore } from './disk-blobstore.js'\nimport { events } from './events.js'\nimport { ImageUrlBuilder } from './image/image-url-builder.js'\nimport { fetchLogger, lexiconResolverLogger, oauthLogger } from './logger.js'\nimport { ServerMailer } from './mailer/index.js'\nimport { ModerationMailer } from './mailer/moderation.js'\nimport { buildProxyAgent } from './pipethrough.js'\nimport {\n LocalViewer,\n type LocalViewerCreator,\n} from './read-after-write/viewer.js'\nimport { getRedisClient } from './redis.js'\nimport { Sequencer } from './sequencer/index.js'\n\nexport type AppContextOptions = {\n actorStore: ActorStore\n blobstore: BlobStoreCreator\n localViewer: LocalViewerCreator\n mailer: ServerMailer\n moderationMailer: ModerationMailer\n didCache: DidSqliteCache\n idResolver: IdResolver\n plcClient: plc.Client\n accountManager: AccountManager\n sequencer: Sequencer\n backgroundQueue: BackgroundQueue\n redisScratch?: Redis\n crawlers: Crawlers\n bskyAppView?: BskyAppView\n moderationClient?: Client\n reportingClient?: Client\n entrywayClient?: Client\n entrywayAdminClient?: Client\n proxyAgent: undici.Dispatcher\n safeFetch: Fetch\n oauthProvider?: OAuthProvider\n authVerifier: AuthVerifier\n plcRotationKey: crypto.Keypair\n cfg: ServerConfig\n}\n\nexport class AppContext implements AsyncDisposable {\n public actorStore: ActorStore\n public blobstore: BlobStoreCreator\n public localViewer: LocalViewerCreator\n public mailer: ServerMailer\n public moderationMailer: ModerationMailer\n public didCache: DidSqliteCache\n public idResolver: IdResolver\n public plcClient: plc.Client\n public accountManager: AccountManager\n public sequencer: Sequencer\n public backgroundQueue: BackgroundQueue\n public redisScratch?: Redis\n public crawlers: Crawlers\n public bskyAppView?: BskyAppView\n public moderationClient: Client | undefined\n public reportingClient: Client | undefined\n public entrywayClient: Client | undefined\n public entrywayAdminClient: Client | undefined\n public proxyAgent: undici.Dispatcher\n public safeFetch: Fetch\n public authVerifier: AuthVerifier\n public oauthProvider?: OAuthProvider\n public plcRotationKey: crypto.Keypair\n public cfg: ServerConfig\n\n constructor(opts: AppContextOptions) {\n this.actorStore = opts.actorStore\n this.blobstore = opts.blobstore\n this.localViewer = opts.localViewer\n this.mailer = opts.mailer\n this.moderationMailer = opts.moderationMailer\n this.didCache = opts.didCache\n this.idResolver = opts.idResolver\n this.plcClient = opts.plcClient\n this.accountManager = opts.accountManager\n this.sequencer = opts.sequencer\n this.backgroundQueue = opts.backgroundQueue\n this.redisScratch = opts.redisScratch\n this.crawlers = opts.crawlers\n this.bskyAppView = opts.bskyAppView\n this.moderationClient = opts.moderationClient\n this.reportingClient = opts.reportingClient\n this.entrywayClient = opts.entrywayClient\n this.entrywayAdminClient = opts.entrywayAdminClient\n this.proxyAgent = opts.proxyAgent\n this.safeFetch = opts.safeFetch\n this.authVerifier = opts.authVerifier\n this.oauthProvider = opts.oauthProvider\n this.plcRotationKey = opts.plcRotationKey\n this.cfg = opts.cfg\n }\n\n static async fromEnv(\n env: ServerEnvironment = readEnv(),\n overrides?: Partial<AppContextOptions>,\n ): Promise<AppContext> {\n const cfg = envToCfg(env)\n const secrets = envToSecrets(env)\n return AppContext.fromConfig(cfg, secrets, overrides)\n }\n\n static async fromConfig(\n cfg: ServerConfig,\n secrets: ServerSecrets,\n overrides?: Partial<AppContextOptions>,\n ): Promise<AppContext> {\n // @TODO Implement using an AsyncDisposableStack\n\n const blobstore: BlobStoreCreator =\n overrides?.blobstore ??\n (cfg.blobstore.provider === 's3'\n ? S3BlobStore.creator({\n bucket: cfg.blobstore.bucket,\n region: cfg.blobstore.region,\n endpoint: cfg.blobstore.endpoint,\n forcePathStyle: cfg.blobstore.forcePathStyle,\n credentials: cfg.blobstore.credentials,\n uploadTimeoutMs: cfg.blobstore.uploadTimeoutMs,\n requestTimeoutMs: cfg.blobstore.requestTimeoutMs,\n })\n : DiskBlobStore.creator(\n cfg.blobstore.location,\n cfg.blobstore.tempLocation,\n ))\n\n const mailTransport =\n cfg.email !== null\n ? nodemailer.createTransport(cfg.email.smtpUrl)\n : nodemailer.createTransport({ jsonTransport: true })\n\n const mailer = new ServerMailer(\n mailTransport,\n cfg.email,\n cfg.branding,\n cfg.oauth.issuer,\n )\n\n const modMailTransport =\n cfg.moderationEmail !== null\n ? nodemailer.createTransport(cfg.moderationEmail.smtpUrl)\n : nodemailer.createTransport({ jsonTransport: true })\n\n const moderationMailer = new ModerationMailer(modMailTransport, cfg)\n\n /**\n * A fetch() function that protects against SSRF attacks, large responses &\n * known bad domains. This function can safely be used to fetch user\n * provided URLs (unless \"disableSsrfProtection\" is true, of course).\n *\n * @note **DO NOT** wrap `safeFetch` with any logging or other transforms as\n * this might prevent the use of explicit `redirect: \"follow\"` init from\n * working. See {@link safeFetchWrap}.\n */\n const safeFetch = safeFetchWrap({\n allowIpHost: false,\n allowImplicitRedirect: false,\n responseMaxSize: cfg.fetch.maxResponseSize,\n ssrfProtection: !cfg.fetch.disableSsrfProtection,\n\n fetch: function (input, init) {\n const method =\n init?.method ?? (input instanceof Request ? input.method : 'GET')\n const uri = input instanceof Request ? input.url : String(input)\n\n fetchLogger.info({ method, uri }, 'fetch')\n\n return globalThis.fetch.call(this, input, init)\n },\n })\n\n const didCache = new DidSqliteCache(\n cfg.db.didCacheDbLoc,\n cfg.identity.cacheStaleTTL,\n cfg.identity.cacheMaxTTL,\n cfg.db.disableWalAutoCheckpoint,\n )\n await didCache.migrateOrThrow()\n\n const idResolver = new IdResolver({\n plcUrl: cfg.identity.plcUrl,\n didCache,\n timeout: cfg.identity.resolverTimeout,\n backupNameservers: cfg.identity.handleBackupNameservers,\n fetch: safeFetch,\n })\n const plcClient = new plc.Client(cfg.identity.plcUrl)\n\n const backgroundQueue = new BackgroundQueue(undefined, { concurrency: 5 })\n const crawlers = new Crawlers(\n backgroundQueue,\n cfg.service.hostname,\n cfg.crawlers,\n )\n const sequencer = new Sequencer(\n cfg.db.sequencerDbLoc,\n crawlers,\n undefined,\n cfg.db.disableWalAutoCheckpoint,\n )\n const redisScratch = cfg.redis\n ? getRedisClient(cfg.redis.address, cfg.redis.password)\n : undefined\n\n const bskyAppView = cfg.bskyAppView\n ? new BskyAppView({\n ...cfg.bskyAppView,\n validateResponse: cfg.service.devMode,\n })\n : undefined\n\n const moderationClient = cfg.modService\n ? new Client(\n { service: cfg.modService.url },\n {\n // Trust internal services to send us well-formed responses\n strictResponseProcessing: false,\n validateResponse: cfg.service.devMode,\n },\n )\n : undefined\n const reportingClient = cfg.reportService\n ? new Client(\n { service: cfg.reportService.url },\n {\n // Trust internal services to send us well-formed responses\n strictResponseProcessing: false,\n validateResponse: cfg.service.devMode,\n },\n )\n : undefined\n const entrywayClient = cfg.entryway\n ? new Client(\n { service: cfg.entryway.url },\n {\n // Trust internal services to send us well-formed responses\n strictResponseProcessing: false,\n validateResponse: cfg.service.devMode,\n },\n )\n : undefined\n const entrywayAdminClient =\n cfg.entryway && secrets.entrywayAdminToken\n ? new Client(\n {\n service: cfg.entryway.url,\n headers: {\n authorization: basicAuthHeader(\n 'admin',\n secrets.entrywayAdminToken,\n ),\n },\n },\n {\n // Trust internal services to send us well-formed responses\n strictResponseProcessing: false,\n validateResponse: cfg.service.devMode,\n },\n )\n : undefined\n\n const jwtSecretKey = createSecretKeyObject(secrets.jwtSecret)\n const jwtPublicKey = cfg.entryway\n ? createPublicKeyObject(cfg.entryway.jwtPublicKeyHex)\n : null\n\n const imageUrlBuilder = new ImageUrlBuilder(\n cfg.service.hostname,\n bskyAppView,\n )\n\n const actorStore = new ActorStore(cfg.actorStore, {\n blobstore,\n backgroundQueue,\n })\n\n const plcRotationKey =\n overrides?.plcRotationKey ??\n (secrets.plcRotationKey?.provider === 'kms'\n ? await KmsKeypair.load({\n keyId: secrets.plcRotationKey.keyId,\n })\n : secrets.plcRotationKey?.provider === 'memory'\n ? await crypto.Secp256k1Keypair.import(\n secrets.plcRotationKey.privateKeyHex,\n )\n : undefined)\n\n if (!plcRotationKey) {\n throw new Error('Must configure plc rotation key')\n }\n\n const accountManager = new AccountManager(\n cfg,\n actorStore,\n idResolver,\n jwtSecretKey,\n mailer,\n sequencer,\n plcClient,\n plcRotationKey,\n )\n await accountManager.migrateOrThrow()\n\n // @TODO Use this lexResolver instance to implement validation of records\n // created with the \"validate\" option. Before doing so, ensure that 1) a\n // didCache is provided, and 2) that nsid->lexicon are cached.\n const lexResolver = new LexResolver({\n fetch: safeFetch,\n didCache: undefined, // @TODO provide a dedicated cache\n plcDirectoryUrl: cfg.identity.plcUrl,\n hooks: {\n // @NOTE Lexicons hosted by this PDS are read straight from the\n // actor store. Fetching them over the network would require this\n // server to reach its own public endpoint, which is not\n // guaranteed to work (SSRF protection, missing NAT hairpin,\n // internal reverse proxies, ...).\n onFetch: async ({ uri, did, nsid, signal }) => {\n const account = await accountManager.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n signal?.throwIfAborted()\n\n // Mirror what com.atproto.sync.getRecord would answer to an\n // unauthenticated requester\n if (account?.takedownRef) {\n throw new LexResolverError(nsid, `Repo is not available: ${did}`)\n }\n\n // Not hosted here: fall back to the network resolution\n if (!account || account.deactivatedAt) return undefined\n\n const record = await actorStore.read(account.did, (store) => {\n return store.record.getRecord(uri, null)\n })\n\n if (!record || record.takedownRef != null) {\n throw new LexResolverError(\n nsid,\n `Lexicon record not found at ${uri}`,\n )\n }\n\n return {\n cid: parseCid(record.cid),\n record: record.value,\n }\n },\n onFetchResult({ uri, cid, source }) {\n lexiconResolverLogger.info(\n { uri: uri.toString(), cid: cid.toString(), source },\n 'Fetched lexicon',\n )\n },\n onFetchError({ err, uri }) {\n lexiconResolverLogger.error(\n { uri: uri.toString(), err },\n 'Lexicon fetch error',\n )\n },\n onResolveAuthority: ({ nsid }) => {\n lexiconResolverLogger.debug(\n { nsid: nsid.toString() },\n 'Resolving lexicon DID authority',\n )\n // Override the lexicon did resolution to point to a custom PDS\n return cfg.lexicon.didAuthority\n },\n onResolveAuthorityResult({ nsid, did, source }) {\n lexiconResolverLogger.info(\n { nsid: nsid.toString(), did, source },\n 'Resolved lexicon DID',\n )\n },\n onResolveAuthorityError({ nsid, err }) {\n lexiconResolverLogger.error(\n { nsid: nsid.toString(), err },\n 'Lexicon DID resolution error',\n )\n },\n },\n })\n\n const localViewer = LocalViewer.creator(\n accountManager,\n imageUrlBuilder,\n bskyAppView,\n )\n\n // An agent for performing HTTP requests based on user provided URLs.\n const proxyAgent = buildProxyAgent(cfg.proxy)\n\n const oauthProvider = cfg.oauth.provider\n ? new OAuthProvider({\n issuer: cfg.oauth.issuer,\n keyset: [await JoseKey.fromKeyLike(jwtSecretKey, undefined, 'HS256')],\n store: new OAuthStore(\n accountManager,\n actorStore,\n imageUrlBuilder,\n backgroundQueue,\n mailer,\n sequencer,\n plcClient,\n plcRotationKey,\n cfg.service.publicUrl,\n cfg.identity.recoveryDidKey,\n ),\n redis: redisScratch,\n dpopSecret: secrets.dpopSecret,\n inviteCodeRequired: cfg.invites.required,\n availableUserDomains: cfg.identity.serviceHandleDomains,\n hcaptcha: cfg.oauth.provider.hcaptcha,\n branding: cfg.oauth.provider.branding,\n // @NOTE Not operator-configurable on purpose: changing the email\n // address unconditionally clears `emailAuthFactorAt` (see\n // `account-manager/helpers/account.ts`), so the warning describes\n // what this implementation always does rather than a preference. This\n // is because updating email writes an unconfirmed email to the email\n // column, which means leaving email based 2FA enabled can result in\n // account lock-out.\n show2FaWarningOnEmailUpdate: true,\n allowHttp: cfg.service.devMode,\n plcDirectoryUrl: cfg.identity.plcUrl,\n fallbackNameservers: cfg.identity.handleBackupNameservers,\n handleCache: undefined, // Memory\n didCache: {\n // Map didCache to SimpleCache<Did, DidDocument>\n get: async (did) => {\n const res = await didCache.checkCache(did)\n // Expired entries are only ever refreshed by a resolution, so\n // report them as missing rather than serving them indefinitely.\n return res && !res.expired ? (res.doc as any) : undefined\n },\n set: async (did, doc) => {\n await didCache.cacheDid(did, doc as any)\n },\n del: async (did) => {\n await didCache.clearEntry(did)\n },\n },\n safeFetch,\n lexResolver,\n metadata: {\n protected_resources: [new URL(cfg.oauth.issuer).origin],\n },\n // If the PDS is both an authorization server & resource server (no\n // entryway), we can afford to check the token validity on every\n // request. This allows revoked tokens to be rejected immediately.\n // This also allows JWT to be shorter since some claims (notably the\n // \"scope\" claim) do not need to be included in the token.\n accessTokenMode: AccessTokenMode.stateful,\n\n getClientInfo(clientId) {\n return {\n isTrusted: cfg.oauth.provider?.trustedClients?.includes(clientId),\n }\n },\n onSignedUp({ account, data, clientId }) {\n events.accountCreated({\n source: 'oauth',\n did: account.did,\n clientId,\n invited: data.inviteCode != null,\n deactivated: false,\n })\n },\n onSignedIn({ account, clientId }) {\n events.signedIn({\n did: account.did,\n clientId,\n })\n },\n onAuthorized({ account, client }) {\n events.oauthAuthorized({\n did: account.did,\n clientId: client.id,\n clientFirstParty: client.isFirstParty,\n clientTrusted: client.isTrusted,\n clientConfidential: client.isConfidential,\n })\n },\n onTokenCreated({ account, client }) {\n events.sessionCreated({\n source: 'oauth',\n did: account.did,\n clientId: client.id,\n })\n },\n onTokenRefreshed({ account, client }) {\n events.sessionRefreshed({\n source: 'oauth',\n did: account.did,\n clientId: client.id,\n })\n },\n })\n : undefined\n\n const scopeRefGetter = entrywayClient\n ? new ScopeReferenceGetter(entrywayClient, redisScratch)\n : undefined\n\n const oauthVerifier: OAuthVerifier =\n oauthProvider ?? // OAuthProvider extends OAuthVerifier\n new OAuthVerifier({\n issuer: cfg.oauth.issuer,\n keyset: [await JoseKey.fromKeyLike(jwtPublicKey!, undefined, 'ES256K')],\n dpopSecret: secrets.dpopSecret,\n redis: redisScratch,\n onDecodeToken: async ({ payload, dpopProof }) => {\n // @TODO drop this once oauth provider no longer accepts DPoP proof with\n // query or fragment in \"htu\" claim.\n if (dpopProof?.htu.match(/[?#]/)) {\n oauthLogger.info(\n { htu: dpopProof.htu, client_id: payload.client_id },\n 'DPoP proof \"htu\" contains query or fragment',\n )\n }\n\n if (scopeRefGetter) {\n payload.scope = await scopeRefGetter.dereference(payload.scope)\n }\n\n return payload\n },\n })\n\n const authVerifier = new AuthVerifier(\n accountManager,\n idResolver,\n oauthVerifier,\n {\n publicUrl: cfg.service.publicUrl,\n jwtKey: jwtPublicKey ?? jwtSecretKey,\n adminPass: secrets.adminPassword,\n dids: {\n pds: cfg.service.did,\n entryway: cfg.entryway?.did,\n modService: cfg.modService?.did,\n },\n },\n )\n\n return new AppContext({\n actorStore,\n blobstore,\n localViewer,\n mailer,\n moderationMailer,\n didCache,\n idResolver,\n plcClient,\n accountManager,\n sequencer,\n backgroundQueue,\n redisScratch,\n crawlers,\n bskyAppView,\n moderationClient,\n reportingClient,\n entrywayClient,\n entrywayAdminClient,\n proxyAgent,\n safeFetch,\n authVerifier,\n oauthProvider,\n plcRotationKey,\n cfg,\n ...(overrides ?? {}),\n })\n }\n\n async appviewAuthHeaders(did: string, lxm: string) {\n assert(this.bskyAppView)\n return this.serviceAuthHeaders(did, this.bskyAppView.did, lxm)\n }\n\n async entrywayAuthHeaders(req: express.Request, did: string, lxm: string) {\n assert(this.cfg.entryway)\n const headers = await this.serviceAuthHeaders(\n did,\n this.cfg.entryway.did,\n lxm,\n )\n return forwardedFor(req, headers)\n }\n\n entrywayPassthruHeaders(req: express.Request) {\n return forwardedFor(req, authPassthru(req))\n }\n\n /**\n * A {@link Client} for a service URL that was resolved from a DID document,\n * i.e. a URL the PDS does not control. Routes the request through\n * {@link safeFetch}, which restricts it to https origins that resolve to\n * unicast addresses, and caps the response size. Lexicon validation follows\n * the service's dev mode, as it does for the AppView client.\n *\n * Any call built from a DID document's service endpoint must use this.\n */\n safeClient(service: string | URL): Client {\n return new Client(\n { service, fetch: this.safeFetch },\n {\n validateRequest: this.cfg.service.devMode,\n validateResponse: this.cfg.service.devMode,\n strictResponseProcessing: this.cfg.service.devMode,\n },\n )\n }\n\n async serviceAuthHeaders(did: string, aud: string, lxm: string) {\n const keypair = await this.actorStore.keypair(did)\n return createServiceAuthHeaders({\n iss: did,\n aud,\n lxm,\n keypair,\n })\n }\n\n async serviceAuthJwt(did: string, aud: string, lxm: string) {\n const keypair = await this.actorStore.keypair(did)\n return createServiceJwt({\n iss: did,\n aud,\n lxm,\n keypair,\n })\n }\n\n async destroy(): Promise<void> {\n // @TODO Implement this using an AsyncDisposableStack when it becomes\n // widely available.\n try {\n await this.backgroundQueue.destroy()\n } finally {\n try {\n await this.sequencer.destroy()\n } finally {\n try {\n await this.accountManager.close()\n } finally {\n try {\n await this.redisScratch?.quit()\n } finally {\n try {\n await this.proxyAgent.destroy()\n } finally {\n await this.blobstore[Symbol.asyncDispose]()\n }\n }\n }\n }\n }\n }\n\n async [Symbol.asyncDispose]() {\n await this.destroy()\n }\n}\n\nconst basicAuthHeader = (username: string, password: string) => {\n const encoded = ui8.toString(\n ui8.fromString(`${username}:${password}`, 'utf8'),\n 'base64pad',\n )\n return `Basic ${encoded}`\n}\n\nexport default AppContext\n"]}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport * as plc from '@did-plc/lib'\nimport type express from 'express'\nimport type { Redis } from 'ioredis'\nimport * as nodemailer from 'nodemailer'\nimport * as ui8 from 'uint8arrays'\nimport type * as undici from 'undici'\nimport { KmsKeypair, S3BlobStore } from '@atproto/aws'\nimport * as crypto from '@atproto/crypto'\nimport { IdResolver } from '@atproto/identity'\nimport { Client } from '@atproto/lex-client'\nimport { parseCid } from '@atproto/lex-data'\nimport {\n AccessTokenMode,\n JoseKey,\n LexResolver,\n LexResolverError,\n OAuthProvider,\n} from '@atproto/oauth-provider/provider'\nimport { OAuthVerifier } from '@atproto/oauth-provider/verifier'\nimport type { BlobStoreCreator } from '@atproto/repo'\nimport {\n createServiceAuthHeaders,\n createServiceJwt,\n} from '@atproto/xrpc-server'\nimport { type Fetch, safeFetchWrap } from '@atproto-labs/fetch-node'\nimport { AccountManager } from './account-manager/account-manager.js'\nimport { OAuthStore } from './account-manager/oauth-store.js'\nimport { ScopeReferenceGetter } from './account-manager/scope-reference-getter.js'\nimport { ActorStore } from './actor-store/actor-store.js'\nimport { authPassthru, forwardedFor } from './api/proxy.js'\nimport {\n AuthVerifier,\n createPublicKeyObject,\n createSecretKeyObject,\n} from './auth-verifier.js'\nimport { BackgroundQueue } from './background.js'\nimport { BskyAppView } from './bsky-app-view.js'\nimport {\n type ServerConfig,\n type ServerEnvironment,\n type ServerSecrets,\n envToCfg,\n envToSecrets,\n readEnv,\n} from './config/index.js'\nimport { Crawlers } from './crawlers.js'\nimport { DidSqliteCache } from './did-cache/index.js'\nimport { DiskBlobStore } from './disk-blobstore.js'\nimport { events } from './events.js'\nimport { ImageUrlBuilder } from './image/image-url-builder.js'\nimport { fetchLogger, lexiconResolverLogger, oauthLogger } from './logger.js'\nimport { ServerMailer } from './mailer/index.js'\nimport { ModerationMailer } from './mailer/moderation.js'\nimport { buildProxyAgent } from './pipethrough.js'\nimport {\n LocalViewer,\n type LocalViewerCreator,\n} from './read-after-write/viewer.js'\nimport { getRedisClient } from './redis.js'\nimport { Sequencer } from './sequencer/index.js'\n\nexport type AppContextOptions = {\n actorStore: ActorStore\n blobstore: BlobStoreCreator\n localViewer: LocalViewerCreator\n mailer: ServerMailer\n moderationMailer: ModerationMailer\n didCache: DidSqliteCache\n idResolver: IdResolver\n plcClient: plc.Client\n accountManager: AccountManager\n sequencer: Sequencer\n backgroundQueue: BackgroundQueue\n redisScratch?: Redis\n crawlers: Crawlers\n bskyAppView?: BskyAppView\n moderationClient?: Client\n reportingClient?: Client\n entrywayClient?: Client\n entrywayAdminClient?: Client\n proxyAgent: undici.Dispatcher\n safeFetch: Fetch\n oauthProvider?: OAuthProvider\n authVerifier: AuthVerifier\n plcRotationKey: crypto.Keypair\n cfg: ServerConfig\n}\n\nexport class AppContext implements AsyncDisposable {\n public actorStore: ActorStore\n public blobstore: BlobStoreCreator\n public localViewer: LocalViewerCreator\n public mailer: ServerMailer\n public moderationMailer: ModerationMailer\n public didCache: DidSqliteCache\n public idResolver: IdResolver\n public plcClient: plc.Client\n public accountManager: AccountManager\n public sequencer: Sequencer\n public backgroundQueue: BackgroundQueue\n public redisScratch?: Redis\n public crawlers: Crawlers\n public bskyAppView?: BskyAppView\n public moderationClient: Client | undefined\n public reportingClient: Client | undefined\n public entrywayClient: Client | undefined\n public entrywayAdminClient: Client | undefined\n public proxyAgent: undici.Dispatcher\n public safeFetch: Fetch\n public authVerifier: AuthVerifier\n public oauthProvider?: OAuthProvider\n public plcRotationKey: crypto.Keypair\n public cfg: ServerConfig\n\n constructor(opts: AppContextOptions) {\n this.actorStore = opts.actorStore\n this.blobstore = opts.blobstore\n this.localViewer = opts.localViewer\n this.mailer = opts.mailer\n this.moderationMailer = opts.moderationMailer\n this.didCache = opts.didCache\n this.idResolver = opts.idResolver\n this.plcClient = opts.plcClient\n this.accountManager = opts.accountManager\n this.sequencer = opts.sequencer\n this.backgroundQueue = opts.backgroundQueue\n this.redisScratch = opts.redisScratch\n this.crawlers = opts.crawlers\n this.bskyAppView = opts.bskyAppView\n this.moderationClient = opts.moderationClient\n this.reportingClient = opts.reportingClient\n this.entrywayClient = opts.entrywayClient\n this.entrywayAdminClient = opts.entrywayAdminClient\n this.proxyAgent = opts.proxyAgent\n this.safeFetch = opts.safeFetch\n this.authVerifier = opts.authVerifier\n this.oauthProvider = opts.oauthProvider\n this.plcRotationKey = opts.plcRotationKey\n this.cfg = opts.cfg\n }\n\n static async fromEnv(\n env: ServerEnvironment = readEnv(),\n overrides?: Partial<AppContextOptions>,\n ): Promise<AppContext> {\n const cfg = envToCfg(env)\n const secrets = envToSecrets(env)\n return AppContext.fromConfig(cfg, secrets, overrides)\n }\n\n static async fromConfig(\n cfg: ServerConfig,\n secrets: ServerSecrets,\n overrides?: Partial<AppContextOptions>,\n ): Promise<AppContext> {\n // @TODO Implement using an AsyncDisposableStack\n\n const blobstore: BlobStoreCreator =\n overrides?.blobstore ??\n (cfg.blobstore.provider === 's3'\n ? S3BlobStore.creator({\n bucket: cfg.blobstore.bucket,\n region: cfg.blobstore.region,\n endpoint: cfg.blobstore.endpoint,\n forcePathStyle: cfg.blobstore.forcePathStyle,\n credentials: cfg.blobstore.credentials,\n uploadTimeoutMs: cfg.blobstore.uploadTimeoutMs,\n requestTimeoutMs: cfg.blobstore.requestTimeoutMs,\n })\n : DiskBlobStore.creator(\n cfg.blobstore.location,\n cfg.blobstore.tempLocation,\n ))\n\n const mailTransport =\n cfg.email !== null\n ? nodemailer.createTransport(cfg.email.smtpUrl)\n : nodemailer.createTransport({ jsonTransport: true })\n\n const mailer = new ServerMailer(\n mailTransport,\n cfg.email,\n cfg.branding,\n cfg.oauth.issuer,\n )\n\n const modMailTransport =\n cfg.moderationEmail !== null\n ? nodemailer.createTransport(cfg.moderationEmail.smtpUrl)\n : nodemailer.createTransport({ jsonTransport: true })\n\n const moderationMailer = new ModerationMailer(modMailTransport, cfg)\n\n /**\n * A fetch() function that protects against SSRF attacks, large responses &\n * known bad domains. This function can safely be used to fetch user\n * provided URLs (unless \"disableSsrfProtection\" is true, of course).\n *\n * @note **DO NOT** wrap `safeFetch` with any logging or other transforms as\n * this might prevent the use of explicit `redirect: \"follow\"` init from\n * working. See {@link safeFetchWrap}.\n */\n const safeFetch = safeFetchWrap({\n allowIpHost: false,\n allowImplicitRedirect: false,\n responseMaxSize: cfg.fetch.maxResponseSize,\n ssrfProtection: !cfg.fetch.disableSsrfProtection,\n\n fetch: function (input, init) {\n const method =\n init?.method ?? (input instanceof Request ? input.method : 'GET')\n const uri = input instanceof Request ? input.url : String(input)\n\n fetchLogger.info({ method, uri }, 'fetch')\n\n return globalThis.fetch.call(this, input, init)\n },\n })\n\n const didCache = new DidSqliteCache(\n cfg.db.didCacheDbLoc,\n cfg.identity.cacheStaleTTL,\n cfg.identity.cacheMaxTTL,\n cfg.db.disableWalAutoCheckpoint,\n )\n await didCache.migrateOrThrow()\n\n const idResolver = new IdResolver({\n plcUrl: cfg.identity.plcUrl,\n didCache,\n timeout: cfg.identity.resolverTimeout,\n backupNameservers: cfg.identity.handleBackupNameservers,\n fetch: safeFetch,\n })\n const plcClient = new plc.Client(cfg.identity.plcUrl)\n\n const backgroundQueue = new BackgroundQueue(undefined, { concurrency: 5 })\n const crawlers = new Crawlers(\n backgroundQueue,\n cfg.service.hostname,\n cfg.crawlers,\n )\n const sequencer = new Sequencer(\n cfg.db.sequencerDbLoc,\n crawlers,\n undefined,\n cfg.db.disableWalAutoCheckpoint,\n )\n const redisScratch = cfg.redis\n ? getRedisClient(cfg.redis.address, cfg.redis.password)\n : undefined\n\n const bskyAppView = cfg.bskyAppView\n ? new BskyAppView({\n ...cfg.bskyAppView,\n validateResponse: cfg.service.devMode,\n })\n : undefined\n\n const moderationClient = cfg.modService\n ? new Client(\n { service: cfg.modService.url },\n {\n // Trust internal services to send us well-formed responses\n strictResponseProcessing: false,\n validateResponse: cfg.service.devMode,\n },\n )\n : undefined\n const reportingClient = cfg.reportService\n ? new Client(\n { service: cfg.reportService.url },\n {\n // Trust internal services to send us well-formed responses\n strictResponseProcessing: false,\n validateResponse: cfg.service.devMode,\n },\n )\n : undefined\n const entrywayClient = cfg.entryway\n ? new Client(\n { service: cfg.entryway.apiUrl },\n {\n // Trust internal services to send us well-formed responses\n strictResponseProcessing: false,\n validateResponse: cfg.service.devMode,\n },\n )\n : undefined\n const entrywayAdminClient =\n cfg.entryway && secrets.entrywayAdminToken\n ? new Client(\n {\n service: cfg.entryway.apiUrl,\n headers: {\n authorization: basicAuthHeader(\n 'admin',\n secrets.entrywayAdminToken,\n ),\n },\n },\n {\n // Trust internal services to send us well-formed responses\n strictResponseProcessing: false,\n validateResponse: cfg.service.devMode,\n },\n )\n : undefined\n\n const jwtSecretKey = createSecretKeyObject(secrets.jwtSecret)\n const jwtPublicKey = cfg.entryway\n ? createPublicKeyObject(cfg.entryway.jwtPublicKeyHex)\n : null\n\n const imageUrlBuilder = new ImageUrlBuilder(\n cfg.service.hostname,\n bskyAppView,\n )\n\n const actorStore = new ActorStore(cfg.actorStore, {\n blobstore,\n backgroundQueue,\n })\n\n const plcRotationKey =\n overrides?.plcRotationKey ??\n (secrets.plcRotationKey?.provider === 'kms'\n ? await KmsKeypair.load({\n keyId: secrets.plcRotationKey.keyId,\n })\n : secrets.plcRotationKey?.provider === 'memory'\n ? await crypto.Secp256k1Keypair.import(\n secrets.plcRotationKey.privateKeyHex,\n )\n : undefined)\n\n if (!plcRotationKey) {\n throw new Error('Must configure plc rotation key')\n }\n\n const accountManager = new AccountManager(\n cfg,\n actorStore,\n idResolver,\n jwtSecretKey,\n mailer,\n sequencer,\n plcClient,\n plcRotationKey,\n )\n await accountManager.migrateOrThrow()\n\n // @TODO Use this lexResolver instance to implement validation of records\n // created with the \"validate\" option. Before doing so, ensure that 1) a\n // didCache is provided, and 2) that nsid->lexicon are cached.\n const lexResolver = new LexResolver({\n fetch: safeFetch,\n didCache: undefined, // @TODO provide a dedicated cache\n plcDirectoryUrl: cfg.identity.plcUrl,\n hooks: {\n // @NOTE Lexicons hosted by this PDS are read straight from the\n // actor store. Fetching them over the network would require this\n // server to reach its own public endpoint, which is not\n // guaranteed to work (SSRF protection, missing NAT hairpin,\n // internal reverse proxies, ...).\n onFetch: async ({ uri, did, nsid, signal }) => {\n const account = await accountManager.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n signal?.throwIfAborted()\n\n // Mirror what com.atproto.sync.getRecord would answer to an\n // unauthenticated requester\n if (account?.takedownRef) {\n throw new LexResolverError(nsid, `Repo is not available: ${did}`)\n }\n\n // Not hosted here: fall back to the network resolution\n if (!account || account.deactivatedAt) return undefined\n\n const record = await actorStore.read(account.did, (store) => {\n return store.record.getRecord(uri, null)\n })\n\n if (!record || record.takedownRef != null) {\n throw new LexResolverError(\n nsid,\n `Lexicon record not found at ${uri}`,\n )\n }\n\n return {\n cid: parseCid(record.cid),\n record: record.value,\n }\n },\n onFetchResult({ uri, cid, source }) {\n lexiconResolverLogger.info(\n { uri: uri.toString(), cid: cid.toString(), source },\n 'Fetched lexicon',\n )\n },\n onFetchError({ err, uri }) {\n lexiconResolverLogger.error(\n { uri: uri.toString(), err },\n 'Lexicon fetch error',\n )\n },\n onResolveAuthority: ({ nsid }) => {\n lexiconResolverLogger.debug(\n { nsid: nsid.toString() },\n 'Resolving lexicon DID authority',\n )\n // Override the lexicon did resolution to point to a custom PDS\n return cfg.lexicon.didAuthority\n },\n onResolveAuthorityResult({ nsid, did, source }) {\n lexiconResolverLogger.info(\n { nsid: nsid.toString(), did, source },\n 'Resolved lexicon DID',\n )\n },\n onResolveAuthorityError({ nsid, err }) {\n lexiconResolverLogger.error(\n { nsid: nsid.toString(), err },\n 'Lexicon DID resolution error',\n )\n },\n },\n })\n\n const localViewer = LocalViewer.creator(\n accountManager,\n imageUrlBuilder,\n bskyAppView,\n )\n\n // An agent for performing HTTP requests based on user provided URLs.\n const proxyAgent = buildProxyAgent(cfg.proxy)\n\n const oauthProvider = cfg.oauth.provider\n ? new OAuthProvider({\n issuer: cfg.oauth.issuer,\n keyset: [await JoseKey.fromKeyLike(jwtSecretKey, undefined, 'HS256')],\n store: new OAuthStore(\n accountManager,\n actorStore,\n imageUrlBuilder,\n backgroundQueue,\n mailer,\n sequencer,\n plcClient,\n plcRotationKey,\n cfg.service.publicUrl,\n cfg.identity.recoveryDidKey,\n ),\n redis: redisScratch,\n dpopSecret: secrets.dpopSecret,\n inviteCodeRequired: cfg.invites.required,\n availableUserDomains: cfg.identity.serviceHandleDomains,\n hcaptcha: cfg.oauth.provider.hcaptcha,\n branding: cfg.oauth.provider.branding,\n // @NOTE Not operator-configurable on purpose: changing the email\n // address unconditionally clears `emailAuthFactorAt` (see\n // `account-manager/helpers/account.ts`), so the warning describes\n // what this implementation always does rather than a preference. This\n // is because updating email writes an unconfirmed email to the email\n // column, which means leaving email based 2FA enabled can result in\n // account lock-out.\n show2FaWarningOnEmailUpdate: true,\n allowHttp: cfg.service.devMode,\n plcDirectoryUrl: cfg.identity.plcUrl,\n fallbackNameservers: cfg.identity.handleBackupNameservers,\n handleCache: undefined, // Memory\n didCache: {\n // Map didCache to SimpleCache<Did, DidDocument>\n get: async (did) => {\n const res = await didCache.checkCache(did)\n // Expired entries are only ever refreshed by a resolution, so\n // report them as missing rather than serving them indefinitely.\n return res && !res.expired ? (res.doc as any) : undefined\n },\n set: async (did, doc) => {\n await didCache.cacheDid(did, doc as any)\n },\n del: async (did) => {\n await didCache.clearEntry(did)\n },\n },\n safeFetch,\n lexResolver,\n metadata: {\n protected_resources: [new URL(cfg.oauth.issuer).origin],\n },\n // If the PDS is both an authorization server & resource server (no\n // entryway), we can afford to check the token validity on every\n // request. This allows revoked tokens to be rejected immediately.\n // This also allows JWT to be shorter since some claims (notably the\n // \"scope\" claim) do not need to be included in the token.\n accessTokenMode: AccessTokenMode.stateful,\n\n getClientInfo(clientId) {\n return {\n isTrusted: cfg.oauth.provider?.trustedClients?.includes(clientId),\n }\n },\n onSignedUp({ account, data, clientId }) {\n events.accountCreated({\n source: 'oauth',\n did: account.did,\n clientId,\n invited: data.inviteCode != null,\n deactivated: false,\n })\n },\n onSignedIn({ account, clientId }) {\n events.signedIn({\n did: account.did,\n clientId,\n })\n },\n onAuthorized({ account, client }) {\n events.oauthAuthorized({\n did: account.did,\n clientId: client.id,\n clientFirstParty: client.isFirstParty,\n clientTrusted: client.isTrusted,\n clientConfidential: client.isConfidential,\n })\n },\n onTokenCreated({ account, client }) {\n events.sessionCreated({\n source: 'oauth',\n did: account.did,\n clientId: client.id,\n })\n },\n onTokenRefreshed({ account, client }) {\n events.sessionRefreshed({\n source: 'oauth',\n did: account.did,\n clientId: client.id,\n })\n },\n })\n : undefined\n\n const scopeRefGetter = entrywayClient\n ? new ScopeReferenceGetter(entrywayClient, redisScratch)\n : undefined\n\n const oauthVerifier: OAuthVerifier =\n oauthProvider ?? // OAuthProvider extends OAuthVerifier\n new OAuthVerifier({\n issuer: cfg.oauth.issuer,\n keyset: [await JoseKey.fromKeyLike(jwtPublicKey!, undefined, 'ES256K')],\n dpopSecret: secrets.dpopSecret,\n redis: redisScratch,\n onDecodeToken: async ({ payload, dpopProof }) => {\n // @TODO drop this once oauth provider no longer accepts DPoP proof with\n // query or fragment in \"htu\" claim.\n if (dpopProof?.htu.match(/[?#]/)) {\n oauthLogger.info(\n { htu: dpopProof.htu, client_id: payload.client_id },\n 'DPoP proof \"htu\" contains query or fragment',\n )\n }\n\n if (scopeRefGetter) {\n payload.scope = await scopeRefGetter.dereference(payload.scope)\n }\n\n return payload\n },\n })\n\n const authVerifier = new AuthVerifier(\n accountManager,\n idResolver,\n oauthVerifier,\n {\n publicUrl: cfg.service.publicUrl,\n jwtKey: jwtPublicKey ?? jwtSecretKey,\n adminPass: secrets.adminPassword,\n dids: {\n pds: cfg.service.did,\n entryway: cfg.entryway?.did,\n modService: cfg.modService?.did,\n },\n entrywayServiceAuth: cfg.entryway\n ? {\n didKey: crypto.formatDidKey(\n crypto.SECP256K1_JWT_ALG,\n ui8.fromString(cfg.entryway.jwtPublicKeyHex, 'hex'),\n ),\n required: cfg.entryway.requireServiceAuth,\n }\n : undefined,\n },\n )\n\n return new AppContext({\n actorStore,\n blobstore,\n localViewer,\n mailer,\n moderationMailer,\n didCache,\n idResolver,\n plcClient,\n accountManager,\n sequencer,\n backgroundQueue,\n redisScratch,\n crawlers,\n bskyAppView,\n moderationClient,\n reportingClient,\n entrywayClient,\n entrywayAdminClient,\n proxyAgent,\n safeFetch,\n authVerifier,\n oauthProvider,\n plcRotationKey,\n cfg,\n ...(overrides ?? {}),\n })\n }\n\n async appviewAuthHeaders(did: string, lxm: string) {\n assert(this.bskyAppView)\n return this.serviceAuthHeaders(did, this.bskyAppView.did, lxm)\n }\n\n async entrywayAuthHeaders(req: express.Request, did: string, lxm: string) {\n assert(this.cfg.entryway)\n const headers = await this.serviceAuthHeaders(\n did,\n this.cfg.entryway.did,\n lxm,\n )\n return forwardedFor(req, headers)\n }\n\n entrywayPassthruHeaders(req: express.Request) {\n return forwardedFor(req, authPassthru(req))\n }\n\n /**\n * A {@link Client} for a service URL that was resolved from a DID document,\n * i.e. a URL the PDS does not control. Routes the request through\n * {@link safeFetch}, which restricts it to https origins that resolve to\n * unicast addresses, and caps the response size. Lexicon validation follows\n * the service's dev mode, as it does for the AppView client.\n *\n * Any call built from a DID document's service endpoint must use this.\n */\n safeClient(service: string | URL): Client {\n return new Client(\n { service, fetch: this.safeFetch },\n {\n validateRequest: this.cfg.service.devMode,\n validateResponse: this.cfg.service.devMode,\n strictResponseProcessing: this.cfg.service.devMode,\n },\n )\n }\n\n async serviceAuthHeaders(did: string, aud: string, lxm: string) {\n const keypair = await this.actorStore.keypair(did)\n return createServiceAuthHeaders({\n iss: did,\n aud,\n lxm,\n keypair,\n })\n }\n\n async serviceAuthJwt(did: string, aud: string, lxm: string) {\n const keypair = await this.actorStore.keypair(did)\n return createServiceJwt({\n iss: did,\n aud,\n lxm,\n keypair,\n })\n }\n\n async destroy(): Promise<void> {\n // @TODO Implement this using an AsyncDisposableStack when it becomes\n // widely available.\n try {\n await this.backgroundQueue.destroy()\n } finally {\n try {\n await this.sequencer.destroy()\n } finally {\n try {\n await this.accountManager.close()\n } finally {\n try {\n await this.redisScratch?.quit()\n } finally {\n try {\n await this.proxyAgent.destroy()\n } finally {\n await this.blobstore[Symbol.asyncDispose]()\n }\n }\n }\n }\n }\n }\n\n async [Symbol.asyncDispose]() {\n await this.destroy()\n }\n}\n\nconst basicAuthHeader = (username: string, password: string) => {\n const encoded = ui8.toString(\n ui8.fromString(`${username}:${password}`, 'utf8'),\n 'base64pad',\n )\n return `Basic ${encoded}`\n}\n\nexport default AppContext\n"]}
@@ -0,0 +1,39 @@
1
+ import type { KeyObject } from 'node:crypto';
2
+ import type express from 'express';
3
+ import type { HandlerContext } from '@atproto/xrpc-server';
4
+ export declare class EntrywayRelayTokenError extends Error {
5
+ readonly reason: string;
6
+ /**
7
+ * @param reason Why the token was refused, as a short code (such as jose's
8
+ * error code) so that logging it reveals nothing of the token or the client.
9
+ */
10
+ constructor(reason: string, options?: ErrorOptions);
11
+ }
12
+ /**
13
+ * Rate limit bypass for requests the entryway makes with its service JWT.
14
+ * Routes authenticate requests before applying rate limits, so this relies on
15
+ * the route having accepted the token rather than verifying it again.
16
+ */
17
+ export declare const entrywayRateLimitBypass: ({ auth }: HandlerContext) => boolean;
18
+ /**
19
+ * Attributes the user requests the entryway proxies to the users rather than
20
+ * to the entryway, by the relay token it signs. The rate limiters key on
21
+ * `req.ip`, and on methods the PDS proxies they run before anything
22
+ * authenticates the request, so the token is verified here, ahead of the XRPC
23
+ * router.
24
+ */
25
+ export declare function entrywayAttribution(relayTokenOpts: EntrywayRelayTokenOptions): express.RequestHandler;
26
+ type EntrywayRelayTokenOptions = {
27
+ entrywayDid: string;
28
+ pdsDid: string;
29
+ key: KeyObject;
30
+ };
31
+ /**
32
+ * Verifies the relay token that the entryway attaches to the user requests it
33
+ * proxies, and returns the client IP address it attests to, in canonical form.
34
+ *
35
+ * @throws {EntrywayRelayTokenError} if the token is not valid
36
+ */
37
+ export declare function verifyEntrywayRelayToken(token: string, opts: EntrywayRelayTokenOptions): Promise<string>;
38
+ export {};
39
+ //# sourceMappingURL=entryway-attribution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entryway-attribution.d.ts","sourceRoot":"","sources":["../src/entryway-attribution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,OAAO,MAAM,SAAS,CAAA;AAElC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAS1D,qBAAa,uBAAwB,SAAQ,KAAK;aAM9B,MAAM,EAAE,MAAM;IALhC;;;OAGG;IACH,YACkB,MAAM,EAAE,MAAM,EAC9B,OAAO,CAAC,EAAE,YAAY,EAGvB;CACF;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,aAAc,cAAc,KAAG,OAIlE,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,yBAAyB,GACxC,OAAO,CAAC,cAAc,CA2BxB;AAED,KAAK,yBAAyB,GAAG;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,SAAS,CAAA;CACf,CAAA;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAiBjB"}
@@ -0,0 +1,101 @@
1
+ import * as jose from 'jose';
2
+ import { httpLogger } from './logger.js';
3
+ import { canonicalIp } from './util/ip.js';
4
+ const ENTRYWAY_RELAY_HEADER = 'x-entryway-relay';
5
+ const ENTRYWAY_RELAY_TOKEN_MAX_LIFETIME_SEC = 2 * 60;
6
+ const ENTRYWAY_RELAY_TOKEN_CLOCK_TOLERANCE_SEC = 30;
7
+ export class EntrywayRelayTokenError extends Error {
8
+ /**
9
+ * @param reason Why the token was refused, as a short code (such as jose's
10
+ * error code) so that logging it reveals nothing of the token or the client.
11
+ */
12
+ constructor(reason, options) {
13
+ super(`Invalid entryway relay token: ${reason}`, options);
14
+ this.reason = reason;
15
+ }
16
+ }
17
+ /**
18
+ * Rate limit bypass for requests the entryway makes with its service JWT.
19
+ * Routes authenticate requests before applying rate limits, so this relies on
20
+ * the route having accepted the token rather than verifying it again.
21
+ */
22
+ export const entrywayRateLimitBypass = ({ auth }) => {
23
+ if (!auth)
24
+ return false;
25
+ const credentials = auth.credentials;
26
+ return credentials?.type === 'entryway_service';
27
+ };
28
+ /**
29
+ * Attributes the user requests the entryway proxies to the users rather than
30
+ * to the entryway, by the relay token it signs. The rate limiters key on
31
+ * `req.ip`, and on methods the PDS proxies they run before anything
32
+ * authenticates the request, so the token is verified here, ahead of the XRPC
33
+ * router.
34
+ */
35
+ export function entrywayAttribution(relayTokenOpts) {
36
+ return async (req, res, next) => {
37
+ const relayToken = req.headers[ENTRYWAY_RELAY_HEADER];
38
+ if (typeof relayToken === 'string') {
39
+ try {
40
+ const clientIp = await verifyEntrywayRelayToken(relayToken, relayTokenOpts);
41
+ // Shadows express's "ip" getter so that everything reading req.ip
42
+ // (rate limit keys, x-forwarded-for to the entryway) sees the client.
43
+ Object.defineProperty(req, 'ip', {
44
+ value: clientIp,
45
+ configurable: true,
46
+ enumerable: true,
47
+ });
48
+ }
49
+ catch (err) {
50
+ // Never fatal: the request stays attributed to its actual source. Only
51
+ // the reason is logged, as the token itself carries the client's IP.
52
+ const reason = err instanceof EntrywayRelayTokenError ? err.reason : 'error';
53
+ httpLogger.debug({ reason }, 'ignoring invalid entryway relay token');
54
+ }
55
+ }
56
+ next();
57
+ };
58
+ }
59
+ /**
60
+ * Verifies the relay token that the entryway attaches to the user requests it
61
+ * proxies, and returns the client IP address it attests to, in canonical form.
62
+ *
63
+ * @throws {EntrywayRelayTokenError} if the token is not valid
64
+ */
65
+ export async function verifyEntrywayRelayToken(token, opts) {
66
+ return jose
67
+ .jwtVerify(token, opts.key, {
68
+ algorithms: ['ES256K'],
69
+ // Pinned so that access tokens ("at+jwt") are refused
70
+ typ: 'JWT',
71
+ issuer: opts.entrywayDid,
72
+ audience: opts.pdsDid,
73
+ requiredClaims: ['iat', 'exp', 'client_ip'],
74
+ // Also refuses an "iat" in the future
75
+ maxTokenAge: ENTRYWAY_RELAY_TOKEN_MAX_LIFETIME_SEC,
76
+ clockTolerance: ENTRYWAY_RELAY_TOKEN_CLOCK_TOLERANCE_SEC,
77
+ })
78
+ .then(checkEntrywayRelayClaims, (err) => {
79
+ const reason = err instanceof jose.errors.JOSEError ? err.code : 'error';
80
+ throw new EntrywayRelayTokenError(reason, { cause: err });
81
+ });
82
+ }
83
+ // Checks what jwtVerify() does not: "lxm" is refused so that a relay token and
84
+ // a service JWT can never stand in for each other, and "exp" may be at most 120
85
+ // seconds after "iat". Returns the attested client IP in canonical form.
86
+ function checkEntrywayRelayClaims({ payload }) {
87
+ const { iat, exp, lxm, client_ip: clientIp } = payload;
88
+ if (lxm !== undefined) {
89
+ throw new EntrywayRelayTokenError('has_lxm');
90
+ }
91
+ // jwtVerify() made "iat" and "exp" required numbers
92
+ if (exp - iat > ENTRYWAY_RELAY_TOKEN_MAX_LIFETIME_SEC) {
93
+ throw new EntrywayRelayTokenError('bad_lifetime');
94
+ }
95
+ const ip = typeof clientIp === 'string' ? canonicalIp(clientIp) : null;
96
+ if (!ip) {
97
+ throw new EntrywayRelayTokenError('bad_client_ip');
98
+ }
99
+ return ip;
100
+ }
101
+ //# sourceMappingURL=entryway-attribution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entryway-attribution.js","sourceRoot":"","sources":["../src/entryway-attribution.ts"],"names":[],"mappings":"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","sourcesContent":["import type { KeyObject } from 'node:crypto'\nimport type express from 'express'\nimport * as jose from 'jose'\nimport type { HandlerContext } from '@atproto/xrpc-server'\nimport { httpLogger } from './logger.js'\nimport { canonicalIp } from './util/ip.js'\n\nconst ENTRYWAY_RELAY_HEADER = 'x-entryway-relay'\n\nconst ENTRYWAY_RELAY_TOKEN_MAX_LIFETIME_SEC = 2 * 60\nconst ENTRYWAY_RELAY_TOKEN_CLOCK_TOLERANCE_SEC = 30\n\nexport class EntrywayRelayTokenError extends Error {\n /**\n * @param reason Why the token was refused, as a short code (such as jose's\n * error code) so that logging it reveals nothing of the token or the client.\n */\n constructor(\n public readonly reason: string,\n options?: ErrorOptions,\n ) {\n super(`Invalid entryway relay token: ${reason}`, options)\n }\n}\n\n/**\n * Rate limit bypass for requests the entryway makes with its service JWT.\n * Routes authenticate requests before applying rate limits, so this relies on\n * the route having accepted the token rather than verifying it again.\n */\nexport const entrywayRateLimitBypass = ({ auth }: HandlerContext): boolean => {\n if (!auth) return false\n const credentials = auth.credentials as { type?: unknown }\n return credentials?.type === 'entryway_service'\n}\n\n/**\n * Attributes the user requests the entryway proxies to the users rather than\n * to the entryway, by the relay token it signs. The rate limiters key on\n * `req.ip`, and on methods the PDS proxies they run before anything\n * authenticates the request, so the token is verified here, ahead of the XRPC\n * router.\n */\nexport function entrywayAttribution(\n relayTokenOpts: EntrywayRelayTokenOptions,\n): express.RequestHandler {\n return async (req, res, next) => {\n const relayToken = req.headers[ENTRYWAY_RELAY_HEADER]\n if (typeof relayToken === 'string') {\n try {\n const clientIp = await verifyEntrywayRelayToken(\n relayToken,\n relayTokenOpts,\n )\n // Shadows express's \"ip\" getter so that everything reading req.ip\n // (rate limit keys, x-forwarded-for to the entryway) sees the client.\n Object.defineProperty(req, 'ip', {\n value: clientIp,\n configurable: true,\n enumerable: true,\n })\n } catch (err) {\n // Never fatal: the request stays attributed to its actual source. Only\n // the reason is logged, as the token itself carries the client's IP.\n const reason =\n err instanceof EntrywayRelayTokenError ? err.reason : 'error'\n httpLogger.debug({ reason }, 'ignoring invalid entryway relay token')\n }\n }\n\n next()\n }\n}\n\ntype EntrywayRelayTokenOptions = {\n entrywayDid: string\n pdsDid: string\n key: KeyObject\n}\n\n/**\n * Verifies the relay token that the entryway attaches to the user requests it\n * proxies, and returns the client IP address it attests to, in canonical form.\n *\n * @throws {EntrywayRelayTokenError} if the token is not valid\n */\nexport async function verifyEntrywayRelayToken(\n token: string,\n opts: EntrywayRelayTokenOptions,\n): Promise<string> {\n return jose\n .jwtVerify(token, opts.key, {\n algorithms: ['ES256K'],\n // Pinned so that access tokens (\"at+jwt\") are refused\n typ: 'JWT',\n issuer: opts.entrywayDid,\n audience: opts.pdsDid,\n requiredClaims: ['iat', 'exp', 'client_ip'],\n // Also refuses an \"iat\" in the future\n maxTokenAge: ENTRYWAY_RELAY_TOKEN_MAX_LIFETIME_SEC,\n clockTolerance: ENTRYWAY_RELAY_TOKEN_CLOCK_TOLERANCE_SEC,\n })\n .then(checkEntrywayRelayClaims, (err) => {\n const reason = err instanceof jose.errors.JOSEError ? err.code : 'error'\n throw new EntrywayRelayTokenError(reason, { cause: err })\n })\n}\n\n// Checks what jwtVerify() does not: \"lxm\" is refused so that a relay token and\n// a service JWT can never stand in for each other, and \"exp\" may be at most 120\n// seconds after \"iat\". Returns the attested client IP in canonical form.\nfunction checkEntrywayRelayClaims({ payload }: jose.JWTVerifyResult): string {\n const { iat, exp, lxm, client_ip: clientIp } = payload\n if (lxm !== undefined) {\n throw new EntrywayRelayTokenError('has_lxm')\n }\n // jwtVerify() made \"iat\" and \"exp\" required numbers\n if (exp! - iat! > ENTRYWAY_RELAY_TOKEN_MAX_LIFETIME_SEC) {\n throw new EntrywayRelayTokenError('bad_lifetime')\n }\n const ip = typeof clientIp === 'string' ? canonicalIp(clientIp) : null\n if (!ip) {\n throw new EntrywayRelayTokenError('bad_client_ip')\n }\n return ip\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -64,9 +64,11 @@ import { DAY, SECOND } from '@atproto/common';
64
64
  import { ResponseType, XRPCError, createServer, } from '@atproto/xrpc-server';
65
65
  import apiRoutes from './api/index.js';
66
66
  import * as authRoutes from './auth-routes.js';
67
+ import { createPublicKeyObject } from './auth-verifier.js';
67
68
  import * as basicRoutes from './basic-routes.js';
68
69
  import { envToCfg, envToSecrets, readEnv, } from './config/index.js';
69
70
  import { AppContext } from './context.js';
71
+ import { entrywayAttribution, entrywayRateLimitBypass, } from './entryway-attribution.js';
70
72
  import * as error from './error.js';
71
73
  import { loggerMiddleware, pdsLogger } from './logger.js';
72
74
  import { proxyHandler } from './pipethrough.js';
@@ -171,7 +173,7 @@ export class PDS {
171
173
  }
172
174
  return XRPCError.fromError(err);
173
175
  },
174
- rateLimits: buildRateLimitsConfig(rateLimits, ctx.redisScratch),
176
+ rateLimits: buildRateLimitsConfig(rateLimits, ctx.redisScratch, cfg.entryway ? entrywayRateLimitBypass : undefined),
175
177
  });
176
178
  apiRoutes(server, ctx);
177
179
  const app = express();
@@ -184,6 +186,13 @@ export class PDS {
184
186
  ...getTrustedIps(cfg),
185
187
  ]);
186
188
  app.use(loggerMiddleware);
189
+ if (cfg.entryway) {
190
+ app.use(entrywayAttribution({
191
+ entrywayDid: cfg.entryway.did,
192
+ pdsDid: cfg.service.did,
193
+ key: createPublicKeyObject(cfg.entryway.jwtPublicKeyHex),
194
+ }));
195
+ }
187
196
  app.use(compression());
188
197
  app.use(authRoutes.createRouter(ctx)); // Before CORS
189
198
  app.use(cors({ maxAge: DAY / SECOND }));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// catch errors that get thrown in async route handlers\n// this is a relatively non-invasive change to express\n// they get handled in the error.handler middleware\n// leave at top of file before importing Routes\nimport 'express-async-errors'\n\nimport events, { once } from 'node:events'\nimport type http from 'node:http'\nimport { PlcClientError } from '@did-plc/lib'\nimport cors from 'cors'\nimport express from 'express'\nimport { type HttpTerminator, createHttpTerminator } from 'http-terminator'\nimport { DAY, SECOND } from '@atproto/common'\nimport {\n type MethodHandler,\n ResponseType,\n XRPCError,\n createServer,\n} from '@atproto/xrpc-server'\nimport apiRoutes from './api/index.js'\nimport * as authRoutes from './auth-routes.js'\nimport * as basicRoutes from './basic-routes.js'\nimport {\n type ServerConfig,\n type ServerEnvironment,\n type ServerSecrets,\n envToCfg,\n envToSecrets,\n readEnv,\n} from './config/index.js'\nimport { AppContext, type AppContextOptions } from './context.js'\nimport * as error from './error.js'\nimport type { app } from './lexicons.js'\nimport { loggerMiddleware, pdsLogger } from './logger.js'\nimport { proxyHandler } from './pipethrough.js'\nimport { buildRateLimitsConfig } from './rate-limits.js'\nimport compression from './util/compression.js'\nimport * as wellKnown from './well-known.js'\n\nexport {\n type KeyObject,\n bearerTokenFromReq,\n createPublicKeyObject,\n createSecretKeyObject,\n} from './auth-verifier.js'\nexport * from './config/index.js'\nexport { AppContext, type AppContextOptions } from './context.js'\nexport { Database } from './db/index.js'\nexport { DiskBlobStore } from './disk-blobstore.js'\nexport * from './lexicons.js'\nexport { httpLogger } from './logger.js'\nexport { type CommitDataWithOps, type PreparedWrite } from './repo/index.js'\nexport * as repoPrepare from './repo/prepare.js'\nexport { scripts } from './scripts/index.js'\nexport * as sequencer from './sequencer/index.js'\n\n/**\n * @deprecated Legacy export for backwards compatibility\n */\nexport type SkeletonHandler = MethodHandler<\n void,\n app.bsky.feed.getFeedSkeleton.$Params,\n void,\n app.bsky.feed.getFeedSkeleton.$Output\n>\n\nexport class PDS implements AsyncDisposable {\n public ctx: AppContext\n public app: express.Application\n public server?: http.Server\n private terminator?: HttpTerminator\n\n constructor(opts: { ctx: AppContext; app: express.Application }) {\n this.ctx = opts.ctx\n this.app = opts.app\n }\n\n static async fromEnv(\n env: ServerEnvironment = readEnv(),\n overrides?: Partial<AppContextOptions>,\n ): Promise<PDS> {\n const cfg = envToCfg(env)\n const secrets = envToSecrets(env)\n return PDS.create(cfg, secrets, overrides)\n }\n\n /**\n * Creates and starts a PDS instance, and waits for a termination signal to\n * stop it.\n */\n static async run({\n env = undefined,\n signal: inputSignal,\n signals = ['SIGINT', 'SIGTERM'],\n onCreated = undefined,\n onStarted = undefined,\n }: {\n env?: ServerEnvironment\n signal?: AbortSignal\n signals?: readonly NodeJS.Signals[]\n /**\n * Hook that allows attaching additional logic (like adding custom HTTP\n * routes) before the PDS is started.\n */\n onCreated?: (pds: PDS) => void | Promise<void>\n onStarted?: (pds: PDS) => void | Promise<void>\n } = {}): Promise<void> {\n const ac = new AbortController()\n const { signal } = ac\n const abort = () => ac.abort()\n\n // Always abort the internal signal, ensuring proper resource cleanup\n using _ = { [Symbol.dispose]: abort }\n\n // Bind the internal signal to the input signal (will automatically remove\n // the listener when the internal signal is aborted)\n inputSignal?.throwIfAborted()\n inputSignal?.addEventListener('abort', abort, { signal })\n\n // Bind the internal signal to the process signals (will automatically\n // remove the listener when the internal signal is aborted)\n for (const sig of signals) {\n process.on(sig, abort)\n signal.addEventListener('abort', () => process.off(sig, abort))\n }\n\n await using pds = await PDS.fromEnv(env)\n\n if (signal.aborted) return\n\n await onCreated?.(pds)\n\n if (signal.aborted) return\n\n pdsLogger.info('starting')\n\n await pds.start()\n\n if (signal.aborted) return\n\n await onStarted?.(pds)\n\n if (signal.aborted) return\n\n pdsLogger.info('started')\n\n await once(signal, 'abort')\n\n pdsLogger.info('stopping')\n }\n\n static async create(\n cfg: ServerConfig,\n secrets: ServerSecrets,\n overrides?: Partial<AppContextOptions>,\n ): Promise<PDS> {\n const ctx = await AppContext.fromConfig(cfg, secrets, overrides)\n\n const { rateLimits } = ctx.cfg\n\n const server = createServer([], {\n validateResponse: cfg.service.devMode,\n payload: {\n jsonLimit: 150 * 1024, // 150kb\n textLimit: 100 * 1024, // 100kb\n blobLimit: cfg.service.blobUploadLimit,\n },\n catchall: proxyHandler(ctx),\n errorParser: (err) => {\n if (err instanceof PlcClientError) {\n const payloadMessage =\n typeof err.data === 'object' &&\n err.data != null &&\n 'message' in err.data &&\n typeof err.data.message === 'string' &&\n err.data.message\n\n const type =\n err.status >= 500\n ? ResponseType.UpstreamFailure\n : ResponseType.InvalidRequest\n\n return new XRPCError(\n type,\n payloadMessage || 'Unable to perform PLC operation',\n )\n }\n\n return XRPCError.fromError(err)\n },\n rateLimits: buildRateLimitsConfig(rateLimits, ctx.redisScratch),\n })\n\n apiRoutes(server, ctx)\n\n const app = express()\n app.set('trust proxy', [\n // e.g. load balancer\n 'loopback',\n 'linklocal',\n 'uniquelocal',\n // e.g. trust x-forwarded-for via entryway ip\n ...getTrustedIps(cfg),\n ])\n app.use(loggerMiddleware)\n app.use(compression())\n app.use(authRoutes.createRouter(ctx)) // Before CORS\n app.use(cors({ maxAge: DAY / SECOND }))\n app.use(basicRoutes.createRouter(ctx))\n app.use(wellKnown.createRouter(ctx))\n app.use(server.router)\n app.use(error.handler)\n\n return new PDS({\n ctx,\n app,\n })\n }\n\n async start(): Promise<http.Server> {\n await this.ctx.sequencer.start()\n const server = this.app.listen(this.ctx.cfg.service.port)\n this.server = server\n this.server.keepAliveTimeout = 90_000\n this.terminator = createHttpTerminator({ server })\n await events.once(server, 'listening')\n return server\n }\n\n async destroy(): Promise<void> {\n try {\n await this.terminator?.terminate()\n } finally {\n await this.ctx.destroy()\n }\n }\n\n async [Symbol.asyncDispose]() {\n await this.destroy()\n }\n}\n\nexport default PDS\n\nconst getTrustedIps = (cfg: ServerConfig) => {\n if (!cfg.rateLimits.enabled) return []\n return cfg.rateLimits.bypassIps ?? []\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// catch errors that get thrown in async route handlers\n// this is a relatively non-invasive change to express\n// they get handled in the error.handler middleware\n// leave at top of file before importing Routes\nimport 'express-async-errors'\n\nimport events, { once } from 'node:events'\nimport type http from 'node:http'\nimport { PlcClientError } from '@did-plc/lib'\nimport cors from 'cors'\nimport express from 'express'\nimport { type HttpTerminator, createHttpTerminator } from 'http-terminator'\nimport { DAY, SECOND } from '@atproto/common'\nimport {\n type MethodHandler,\n ResponseType,\n XRPCError,\n createServer,\n} from '@atproto/xrpc-server'\nimport apiRoutes from './api/index.js'\nimport * as authRoutes from './auth-routes.js'\nimport { createPublicKeyObject } from './auth-verifier.js'\nimport * as basicRoutes from './basic-routes.js'\nimport {\n type ServerConfig,\n type ServerEnvironment,\n type ServerSecrets,\n envToCfg,\n envToSecrets,\n readEnv,\n} from './config/index.js'\nimport { AppContext, type AppContextOptions } from './context.js'\nimport {\n entrywayAttribution,\n entrywayRateLimitBypass,\n} from './entryway-attribution.js'\nimport * as error from './error.js'\nimport type { app } from './lexicons.js'\nimport { loggerMiddleware, pdsLogger } from './logger.js'\nimport { proxyHandler } from './pipethrough.js'\nimport { buildRateLimitsConfig } from './rate-limits.js'\nimport compression from './util/compression.js'\nimport * as wellKnown from './well-known.js'\n\nexport {\n type KeyObject,\n bearerTokenFromReq,\n createPublicKeyObject,\n createSecretKeyObject,\n} from './auth-verifier.js'\nexport * from './config/index.js'\nexport { AppContext, type AppContextOptions } from './context.js'\nexport { Database } from './db/index.js'\nexport { DiskBlobStore } from './disk-blobstore.js'\nexport * from './lexicons.js'\nexport { httpLogger } from './logger.js'\nexport { type CommitDataWithOps, type PreparedWrite } from './repo/index.js'\nexport * as repoPrepare from './repo/prepare.js'\nexport { scripts } from './scripts/index.js'\nexport * as sequencer from './sequencer/index.js'\n\n/**\n * @deprecated Legacy export for backwards compatibility\n */\nexport type SkeletonHandler = MethodHandler<\n void,\n app.bsky.feed.getFeedSkeleton.$Params,\n void,\n app.bsky.feed.getFeedSkeleton.$Output\n>\n\nexport class PDS implements AsyncDisposable {\n public ctx: AppContext\n public app: express.Application\n public server?: http.Server\n private terminator?: HttpTerminator\n\n constructor(opts: { ctx: AppContext; app: express.Application }) {\n this.ctx = opts.ctx\n this.app = opts.app\n }\n\n static async fromEnv(\n env: ServerEnvironment = readEnv(),\n overrides?: Partial<AppContextOptions>,\n ): Promise<PDS> {\n const cfg = envToCfg(env)\n const secrets = envToSecrets(env)\n return PDS.create(cfg, secrets, overrides)\n }\n\n /**\n * Creates and starts a PDS instance, and waits for a termination signal to\n * stop it.\n */\n static async run({\n env = undefined,\n signal: inputSignal,\n signals = ['SIGINT', 'SIGTERM'],\n onCreated = undefined,\n onStarted = undefined,\n }: {\n env?: ServerEnvironment\n signal?: AbortSignal\n signals?: readonly NodeJS.Signals[]\n /**\n * Hook that allows attaching additional logic (like adding custom HTTP\n * routes) before the PDS is started.\n */\n onCreated?: (pds: PDS) => void | Promise<void>\n onStarted?: (pds: PDS) => void | Promise<void>\n } = {}): Promise<void> {\n const ac = new AbortController()\n const { signal } = ac\n const abort = () => ac.abort()\n\n // Always abort the internal signal, ensuring proper resource cleanup\n using _ = { [Symbol.dispose]: abort }\n\n // Bind the internal signal to the input signal (will automatically remove\n // the listener when the internal signal is aborted)\n inputSignal?.throwIfAborted()\n inputSignal?.addEventListener('abort', abort, { signal })\n\n // Bind the internal signal to the process signals (will automatically\n // remove the listener when the internal signal is aborted)\n for (const sig of signals) {\n process.on(sig, abort)\n signal.addEventListener('abort', () => process.off(sig, abort))\n }\n\n await using pds = await PDS.fromEnv(env)\n\n if (signal.aborted) return\n\n await onCreated?.(pds)\n\n if (signal.aborted) return\n\n pdsLogger.info('starting')\n\n await pds.start()\n\n if (signal.aborted) return\n\n await onStarted?.(pds)\n\n if (signal.aborted) return\n\n pdsLogger.info('started')\n\n await once(signal, 'abort')\n\n pdsLogger.info('stopping')\n }\n\n static async create(\n cfg: ServerConfig,\n secrets: ServerSecrets,\n overrides?: Partial<AppContextOptions>,\n ): Promise<PDS> {\n const ctx = await AppContext.fromConfig(cfg, secrets, overrides)\n\n const { rateLimits } = ctx.cfg\n\n const server = createServer([], {\n validateResponse: cfg.service.devMode,\n payload: {\n jsonLimit: 150 * 1024, // 150kb\n textLimit: 100 * 1024, // 100kb\n blobLimit: cfg.service.blobUploadLimit,\n },\n catchall: proxyHandler(ctx),\n errorParser: (err) => {\n if (err instanceof PlcClientError) {\n const payloadMessage =\n typeof err.data === 'object' &&\n err.data != null &&\n 'message' in err.data &&\n typeof err.data.message === 'string' &&\n err.data.message\n\n const type =\n err.status >= 500\n ? ResponseType.UpstreamFailure\n : ResponseType.InvalidRequest\n\n return new XRPCError(\n type,\n payloadMessage || 'Unable to perform PLC operation',\n )\n }\n\n return XRPCError.fromError(err)\n },\n rateLimits: buildRateLimitsConfig(\n rateLimits,\n ctx.redisScratch,\n cfg.entryway ? entrywayRateLimitBypass : undefined,\n ),\n })\n\n apiRoutes(server, ctx)\n\n const app = express()\n app.set('trust proxy', [\n // e.g. load balancer\n 'loopback',\n 'linklocal',\n 'uniquelocal',\n // e.g. trust x-forwarded-for via entryway ip\n ...getTrustedIps(cfg),\n ])\n app.use(loggerMiddleware)\n if (cfg.entryway) {\n app.use(\n entrywayAttribution({\n entrywayDid: cfg.entryway.did,\n pdsDid: cfg.service.did,\n key: createPublicKeyObject(cfg.entryway.jwtPublicKeyHex),\n }),\n )\n }\n app.use(compression())\n app.use(authRoutes.createRouter(ctx)) // Before CORS\n app.use(cors({ maxAge: DAY / SECOND }))\n app.use(basicRoutes.createRouter(ctx))\n app.use(wellKnown.createRouter(ctx))\n app.use(server.router)\n app.use(error.handler)\n\n return new PDS({\n ctx,\n app,\n })\n }\n\n async start(): Promise<http.Server> {\n await this.ctx.sequencer.start()\n const server = this.app.listen(this.ctx.cfg.service.port)\n this.server = server\n this.server.keepAliveTimeout = 90_000\n this.terminator = createHttpTerminator({ server })\n await events.once(server, 'listening')\n return server\n }\n\n async destroy(): Promise<void> {\n try {\n await this.terminator?.terminate()\n } finally {\n await this.ctx.destroy()\n }\n }\n\n async [Symbol.asyncDispose]() {\n await this.destroy()\n }\n}\n\nexport default PDS\n\nconst getTrustedIps = (cfg: ServerConfig) => {\n if (!cfg.rateLimits.enabled) return []\n return cfg.rateLimits.bypassIps ?? []\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAKhD,eAAO,MAAM,SAAS,uBAAsB,CAAA;AAC5C,eAAO,MAAM,eAAe,uBAAiC,CAAA;AAC7D,eAAO,MAAM,QAAQ,uBAAyB,CAAA;AAC9C,eAAO,MAAM,cAAc,uBAAgC,CAAA;AAC3D,eAAO,MAAM,YAAY,uBAA6B,CAAA;AACtD,eAAO,MAAM,gBAAgB,uBAAkC,CAAA;AAC/D,eAAO,MAAM,WAAW,uBAA4B,CAAA;AACpD,eAAO,MAAM,SAAS,uBAAgC,CAAA;AACtD,eAAO,MAAM,YAAY,uBAA6B,CAAA;AACtD,eAAO,MAAM,aAAa,uBAA8B,CAAA;AACxD,eAAO,MAAM,aAAa,uBAA8B,CAAA;AAGxD,eAAO,MAAM,UAAU,uBAAY,CAAA;AACnC,eAAO,MAAM,WAAW,uBAA4B,CAAA;AACpD,eAAO,MAAM,aAAa,uBAIxB,CAAA;AACF,eAAO,MAAM,WAAW,uBAKtB,CAAA;AACF,eAAO,MAAM,aAAa,uBAKxB,CAAA;AACF,eAAO,MAAM,qBAAqB,uBAAuC,CAAA;AAEzE,eAAO,MAAM,gBAAgB,wGAS3B,CAAA"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAShD,eAAO,MAAM,SAAS,uBAAsB,CAAA;AAC5C,eAAO,MAAM,eAAe,uBAAiC,CAAA;AAC7D,eAAO,MAAM,QAAQ,uBAAyB,CAAA;AAC9C,eAAO,MAAM,cAAc,uBAAgC,CAAA;AAC3D,eAAO,MAAM,YAAY,uBAA6B,CAAA;AACtD,eAAO,MAAM,gBAAgB,uBAAkC,CAAA;AAC/D,eAAO,MAAM,WAAW,uBAA4B,CAAA;AACpD,eAAO,MAAM,SAAS,uBAAgC,CAAA;AACtD,eAAO,MAAM,YAAY,uBAA6B,CAAA;AACtD,eAAO,MAAM,aAAa,uBAA8B,CAAA;AACxD,eAAO,MAAM,aAAa,uBAA8B,CAAA;AAGxD,eAAO,MAAM,UAAU,uBAAY,CAAA;AACnC,eAAO,MAAM,WAAW,uBAA4B,CAAA;AACpD,eAAO,MAAM,aAAa,uBAIxB,CAAA;AACF,eAAO,MAAM,WAAW,uBAKtB,CAAA;AACF,eAAO,MAAM,aAAa,uBAKxB,CAAA;AACF,eAAO,MAAM,qBAAqB,uBAAuC,CAAA;AAEzE,eAAO,MAAM,gBAAgB,wGAU3B,CAAA"}
package/dist/logger.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { stdSerializers } from 'pino';
2
2
  import { pinoHttp } from 'pino-http';
3
- import { createLogger, obfuscateHeaders } from '@atproto/common';
3
+ import { createLogger, obfuscateHeaders, obfuscateResSerializer, } from '@atproto/common';
4
4
  export const pdsLogger = createLogger('pds');
5
5
  export const blobStoreLogger = createLogger('pds:blob-store');
6
6
  export const dbLogger = createLogger('pds:db');
@@ -37,6 +37,7 @@ export const lexiconResolverLogger = createLogger('pds:lexicon-resolver');
37
37
  export const loggerMiddleware = pinoHttp({
38
38
  logger: httpLogger,
39
39
  serializers: {
40
+ res: obfuscateResSerializer,
40
41
  req: reqSerializer,
41
42
  err: (err) => ({
42
43
  code: err?.['code'],
@@ -50,6 +51,12 @@ function accountSerializer(account) {
50
51
  function reqSerializer(req) {
51
52
  const serialized = stdSerializers.req(req);
52
53
  const headers = obfuscateHeaders(serialized.headers);
54
+ // Unlike obfuscateJwt(), which keeps a JWT's payload, hide the entryway's
55
+ // relay token entirely: its payload is the end user's IP address, and the
56
+ // token can be replayed until it expires.
57
+ if (headers['x-entryway-relay'] !== undefined) {
58
+ headers['x-entryway-relay'] = '***';
59
+ }
53
60
  return { ...serialized, headers };
54
61
  }
55
62
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEhE,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;AAC5C,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAA;AAC7D,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;AAC9C,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC,eAAe,CAAC,CAAA;AAC3D,MAAM,CAAC,MAAM,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC,CAAA;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAC,iBAAiB,CAAC,CAAA;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;AACpD,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC,eAAe,CAAC,CAAA;AACtD,MAAM,CAAC,MAAM,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC,CAAA;AACtD,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC,aAAa,CAAC,CAAA;AACxD,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC,aAAa,CAAC,CAAA;AACxD,gFAAgF;AAChF,kBAAkB;AAClB,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAA;AACnC,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;AACpD,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE;IACvD,WAAW,EAAE;QACX,OAAO,EAAE,iBAAiB;KAC3B;CACF,CAAC,CAAA;AACF,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,EAAE;IACnD,WAAW,EAAE;QACX,OAAO,EAAE,iBAAiB;QAC1B,GAAG,EAAE,aAAa;KACnB;CACF,CAAC,CAAA;AACF,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE;IACvD,WAAW,EAAE;QACX,OAAO,EAAE,iBAAiB;QAC1B,GAAG,EAAE,aAAa;KACnB;CACF,CAAC,CAAA;AACF,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAC,sBAAsB,CAAC,CAAA;AAEzE,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACvC,MAAM,EAAE,UAAU;IAClB,WAAW,EAAE;QACX,GAAG,EAAE,aAAa;QAClB,GAAG,EAAE,CAAC,GAAY,EAAE,EAAE,CAAC,CAAC;YACtB,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC;YACnB,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC;SAC1B,CAAC;KACH;CACF,CAAC,CAAA;AAEF,SAAS,iBAAiB,CAAC,OAAwB;IACjD,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAA;AAC7B,CAAC;AAED,SAAS,aAAa,CAAC,GAAoB;IACzC,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IACpD,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,CAAA;AACnC,CAAC","sourcesContent":["import type { IncomingMessage } from 'node:http'\nimport { stdSerializers } from 'pino'\nimport { pinoHttp } from 'pino-http'\nimport { createLogger, obfuscateHeaders } from '@atproto/common'\n\nexport const pdsLogger = createLogger('pds')\nexport const blobStoreLogger = createLogger('pds:blob-store')\nexport const dbLogger = createLogger('pds:db')\nexport const didCacheLogger = createLogger('pds:did-cache')\nexport const eventsLogger = createLogger('pds:events')\nexport const readStickyLogger = createLogger('pds:read-sticky')\nexport const redisLogger = createLogger('pds:redis')\nexport const seqLogger = createLogger('pds:sequencer')\nexport const mailerLogger = createLogger('pds:mailer')\nexport const labelerLogger = createLogger('pds:labeler')\nexport const crawlerLogger = createLogger('pds:crawler')\n// @TODO Use a distinct namespace for the \"http\" subsystem. Also, review uses of\n// the httpLogger.\nexport const httpLogger = pdsLogger\nexport const fetchLogger = createLogger('pds:fetch')\nexport const accountLogger = createLogger('pds:account', {\n serializers: {\n account: accountSerializer,\n },\n})\nexport const oauthLogger = createLogger('pds:oauth', {\n serializers: {\n account: accountSerializer,\n req: reqSerializer,\n },\n})\nexport const sessionLogger = createLogger('pds:session', {\n serializers: {\n account: accountSerializer,\n req: reqSerializer,\n },\n})\nexport const lexiconResolverLogger = createLogger('pds:lexicon-resolver')\n\nexport const loggerMiddleware = pinoHttp({\n logger: httpLogger,\n serializers: {\n req: reqSerializer,\n err: (err: unknown) => ({\n code: err?.['code'],\n message: err?.['message'],\n }),\n },\n})\n\nfunction accountSerializer(account: { did: string }) {\n return { did: account.did }\n}\n\nfunction reqSerializer(req: IncomingMessage) {\n const serialized = stdSerializers.req(req)\n const headers = obfuscateHeaders(serialized.headers)\n return { ...serialized, headers }\n}\n"]}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage } from 'node:http'\nimport { stdSerializers } from 'pino'\nimport { pinoHttp } from 'pino-http'\nimport {\n createLogger,\n obfuscateHeaders,\n obfuscateResSerializer,\n} from '@atproto/common'\n\nexport const pdsLogger = createLogger('pds')\nexport const blobStoreLogger = createLogger('pds:blob-store')\nexport const dbLogger = createLogger('pds:db')\nexport const didCacheLogger = createLogger('pds:did-cache')\nexport const eventsLogger = createLogger('pds:events')\nexport const readStickyLogger = createLogger('pds:read-sticky')\nexport const redisLogger = createLogger('pds:redis')\nexport const seqLogger = createLogger('pds:sequencer')\nexport const mailerLogger = createLogger('pds:mailer')\nexport const labelerLogger = createLogger('pds:labeler')\nexport const crawlerLogger = createLogger('pds:crawler')\n// @TODO Use a distinct namespace for the \"http\" subsystem. Also, review uses of\n// the httpLogger.\nexport const httpLogger = pdsLogger\nexport const fetchLogger = createLogger('pds:fetch')\nexport const accountLogger = createLogger('pds:account', {\n serializers: {\n account: accountSerializer,\n },\n})\nexport const oauthLogger = createLogger('pds:oauth', {\n serializers: {\n account: accountSerializer,\n req: reqSerializer,\n },\n})\nexport const sessionLogger = createLogger('pds:session', {\n serializers: {\n account: accountSerializer,\n req: reqSerializer,\n },\n})\nexport const lexiconResolverLogger = createLogger('pds:lexicon-resolver')\n\nexport const loggerMiddleware = pinoHttp({\n logger: httpLogger,\n serializers: {\n res: obfuscateResSerializer,\n req: reqSerializer,\n err: (err: unknown) => ({\n code: err?.['code'],\n message: err?.['message'],\n }),\n },\n})\n\nfunction accountSerializer(account: { did: string }) {\n return { did: account.did }\n}\n\nfunction reqSerializer(req: IncomingMessage) {\n const serialized = stdSerializers.req(req)\n const headers = obfuscateHeaders(serialized.headers)\n // Unlike obfuscateJwt(), which keeps a JWT's payload, hide the entryway's\n // relay token entirely: its payload is the end user's IP address, and the\n // token can be replayed until it expires.\n if (headers['x-entryway-relay'] !== undefined) {\n headers['x-entryway-relay'] = '***'\n }\n return { ...serialized, headers }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import type { Redis } from 'ioredis';
2
- import type { Options } from '@atproto/xrpc-server';
2
+ import type { HandlerContext, Options } from '@atproto/xrpc-server';
3
3
  import type { RateLimitsConfig } from './config/index.js';
4
4
  type RateLimitDescriptions = NonNullable<Options['rateLimits']>;
5
- export declare const buildRateLimitsConfig: (rateLimits: RateLimitsConfig, redisScratch?: Redis) => RateLimitDescriptions | undefined;
5
+ export declare const buildRateLimitsConfig: (rateLimits: RateLimitsConfig, redisScratch?: Redis, bypass?: (ctx: HandlerContext) => boolean) => RateLimitDescriptions | undefined;
6
6
  export {};
7
7
  //# sourceMappingURL=rate-limits.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limits.d.ts","sourceRoot":"","sources":["../src/rate-limits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAGpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,KAAK,qBAAqB,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAA;AAI/D,eAAO,MAAM,qBAAqB,eACpB,gBAAgB,iBACb,KAAK,KACnB,qBAAqB,GAAG,SA6C1B,CAAA"}
1
+ {"version":3,"file":"rate-limits.d.ts","sourceRoot":"","sources":["../src/rate-limits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAGpC,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,KAAK,qBAAqB,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAA;AAI/D,eAAO,MAAM,qBAAqB,eACpB,gBAAgB,iBACb,KAAK,WACX,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,KACxC,qBAAqB,GAAG,SA6C1B,CAAA"}