@dereekb/firebase-server 13.36.0 → 13.38.0

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 (45) hide show
  1. package/calcom/package.json +10 -10
  2. package/discord/package.json +10 -10
  3. package/index.cjs.js +1732 -510
  4. package/index.esm.js +1717 -513
  5. package/mailgun/package.json +9 -9
  6. package/mcp/index.cjs.js +913 -167
  7. package/mcp/index.esm.js +906 -166
  8. package/mcp/package.json +13 -12
  9. package/mcp/src/lib/controller/mcp.controller.d.ts +28 -3
  10. package/mcp/src/lib/controller/mcp.wellknown.controller.d.ts +21 -1
  11. package/mcp/src/lib/mcp.config.d.ts +31 -8
  12. package/mcp/src/lib/mcp.module.d.ts +2 -1
  13. package/mcp/src/lib/service/index.d.ts +1 -0
  14. package/mcp/src/lib/service/mcp.server.factory.d.ts +8 -6
  15. package/mcp/src/lib/service/mcp.tool-generator.d.ts +1 -1
  16. package/mcp/src/lib/service/mcp.visibility.d.ts +1 -1
  17. package/mcp/src/lib/service/tools/mcp.tool.model-roles.d.ts +95 -0
  18. package/mcp/src/lib/transport/streamable-http.transport.d.ts +16 -11
  19. package/model/index.cjs.js +1 -1
  20. package/model/index.esm.js +1 -1
  21. package/model/package.json +9 -9
  22. package/oidc/index.cjs.js +257 -67
  23. package/oidc/index.esm.js +256 -69
  24. package/oidc/package.json +10 -10
  25. package/oidc/src/lib/profile.d.ts +21 -0
  26. package/oidc/src/lib/service/index.d.ts +1 -0
  27. package/oidc/src/lib/service/oidc.config.service.d.ts +14 -0
  28. package/oidc/src/lib/service/oidc.interaction-policy.d.ts +35 -0
  29. package/oidc/src/lib/service/oidc.service.d.ts +29 -0
  30. package/package.json +14 -13
  31. package/src/lib/env/env.service.d.ts +27 -3
  32. package/src/lib/nest/controller/api.scope.d.ts +63 -0
  33. package/src/lib/nest/controller/index.d.ts +2 -0
  34. package/src/lib/nest/controller/model/model.api.get.service.d.ts +146 -1
  35. package/src/lib/nest/controller/model/model.api.scope.d.ts +3 -2
  36. package/src/lib/nest/controller/session/index.d.ts +4 -0
  37. package/src/lib/nest/controller/session/session.api.config.d.ts +104 -0
  38. package/src/lib/nest/controller/session/session.api.controller.d.ts +26 -0
  39. package/src/lib/nest/controller/session/session.api.module.d.ts +49 -0
  40. package/src/lib/nest/controller/session/session.api.service.d.ts +71 -0
  41. package/test/index.cjs.js +8 -8
  42. package/test/index.esm.js +8 -8
  43. package/test/package.json +11 -11
  44. package/twilio/package.json +8 -8
  45. package/zoho/package.json +10 -10
