@futdevpro/fsm-dynamo 1.20.67 → 1.20.69

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.
@@ -1,6 +1,17 @@
1
1
  import { DyFM_OperationContext_ControlModel } from '../../_models/control-models/operation-context.control-model';
2
2
  import { DyFM_OperationSettings_ControlModel } from '../../_models/control-models/operation-settings.control-model';
3
3
  import { DyFM_OperationAuthz_Result } from '../../_models/interfaces/operation-authz-result.interface';
4
+ /**
5
+ * The scope that grants EVERY operation (owner decision D-9, 2026-09-18: "legyen all scope").
6
+ *
7
+ * ⚠️ **What it means, stated plainly:** a key holding this scope passes every scope check — including the
8
+ * checks of operations that DO NOT EXIST YET. A capability added next month is granted to it automatically,
9
+ * with nobody re-approving. That is the deliberate trade of this decision: one token instead of a list.
10
+ *
11
+ * ⛔ It can not collide with a real scope: an operation scope always names a domain and an action
12
+ * (`note:read`), so no declared `apiKeyScope` can ever be this token.
13
+ */
14
+ export declare const DyFM_operationAllScope: string;
4
15
  /**
5
16
  * Transport-independent authorization checks of an operation call (HP-DOPL MP-1.4).
6
17
  *
@@ -37,6 +48,13 @@ export declare class DyFM_OperationAuthz_Util {
37
48
  /** Same as `checkOwnership`, but throws a coded `DyFM_Error` (with `status`) on denial. */
38
49
  static assertOwnership(operation: DyFM_OperationSettings_ControlModel<unknown, unknown[], unknown>, ctx: DyFM_OperationContext_ControlModel, target: object): DyFM_OperationAuthz_Result;
39
50
  /** Builds a denial result. */
51
+ /**
52
+ * Whether a key's scope list covers the required scope — either exactly, or through the all-scope (D-9).
53
+ *
54
+ * @param scopes - the scopes the key carries
55
+ * @param requiredScope - the scope the operation declares
56
+ */
57
+ static grantsScope(scopes: string[] | undefined, requiredScope: string): boolean;
40
58
  private static deny;
41
59
  /** Converts a denial into a thrown `DyFM_Error`; the identity is logged by requestId only. */
42
60
  private static throwIfDenied;
