@dereekb/firebase-server 13.37.0 → 13.39.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.
- package/calcom/package.json +15 -15
- package/discord/package.json +15 -15
- package/index.esm.js +1716 -512
- package/mailgun/package.json +14 -14
- package/mcp/index.esm.js +561 -40
- package/mcp/package.json +16 -16
- package/mcp/src/lib/mcp.config.d.ts +22 -1
- package/mcp/src/lib/service/index.d.ts +1 -0
- package/mcp/src/lib/service/mcp.server.factory.d.ts +3 -2
- package/mcp/src/lib/service/tools/mcp.tool.model-roles.d.ts +95 -0
- package/model/package.json +14 -14
- package/model/src/lib/notification/notification.module.d.ts +1 -1
- package/oidc/package.json +15 -15
- package/package.json +36 -45
- package/src/lib/env/env.service.d.ts +27 -3
- package/src/lib/nest/controller/api.scope.d.ts +63 -0
- package/src/lib/nest/controller/index.d.ts +2 -0
- package/src/lib/nest/controller/model/model.api.get.service.d.ts +146 -1
- package/src/lib/nest/controller/model/model.api.scope.d.ts +3 -2
- package/src/lib/nest/controller/session/index.d.ts +4 -0
- package/src/lib/nest/controller/session/session.api.config.d.ts +104 -0
- package/src/lib/nest/controller/session/session.api.controller.d.ts +26 -0
- package/src/lib/nest/controller/session/session.api.module.d.ts +49 -0
- package/src/lib/nest/controller/session/session.api.service.d.ts +71 -0
- package/test/package.json +16 -16
- package/twilio/package.json +13 -13
- package/zoho/package.json +15 -15
- package/calcom/index.cjs.default.js +0 -1
- package/calcom/index.cjs.js +0 -1451
- package/calcom/index.cjs.mjs +0 -2
- package/discord/index.cjs.default.js +0 -1
- package/discord/index.cjs.js +0 -761
- package/discord/index.cjs.mjs +0 -2
- package/index.cjs.default.js +0 -1
- package/index.cjs.js +0 -13491
- package/index.cjs.mjs +0 -2
- package/mailgun/index.cjs.default.js +0 -1
- package/mailgun/index.cjs.js +0 -436
- package/mailgun/index.cjs.mjs +0 -2
- package/mcp/index.cjs.default.js +0 -1
- package/mcp/index.cjs.js +0 -8254
- package/mcp/index.cjs.mjs +0 -2
- package/model/index.cjs.default.js +0 -1
- package/model/index.cjs.js +0 -19965
- package/model/index.cjs.mjs +0 -2
- package/oidc/index.cjs.default.js +0 -1
- package/oidc/index.cjs.js +0 -8085
- package/oidc/index.cjs.mjs +0 -2
- package/test/index.cjs.default.js +0 -1
- package/test/index.cjs.js +0 -5728
- package/test/index.cjs.mjs +0 -2
- package/twilio/index.cjs.default.js +0 -1
- package/twilio/index.cjs.js +0 -404
- package/twilio/index.cjs.mjs +0 -2
- package/zoho/index.cjs.default.js +0 -1
- package/zoho/index.cjs.js +0 -1810
- package/zoho/index.cjs.mjs +0 -2
package/mcp/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/mcp",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.39.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/analytics": "13.
|
|
6
|
-
"@dereekb/date": "13.
|
|
7
|
-
"@dereekb/firebase": "13.
|
|
8
|
-
"@dereekb/firebase-server": "13.
|
|
9
|
-
"@dereekb/firebase-server/oidc": "13.
|
|
10
|
-
"@dereekb/model": "13.
|
|
11
|
-
"@dereekb/nestjs": "13.
|
|
12
|
-
"@dereekb/rxjs": "13.
|
|
13
|
-
"@dereekb/util": "13.
|
|
14
|
-
"@dereekb/zoho": "13.
|
|
6
|
+
"@dereekb/analytics": "13.39.0",
|
|
7
|
+
"@dereekb/date": "13.39.0",
|
|
8
|
+
"@dereekb/firebase": "13.39.0",
|
|
9
|
+
"@dereekb/firebase-server": "13.39.0",
|
|
10
|
+
"@dereekb/firebase-server/oidc": "13.39.0",
|
|
11
|
+
"@dereekb/model": "13.39.0",
|
|
12
|
+
"@dereekb/nestjs": "13.39.0",
|
|
13
|
+
"@dereekb/rxjs": "13.39.0",
|
|
14
|
+
"@dereekb/util": "13.39.0",
|
|
15
|
+
"@dereekb/zoho": "13.39.0",
|
|
15
16
|
"@modelcontextprotocol/node": "2.0.0",
|
|
16
17
|
"@modelcontextprotocol/server": "2.0.0",
|
|
17
18
|
"@nestjs/common": "^11.1.19",
|
|
@@ -23,13 +24,12 @@
|
|
|
23
24
|
"exports": {
|
|
24
25
|
"./package.json": "./package.json",
|
|
25
26
|
".": {
|
|
26
|
-
"module": "./index.esm.js",
|
|
27
27
|
"types": "./index.d.ts",
|
|
28
|
-
"import": "./index.
|
|
29
|
-
"default": "./index.
|
|
28
|
+
"import": "./index.esm.js",
|
|
29
|
+
"default": "./index.esm.js"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
"module": "./index.esm.js",
|
|
33
|
-
"main": "./index.
|
|
33
|
+
"main": "./index.esm.js",
|
|
34
34
|
"types": "./index.d.ts"
|
|
35
|
-
}
|
|
35
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type AuthClaims, type AuthRoleSet } from '@dereekb/util';
|
|
1
|
+
import { type AuthClaims, type AuthRoleSet, type Maybe, type PromiseOrValue } from '@dereekb/util';
|
|
2
|
+
import { type FirebaseServerAuthData } from '@dereekb/firebase-server';
|
|
2
3
|
import { type FirestoreModelType, type OidcModelScopeRequirement, type OidcScope, type OidcScopeTerm } from '@dereekb/firebase';
|
|
3
4
|
/**
|
|
4
5
|
* Default path the MCP Streamable HTTP transport is mounted at.
|
|
@@ -238,3 +239,23 @@ export type McpAuthRoleReader = (claims: AuthClaims) => AuthRoleSet;
|
|
|
238
239
|
* NestJS injection token for the optional {@link McpAuthRoleReader} provider.
|
|
239
240
|
*/
|
|
240
241
|
export declare const MCP_AUTH_ROLE_READER = "MCP_AUTH_ROLE_READER";
|
|
242
|
+
/**
|
|
243
|
+
* Signature for the optional predicate that authorizes `model-roles` calls which target another
|
|
244
|
+
* user's uid.
|
|
245
|
+
*
|
|
246
|
+
* `model-roles` resolves permissions for the calling user by default, which is always safe. Passing
|
|
247
|
+
* a `uid` asks the server "what can *that* user do here?" — an answer that leaks the target's
|
|
248
|
+
* effective access, so it is gated behind this app-supplied predicate rather than being open.
|
|
249
|
+
*
|
|
250
|
+
* Receives the calling request's auth data (`undefined` for an unauthenticated request) and returns
|
|
251
|
+
* true if that caller may resolve roles for arbitrary uids. Typically an admin check, e.g.
|
|
252
|
+
* `(auth) => authRoleClaimsService.toRoles(auth?.token ?? {}).has('admin')`.
|
|
253
|
+
*
|
|
254
|
+
* When no predicate is provided the `uid` parameter fails closed for every caller — the tool is
|
|
255
|
+
* still registered and still answers for the caller themselves.
|
|
256
|
+
*/
|
|
257
|
+
export type McpModelRolesTargetUidPredicate = (auth: Maybe<FirebaseServerAuthData>) => PromiseOrValue<boolean>;
|
|
258
|
+
/**
|
|
259
|
+
* NestJS injection token for the optional {@link McpModelRolesTargetUidPredicate} provider.
|
|
260
|
+
*/
|
|
261
|
+
export declare const MCP_MODEL_ROLES_TARGET_UID_PREDICATE = "MCP_MODEL_ROLES_TARGET_UID_PREDICATE";
|
|
@@ -7,6 +7,7 @@ export * from './mcp.server.factory';
|
|
|
7
7
|
export * from './mcp.tool-generator';
|
|
8
8
|
export * from './mcp.visibility';
|
|
9
9
|
export * from './tools/mcp.tool.model-get';
|
|
10
|
+
export * from './tools/mcp.tool.model-roles';
|
|
10
11
|
export * from './tools/mcp.tool.model-info';
|
|
11
12
|
export * from './tools/mcp.tool.model-decode';
|
|
12
13
|
export * from './tools/mcp.tool.enum-info';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/server';
|
|
2
2
|
import { type Request } from 'express';
|
|
3
3
|
import { ModelApiCallModelDispatchService, ModelApiGetService, FirebaseServerStorageService, type FirebaseServerAuthData } from '@dereekb/firebase-server';
|
|
4
|
-
import { McpModuleConfig, type McpAuthRoleReader } from '../mcp.config';
|
|
4
|
+
import { McpModuleConfig, type McpAuthRoleReader, type McpModelRolesTargetUidPredicate } from '../mcp.config';
|
|
5
5
|
import { type McpAnalyticsService } from './analytics/mcp.analytics.handler';
|
|
6
6
|
/**
|
|
7
7
|
* Optional per-request context passed when invoking the MCP server through a
|
|
@@ -28,6 +28,7 @@ export declare class McpServerFactoryService {
|
|
|
28
28
|
private readonly modelApiGetService?;
|
|
29
29
|
private readonly roleReader?;
|
|
30
30
|
private readonly storageService?;
|
|
31
|
+
private readonly modelRolesTargetUidPredicate?;
|
|
31
32
|
private readonly _logger;
|
|
32
33
|
private _cachedTools;
|
|
33
34
|
private _cachedStaticTools;
|
|
@@ -42,7 +43,7 @@ export declare class McpServerFactoryService {
|
|
|
42
43
|
private _warnedMissingRoleReader;
|
|
43
44
|
private _resolvedReasonConfig?;
|
|
44
45
|
private readonly _analyticsService;
|
|
45
|
-
constructor(mcpConfig: McpModuleConfig, dispatchService: ModelApiCallModelDispatchService, modelApiGetService?: ModelApiGetService | undefined, roleReader?: McpAuthRoleReader | undefined, analyticsService?: McpAnalyticsService, storageService?: FirebaseServerStorageService | undefined);
|
|
46
|
+
constructor(mcpConfig: McpModuleConfig, dispatchService: ModelApiCallModelDispatchService, modelApiGetService?: ModelApiGetService | undefined, roleReader?: McpAuthRoleReader | undefined, analyticsService?: McpAnalyticsService, storageService?: FirebaseServerStorageService | undefined, modelRolesTargetUidPredicate?: McpModelRolesTargetUidPredicate | undefined);
|
|
46
47
|
/**
|
|
47
48
|
* Builds a configured MCP server with tool listing + dispatch handlers wired up.
|
|
48
49
|
*
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type Maybe, type PromiseOrValue } from '@dereekb/util';
|
|
2
|
+
import { type FirebaseAuthUserId, type FirestoreModelIdentity, type FirestoreModelKey, type FirestoreModelType } from '@dereekb/firebase';
|
|
3
|
+
import { type ModelAccessMultiRoleMapResult, type FirebaseServerAuthData } from '@dereekb/firebase-server';
|
|
4
|
+
import { type McpToolDefinition } from '../mcp.tool-generator';
|
|
5
|
+
/**
|
|
6
|
+
* Reserved tool name for the built-in `model-roles` static tool.
|
|
7
|
+
*/
|
|
8
|
+
export declare const MODEL_ROLES_TOOL_NAME = "model-roles";
|
|
9
|
+
/**
|
|
10
|
+
* Synthetic call type used in the tool's dispatch identity. Distinct from `model-get`'s `get` so
|
|
11
|
+
* visibility predicates can target the two independently.
|
|
12
|
+
*/
|
|
13
|
+
export declare const MODEL_ROLES_DISPATCH_CALL = "roles";
|
|
14
|
+
/**
|
|
15
|
+
* Synthetic model type used in the tool's dispatch identity. Mirrors {@link MODEL_GET_DISPATCH_MODEL_TYPE}
|
|
16
|
+
* — the tool isn't bound to one model type, so the literal "model" stands in.
|
|
17
|
+
*/
|
|
18
|
+
export declare const MODEL_ROLES_DISPATCH_MODEL_TYPE = "model";
|
|
19
|
+
/**
|
|
20
|
+
* Maximum number of keys accepted per `model-roles` call. Role resolution runs the model's real
|
|
21
|
+
* permission delegate per key (which may itself read parent documents), so this is deliberately
|
|
22
|
+
* lower than the `model-get` batch size.
|
|
23
|
+
*/
|
|
24
|
+
export declare const MCP_MODEL_ROLES_MAX_KEYS = 25;
|
|
25
|
+
/**
|
|
26
|
+
* Resolves granted role maps for a batch of keys. Signature matches
|
|
27
|
+
* `ModelApiGetService.readRoleMaps` so the service method can be passed directly.
|
|
28
|
+
*/
|
|
29
|
+
export type McpModelRolesReadRoleMaps = (params: {
|
|
30
|
+
readonly modelType: FirestoreModelType;
|
|
31
|
+
readonly keys: FirestoreModelKey[];
|
|
32
|
+
readonly auth: Maybe<FirebaseServerAuthData>;
|
|
33
|
+
readonly targetUid?: Maybe<FirebaseAuthUserId>;
|
|
34
|
+
}) => Promise<ModelAccessMultiRoleMapResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Lookup that resolves a `modelType` to its registered {@link FirestoreModelIdentity}, so bare ids
|
|
37
|
+
* can be promoted to full keys. Mirrors `McpModelGetResolveIdentity`.
|
|
38
|
+
*/
|
|
39
|
+
export type McpModelRolesResolveIdentity = (modelType: FirestoreModelType, auth: Maybe<FirebaseServerAuthData>) => Maybe<FirestoreModelIdentity>;
|
|
40
|
+
/**
|
|
41
|
+
* Predicate authorizing a caller to resolve roles for a uid other than their own. Mirrors
|
|
42
|
+
* `McpModelRolesTargetUidPredicate` from the module config; redeclared here so this module does not
|
|
43
|
+
* depend on the config module.
|
|
44
|
+
*/
|
|
45
|
+
export type McpModelRolesTargetUidCheck = (auth: Maybe<FirebaseServerAuthData>) => PromiseOrValue<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Constructor dependencies for {@link createModelRolesTool}.
|
|
48
|
+
*/
|
|
49
|
+
export interface CreateModelRolesToolDeps {
|
|
50
|
+
/**
|
|
51
|
+
* Resolves the granted role maps for a batch of keys.
|
|
52
|
+
*/
|
|
53
|
+
readonly readRoleMaps: McpModelRolesReadRoleMaps;
|
|
54
|
+
/**
|
|
55
|
+
* Resolves the registered identity for a model type so bare ids can be promoted into full keys.
|
|
56
|
+
*/
|
|
57
|
+
readonly resolveIdentity: McpModelRolesResolveIdentity;
|
|
58
|
+
/**
|
|
59
|
+
* Authorizes use of the `uid` parameter. Omitted means the parameter fails closed for everyone;
|
|
60
|
+
* the tool still answers for the calling user.
|
|
61
|
+
*/
|
|
62
|
+
readonly canTargetOtherUids?: Maybe<McpModelRolesTargetUidCheck>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Shape of the `model-roles` tool input.
|
|
66
|
+
*/
|
|
67
|
+
export interface ModelRolesToolInput {
|
|
68
|
+
readonly modelType: string;
|
|
69
|
+
readonly keys: ReadonlyArray<string>;
|
|
70
|
+
readonly uid?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Builds the built-in `model-roles` MCP tool definition.
|
|
74
|
+
*
|
|
75
|
+
* Answers "what is this user actually allowed to do with this document?" by running the same
|
|
76
|
+
* `roleMapForModel()` delegate the permission-checked read/write paths use, and returning the
|
|
77
|
+
* resolved roles instead of consuming them. Because the model's real delegate runs, derived and
|
|
78
|
+
* cascading roles appear exactly as the API grants them — there is no second implementation of the
|
|
79
|
+
* rules to drift.
|
|
80
|
+
*
|
|
81
|
+
* Two things it disambiguates that a plain read cannot:
|
|
82
|
+
* - **Missing vs. forbidden.** A key that resolves to a missing document returns
|
|
83
|
+
* `exists: false, roles: []` rather than an error, so "the document is not there" reads
|
|
84
|
+
* differently from "it is there and you have no access" (`exists: true, roles: []`).
|
|
85
|
+
* - **Full access.** Admin short-circuits that grant the full-access marker come back as
|
|
86
|
+
* `fullAccess: true` rather than as an opaque enumerated set.
|
|
87
|
+
*
|
|
88
|
+
* By default roles are resolved for the calling user. Passing `uid` resolves them for another user
|
|
89
|
+
* and is gated behind {@link CreateModelRolesToolDeps.canTargetOtherUids}.
|
|
90
|
+
*
|
|
91
|
+
* @param deps - Role-map reader, identity resolver, and the target-uid authorization predicate.
|
|
92
|
+
* @returns A statically-registered {@link McpToolDefinition} ready to be appended to the MCP
|
|
93
|
+
* server factory's tool registry.
|
|
94
|
+
*/
|
|
95
|
+
export declare function createModelRolesTool(deps: CreateModelRolesToolDeps): McpToolDefinition;
|
package/model/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/model",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.39.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/analytics": "13.
|
|
6
|
-
"@dereekb/date": "13.
|
|
7
|
-
"@dereekb/firebase": "13.
|
|
8
|
-
"@dereekb/firebase-server": "13.
|
|
9
|
-
"@dereekb/model": "13.
|
|
10
|
-
"@dereekb/nestjs": "13.
|
|
11
|
-
"@dereekb/rxjs": "13.
|
|
12
|
-
"@dereekb/util": "13.
|
|
6
|
+
"@dereekb/analytics": "13.39.0",
|
|
7
|
+
"@dereekb/date": "13.39.0",
|
|
8
|
+
"@dereekb/firebase": "13.39.0",
|
|
9
|
+
"@dereekb/firebase-server": "13.39.0",
|
|
10
|
+
"@dereekb/model": "13.39.0",
|
|
11
|
+
"@dereekb/nestjs": "13.39.0",
|
|
12
|
+
"@dereekb/rxjs": "13.39.0",
|
|
13
|
+
"@dereekb/util": "13.39.0",
|
|
13
14
|
"@nestjs/common": "^11.1.19",
|
|
14
15
|
"@nestjs/config": "^4.0.4",
|
|
15
16
|
"archiver": "^7.0.1",
|
|
@@ -23,13 +24,12 @@
|
|
|
23
24
|
"exports": {
|
|
24
25
|
"./package.json": "./package.json",
|
|
25
26
|
".": {
|
|
26
|
-
"module": "./index.esm.js",
|
|
27
27
|
"types": "./index.d.ts",
|
|
28
|
-
"import": "./index.
|
|
29
|
-
"default": "./index.
|
|
28
|
+
"import": "./index.esm.js",
|
|
29
|
+
"default": "./index.esm.js"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
"module": "./index.esm.js",
|
|
33
|
-
"main": "./index.
|
|
33
|
+
"main": "./index.esm.js",
|
|
34
34
|
"types": "./index.d.ts"
|
|
35
|
-
}
|
|
35
|
+
}
|
|
@@ -35,7 +35,7 @@ export declare function notificationServerActionsContextFactory(context: BaseNot
|
|
|
35
35
|
notificationLoggedEventDayCollectionGroup: import("@dereekb/firebase").NotificationLoggedEventDayFirestoreCollectionGroup;
|
|
36
36
|
notificationLoggedEventDayPagedItemsCollectionFactory: import("@dereekb/firebase").NotificationLoggedEventDayPagedItemsFirestoreCollectionFactory;
|
|
37
37
|
notificationLoggedEventDayPageCollectionGroup: import("@dereekb/firebase").NotificationLoggedEventDayPageFirestoreCollectionGroup;
|
|
38
|
-
authService: import("
|
|
38
|
+
authService: import("@dereekb/firebase-server").FirebaseServerAuthService<import("@dereekb/firebase-server").FirebaseServerAuthUserContext, import("@dereekb/firebase-server").FirebaseServerAuthContext<import("@dereekb/firebase-server").FirebaseServerAuthUserContext>>;
|
|
39
39
|
firestoreContext: import("@dereekb/firebase").FirestoreContext<import("@dereekb/firebase").Firestore>;
|
|
40
40
|
};
|
|
41
41
|
/**
|
package/oidc/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/oidc",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.39.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/analytics": "13.
|
|
6
|
-
"@dereekb/date": "13.
|
|
7
|
-
"@dereekb/firebase": "13.
|
|
8
|
-
"@dereekb/firebase-server": "13.
|
|
9
|
-
"@dereekb/model": "13.
|
|
10
|
-
"@dereekb/nestjs": "13.
|
|
11
|
-
"@dereekb/rxjs": "13.
|
|
12
|
-
"@dereekb/util": "13.
|
|
13
|
-
"@dereekb/zoho": "13.
|
|
6
|
+
"@dereekb/analytics": "13.39.0",
|
|
7
|
+
"@dereekb/date": "13.39.0",
|
|
8
|
+
"@dereekb/firebase": "13.39.0",
|
|
9
|
+
"@dereekb/firebase-server": "13.39.0",
|
|
10
|
+
"@dereekb/model": "13.39.0",
|
|
11
|
+
"@dereekb/nestjs": "13.39.0",
|
|
12
|
+
"@dereekb/rxjs": "13.39.0",
|
|
13
|
+
"@dereekb/util": "13.39.0",
|
|
14
|
+
"@dereekb/zoho": "13.39.0",
|
|
14
15
|
"@nestjs/common": "^11.1.19",
|
|
15
16
|
"@nestjs/config": "^4.0.4",
|
|
16
17
|
"express": "^5.2.1",
|
|
@@ -21,13 +22,12 @@
|
|
|
21
22
|
"exports": {
|
|
22
23
|
"./package.json": "./package.json",
|
|
23
24
|
".": {
|
|
24
|
-
"module": "./index.esm.js",
|
|
25
25
|
"types": "./index.d.ts",
|
|
26
|
-
"import": "./index.
|
|
27
|
-
"default": "./index.
|
|
26
|
+
"import": "./index.esm.js",
|
|
27
|
+
"default": "./index.esm.js"
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"module": "./index.esm.js",
|
|
31
|
-
"main": "./index.
|
|
31
|
+
"main": "./index.esm.js",
|
|
32
32
|
"types": "./index.d.ts"
|
|
33
|
-
}
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,85 +1,74 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.39.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"sideEffects": false,
|
|
5
6
|
"exports": {
|
|
6
7
|
"./test": {
|
|
7
|
-
"module": "./test/index.esm.js",
|
|
8
8
|
"types": "./test/index.d.ts",
|
|
9
|
-
"import": "./test/index.
|
|
10
|
-
"default": "./test/index.
|
|
9
|
+
"import": "./test/index.esm.js",
|
|
10
|
+
"default": "./test/index.esm.js"
|
|
11
11
|
},
|
|
12
12
|
"./calcom": {
|
|
13
|
-
"module": "./calcom/index.esm.js",
|
|
14
13
|
"types": "./calcom/index.d.ts",
|
|
15
|
-
"import": "./calcom/index.
|
|
16
|
-
"default": "./calcom/index.
|
|
14
|
+
"import": "./calcom/index.esm.js",
|
|
15
|
+
"default": "./calcom/index.esm.js"
|
|
17
16
|
},
|
|
18
17
|
"./discord": {
|
|
19
|
-
"module": "./discord/index.esm.js",
|
|
20
18
|
"types": "./discord/index.d.ts",
|
|
21
|
-
"import": "./discord/index.
|
|
22
|
-
"default": "./discord/index.
|
|
19
|
+
"import": "./discord/index.esm.js",
|
|
20
|
+
"default": "./discord/index.esm.js"
|
|
23
21
|
},
|
|
24
22
|
"./mailgun": {
|
|
25
|
-
"module": "./mailgun/index.esm.js",
|
|
26
23
|
"types": "./mailgun/index.d.ts",
|
|
27
|
-
"import": "./mailgun/index.
|
|
28
|
-
"default": "./mailgun/index.
|
|
24
|
+
"import": "./mailgun/index.esm.js",
|
|
25
|
+
"default": "./mailgun/index.esm.js"
|
|
29
26
|
},
|
|
30
27
|
"./twilio": {
|
|
31
|
-
"module": "./twilio/index.esm.js",
|
|
32
28
|
"types": "./twilio/index.d.ts",
|
|
33
|
-
"import": "./twilio/index.
|
|
34
|
-
"default": "./twilio/index.
|
|
29
|
+
"import": "./twilio/index.esm.js",
|
|
30
|
+
"default": "./twilio/index.esm.js"
|
|
35
31
|
},
|
|
36
32
|
"./zoho": {
|
|
37
|
-
"module": "./zoho/index.esm.js",
|
|
38
33
|
"types": "./zoho/index.d.ts",
|
|
39
|
-
"import": "./zoho/index.
|
|
40
|
-
"default": "./zoho/index.
|
|
34
|
+
"import": "./zoho/index.esm.js",
|
|
35
|
+
"default": "./zoho/index.esm.js"
|
|
41
36
|
},
|
|
42
37
|
"./model": {
|
|
43
|
-
"module": "./model/index.esm.js",
|
|
44
38
|
"types": "./model/index.d.ts",
|
|
45
|
-
"import": "./model/index.
|
|
46
|
-
"default": "./model/index.
|
|
39
|
+
"import": "./model/index.esm.js",
|
|
40
|
+
"default": "./model/index.esm.js"
|
|
47
41
|
},
|
|
48
42
|
"./oidc": {
|
|
49
|
-
"module": "./oidc/index.esm.js",
|
|
50
43
|
"types": "./oidc/index.d.ts",
|
|
51
|
-
"import": "./oidc/index.
|
|
52
|
-
"default": "./oidc/index.
|
|
44
|
+
"import": "./oidc/index.esm.js",
|
|
45
|
+
"default": "./oidc/index.esm.js"
|
|
53
46
|
},
|
|
54
47
|
"./mcp": {
|
|
55
|
-
"module": "./mcp/index.esm.js",
|
|
56
48
|
"types": "./mcp/index.d.ts",
|
|
57
49
|
"import": "./mcp/index.esm.js",
|
|
58
|
-
"default": "./mcp/index.
|
|
50
|
+
"default": "./mcp/index.esm.js"
|
|
59
51
|
},
|
|
60
52
|
"./package.json": "./package.json",
|
|
61
53
|
".": {
|
|
62
|
-
"module": "./index.esm.js",
|
|
63
54
|
"types": "./index.d.ts",
|
|
64
|
-
"import": "./index.
|
|
65
|
-
"default": "./index.
|
|
55
|
+
"import": "./index.esm.js",
|
|
56
|
+
"default": "./index.esm.js"
|
|
66
57
|
}
|
|
67
58
|
},
|
|
68
|
-
"main": "./index.cjs.js",
|
|
69
|
-
"types": "./src/index.d.ts",
|
|
70
59
|
"peerDependencies": {
|
|
71
60
|
"@cantoo/pdf-lib": "^2.6.5",
|
|
72
|
-
"@dereekb/analytics": "13.
|
|
73
|
-
"@dereekb/calcom": "13.
|
|
74
|
-
"@dereekb/date": "13.
|
|
75
|
-
"@dereekb/dbx-core": "13.
|
|
76
|
-
"@dereekb/discord": "13.
|
|
77
|
-
"@dereekb/firebase": "13.
|
|
78
|
-
"@dereekb/model": "13.
|
|
79
|
-
"@dereekb/nestjs": "13.
|
|
80
|
-
"@dereekb/rxjs": "13.
|
|
81
|
-
"@dereekb/util": "13.
|
|
82
|
-
"@dereekb/zoho": "13.
|
|
61
|
+
"@dereekb/analytics": "13.39.0",
|
|
62
|
+
"@dereekb/calcom": "13.39.0",
|
|
63
|
+
"@dereekb/date": "13.39.0",
|
|
64
|
+
"@dereekb/dbx-core": "13.39.0",
|
|
65
|
+
"@dereekb/discord": "13.39.0",
|
|
66
|
+
"@dereekb/firebase": "13.39.0",
|
|
67
|
+
"@dereekb/model": "13.39.0",
|
|
68
|
+
"@dereekb/nestjs": "13.39.0",
|
|
69
|
+
"@dereekb/rxjs": "13.39.0",
|
|
70
|
+
"@dereekb/util": "13.39.0",
|
|
71
|
+
"@dereekb/zoho": "13.39.0",
|
|
83
72
|
"@google-cloud/firestore": "^7.11.6",
|
|
84
73
|
"@google-cloud/storage": "^7.19.0",
|
|
85
74
|
"@modelcontextprotocol/node": "2.0.0",
|
|
@@ -105,5 +94,7 @@
|
|
|
105
94
|
"supertest": "^7.2.2",
|
|
106
95
|
"ts-essentials": "^10.2.0"
|
|
107
96
|
},
|
|
108
|
-
"module": "./index.esm.js"
|
|
109
|
-
|
|
97
|
+
"module": "./index.esm.js",
|
|
98
|
+
"main": "./index.esm.js",
|
|
99
|
+
"types": "./index.d.ts"
|
|
100
|
+
}
|
|
@@ -14,15 +14,39 @@ export interface FirebaseServerEnvServiceRef<S extends FirebaseServerEnvService
|
|
|
14
14
|
*/
|
|
15
15
|
export declare abstract class FirebaseServerEnvService {
|
|
16
16
|
/**
|
|
17
|
-
* Whether the server is running
|
|
17
|
+
* Whether the server is running under a test runner / in CI.
|
|
18
|
+
*
|
|
19
|
+
* NOT the complement of {@link isProduction}. There are three distinct situations, and a local
|
|
20
|
+
* emulator run (`nx run <app>:serve`) is the third one — neither testing nor deployed:
|
|
21
|
+
*
|
|
22
|
+
* | situation | isTestingEnv | isProduction |
|
|
23
|
+
* | -------------------------- | ------------ | ------------ |
|
|
24
|
+
* | test / CI run | true | false |
|
|
25
|
+
* | local emulator `serve` | false | false |
|
|
26
|
+
* | deployed (staging or prod) | false | true |
|
|
27
|
+
*
|
|
28
|
+
* Use this only to branch on "a test runner is driving this" — seeded fixtures, relaxed timeouts,
|
|
29
|
+
* assertions. To decide whether real Firebase infrastructure is reachable, use {@link isProduction}:
|
|
30
|
+
* `!isTestingEnv` wrongly includes local emulator runs, which is a common source of calls to live
|
|
31
|
+
* backends (App Check, IAM signing, service-account discovery) that fail with no emulator behind them.
|
|
18
32
|
*/
|
|
19
33
|
abstract readonly isTestingEnv: boolean;
|
|
20
34
|
/**
|
|
21
|
-
* Whether the server is
|
|
35
|
+
* Whether the server is DEPLOYED — true for every deployed environment, including staging.
|
|
36
|
+
*
|
|
37
|
+
* This is the gate for "real Firebase infrastructure is reachable": services with no emulator
|
|
38
|
+
* (App Check token minting, IAM signing, GCE metadata service-account discovery) may only be
|
|
39
|
+
* called when this is true. It is false for both a test run and a local emulator `serve`, which is
|
|
40
|
+
* what makes it — and not `!isTestingEnv` — the correct check for those calls.
|
|
41
|
+
*
|
|
42
|
+
* Use {@link isStaging} to distinguish staging from true production.
|
|
22
43
|
*/
|
|
23
44
|
abstract readonly isProduction: boolean;
|
|
24
45
|
/**
|
|
25
|
-
* Whether the server is running in a staging environment.
|
|
46
|
+
* Whether the server is running in a staging environment.
|
|
47
|
+
*
|
|
48
|
+
* Narrows within a deployed environment: {@link isProduction} is also true when this is true, since
|
|
49
|
+
* staging runs as production against real infrastructure.
|
|
26
50
|
*/
|
|
27
51
|
abstract readonly isStaging: boolean;
|
|
28
52
|
/**
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type Maybe } from '@dereekb/util';
|
|
2
|
+
import { type OidcScope, type OidcScopeTerm } from '@dereekb/firebase';
|
|
3
|
+
import { type FirebaseServerAuthData } from './auth.context.server';
|
|
4
|
+
/**
|
|
5
|
+
* Error code thrown by {@link assertEndpointOidcScope} when an OIDC caller is missing the scope a
|
|
6
|
+
* non-model endpoint requires.
|
|
7
|
+
*
|
|
8
|
+
* Distinct from the callModel-layer code so a client can tell "you cannot call this endpoint" apart
|
|
9
|
+
* from "you cannot make this model call".
|
|
10
|
+
*/
|
|
11
|
+
export declare const MISSING_ENDPOINT_OIDC_SCOPE_ERROR_CODE = "MISSING_ENDPOINT_OIDC_SCOPE_ERROR";
|
|
12
|
+
/**
|
|
13
|
+
* Reads the set of OIDC scopes carried by an authenticated request, or `undefined` for a non-OIDC
|
|
14
|
+
* (regular Firebase ID-token) caller.
|
|
15
|
+
*
|
|
16
|
+
* The OIDC bearer-token middleware attaches the validated access-token claims at
|
|
17
|
+
* `auth.oidcValidatedToken` (with the space-delimited `scope` string); a non-OIDC caller has neither
|
|
18
|
+
* that field nor a `scope` on `auth.token`. Reading is defensive — the auth shape is only typed as
|
|
19
|
+
* {@link FirebaseServerAuthData} here, since the OIDC-specific `oidcValidatedToken` lives in the
|
|
20
|
+
* `@dereekb/firebase-server/oidc` sub-package this core layer cannot import — and the actual parse is
|
|
21
|
+
* delegated to the shared {@link oidcScopesFromScopeClaim} so there is no drift with
|
|
22
|
+
* `getOidcScopesFromRequest`.
|
|
23
|
+
*
|
|
24
|
+
* @param auth - The request auth data, or undefined for unauthenticated requests.
|
|
25
|
+
* @returns The granted scope set, or `undefined` when the request carries no OIDC `scope` claim.
|
|
26
|
+
*/
|
|
27
|
+
export declare function oidcScopesFromRequestAuth(auth: Maybe<FirebaseServerAuthData>): Maybe<Set<OidcScope>>;
|
|
28
|
+
/**
|
|
29
|
+
* Inputs to {@link assertEndpointOidcScope}.
|
|
30
|
+
*/
|
|
31
|
+
export interface AssertEndpointOidcScopeInput {
|
|
32
|
+
/**
|
|
33
|
+
* The scope term the endpoint requires — a single scope, or an OR-group satisfied by holding any
|
|
34
|
+
* one of its scopes. `undefined`/`null` imposes no requirement.
|
|
35
|
+
*/
|
|
36
|
+
readonly requiredScope: Maybe<OidcScopeTerm>;
|
|
37
|
+
/**
|
|
38
|
+
* The scopes the caller was granted, or `undefined` for a non-OIDC caller (bypasses enforcement).
|
|
39
|
+
*/
|
|
40
|
+
readonly grantedScopes: Maybe<ReadonlySet<OidcScope>>;
|
|
41
|
+
/**
|
|
42
|
+
* Human-readable endpoint identifier used in the thrown error message (e.g. `/api/session/firestore`).
|
|
43
|
+
*/
|
|
44
|
+
readonly endpoint: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Enforces a single OIDC scope requirement for a plain (non-callModel) endpoint, throwing a `403`
|
|
48
|
+
* when an OIDC caller does not hold it.
|
|
49
|
+
*
|
|
50
|
+
* The non-model counterpart to `assertModelApiOidcScope`, which is unusable outside the model API
|
|
51
|
+
* because it requires a `{ call, modelType }` pair. Evaluation reuses the same shipped
|
|
52
|
+
* {@link oidcScopeTermSatisfied} primitive so a term means the same thing on both surfaces.
|
|
53
|
+
*
|
|
54
|
+
* Bypasses (no-op) when `grantedScopes` is `undefined` — i.e. a non-OIDC caller carrying a plain
|
|
55
|
+
* Firebase ID token, which has no `scope` claim to enforce against. **This is why scope-gating alone
|
|
56
|
+
* is never a sufficient gate**: an endpoint that must reject non-admins needs its own admin check,
|
|
57
|
+
* with the scope acting as defence in depth.
|
|
58
|
+
*
|
|
59
|
+
* @param input - The required term, the caller's granted scopes, and the endpoint name for the message.
|
|
60
|
+
* @throws A `403` forbidden error (code {@link MISSING_ENDPOINT_OIDC_SCOPE_ERROR_CODE}) when an OIDC
|
|
61
|
+
* caller does not satisfy the requirement.
|
|
62
|
+
*/
|
|
63
|
+
export declare function assertEndpointOidcScope(input: AssertEndpointOidcScopeInput): void;
|