@@ -0,0 +1,49 @@
1
+ import { type ModuleMetadata } from '@nestjs/common';
2
+ import { type ClassType } from '@dereekb/util';
3
+ /**
4
+ * Configuration for {@link sessionApiModuleMetadata}.
5
+ */
6
+ export interface SessionApiModuleMetadataConfig extends Pick<ModuleMetadata, 'imports' | 'exports' | 'providers'> {
7
+ /**
8
+ * Module that exports the session endpoint's dependencies.
9
+ *
10
+ * Should provide:
11
+ * - `FIRESTORE_SESSION_ADMIN_PREDICATE` — the app's admin check. Without it the endpoint rejects
12
+ * EVERY caller (fail-closed), and logs a warning at boot.
13
+ * - {@link SessionApiModuleConfig} — the registered web app's `appId` to mint App Check tokens for,
14
+ * plus optional TTL / scope overrides. Without it sessions carry no App Check attestation.
15
+ *
16
+ * `FIREBASE_APP_TOKEN` is not listed because `nestServerInstance` provides it globally.
17
+ */
18
+ readonly dependencyModule: ClassType;
19
+ }
20
+ /**
21
+ * Generates NestJS module metadata for the direct-Firestore session API.
22
+ *
23
+ * Mirrors the convention used by `modelApiModuleMetadata` and `mcpModuleMetadata`: the consumer
24
+ * provides a dependency module exposing the required tokens, and this factory wires the controller +
25
+ * service.
26
+ *
27
+ * Remember to add `FIREBASE_SERVER_SESSION_API_PROTECTED_PATH` (`'/api/session'`) to the OIDC module's
28
+ * `protectedPaths` — the controller relies on the bearer middleware having populated `req.auth`.
29
+ *
30
+ * @param metadataConfig - Configuration including the dependency module.
31
+ * @returns NestJS module metadata exposing the session controller + service.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * @Module({
36
+ * imports: [DemoApiAuthModule],
37
+ * providers: [
38
+ * { provide: SessionApiModuleConfig, useValue: { appCheckAppId: environment.firebase.appId } },
39
+ * { provide: FIRESTORE_SESSION_ADMIN_PREDICATE, useValue: (auth) => DEMO_AUTH_CLAIMS_SERVICE.toRoles(auth?.token ?? {}).has('admin') }
40
+ * ],
41
+ * exports: [SessionApiModuleConfig, FIRESTORE_SESSION_ADMIN_PREDICATE]
42
+ * })
43
+ * export class DemoSessionApiDependencyModule {}
44
+ *
45
+ * @Module(sessionApiModuleMetadata({ dependencyModule: DemoSessionApiDependencyModule }))
46
+ * export class DemoSessionApiModule {}
47
+ * ```
48
+ */
49
+ export declare function sessionApiModuleMetadata(metadataConfig: SessionApiModuleMetadataConfig): ModuleMetadata;
@@ -0,0 +1,71 @@
1
+ import type * as admin from 'firebase-admin';
2
+ import { type ISO8601DateString, type Maybe } from '@dereekb/util';
3
+ import { type FirebaseAuthUserId } from '@dereekb/firebase';
4
+ import { type FirebaseServerAuthData } from '../auth.context.server';
5
+ import { type FirestoreSessionAdminPredicate, SessionApiModuleConfig } from './session.api.config';
6
+ /**
7
+ * Error code thrown when the caller is not authorized to open a direct-Firestore session.
8
+ */
9
+ export declare const FIRESTORE_SESSION_FORBIDDEN_ERROR_CODE = "FIRESTORE_SESSION_FORBIDDEN_ERROR";
10
+ /**
11
+ * A short-lived credential bundle that lets a headless client connect directly to Firestore as the
12
+ * authenticated user, through the app's security rules.
13
+ */
14
+ export interface FirestoreSessionResult {
15
+ /**
16
+ * The uid the session was minted for — the calling user's real Firebase Auth uid.
17
+ */
18
+ readonly uid: FirebaseAuthUserId;
19
+ /**
20
+ * A Firebase Auth custom token to exchange via `signInWithCustomToken`. The user's stored
21
+ * `setCustomUserClaims` claims are spread at the TOP LEVEL of the exchanged ID token, so security
22
+ * rules reading `request.auth.token.<claim>` behave exactly as they do for the browser app.
23
+ */
24
+ readonly customToken: string;
25
+ /**
26
+ * An App Check attestation minted for the project's registered web app, for clients that cannot run
27
+ * a browser-only attestation provider (reCAPTCHA v3). Feed it to `initializeAppCheck` through a
28
+ * `CustomProvider`.
29
+ *
30
+ * Omitted when the app did not configure {@link SessionApiModuleConfig.appCheckAppId}.
31
+ */
32
+ readonly appCheckToken?: string;
33
+ /**
34
+ * When the session as a whole stops being usable — the earliest expiry among its credentials.
35
+ * A long-running client should re-fetch rather than assume one session covers the whole job.
36
+ */
37
+ readonly expiresAt: ISO8601DateString;
38
+ }
39
+ /**
40
+ * Mints the direct-Firestore session credential bundle returned by `SessionApiController`.
41
+ *
42
+ * ## Security
43
+ *
44
+ * This service hands out a valid web-app App Check token and a custom token for the caller's own uid.
45
+ * Two gates apply, in order:
46
+ *
47
+ * 1. The app-supplied {@link FirestoreSessionAdminPredicate} — the load-bearing check. **Fails closed**
48
+ * when the app provides no predicate.
49
+ * 2. The OIDC scope requirement (default {@link FIRESTORE_SESSION_OIDC_SCOPE}) — defence in depth only.
50
+ * It cannot stand alone: a non-OIDC caller carries no `scope` claim and every enforcement site in
51
+ * this codebase treats that as "skip".
52
+ *
53
+ * The custom token is ALWAYS minted for `auth.uid`; there is no way to ask for someone else's session,
54
+ * so a granted session is exactly as privileged as the caller already is under Firestore rules.
55
+ */
56
+ export declare class FirestoreSessionApiService {
57
+ private readonly _logger;
58
+ private readonly _app;
59
+ private readonly _config;
60
+ private readonly _adminPredicate;
61
+ constructor(app: admin.app.App, config?: SessionApiModuleConfig, adminPredicate?: FirestoreSessionAdminPredicate);
62
+ /**
63
+ * Mints a direct-Firestore session for the calling user after enforcing the admin predicate and the
64
+ * OIDC scope requirement.
65
+ *
66
+ * @param auth - The authenticated request's auth data (`req.auth`).
67
+ * @returns The credential bundle the client needs to connect to Firestore as this user.
68
+ * @throws {HttpsError} A `401` when the request carries no uid, or a `403` when either gate rejects the caller.
69
+ */
70
+ createFirestoreSession(auth: Maybe<FirebaseServerAuthData>): Promise<FirestoreSessionResult>;
71
+ }
package/test/index.cjs.js CHANGED
@@ -824,7 +824,7 @@ function _ts_generator$a(thisArg, body) {
824
824
  auth_time: decoded.iat,
825
825
  firebase: (_ref = (_decoded_claims = decoded.claims) === null || _decoded_claims === void 0 ? void 0 : _decoded_claims.firebase) !== null && _ref !== void 0 ? _ref : {}
826
826
  });