@@ -1 +1 @@
1
- {"version":3,"file":"operation-authz.util.d.ts","sourceRoot":"","sources":["../../../src/_collections/utils/operation-authz.util.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kCAAkC,EACnC,MAAM,8DAA8D,CAAC;AAEtE,OAAO,EACL,mCAAmC,EACpC,MAAM,+DAA+D,CAAC;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2DAA2D,CAAC;AAGvG;;;;;;;;;;;;;GAaG;AACH,qBAAa,wBAAwB;IACnC;;;;OAIG;IACH,MAAM,CAAC,KAAK,CACV,SAAS,EAAE,mCAAmC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAC3E,GAAG,EAAE,kCAAkC,GACtC,0BAA0B;IA8C7B;;;OAGG;IACH,MAAM,CAAC,MAAM,CACX,SAAS,EAAE,mCAAmC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAC3E,GAAG,EAAE,kCAAkC,GACtC,0BAA0B;IAM7B;;;;;OAKG;IACH,MAAM,CAAC,cAAc,CACnB,SAAS,EAAE,mCAAmC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAC3E,GAAG,EAAE,kCAAkC,EACvC,MAAM,EAAE,MAAM,GACb,0BAA0B;IA6B7B,2FAA2F;IAC3F,MAAM,CAAC,eAAe,CACpB,SAAS,EAAE,mCAAmC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAC3E,GAAG,EAAE,kCAAkC,EACvC,MAAM,EAAE,MAAM,GACb,0BAA0B;IAM7B,8BAA8B;IAC9B,OAAO,CAAC,MAAM,CAAC,IAAI;IAInB,8FAA8F;IAC9F,OAAO,CAAC,MAAM,CAAC,aAAa;CAoB7B"}
1
+ {"version":3,"file":"operation-authz.util.d.ts","sourceRoot":"","sources":["../../../src/_collections/utils/operation-authz.util.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kCAAkC,EACnC,MAAM,8DAA8D,CAAC;AAEtE,OAAO,EACL,mCAAmC,EACpC,MAAM,+DAA+D,CAAC;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2DAA2D,CAAC;AAGvG;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAY,CAAC;AAElD;;;;;;;;;;;;;GAaG;AACH,qBAAa,wBAAwB;IACnC;;;;OAIG;IACH,MAAM,CAAC,KAAK,CACV,SAAS,EAAE,mCAAmC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAC3E,GAAG,EAAE,kCAAkC,GACtC,0BAA0B;IAkD7B;;;OAGG;IACH,MAAM,CAAC,MAAM,CACX,SAAS,EAAE,mCAAmC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAC3E,GAAG,EAAE,kCAAkC,GACtC,0BAA0B;IAM7B;;;;;OAKG;IACH,MAAM,CAAC,cAAc,CACnB,SAAS,EAAE,mCAAmC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAC3E,GAAG,EAAE,kCAAkC,EACvC,MAAM,EAAE,MAAM,GACb,0BAA0B;IAgC7B,2FAA2F;IAC3F,MAAM,CAAC,eAAe,CACpB,SAAS,EAAE,mCAAmC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAC3E,GAAG,EAAE,kCAAkC,EACvC,MAAM,EAAE,MAAM,GACb,0BAA0B;IAM7B,8BAA8B;IAC9B;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO;IAMhF,OAAO,CAAC,MAAM,CAAC,IAAI;IAQnB,8FAA8F;IAC9F,OAAO,CAAC,MAAM,CAAC,aAAa;CAsB7B"}
@@ -1,9 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DyFM_OperationAuthz_Util = void 0;
3
+ exports.DyFM_OperationAuthz_Util = exports.DyFM_operationAllScope = void 0;
4
4
  const operation_auth_type_enum_1 = require("../../_enums/operation-auth.type-enum");
5
5
  const operation_context_control_model_1 = require("../../_models/control-models/operation-context.control-model");
6
6
  const error_control_model_1 = require("../../_models/control-models/error.control-model");
7
+ /**
8
+ * The scope that grants EVERY operation (owner decision D-9, 2026-09-18: "legyen all scope").
9
+ *
10
+ * ⚠️ **What it means, stated plainly:** a key holding this scope passes every scope check — including the
11
+ * checks of operations that DO NOT EXIST YET. A capability added next month is granted to it automatically,
12
+ * with nobody re-approving. That is the deliberate trade of this decision: one token instead of a list.
13
+ *
14
+ * ⛔ It can not collide with a real scope: an operation scope always names a domain and an action
15
+ * (`note:read`), so no declared `apiKeyScope` can ever be this token.
16
+ */
17
+ exports.DyFM_operationAllScope = '*';
7
18
  /**
8
19
  * Transport-independent authorization checks of an operation call (HP-DOPL MP-1.4).
9
20
  *
@@ -29,7 +40,7 @@ class DyFM_OperationAuthz_Util {
29
40
  const authKind = ctx?.authKind ?? operation_auth_type_enum_1.DyFM_OperationAuth_Type.none;
30
41
  // a missing identity is 401, the caller may retry with credentials
31
42
  if (issuerRequired && (authKind === operation_auth_type_enum_1.DyFM_OperationAuth_Type.none || !ctx?.issuer)) {
32
- return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-UNA', 401, `operation "${operation?.name}" requires an authenticated caller`);
43
+ return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-UNA', 401, `operation "${operation?.name}" requires an authenticated caller`, 'This operation needs an authenticated caller — send an API key or a token.');
33
44
  }
34
45
  // scopes only restrict API keys; a token call is not scope-limited
35
46
  if (authKind !== operation_auth_type_enum_1.DyFM_OperationAuth_Type.apiKey) {
@@ -46,11 +57,12 @@ class DyFM_OperationAuthz_Util {
46
57
  }
47
58
  // least privilege: a scoped key can not reach a protected operation that belongs to no scope
48
59
  if (!requiredScope) {
49
- return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-NSC', 403, `operation "${operation?.name}" declares no apiKeyScope, a scoped API key can not call it`);
60
+ return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-NSC', 403, `operation "${operation?.name}" declares no apiKeyScope, a scoped API key can not call it`, 'This operation can not be called with an API key. Call it with a user token.');
50
61
  }
51
- // exact match only — no wildcard until it is an explicit decision
52
- if (!(ctx.apiKeyScopes ?? []).includes(requiredScope)) {
53
- return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-SCP', 403, `API key lacks scope "${requiredScope}" for operation "${operation?.name}"`);
62
+ // the all-scope grants every operation (D-9); otherwise the match is EXACT — a scope is never a prefix
63
+ if (!DyFM_OperationAuthz_Util.grantsScope(ctx.apiKeyScopes, requiredScope)) {
64
+ return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-SCP', 403, `API key lacks scope "${requiredScope}" for operation "${operation?.name}"`, `The API key is missing the "${requiredScope}" scope, which this operation needs. ` +
65
+ 'Create a key that has it (an existing key\'s scopes can not be widened).');
54
66
  }
55
67
  return { allowed: true };
56
68
  }
@@ -75,12 +87,14 @@ class DyFM_OperationAuthz_Util {
75
87
  }
76
88
  // a declared ownership check without a caller identity must fail closed, not pass
77
89
  if (!ctx?.clientUserId) {
78
- return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-OWN', 403, `operation "${operation?.name}" requires the caller's clientUserId for the ownership check`);
90
+ return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-OWN', 403, `operation "${operation?.name}" requires the caller's clientUserId for the ownership check`, 'This operation works on your own data, so it needs to know which user you are.');
79
91
  }
80
92
  const owner = target ? Reflect.get(target, ownershipField) : undefined;
81
93
  // strict equality: an entity without owner is not owned by anybody
82
94
  if (owner === undefined || owner === null || String(owner) !== ctx.clientUserId) {
83
- return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-OWN', 403, `caller does not own the target of operation "${operation?.name}" (field: ${ownershipField})`);
95
+ return DyFM_OperationAuthz_Util.deny('DyFM-OPZ-OWN', 403, `caller does not own the target of operation "${operation?.name}" (field: ${ownershipField})`,
96
+ // ⛔ the owner and the field name stay inside: the caller only learns that it is not theirs
97
+ 'This item belongs to somebody else.');
84
98
  }
85
99
  return { allowed: true };
86
100
  }
@@ -89,8 +103,20 @@ class DyFM_OperationAuthz_Util {
89
103
  return DyFM_OperationAuthz_Util.throwIfDenied(DyFM_OperationAuthz_Util.checkOwnership(operation, ctx, target), operation, ctx);
90
104
  }
91
105
  /** Builds a denial result. */
92
- static deny(errorCode, status, reason) {
93
- return { allowed: false, errorCode: errorCode, status: status, reason: reason };
106
+ /**
107
+ * Whether a key's scope list covers the required scope — either exactly, or through the all-scope (D-9).
108
+ *
109
+ * @param scopes - the scopes the key carries
110
+ * @param requiredScope - the scope the operation declares
111
+ */
112
+ static grantsScope(scopes, requiredScope) {
113
+ const held = scopes ?? [];
114
+ return held.includes(requiredScope) || held.includes(exports.DyFM_operationAllScope);
115
+ }
116
+ static deny(errorCode, status, reason, userMessage) {
117
+ return {
118
+ allowed: false, errorCode: errorCode, status: status, reason: reason, userMessage: userMessage,
119
+ };
94
120
  }
95
121
  /** Converts a denial into a thrown `DyFM_Error`; the identity is logged by requestId only. */
96
122
  static throwIfDenied(result, operation, ctx) {
@@ -101,6 +127,8 @@ class DyFM_OperationAuthz_Util {
101
127
  errorCode: result.errorCode,
102
128
  status: result.status,
103
129
  message: `Operation authorization failed: ${result.reason}`,
130
+ // ⛔ the internal `message` never reaches the caller — this is the text written FOR them
131
+ userMessage: result.userMessage,
104
132
  additionalContent: {
105
133
  operation: operation?.name,
106
134
  requestId: ctx?.requestId,
@@ -1 +1 @@
1
- {"version":3,"file":"operation-authz.util.js","sourceRoot":"","sources":["../../../src/_collections/utils/operation-authz.util.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"operation-authz.util.js","sourceRoot":"","sources":["../../../src/_collections/utils/operation-authz.util.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,13 @@ export interface DyFM_OperationAuthz_Result {
17
17
  status?: 401 | 403;
18
18
  /** Human-readable reason of the denial. */
19
19
  reason?: string;
20
+ /**
21
+ * What the CALLER is told (HP-DOPL MP-5 closing review). The internal `reason` never leaves the server, so
22
+ * without this the caller only sees a generic text with the error code — and a key-based integration would
23
+ * not learn the ONE actionable fact: which scope it is missing. The scope name is part of the operation's
24
+ * own contract, not a secret (this is what `WWW-Authenticate: scope="…"` does).
25
+ */
26
+ userMessage?: string;
20
27
  /** Set when the call is allowed only through the legacy, scope-less API key path (D-6). */
21
28
  warning?: 'legacy-api-key';
22
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"operation-authz-result.interface.d.ts","sourceRoot":"","sources":["../../../src/_models/interfaces/operation-authz-result.interface.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;IACnB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B"}
1
+ {"version":3,"file":"operation-authz-result.interface.d.ts","sourceRoot":"","sources":["../../../src/_models/interfaces/operation-authz-result.interface.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;IACnB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@futdevpro/fsm-dynamo",
3
- "version": "1.20.67",
3
+ "version": "1.20.69",
4
4
  "description": "Full Stack Model Collection for Dynamic (NodeJS-Typescript) Framework called Dynamo, by Future Development Ltd.",
5
5
  "DyBu_settings": {
6
6
  "packageType": "full-stack-package",