@dereekb/firebase-server 13.29.0 → 13.30.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/index.cjs.js +129 -1
- package/index.esm.js +129 -3
- package/mailgun/package.json +9 -9
- package/mcp/index.cjs.js +42 -17
- package/mcp/index.esm.js +43 -18
- package/mcp/package.json +11 -11
- package/mcp/src/lib/mcp.config.d.ts +19 -1
- package/mcp/src/lib/service/mcp.server.factory.d.ts +1 -1
- package/mcp/src/lib/service/mcp.tool-generator.d.ts +12 -1
- package/mcp/src/lib/service/mcp.visibility.d.ts +9 -6
- package/model/package.json +9 -9
- package/oidc/index.cjs.js +2 -53
- package/oidc/index.esm.js +6 -56
- package/oidc/package.json +10 -10
- package/oidc/src/lib/index.d.ts +0 -1
- package/oidc/src/lib/service/oidc.auth.d.ts +1 -1
- package/package.json +10 -10
- package/src/lib/nest/controller/model/index.d.ts +1 -0
- package/src/lib/nest/controller/model/model.api.dispatch.d.ts +14 -2
- package/src/lib/nest/controller/model/model.api.get.service.d.ts +14 -0
- package/src/lib/nest/controller/model/model.api.scope.d.ts +102 -0
- package/src/lib/nest/model/api.details.d.ts +13 -8
- package/src/lib/nest/model/crud.assert.function.d.ts +7 -6
- package/test/package.json +11 -11
- package/twilio/package.json +8 -8
- package/zoho/package.json +9 -9
- package/oidc/src/lib/scope.d.ts +0 -24
package/mcp/index.esm.js
CHANGED
|
@@ -2,12 +2,12 @@ import { Injectable, Inject, Optional, Logger, Post, Req, Res, Controller, Get }
|
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
4
|
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { callModelOidcScopeForCallType, resolveEffectiveOidcScopeTerms, inferKeyFromTwoWayFlatFirestoreModelKey, oidcScopeTermsSatisfied } from '@dereekb/firebase';
|
|
5
6
|
import { getOidcScopesFromRequest, OidcProviderConfigService } from '@dereekb/firebase-server/oidc';
|
|
6
|
-
import {
|
|
7
|
+
import { makeValuesGroupMap, IMPERSONATION_URL_QUERY_PARAM, performAsyncTasks, authRolesSetHasRoles } from '@dereekb/util';
|
|
7
8
|
import { ModelApiCallModelDispatchService, ModelApiGetService, FirebaseServerStorageService, FirebaseServerEnvService, FirebaseServerAnalyticsService } from '@dereekb/firebase-server';
|
|
8
9
|
import { inspect } from 'node:util';
|
|
9
10
|
import { arktypeToJsonSchemaForExport } from '@dereekb/model';
|
|
10
|
-
import { callModelOidcScopeForCallType, inferKeyFromTwoWayFlatFirestoreModelKey } from '@dereekb/firebase';
|
|
11
11
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
12
12
|
|
|
13
13
|
function _class_call_check$5(instance, Constructor) {
|
|
@@ -165,6 +165,22 @@ function _define_property$9(obj, key, value) {
|
|
|
165
165
|
* fills with a short justification for the call. The value is forwarded to analytics and stripped
|
|
166
166
|
* from the dispatched handler body. See {@link McpReasonParameterConfig}.
|
|
167
167
|
*/ _define_property$9(this, "reasonParameter", void 0);
|
|
168
|
+
/**
|
|
169
|
+
* Default OIDC scope group term required on EVERY `callModel` op, mirrored into MCP tool-list
|
|
170
|
+
* visibility, unless a finer term overrides it (a per-function `requiredScope`, then a
|
|
171
|
+
* {@link McpModuleConfig.modelRequiredScopes} entry). Threaded into the same
|
|
172
|
+
* `resolveEffectiveOidcScopeTerms` composition the server-side model-api scope gate
|
|
173
|
+
* (`assertModelApiOidcScope`) uses, so a tool is advertised only when the caller could actually invoke it.
|
|
174
|
+
*
|
|
175
|
+
* Set this to the SAME value passed to `ModelApiDispatchConfig.defaultRequiredScope` to
|
|
176
|
+
* keep tool visibility and enforcement in lockstep.
|
|
177
|
+
*/ _define_property$9(this, "defaultRequiredScope", void 0);
|
|
178
|
+
/**
|
|
179
|
+
* Per-model OIDC scope group-term overrides, keyed by {@link FirestoreModelType}, mirrored into MCP
|
|
180
|
+
* tool-list visibility. Set this to the SAME value passed to
|
|
181
|
+
* `ModelApiDispatchConfig.modelRequiredScopes` so per-model / verb-keyed restrictions that
|
|
182
|
+
* confine a subset client apply identically to the advertised tool list.
|
|
183
|
+
*/ _define_property$9(this, "modelRequiredScopes", void 0);
|
|
168
184
|
};
|
|
169
185
|
/**
|
|
170
186
|
* NestJS injection token for the optional {@link McpAuthRoleReader} provider.
|
|
@@ -1398,6 +1414,8 @@ function _unsupported_iterable_to_array$9(o, minLen) {
|
|
|
1398
1414
|
var seenNames = new Set();
|
|
1399
1415
|
var manifest = context === null || context === void 0 ? void 0 : context.manifest;
|
|
1400
1416
|
var naming = context === null || context === void 0 ? void 0 : context.naming;
|
|
1417
|
+
var defaultRequiredScope = context === null || context === void 0 ? void 0 : context.defaultRequiredScope;
|
|
1418
|
+
var modelRequiredScopes = context === null || context === void 0 ? void 0 : context.modelRequiredScopes;
|
|
1401
1419
|
var candidates = planMcpToolCandidates(apiDetails, naming);
|
|
1402
1420
|
var clashCounts = countVisibleAutoNameClashes(candidates);
|
|
1403
1421
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -1409,6 +1427,8 @@ function _unsupported_iterable_to_array$9(o, minLen) {
|
|
|
1409
1427
|
clashCounts: clashCounts,
|
|
1410
1428
|
options: options,
|
|
1411
1429
|
manifest: manifest,
|
|
1430
|
+
defaultRequiredScope: defaultRequiredScope,
|
|
1431
|
+
modelRequiredScopes: modelRequiredScopes,
|
|
1412
1432
|
seenNames: seenNames,
|
|
1413
1433
|
outTools: tools,
|
|
1414
1434
|
outNeverVisibleTools: neverVisibleTools,
|
|
@@ -1580,7 +1600,7 @@ function _unsupported_iterable_to_array$9(o, minLen) {
|
|
|
1580
1600
|
*/ function buildToolFromCandidate(context) {
|
|
1581
1601
|
var _clashCounts_get, _ref;
|
|
1582
1602
|
var _handlerDetails_mcp, _handlerDetails_mcp1;
|
|
1583
|
-
var candidate = context.candidate, clashCounts = context.clashCounts, options = context.options, manifest = context.manifest, seenNames = context.seenNames, outTools = context.outTools, outNeverVisibleTools = context.outNeverVisibleTools, outSkipped = context.outSkipped, outWarnings = context.outWarnings;
|
|
1603
|
+
var candidate = context.candidate, clashCounts = context.clashCounts, options = context.options, manifest = context.manifest, defaultRequiredScope = context.defaultRequiredScope, modelRequiredScopes = context.modelRequiredScopes, seenNames = context.seenNames, outTools = context.outTools, outNeverVisibleTools = context.outNeverVisibleTools, outSkipped = context.outSkipped, outWarnings = context.outWarnings;
|
|
1584
1604
|
var modelType = candidate.modelType, callType = candidate.callType, handlerDetails = candidate.handlerDetails, specifier = candidate.specifier, dispatch = candidate.dispatch, modelSegment = candidate.modelSegment, overrideName = candidate.overrideName, baseName = candidate.baseName, classified = candidate.classified, isVisible = candidate.isVisible;
|
|
1585
1605
|
// A visible auto-named tool whose preferred name is produced by more than one visible tool is
|
|
1586
1606
|
// re-derived with the abbreviated call type so both survive on the wire. Overrides and hidden tools
|
|
@@ -1630,13 +1650,18 @@ function _unsupported_iterable_to_array$9(o, minLen) {
|
|
|
1630
1650
|
});
|
|
1631
1651
|
}
|
|
1632
1652
|
}
|
|
1633
|
-
//
|
|
1634
|
-
//
|
|
1635
|
-
//
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1653
|
+
// AND-of-ORs scope terms: the per-verb call-type scope (model.<call>) plus the effective group term,
|
|
1654
|
+
// resolved by the same precedence the server model-api scope gate uses (per-function requiredScope > per-model
|
|
1655
|
+
// requirement > module default) via the shared resolveEffectiveOidcScopeTerms — so tool visibility
|
|
1656
|
+
// tracks callability. Empty when no term applies (a non-CRUD call type with no per-function/model/
|
|
1657
|
+
// default term → no scope gate).
|
|
1658
|
+
var requiredScopeTerms = resolveEffectiveOidcScopeTerms({
|
|
1659
|
+
perVerbScope: resolveRequiredScope(callType),
|
|
1660
|
+
requiredScope: handlerDetails.requiredScope,
|
|
1661
|
+
modelRequirement: modelRequiredScopes === null || modelRequiredScopes === void 0 ? void 0 : modelRequiredScopes[modelType],
|
|
1662
|
+
call: callType,
|
|
1663
|
+
defaultRequiredScope: defaultRequiredScope
|
|
1664
|
+
});
|
|
1640
1665
|
var effectiveReadOnly = resolveEffectiveReadOnly((_handlerDetails_mcp = handlerDetails.mcp) === null || _handlerDetails_mcp === void 0 ? void 0 : _handlerDetails_mcp.readOnly, callType);
|
|
1641
1666
|
var annotations = resolveMcpToolAnnotations(effectiveReadOnly);
|
|
1642
1667
|
var description = applyWriteMarker(baseDescription, annotations);
|
|
@@ -1645,20 +1670,20 @@ function _unsupported_iterable_to_array$9(o, minLen) {
|
|
|
1645
1670
|
filterMetadata = {
|
|
1646
1671
|
visibilityKind: 'declarative',
|
|
1647
1672
|
rule: classified.rule,
|
|
1648
|
-
|
|
1673
|
+
requiredScopeTerms: requiredScopeTerms,
|
|
1649
1674
|
effectiveReadOnly: effectiveReadOnly
|
|
1650
1675
|
};
|
|
1651
1676
|
} else if (classified.visibilityKind === 'dynamic') {
|
|
1652
1677
|
filterMetadata = {
|
|
1653
1678
|
visibilityKind: 'dynamic',
|
|
1654
1679
|
visibilityFn: classified.visibilityFn,
|
|
1655
|
-
|
|
1680
|
+
requiredScopeTerms: requiredScopeTerms,
|
|
1656
1681
|
effectiveReadOnly: effectiveReadOnly
|
|
1657
1682
|
};
|
|
1658
1683
|
} else {
|
|
1659
1684
|
filterMetadata = {
|
|
1660
1685
|
visibilityKind: classified.visibilityKind,
|
|
1661
|
-
|
|
1686
|
+
requiredScopeTerms: requiredScopeTerms,
|
|
1662
1687
|
effectiveReadOnly: effectiveReadOnly
|
|
1663
1688
|
};
|
|
1664
1689
|
}
|
|
@@ -6161,7 +6186,9 @@ var McpServerFactoryService_1;
|
|
|
6161
6186
|
} else {
|
|
6162
6187
|
result = generateMcpToolDefinitions(apiDetails, undefined, {
|
|
6163
6188
|
manifest: manifest,
|
|
6164
|
-
naming: this._resolveToolNamingOptions()
|
|
6189
|
+
naming: this._resolveToolNamingOptions(),
|
|
6190
|
+
defaultRequiredScope: this.mcpConfig.defaultRequiredScope,
|
|
6191
|
+
modelRequiredScopes: this.mcpConfig.modelRequiredScopes
|
|
6165
6192
|
});
|
|
6166
6193
|
}
|
|
6167
6194
|
this._cachedTools = result;
|
|
@@ -6630,7 +6657,7 @@ var McpServerFactoryService_1;
|
|
|
6630
6657
|
* Synthesizes the same `{ auth: { token } }` shape that `getOidcScopesFromRequest`
|
|
6631
6658
|
* expects post-dispatch, so the upstream helper stays the single source of scope parsing.
|
|
6632
6659
|
* Returns `undefined` for non-OIDC callers (no `oidcValidatedToken.scope`) — the filter
|
|
6633
|
-
* loop treats that as "skip scope enforcement", matching `
|
|
6660
|
+
* loop treats that as "skip scope enforcement", matching the model-api scope gate (`assertModelApiOidcScope`).
|
|
6634
6661
|
*
|
|
6635
6662
|
* @param ctx - The per-request context carrying the validated auth payload.
|
|
6636
6663
|
* @returns The set of granted OIDC scopes, or `undefined` when scope enforcement should be skipped.
|
|
@@ -6674,9 +6701,7 @@ var McpServerFactoryService_1;
|
|
|
6674
6701
|
for(var _iterator = tools[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
6675
6702
|
var tool = _step.value;
|
|
6676
6703
|
var filterMetadata = tool.filterMetadata;
|
|
6677
|
-
if (scopes != null && filterMetadata.
|
|
6678
|
-
return scopes.has(scope);
|
|
6679
|
-
})) {
|
|
6704
|
+
if (scopes != null && filterMetadata.requiredScopeTerms != null && !oidcScopeTermsSatisfied(filterMetadata.requiredScopeTerms, scopes)) {
|
|
6680
6705
|
continue;
|
|
6681
6706
|
}
|
|
6682
6707
|
if (readOnlyMode && filterMetadata.effectiveReadOnly !== true) {
|
package/mcp/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/mcp",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.30.0",
|
|
4
4
|
"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.
|
|
5
|
+
"@dereekb/analytics": "13.30.0",
|
|
6
|
+
"@dereekb/date": "13.30.0",
|
|
7
|
+
"@dereekb/firebase": "13.30.0",
|
|
8
|
+
"@dereekb/firebase-server": "13.30.0",
|
|
9
|
+
"@dereekb/firebase-server/oidc": "13.30.0",
|
|
10
|
+
"@dereekb/model": "13.30.0",
|
|
11
|
+
"@dereekb/nestjs": "13.30.0",
|
|
12
|
+
"@dereekb/rxjs": "13.30.0",
|
|
13
|
+
"@dereekb/util": "13.30.0",
|
|
14
|
+
"@dereekb/zoho": "13.30.0",
|
|
15
15
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
16
16
|
"@nestjs/common": "^11.1.19",
|
|
17
17
|
"@nestjs/core": "^11.1.19",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AuthClaims, type AuthRoleSet } from '@dereekb/util';
|
|
2
|
-
import { type OidcScope } from '@dereekb/firebase';
|
|
2
|
+
import { type FirestoreModelType, type OidcModelScopeRequirement, type OidcScope, type OidcScopeTerm } from '@dereekb/firebase';
|
|
3
3
|
/**
|
|
4
4
|
* Default path the MCP Streamable HTTP transport is mounted at.
|
|
5
5
|
*
|
|
@@ -200,6 +200,24 @@ export declare abstract class McpModuleConfig {
|
|
|
200
200
|
* from the dispatched handler body. See {@link McpReasonParameterConfig}.
|
|
201
201
|
*/
|
|
202
202
|
readonly reasonParameter?: McpReasonParameterConfig | boolean;
|
|
203
|
+
/**
|
|
204
|
+
* Default OIDC scope group term required on EVERY `callModel` op, mirrored into MCP tool-list
|
|
205
|
+
* visibility, unless a finer term overrides it (a per-function `requiredScope`, then a
|
|
206
|
+
* {@link McpModuleConfig.modelRequiredScopes} entry). Threaded into the same
|
|
207
|
+
* `resolveEffectiveOidcScopeTerms` composition the server-side model-api scope gate
|
|
208
|
+
* (`assertModelApiOidcScope`) uses, so a tool is advertised only when the caller could actually invoke it.
|
|
209
|
+
*
|
|
210
|
+
* Set this to the SAME value passed to `ModelApiDispatchConfig.defaultRequiredScope` to
|
|
211
|
+
* keep tool visibility and enforcement in lockstep.
|
|
212
|
+
*/
|
|
213
|
+
readonly defaultRequiredScope?: OidcScopeTerm;
|
|
214
|
+
/**
|
|
215
|
+
* Per-model OIDC scope group-term overrides, keyed by {@link FirestoreModelType}, mirrored into MCP
|
|
216
|
+
* tool-list visibility. Set this to the SAME value passed to
|
|
217
|
+
* `ModelApiDispatchConfig.modelRequiredScopes` so per-model / verb-keyed restrictions that
|
|
218
|
+
* confine a subset client apply identically to the advertised tool list.
|
|
219
|
+
*/
|
|
220
|
+
readonly modelRequiredScopes?: Record<FirestoreModelType, OidcModelScopeRequirement>;
|
|
203
221
|
}
|
|
204
222
|
/**
|
|
205
223
|
* Signature for the optional role reader the MCP module uses when evaluating
|
|
@@ -152,7 +152,7 @@ export declare class McpServerFactoryService {
|
|
|
152
152
|
* Synthesizes the same `{ auth: { token } }` shape that `getOidcScopesFromRequest`
|
|
153
153
|
* expects post-dispatch, so the upstream helper stays the single source of scope parsing.
|
|
154
154
|
* Returns `undefined` for non-OIDC callers (no `oidcValidatedToken.scope`) — the filter
|
|
155
|
-
* loop treats that as "skip scope enforcement", matching `
|
|
155
|
+
* loop treats that as "skip scope enforcement", matching the model-api scope gate (`assertModelApiOidcScope`).
|
|
156
156
|
*
|
|
157
157
|
* @param ctx - The per-request context carrying the validated auth payload.
|
|
158
158
|
* @returns The set of granted OIDC scopes, or `undefined` when scope enforcement should be skipped.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Maybe } from '@dereekb/util';
|
|
2
|
-
import { type KnownOnCallFunctionType } from '@dereekb/firebase';
|
|
2
|
+
import { type FirestoreModelType, type KnownOnCallFunctionType, type OidcModelScopeRequirement, type OidcScopeTerm } from '@dereekb/firebase';
|
|
3
3
|
import { type ModelApiDetailsResult, type OnCallModelFunctionApiDetails, type FirebaseServerAuthData, type McpToolDetailsBuilder, type McpVisibilityRule } from '@dereekb/firebase-server';
|
|
4
4
|
import { type Request } from 'express';
|
|
5
5
|
import { type CallToolResult, type ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
@@ -452,6 +452,17 @@ export interface GenerateMcpToolDefinitionsContext {
|
|
|
452
452
|
* Per-model name segment overrides (e.g. collection prefixes).
|
|
453
453
|
*/
|
|
454
454
|
readonly naming?: McpToolGenerationNamingOptions;
|
|
455
|
+
/**
|
|
456
|
+
* Default OIDC scope group term required on every op unless a finer term overrides it. Mirrors the
|
|
457
|
+
* model-api layer's `ModelApiDispatchConfig.defaultRequiredScope` so a tool is advertised only when
|
|
458
|
+
* the caller could invoke it.
|
|
459
|
+
*/
|
|
460
|
+
readonly defaultRequiredScope?: OidcScopeTerm;
|
|
461
|
+
/**
|
|
462
|
+
* Per-model OIDC scope group-term overrides, keyed by {@link FirestoreModelType}. Mirrors the model-api
|
|
463
|
+
* layer's `ModelApiDispatchConfig.modelRequiredScopes` so per-model / verb-keyed restrictions apply to tool visibility.
|
|
464
|
+
*/
|
|
465
|
+
readonly modelRequiredScopes?: Record<FirestoreModelType, OidcModelScopeRequirement>;
|
|
455
466
|
}
|
|
456
467
|
/**
|
|
457
468
|
* Generates MCP tool definitions from a model-first API details tree.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Maybe } from '@dereekb/util';
|
|
2
|
-
import { type CallModelOidcScope, type
|
|
2
|
+
import { type CallModelOidcScope, type OidcScopeTerm } from '@dereekb/firebase';
|
|
3
3
|
import { type McpToolVisibility, type McpVisibilityContext, type McpVisibilityRule } from '@dereekb/firebase-server';
|
|
4
4
|
import { type ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
/**
|
|
@@ -41,12 +41,15 @@ export interface ClassifiedMcpToolVisibilityDynamic {
|
|
|
41
41
|
export type McpToolFilterMetadata = McpToolFilterMetadataAlways | McpToolFilterMetadataNever | McpToolFilterMetadataDeclarative | McpToolFilterMetadataDynamic;
|
|
42
42
|
interface McpToolFilterMetadataBase {
|
|
43
43
|
/**
|
|
44
|
-
* OIDC
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
44
|
+
* OIDC scope TERMS required to invoke this tool, evaluated AND-of-ORs — the caller must satisfy
|
|
45
|
+
* EVERY term, and an array term (OR-group) is satisfied by holding ANY member. Checked with the
|
|
46
|
+
* shared `oidcScopeTermsSatisfied` so tool-list visibility matches the server-side `callModel` gate
|
|
47
|
+
* exactly. Precomputed from the dispatch call type's per-verb scope (`model.<call>`) plus the
|
|
48
|
+
* effective group term (per-function `requiredScope` > per-model requirement > module default).
|
|
49
|
+
* Empty when no scope is enforced (a non-CRUD call type with no per-function/model/default term);
|
|
50
|
+
* apps gate custom verbs via their own preAssert.
|
|
48
51
|
*/
|
|
49
|
-
readonly
|
|
52
|
+
readonly requiredScopeTerms?: readonly OidcScopeTerm[];
|
|
50
53
|
/**
|
|
51
54
|
* Effective read-only classification used by the module-level `readOnly` filter.
|
|
52
55
|
*
|
package/model/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/model",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.30.0",
|
|
4
4
|
"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.
|
|
5
|
+
"@dereekb/analytics": "13.30.0",
|
|
6
|
+
"@dereekb/date": "13.30.0",
|
|
7
|
+
"@dereekb/firebase": "13.30.0",
|
|
8
|
+
"@dereekb/firebase-server": "13.30.0",
|
|
9
|
+
"@dereekb/model": "13.30.0",
|
|
10
|
+
"@dereekb/nestjs": "13.30.0",
|
|
11
|
+
"@dereekb/rxjs": "13.30.0",
|
|
12
|
+
"@dereekb/util": "13.30.0",
|
|
13
13
|
"@nestjs/common": "^11.1.19",
|
|
14
14
|
"@nestjs/config": "^4.0.4",
|
|
15
15
|
"archiver": "^7.0.1",
|
package/oidc/index.cjs.js
CHANGED
|
@@ -5395,7 +5395,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
|
|
|
5395
5395
|
* `request.auth.token.scope` for OIDC callers and is `undefined` for non-OIDC
|
|
5396
5396
|
* (regular Firebase ID-token) callers.
|
|
5397
5397
|
*
|
|
5398
|
-
* Returning `undefined` for non-OIDC callers lets
|
|
5398
|
+
* Returning `undefined` for non-OIDC callers lets consumers (e.g. the MCP tool-visibility filter)
|
|
5399
5399
|
* skip scope enforcement instead of falsely treating the missing claim as "no scopes granted".
|
|
5400
5400
|
*
|
|
5401
5401
|
* The parameter is intentionally typed as `unknown` because `DecodedIdToken` (Firebase
|
|
@@ -5407,10 +5407,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
|
|
|
5407
5407
|
*/ function getOidcScopesFromRequest(request) {
|
|
5408
5408
|
var _request_auth_token, _request_auth;
|
|
5409
5409
|
var scope = request === null || request === void 0 ? void 0 : (_request_auth = request.auth) === null || _request_auth === void 0 ? void 0 : (_request_auth_token = _request_auth.token) === null || _request_auth_token === void 0 ? void 0 : _request_auth_token.scope;
|
|
5410
|
-
|
|
5411
|
-
return value.length > 0;
|
|
5412
|
-
})) : undefined;
|
|
5413
|
-
return result;
|
|
5410
|
+
return firebase.oidcScopesFromScopeClaim(scope);
|
|
5414
5411
|
}
|
|
5415
5412
|
|
|
5416
5413
|
function asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, key, arg) {
|
|
@@ -7781,53 +7778,6 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
7781
7778
|
};
|
|
7782
7779
|
}
|
|
7783
7780
|
|
|
7784
|
-
/**
|
|
7785
|
-
* Builds a {@link AssertModelCrudRequestFunction} that rejects callModel requests
|
|
7786
|
-
* lacking the required OIDC scope(s) for the call.
|
|
7787
|
-
*
|
|
7788
|
-
* Enforcement is additive: an OIDC caller must hold BOTH the per-verb scope mapped
|
|
7789
|
-
* from the call type (`model.<call>`) AND any per-function scope a handler declared
|
|
7790
|
-
* via `withApiDetails({ requiredScope })` — surfaced on `context.requiredScope`.
|
|
7791
|
-
*
|
|
7792
|
-
* Bypasses the check (no-op) when the request is not OIDC-authenticated — i.e.
|
|
7793
|
-
* when {@link getOidcScopesFromRequest} returns `undefined` because there is no
|
|
7794
|
-
* `auth.token.scope` claim on the request. Regular Firebase ID-token callers are
|
|
7795
|
-
* unaffected and continue to be gated by auth roles.
|
|
7796
|
-
*
|
|
7797
|
-
* Bypasses the check for custom (non-CRUD) call types that declare no per-function
|
|
7798
|
-
* scope, so app-specific verbs remain unrestricted unless an app wires its own
|
|
7799
|
-
* assertion or declares a `requiredScope`.
|
|
7800
|
-
*
|
|
7801
|
-
* Wire as the `preAssert` of {@link onCallModel}.
|
|
7802
|
-
*
|
|
7803
|
-
* @returns The pre-assertion function ready to plug into `OnCallModelConfig.preAssert`.
|
|
7804
|
-
*/ function oidcCallModelScopePreAssert() {
|
|
7805
|
-
var fn = function fn(context) {
|
|
7806
|
-
var requiredScopes = util.filterMaybeArrayValues([
|
|
7807
|
-
firebase.callModelOidcScopeForCallType(context.call),
|
|
7808
|
-
context.requiredScope
|
|
7809
|
-
]);
|
|
7810
|
-
// No requirement (custom verb + no per-function scope) short-circuits without reading scopes.
|
|
7811
|
-
// A non-OIDC caller yields `undefined` scopes below and bypasses just like the per-verb check.
|
|
7812
|
-
var scopes = requiredScopes.length === 0 ? undefined : getOidcScopesFromRequest(context.request);
|
|
7813
|
-
var missingScopes = scopes == null ? [] : requiredScopes.filter(function(scope) {
|
|
7814
|
-
return !scopes.has(scope);
|
|
7815
|
-
});
|
|
7816
|
-
if (missingScopes.length > 0) {
|
|
7817
|
-
throw firebaseServer.forbiddenError({
|
|
7818
|
-
status: 403,
|
|
7819
|
-
code: firebase.CALL_MODEL_MISSING_OIDC_SCOPE_ERROR_CODE,
|
|
7820
|
-
message: "Missing required OIDC scope for callModel: ".concat(missingScopes.join(', ')),
|
|
7821
|
-
data: {
|
|
7822
|
-
requiredScopes: missingScopes,
|
|
7823
|
-
call: context.call
|
|
7824
|
-
}
|
|
7825
|
-
});
|
|
7826
|
-
}
|
|
7827
|
-
};
|
|
7828
|
-
return fn;
|
|
7829
|
-
}
|
|
7830
|
-
|
|
7831
7781
|
exports.DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA = DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA;
|
|
7832
7782
|
exports.DEFAULT_APP_OAUTH_CONSENT_PATH_PART = DEFAULT_APP_OAUTH_CONSENT_PATH_PART;
|
|
7833
7783
|
exports.DEFAULT_APP_OAUTH_INTERACTION_PATH = DEFAULT_APP_OAUTH_INTERACTION_PATH;
|
|
@@ -7890,7 +7840,6 @@ exports.jwksKeyIdentity = jwksKeyIdentity;
|
|
|
7890
7840
|
exports.jwksKeysWithStatusQuery = jwksKeysWithStatusQuery;
|
|
7891
7841
|
exports.nonRetiredJwksKeysQuery = nonRetiredJwksKeysQuery;
|
|
7892
7842
|
exports.noopOidcAnalyticsService = noopOidcAnalyticsService;
|
|
7893
|
-
exports.oidcCallModelScopePreAssert = oidcCallModelScopePreAssert;
|
|
7894
7843
|
exports.oidcClientProviderProfileScopes = oidcClientProviderProfileScopes;
|
|
7895
7844
|
exports.oidcCorsOriginDelegate = oidcCorsOriginDelegate;
|
|
7896
7845
|
exports.oidcFirestoreCollectionsFactory = oidcFirestoreCollectionsFactory;
|
package/oidc/index.esm.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createParamDecorator, Injectable, Inject, Optional, Logger, UnauthorizedException, Get, Param, Req, Res, Post, HttpCode, HttpStatus, Body, Controller, HttpException, All } from '@nestjs/common';
|
|
2
2
|
import { errors } from 'oidc-provider';
|
|
3
|
-
import { SECONDS_IN_MINUTE, SECONDS_IN_DAY, cachedGetter, unixDateTimeSecondsNumberToDate, unixDateTimeSecondsNumberForNow, selectiveFieldEncryptor, filterUndefinedValues, websiteUrlFromPaths, firstValue, hasHttpPrefix
|
|
3
|
+
import { SECONDS_IN_MINUTE, SECONDS_IN_DAY, cachedGetter, unixDateTimeSecondsNumberToDate, unixDateTimeSecondsNumberForNow, selectiveFieldEncryptor, filterUndefinedValues, websiteUrlFromPaths, firstValue, hasHttpPrefix } from '@dereekb/util';
|
|
4
4
|
import { generateKeyPairSync, randomBytes } from 'node:crypto';
|
|
5
5
|
import { resolveEncryptionKey, encryptValue, decryptValue, createAesStringEncryptionProvider, isValidAES256GCMEncryptionSecret } from '@dereekb/nestjs';
|
|
6
|
-
import { where, iterateFirestoreDocumentSnapshotPairs, firestoreModelIdentity, snapshotConverterFunctions, optionalFirestoreDate, firestoreDate, firestoreEnum, firestorePassThroughField, AbstractFirestoreDocument, createOidcClientParamsType, deleteOidcClientParamsType, deleteOidcTokenParamsType, rotateOidcClientSecretParamsType, updateOidcClientParamsType, firestoreModelKey, oidcEntryIdentity, PUBLIC_PKCE_TOKEN_ENDPOINT_AUTH_METHOD, OIDC_ENTRY_CLIENT_TYPE, oidcEntriesByUserCodeQuery, oidcEntriesByUidQuery, oidcEntriesByGrantIdQuery, oidcProviderProfilesForKeys, requiredScopesForOidcProviderProfiles, scopesForOidcProviderProfiles,
|
|
7
|
-
import { firestoreEncryptedField, firebaseServerActionsContext, FirebaseServerEnvService, FirebaseServerAnalyticsService, FIREBASE_FIRESTORE_CONTEXT_TOKEN, FirebaseServerFirestoreContextModule
|
|
6
|
+
import { where, iterateFirestoreDocumentSnapshotPairs, firestoreModelIdentity, snapshotConverterFunctions, optionalFirestoreDate, firestoreDate, firestoreEnum, firestorePassThroughField, AbstractFirestoreDocument, createOidcClientParamsType, deleteOidcClientParamsType, deleteOidcTokenParamsType, rotateOidcClientSecretParamsType, updateOidcClientParamsType, firestoreModelKey, oidcEntryIdentity, PUBLIC_PKCE_TOKEN_ENDPOINT_AUTH_METHOD, OIDC_ENTRY_CLIENT_TYPE, oidcEntriesByUserCodeQuery, oidcEntriesByUidQuery, oidcEntriesByGrantIdQuery, oidcProviderProfilesForKeys, requiredScopesForOidcProviderProfiles, scopesForOidcProviderProfiles, oidcScopesFromScopeClaim, oidcEntryFirestoreCollection } from '@dereekb/firebase';
|
|
7
|
+
import { firestoreEncryptedField, firebaseServerActionsContext, FirebaseServerEnvService, FirebaseServerAnalyticsService, FIREBASE_FIRESTORE_CONTEXT_TOKEN, FirebaseServerFirestoreContextModule } from '@dereekb/firebase-server';
|
|
8
8
|
import { nanoid } from 'nanoid';
|
|
9
9
|
import { safeToJsDate } from '@dereekb/date';
|
|
10
10
|
import { makeUrlSearchParamsString } from '@dereekb/util/fetch';
|
|
@@ -5393,7 +5393,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
|
|
|
5393
5393
|
* `request.auth.token.scope` for OIDC callers and is `undefined` for non-OIDC
|
|
5394
5394
|
* (regular Firebase ID-token) callers.
|
|
5395
5395
|
*
|
|
5396
|
-
* Returning `undefined` for non-OIDC callers lets
|
|
5396
|
+
* Returning `undefined` for non-OIDC callers lets consumers (e.g. the MCP tool-visibility filter)
|
|
5397
5397
|
* skip scope enforcement instead of falsely treating the missing claim as "no scopes granted".
|
|
5398
5398
|
*
|
|
5399
5399
|
* The parameter is intentionally typed as `unknown` because `DecodedIdToken` (Firebase
|
|
@@ -5405,10 +5405,7 @@ function _unsupported_iterable_to_array$2(o, minLen) {
|
|
|
5405
5405
|
*/ function getOidcScopesFromRequest(request) {
|
|
5406
5406
|
var _request_auth_token, _request_auth;
|
|
5407
5407
|
var scope = request === null || request === void 0 ? void 0 : (_request_auth = request.auth) === null || _request_auth === void 0 ? void 0 : (_request_auth_token = _request_auth.token) === null || _request_auth_token === void 0 ? void 0 : _request_auth_token.scope;
|
|
5408
|
-
|
|
5409
|
-
return value.length > 0;
|
|
5410
|
-
})) : undefined;
|
|
5411
|
-
return result;
|
|
5408
|
+
return oidcScopesFromScopeClaim(scope);
|
|
5412
5409
|
}
|
|
5413
5410
|
|
|
5414
5411
|
function asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, key, arg) {
|
|
@@ -7779,51 +7776,4 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
7779
7776
|
};
|
|
7780
7777
|
}
|
|
7781
7778
|
|
|
7782
|
-
|
|
7783
|
-
* Builds a {@link AssertModelCrudRequestFunction} that rejects callModel requests
|
|
7784
|
-
* lacking the required OIDC scope(s) for the call.
|
|
7785
|
-
*
|
|
7786
|
-
* Enforcement is additive: an OIDC caller must hold BOTH the per-verb scope mapped
|
|
7787
|
-
* from the call type (`model.<call>`) AND any per-function scope a handler declared
|
|
7788
|
-
* via `withApiDetails({ requiredScope })` — surfaced on `context.requiredScope`.
|
|
7789
|
-
*
|
|
7790
|
-
* Bypasses the check (no-op) when the request is not OIDC-authenticated — i.e.
|
|
7791
|
-
* when {@link getOidcScopesFromRequest} returns `undefined` because there is no
|
|
7792
|
-
* `auth.token.scope` claim on the request. Regular Firebase ID-token callers are
|
|
7793
|
-
* unaffected and continue to be gated by auth roles.
|
|
7794
|
-
*
|
|
7795
|
-
* Bypasses the check for custom (non-CRUD) call types that declare no per-function
|
|
7796
|
-
* scope, so app-specific verbs remain unrestricted unless an app wires its own
|
|
7797
|
-
* assertion or declares a `requiredScope`.
|
|
7798
|
-
*
|
|
7799
|
-
* Wire as the `preAssert` of {@link onCallModel}.
|
|
7800
|
-
*
|
|
7801
|
-
* @returns The pre-assertion function ready to plug into `OnCallModelConfig.preAssert`.
|
|
7802
|
-
*/ function oidcCallModelScopePreAssert() {
|
|
7803
|
-
var fn = function fn(context) {
|
|
7804
|
-
var requiredScopes = filterMaybeArrayValues([
|
|
7805
|
-
callModelOidcScopeForCallType(context.call),
|
|
7806
|
-
context.requiredScope
|
|
7807
|
-
]);
|
|
7808
|
-
// No requirement (custom verb + no per-function scope) short-circuits without reading scopes.
|
|
7809
|
-
// A non-OIDC caller yields `undefined` scopes below and bypasses just like the per-verb check.
|
|
7810
|
-
var scopes = requiredScopes.length === 0 ? undefined : getOidcScopesFromRequest(context.request);
|
|
7811
|
-
var missingScopes = scopes == null ? [] : requiredScopes.filter(function(scope) {
|
|
7812
|
-
return !scopes.has(scope);
|
|
7813
|
-
});
|
|
7814
|
-
if (missingScopes.length > 0) {
|
|
7815
|
-
throw forbiddenError({
|
|
7816
|
-
status: 403,
|
|
7817
|
-
code: CALL_MODEL_MISSING_OIDC_SCOPE_ERROR_CODE,
|
|
7818
|
-
message: "Missing required OIDC scope for callModel: ".concat(missingScopes.join(', ')),
|
|
7819
|
-
data: {
|
|
7820
|
-
requiredScopes: missingScopes,
|
|
7821
|
-
call: context.call
|
|
7822
|
-
}
|
|
7823
|
-
});
|
|
7824
|
-
}
|
|
7825
|
-
};
|
|
7826
|
-
return fn;
|
|
7827
|
-
}
|
|
7828
|
-
|
|
7829
|
-
export { DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA, DEFAULT_APP_OAUTH_CONSENT_PATH_PART, DEFAULT_APP_OAUTH_INTERACTION_PATH, DEFAULT_APP_OAUTH_LOGIN_PATH_PART, DEFAULT_MAX_ADMIN_LOGIN_DURATION_SECONDS, DEFAULT_MAX_NONADMIN_LOGIN_DURATION_SECONDS, DEFAULT_MAX_REQUESTED_LOGIN_DURATION_SECONDS, DEFAULT_MAX_SERVICE_TOKEN_LOGIN_DURATION_SECONDS, DEFAULT_MIN_REQUESTED_LOGIN_DURATION_SECONDS, DEFAULT_OIDC_ANALYTICS_EVENT_NAMES, DEFAULT_OIDC_ANALYTICS_EVENT_NAME_PREFIX, DEFAULT_OIDC_CODE_CHALLENGE_METHODS, DEFAULT_OIDC_ID_TOKEN_SIGNING_ALG_VALUES, DEFAULT_OIDC_ISSUER_PATH, DEFAULT_OIDC_ROUTES, DEFAULT_OIDC_SUBJECT_TYPES, DEFAULT_OIDC_TOKEN_ENDPOINT_AUTH_METHODS, DEFAULT_OIDC_TOKEN_LIFETIMES, DEFAULT_ROTATED_KEY_MAX_AGE, FIREBASE_SERVER_OIDC_ANALYTICS_CONFIG, FIREBASE_SERVER_OIDC_ROUTES_FOR_GLOBAL_ROUTE_EXCLUDE, FirebaseServerOidcAnalyticsService, GRANTABLE_MODEL_NAMES, JwksFirestoreCollections, JwksKeyDocument, JwksService, JwksServiceConfig, JwksServiceStorageConfig, OIDC_ANALYTICS_SERVICE, OIDC_ENCRYPTED_PAYLOAD_FIELDS, OIDC_JSON_RENDER_ERROR_FUNCTION, OIDC_JWKS_ENCRYPTION_SECRET_ENV_KEY, OidcAccountService, OidcAccountServiceDelegate, OidcAccountServiceUserContext, OidcAnalyticsService, OidcAuth, OidcAuthBearerTokenMiddleware, OidcAuthMiddlewareConfig, OidcClientService, OidcEncryptionService, OidcInteractionController, OidcInteractionService, OidcModelServerActions, OidcModuleConfig, OidcProviderConfigService, OidcProviderController, OidcServerFirestoreCollections, OidcService, OidcWellKnownController, activeJwksKeysQuery, allOidcScopesStringForProviderConfig, appOidcAnalyticsModuleMetadata, appOidcModelModuleMetadata, applyOidcAuthMiddleware, applyOidcCorsMiddleware, buildBearerChallenge, buildFirebaseServerMcpResourceServer, createAdapterFactory, createOidcClientFactory, deleteOidcClientFactory, deleteOidcTokenFactory, deriveResourceMetadataUrlFromEnv, emitOidcAnalyticsEvent, getOidcScopesFromRequest, jwksKeyCollectionReference, jwksKeyConverter, jwksKeyFirestoreCollection, jwksKeyIdentity, jwksKeysWithStatusQuery, nonRetiredJwksKeysQuery, noopOidcAnalyticsService, oidcCallModelScopePreAssert, oidcClientProviderProfileScopes, oidcCorsOriginDelegate, oidcFirestoreCollectionsFactory, oidcModelServerActions, oidcModelServerActionsFactory, oidcModuleConfigFactory, oidcModuleMetadata, resolveEffectiveSubset, rotateOidcClientSecretFactory, rotatedJwksKeysQuery, updateOidcClientFactory };
|
|
7779
|
+
export { DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA, DEFAULT_APP_OAUTH_CONSENT_PATH_PART, DEFAULT_APP_OAUTH_INTERACTION_PATH, DEFAULT_APP_OAUTH_LOGIN_PATH_PART, DEFAULT_MAX_ADMIN_LOGIN_DURATION_SECONDS, DEFAULT_MAX_NONADMIN_LOGIN_DURATION_SECONDS, DEFAULT_MAX_REQUESTED_LOGIN_DURATION_SECONDS, DEFAULT_MAX_SERVICE_TOKEN_LOGIN_DURATION_SECONDS, DEFAULT_MIN_REQUESTED_LOGIN_DURATION_SECONDS, DEFAULT_OIDC_ANALYTICS_EVENT_NAMES, DEFAULT_OIDC_ANALYTICS_EVENT_NAME_PREFIX, DEFAULT_OIDC_CODE_CHALLENGE_METHODS, DEFAULT_OIDC_ID_TOKEN_SIGNING_ALG_VALUES, DEFAULT_OIDC_ISSUER_PATH, DEFAULT_OIDC_ROUTES, DEFAULT_OIDC_SUBJECT_TYPES, DEFAULT_OIDC_TOKEN_ENDPOINT_AUTH_METHODS, DEFAULT_OIDC_TOKEN_LIFETIMES, DEFAULT_ROTATED_KEY_MAX_AGE, FIREBASE_SERVER_OIDC_ANALYTICS_CONFIG, FIREBASE_SERVER_OIDC_ROUTES_FOR_GLOBAL_ROUTE_EXCLUDE, FirebaseServerOidcAnalyticsService, GRANTABLE_MODEL_NAMES, JwksFirestoreCollections, JwksKeyDocument, JwksService, JwksServiceConfig, JwksServiceStorageConfig, OIDC_ANALYTICS_SERVICE, OIDC_ENCRYPTED_PAYLOAD_FIELDS, OIDC_JSON_RENDER_ERROR_FUNCTION, OIDC_JWKS_ENCRYPTION_SECRET_ENV_KEY, OidcAccountService, OidcAccountServiceDelegate, OidcAccountServiceUserContext, OidcAnalyticsService, OidcAuth, OidcAuthBearerTokenMiddleware, OidcAuthMiddlewareConfig, OidcClientService, OidcEncryptionService, OidcInteractionController, OidcInteractionService, OidcModelServerActions, OidcModuleConfig, OidcProviderConfigService, OidcProviderController, OidcServerFirestoreCollections, OidcService, OidcWellKnownController, activeJwksKeysQuery, allOidcScopesStringForProviderConfig, appOidcAnalyticsModuleMetadata, appOidcModelModuleMetadata, applyOidcAuthMiddleware, applyOidcCorsMiddleware, buildBearerChallenge, buildFirebaseServerMcpResourceServer, createAdapterFactory, createOidcClientFactory, deleteOidcClientFactory, deleteOidcTokenFactory, deriveResourceMetadataUrlFromEnv, emitOidcAnalyticsEvent, getOidcScopesFromRequest, jwksKeyCollectionReference, jwksKeyConverter, jwksKeyFirestoreCollection, jwksKeyIdentity, jwksKeysWithStatusQuery, nonRetiredJwksKeysQuery, noopOidcAnalyticsService, oidcClientProviderProfileScopes, oidcCorsOriginDelegate, oidcFirestoreCollectionsFactory, oidcModelServerActions, oidcModelServerActionsFactory, oidcModuleConfigFactory, oidcModuleMetadata, resolveEffectiveSubset, rotateOidcClientSecretFactory, rotatedJwksKeysQuery, updateOidcClientFactory };
|
package/oidc/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/oidc",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.30.0",
|
|
4
4
|
"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.
|
|
5
|
+
"@dereekb/analytics": "13.30.0",
|
|
6
|
+
"@dereekb/date": "13.30.0",
|
|
7
|
+
"@dereekb/firebase": "13.30.0",
|
|
8
|
+
"@dereekb/firebase-server": "13.30.0",
|
|
9
|
+
"@dereekb/model": "13.30.0",
|
|
10
|
+
"@dereekb/nestjs": "13.30.0",
|
|
11
|
+
"@dereekb/rxjs": "13.30.0",
|
|
12
|
+
"@dereekb/util": "13.30.0",
|
|
13
|
+
"@dereekb/zoho": "13.30.0",
|
|
14
14
|
"@nestjs/common": "^11.1.19",
|
|
15
15
|
"@nestjs/config": "^4.0.4",
|
|
16
16
|
"express": "^5.2.1",
|
package/oidc/src/lib/index.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export type OidcAuthenticatedRequest = FirebaseServerAuthenticatedRequest<OidcAu
|
|
|
33
33
|
* `request.auth.token.scope` for OIDC callers and is `undefined` for non-OIDC
|
|
34
34
|
* (regular Firebase ID-token) callers.
|
|
35
35
|
*
|
|
36
|
-
* Returning `undefined` for non-OIDC callers lets
|
|
36
|
+
* Returning `undefined` for non-OIDC callers lets consumers (e.g. the MCP tool-visibility filter)
|
|
37
37
|
* skip scope enforcement instead of falsely treating the missing claim as "no scopes granted".
|
|
38
38
|
*
|
|
39
39
|
* The parameter is intentionally typed as `unknown` because `DecodedIdToken` (Firebase
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.30.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"exports": {
|
|
6
6
|
"./test": {
|
|
@@ -57,15 +57,15 @@
|
|
|
57
57
|
"types": "./src/index.d.ts",
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"@cantoo/pdf-lib": "^2.6.5",
|
|
60
|
-
"@dereekb/analytics": "13.
|
|
61
|
-
"@dereekb/date": "13.
|
|
62
|
-
"@dereekb/dbx-core": "13.
|
|
63
|
-
"@dereekb/firebase": "13.
|
|
64
|
-
"@dereekb/model": "13.
|
|
65
|
-
"@dereekb/nestjs": "13.
|
|
66
|
-
"@dereekb/rxjs": "13.
|
|
67
|
-
"@dereekb/util": "13.
|
|
68
|
-
"@dereekb/zoho": "13.
|
|
60
|
+
"@dereekb/analytics": "13.30.0",
|
|
61
|
+
"@dereekb/date": "13.30.0",
|
|
62
|
+
"@dereekb/dbx-core": "13.30.0",
|
|
63
|
+
"@dereekb/firebase": "13.30.0",
|
|
64
|
+
"@dereekb/model": "13.30.0",
|
|
65
|
+
"@dereekb/nestjs": "13.30.0",
|
|
66
|
+
"@dereekb/rxjs": "13.30.0",
|
|
67
|
+
"@dereekb/util": "13.30.0",
|
|
68
|
+
"@dereekb/zoho": "13.30.0",
|
|
69
69
|
"@google-cloud/firestore": "^7.11.6",
|
|
70
70
|
"@google-cloud/storage": "^7.19.0",
|
|
71
71
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { type Maybe } from '@dereekb/util';
|
|
2
|
-
import { type OnCallTypedModelParams } from '@dereekb/firebase';
|
|
2
|
+
import { type FirestoreModelType, type OidcModelScopeRequirement, type OidcScopeTerm, type OnCallTypedModelParams } from '@dereekb/firebase';
|
|
3
3
|
import { type INestApplicationContext } from '@nestjs/common';
|
|
4
4
|
import { type Request } from 'express';
|
|
5
5
|
import { type OnCallWithNestContext } from '../../function/call';
|
|
6
6
|
import { type OnCallApiDetailsRef, type ModelApiDetailsResult } from '../../model/api.details';
|
|
7
7
|
import { type MakeNestContext } from '../../nest.provider';
|
|
8
8
|
import { type FirebaseServerAuthData } from '../auth.context.server';
|
|
9
|
+
import { type ModelApiOidcScopeConfig } from './model.api.scope';
|
|
9
10
|
/**
|
|
10
11
|
* The combined type of the function returned by onCallModel() with _apiDetails attached.
|
|
11
12
|
*/
|
|
@@ -27,7 +28,7 @@ export type OnCallModelFnWithApiDetails = OnCallWithNestContext<unknown, OnCallT
|
|
|
27
28
|
* }
|
|
28
29
|
* ```
|
|
29
30
|
*/
|
|
30
|
-
export declare abstract class ModelApiDispatchConfig {
|
|
31
|
+
export declare abstract class ModelApiDispatchConfig implements ModelApiOidcScopeConfig {
|
|
31
32
|
/**
|
|
32
33
|
* The onCallModel() return value with _apiDetails attached.
|
|
33
34
|
*/
|
|
@@ -36,6 +37,17 @@ export declare abstract class ModelApiDispatchConfig {
|
|
|
36
37
|
* Factory to create typed nest context from INestApplicationContext.
|
|
37
38
|
*/
|
|
38
39
|
readonly makeNestContext: MakeNestContext<unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* Optional model-api-layer OIDC group-scope default. See {@link ModelApiOidcScopeConfig.defaultRequiredScope}.
|
|
42
|
+
* This is the home for the callModel group-scope default; providing it here enforces it across
|
|
43
|
+
* dispatch AND the `/get` reads.
|
|
44
|
+
*/
|
|
45
|
+
readonly defaultRequiredScope?: OidcScopeTerm;
|
|
46
|
+
/**
|
|
47
|
+
* Optional per-model OIDC group-scope overrides. See {@link ModelApiOidcScopeConfig.modelRequiredScopes}.
|
|
48
|
+
* The only place a plain `/get` read (no per-function handler) can be scope-gated beyond `model.read`.
|
|
49
|
+
*/
|
|
50
|
+
readonly modelRequiredScopes?: Record<FirestoreModelType, OidcModelScopeRequirement>;
|
|
39
51
|
}
|
|
40
52
|
/**
|
|
41
53
|
* Injection token for providing the NestJS application context to the dispatch service.
|
|
@@ -61,8 +61,22 @@ export declare function modelAccessReadErrorFromUseMultipleModelsFailure(entry:
|
|
|
61
61
|
*/
|
|
62
62
|
export declare class ModelApiGetService {
|
|
63
63
|
private readonly _nestContext;
|
|
64
|
+
private readonly _defaultRequiredScope;
|
|
65
|
+
private readonly _modelRequiredScopes;
|
|
64
66
|
private _identityByModelType;
|
|
65
67
|
constructor(config: ModelApiDispatchConfig, nestApplication: INestApplicationContext);
|
|
68
|
+
/**
|
|
69
|
+
* Enforces the OIDC read-scope requirement for a direct document read before it hits Firestore.
|
|
70
|
+
*
|
|
71
|
+
* A direct `/get` read is the `read` verb: it requires the per-verb `model.read` scope AND any
|
|
72
|
+
* effective group term for the target model (per-model requirement > module default). This is the
|
|
73
|
+
* ONLY gate on the direct-read path — it does not touch the callModel dispatch chain — so without it
|
|
74
|
+
* an OIDC client scoped to a subset could read any model through `/get`. Non-OIDC callers bypass.
|
|
75
|
+
*
|
|
76
|
+
* @param modelType - The Firestore model type being read.
|
|
77
|
+
* @param auth - The request's auth data (OIDC scopes are read from it).
|
|
78
|
+
*/
|
|
79
|
+
private _assertReadScope;
|
|
66
80
|
/**
|
|
67
81
|
* Returns the registered {@link FirestoreModelIdentity} for the given `modelType` string, or
|
|
68
82
|
* `undefined` when no model of that type is registered.
|