827
- delete decodedToken.claims; // remove the "claims" item if it exists.
827
+ delete decodedToken['claims']; // remove the "claims" item if it exists.
828
828
  return decodedToken;
829
829
  }
830
830
  /**
@@ -1318,8 +1318,8 @@ var adminEnvironmentInitialized = false;
1318
1318
  * @returns The newly generated project ID.
1319
1319
  */ function rollNewGCloudProjectEnvironmentVariable() {
1320
1320
  var projectId = generateNewProjectId();
1321
- process.env.GCLOUD_TEST_PROJECT = projectId;
1322
- process.env.GCLOUD_PROJECT = projectId;
1321
+ process.env['GCLOUD_TEST_PROJECT'] = projectId;
1322
+ process.env['GCLOUD_PROJECT'] = projectId;
1323
1323
  applyFirebaseGCloudTestProjectIdToFirebaseConfigEnv();
1324
1324
  return projectId;
1325
1325
  }
@@ -1330,7 +1330,7 @@ var adminEnvironmentInitialized = false;
1330
1330
  *
1331
1331
  * @returns The current value of `process.env.GCLOUD_PROJECT`, or `undefined` when unset.
1332
1332
  */ function getGCloudProjectId() {
1333
- return process.env.GCLOUD_PROJECT;
1333
+ return process.env['GCLOUD_PROJECT'];
1334
1334
  }
1335
1335
  /**
1336
1336
  * Reads the current `GCLOUD_TEST_PROJECT` environment variable.
@@ -1341,7 +1341,7 @@ var adminEnvironmentInitialized = false;
1341
1341
  *
1342
1342
  * @returns The current value of `process.env.GCLOUD_TEST_PROJECT`, or `undefined` when unset.
1343
1343
  */ function getGCloudTestProjectId() {
1344
- return process.env.GCLOUD_TEST_PROJECT;
1344
+ return process.env['GCLOUD_TEST_PROJECT'];
1345
1345
  }
1346
1346
  /**
1347
1347
  * Applies the current GCLOUD_PROJECT to FIREBASE_CONFIG.
@@ -1360,10 +1360,10 @@ var adminEnvironmentInitialized = false;
1360
1360
  if (!testProjectId) {
1361
1361
  throw new Error('No test project id was available in the environment. Did you call initFirebaseAdminTestEnvironment() first?');
1362
1362
  }
1363
- var config = JSON.parse((_process_env_FIREBASE_CONFIG = process.env.FIREBASE_CONFIG) !== null && _process_env_FIREBASE_CONFIG !== void 0 ? _process_env_FIREBASE_CONFIG : '{}');
1363
+ var config = JSON.parse((_process_env_FIREBASE_CONFIG = process.env['FIREBASE_CONFIG']) !== null && _process_env_FIREBASE_CONFIG !== void 0 ? _process_env_FIREBASE_CONFIG : '{}');
1364
1364
  config.projectId = testProjectId;
1365
- process.env.FIREBASE_CONFIG = JSON.stringify(config);
1366
- process.env.GCLOUD_PROJECT = testProjectId; // re-apply to GCLOUD_PROJECT too
1365
+ process.env['FIREBASE_CONFIG'] = JSON.stringify(config);
1366
+ process.env['GCLOUD_PROJECT'] = testProjectId; // re-apply to GCLOUD_PROJECT too
1367
1367
  return testProjectId;
1368
1368
  }
1369
1369
  /**
package/test/index.esm.js CHANGED
@@ -823,7 +823,7 @@ function _ts_generator$a(thisArg, body) {
823
823
  auth_time: decoded.iat,
824
824
  firebase: (_ref = (_decoded_claims = decoded.claims) === null || _decoded_claims === void 0 ? void 0 : _decoded_claims.firebase) !== null && _ref !== void 0 ? _ref : {}
825
825
  });
826
- delete decodedToken.claims; // remove the "claims" item if it exists.
826
+ delete decodedToken['claims']; // remove the "claims" item if it exists.
827
827
  return decodedToken;
828
828
  }
829
829
  /**
@@ -1317,8 +1317,8 @@ var adminEnvironmentInitialized = false;
1317
1317
  * @returns The newly generated project ID.
1318
1318
  */ function rollNewGCloudProjectEnvironmentVariable() {
1319
1319
  var projectId = generateNewProjectId();
1320
- process.env.GCLOUD_TEST_PROJECT = projectId;
1321
- process.env.GCLOUD_PROJECT = projectId;
1320
+ process.env['GCLOUD_TEST_PROJECT'] = projectId;
1321
+ process.env['GCLOUD_PROJECT'] = projectId;
1322
1322
  applyFirebaseGCloudTestProjectIdToFirebaseConfigEnv();
1323
1323
  return projectId;
1324
1324
  }
@@ -1329,7 +1329,7 @@ var adminEnvironmentInitialized = false;
1329
1329
  *
1330
1330
  * @returns The current value of `process.env.GCLOUD_PROJECT`, or `undefined` when unset.
1331
1331
  */ function getGCloudProjectId() {
1332
- return process.env.GCLOUD_PROJECT;
1332
+ return process.env['GCLOUD_PROJECT'];
1333
1333
  }
1334
1334
  /**
1335
1335
  * Reads the current `GCLOUD_TEST_PROJECT` environment variable.
@@ -1340,7 +1340,7 @@ var adminEnvironmentInitialized = false;
1340
1340
  *
1341
1341
  * @returns The current value of `process.env.GCLOUD_TEST_PROJECT`, or `undefined` when unset.
1342
1342
  */ function getGCloudTestProjectId() {
1343
- return process.env.GCLOUD_TEST_PROJECT;
1343
+ return process.env['GCLOUD_TEST_PROJECT'];
1344
1344
  }
1345
1345
  /**
1346
1346
  * Applies the current GCLOUD_PROJECT to FIREBASE_CONFIG.
@@ -1359,10 +1359,10 @@ var adminEnvironmentInitialized = false;
1359
1359
  if (!testProjectId) {
1360
1360
  throw new Error('No test project id was available in the environment. Did you call initFirebaseAdminTestEnvironment() first?');
1361
1361
  }
1362
- var config = JSON.parse((_process_env_FIREBASE_CONFIG = process.env.FIREBASE_CONFIG) !== null && _process_env_FIREBASE_CONFIG !== void 0 ? _process_env_FIREBASE_CONFIG : '{}');
1362
+ var config = JSON.parse((_process_env_FIREBASE_CONFIG = process.env['FIREBASE_CONFIG']) !== null && _process_env_FIREBASE_CONFIG !== void 0 ? _process_env_FIREBASE_CONFIG : '{}');
1363
1363
  config.projectId = testProjectId;
1364
- process.env.FIREBASE_CONFIG = JSON.stringify(config);
1365
- process.env.GCLOUD_PROJECT = testProjectId; // re-apply to GCLOUD_PROJECT too
1364
+ process.env['FIREBASE_CONFIG'] = JSON.stringify(config);
1365
+ process.env['GCLOUD_PROJECT'] = testProjectId; // re-apply to GCLOUD_PROJECT too
1366
1366
  return testProjectId;
1367
1367
  }
1368
1368
  /**
package/test/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/test",
3
- "version": "13.36.0",
3
+ "version": "13.38.0",
4
4
  "peerDependencies": {
5
- "@dereekb/analytics": "13.36.0",
6
- "@dereekb/date": "13.36.0",
7
- "@dereekb/firebase": "13.36.0",
8
- "@dereekb/firebase-server": "13.36.0",
9
- "@dereekb/firebase-server/oidc": "13.36.0",
10
- "@dereekb/model": "13.36.0",
11
- "@dereekb/nestjs": "13.36.0",
12
- "@dereekb/rxjs": "13.36.0",
13
- "@dereekb/util": "13.36.0",
5
+ "@dereekb/analytics": "13.38.0",
6
+ "@dereekb/date": "13.38.0",
7
+ "@dereekb/firebase": "13.38.0",
8
+ "@dereekb/firebase-server": "13.38.0",
9
+ "@dereekb/firebase-server/oidc": "13.38.0",
10
+ "@dereekb/model": "13.38.0",
11
+ "@dereekb/nestjs": "13.38.0",
12
+ "@dereekb/rxjs": "13.38.0",
13
+ "@dereekb/util": "13.38.0",
14
14
  "@google-cloud/firestore": "^7.11.6",
15
15
  "@google-cloud/storage": "^7.19.0",
16
16
  "@nestjs/common": "^11.1.19",
@@ -23,7 +23,7 @@
23
23
  "supertest": "^7.2.2"
24
24
  },
25
25
  "devDependencies": {
26
- "@dereekb/nestjs": "13.36.0"
26
+ "@dereekb/nestjs": "13.38.0"
27
27
  },
28
28
  "exports": {
29
29
  "./package.json": "./package.json",
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/twilio",
3
- "version": "13.36.0",
3
+ "version": "13.38.0",
4
4
  "peerDependencies": {
5
- "@dereekb/date": "13.36.0",
6
- "@dereekb/firebase": "13.36.0",
7
- "@dereekb/firebase-server": "13.36.0",
8
- "@dereekb/model": "13.36.0",
9
- "@dereekb/nestjs": "13.36.0",
10
- "@dereekb/rxjs": "13.36.0",
11
- "@dereekb/util": "13.36.0"
5
+ "@dereekb/date": "13.38.0",
6
+ "@dereekb/firebase": "13.38.0",
7
+ "@dereekb/firebase-server": "13.38.0",
8
+ "@dereekb/model": "13.38.0",
9
+ "@dereekb/nestjs": "13.38.0",
10
+ "@dereekb/rxjs": "13.38.0",
11
+ "@dereekb/util": "13.38.0"
12
12
  },
13
13
  "exports": {
14
14
  "./package.json": "./package.json",
package/zoho/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/zoho",
3
- "version": "13.36.0",
3
+ "version": "13.38.0",
4
4
  "peerDependencies": {
5
- "@dereekb/analytics": "13.36.0",
6
- "@dereekb/date": "13.36.0",
7
- "@dereekb/model": "13.36.0",
8
- "@dereekb/nestjs": "13.36.0",
9
- "@dereekb/rxjs": "13.36.0",
10
- "@dereekb/firebase": "13.36.0",
11
- "@dereekb/firebase-server": "13.36.0",
12
- "@dereekb/util": "13.36.0",
13
- "@dereekb/zoho": "13.36.0",
5
+ "@dereekb/analytics": "13.38.0",
6
+ "@dereekb/date": "13.38.0",
7
+ "@dereekb/model": "13.38.0",
8
+ "@dereekb/nestjs": "13.38.0",
9
+ "@dereekb/rxjs": "13.38.0",
10
+ "@dereekb/firebase": "13.38.0",
11
+ "@dereekb/firebase-server": "13.38.0",
12
+ "@dereekb/util": "13.38.0",
13
+ "@dereekb/zoho": "13.38.0",
14
14
  "@nestjs/common": "^11.1.19",
15
15
  "@nestjs/config": "^4.0.4",
16
16
  "express": "^5.2.1"