@prosopo/user-access-policy 3.12.14 → 3.12.16

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,5 +1,5 @@
1
1
 
2
- > @prosopo/user-access-policy@3.12.14 build:cjs
2
+ > @prosopo/user-access-policy@3.12.16 build:cjs
3
3
  > NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
4
4
 
5
5
  ViteCommonJSConfig: .
@@ -33,7 +33,7 @@ ViteCommonJSConfig: .
33
33
  vite v8.1.5 building ssr environment for production...
34
34
  Bundle build started
35
35
  
36
- ✓ 37 modules transformed.
36
+ ✓ 38 modules transformed.
37
37
  rendering chunks...
38
38
  computing gzip size...
39
39
  dist/cjs/api/accessRulesApiClient.cjs 0.00 kB │ gzip: 0.02 kB
@@ -56,12 +56,13 @@ dist/cjs/api/delete/deleteRuleGroups.cjs 1.43 kB │ gzip: 0.65 kB
56
56
  dist/cjs/api/write/rehashRules.cjs 1.48 kB │ gzip: 0.56 kB
57
57
  dist/cjs/api/delete/deleteRules.cjs 1.52 kB │ gzip: 0.65 kB
58
58
  dist/cjs/mongoose/mongooseRuleSchema.cjs 1.52 kB │ gzip: 0.42 kB
59
- dist/cjs/.export.cjs 1.55 kB │ gzip: 0.39 kB
60
59
  dist/cjs/api/read/findRuleIds.cjs 1.58 kB │ gzip: 0.66 kB
60
+ dist/cjs/.export.cjs 1.68 kB │ gzip: 0.42 kB
61
61
  dist/cjs/redis/redisClient.cjs 1.92 kB │ gzip: 0.72 kB
62
62
  dist/cjs/classifyOs.cjs 2.04 kB │ gzip: 1.05 kB
63
63
  dist/cjs/ruleInput/policyInput.cjs 2.09 kB │ gzip: 0.79 kB
64
64
  dist/cjs/ruleInput/ruleInput.cjs 2.24 kB │ gzip: 0.67 kB
65
+ dist/cjs/matchedRule.cjs 2.29 kB │ gzip: 1.03 kB
65
66
  dist/cjs/ruleInput/userScopeInput.cjs 2.44 kB │ gzip: 0.77 kB
66
67
  dist/cjs/api/rulesApiClient.cjs 2.53 kB │ gzip: 0.68 kB
67
68
  dist/cjs/redis/reader/redisAggregate.cjs 2.57 kB │ gzip: 1.04 kB
@@ -74,4 +75,4 @@ dist/cjs/redis/reader/redisRulesSplitQuery.cjs 4.27 kB │ gzip: 1.92 kB
74
75
  dist/cjs/redis/reader/redisRulesQuery.cjs 4.49 kB │ gzip: 1.51 kB
75
76
  dist/cjs/redis/reader/redisRulesReader.cjs 11.61 kB │ gzip: 2.81 kB
76
77
 
77
- ✓ built in 162ms
78
+ ✓ built in 140ms
@@ -1,8 +1,8 @@
1
1
 
2
- > @prosopo/user-access-policy@3.12.14 build:tsc
2
+ > @prosopo/user-access-policy@3.12.16 build:tsc
3
3
  > tsc --build --verbose
4
4
 
5
- 7:04:59 AM - Projects in this build:
5
+ 8:07:49 AM - Projects in this build:
6
6
  * ../../dev/config/tsconfig.json
7
7
  * ../locale/tsconfig.json
8
8
  * ../util/tsconfig.json
@@ -15,27 +15,27 @@
15
15
  * ../api/tsconfig.json
16
16
  * tsconfig.json
17
17
 
18
- 7:04:59 AM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/vite/vite-plugin-copy.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
18
+ 8:07:49 AM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
19
19
 
20
- 7:04:59 AM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
20
+ 8:07:49 AM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
21
21
 
22
- 7:04:59 AM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
22
+ 8:07:49 AM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
23
23
 
24
- 7:04:59 AM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
24
+ 8:07:49 AM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
25
25
 
26
- 7:04:59 AM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
26
+ 8:07:49 AM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
27
27
 
28
- 7:04:59 AM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/types.test-d.ts' is older than output '../types/tsconfig.tsbuildinfo'
28
+ 8:07:49 AM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/types.test-d.ts' is older than output '../types/tsconfig.tsbuildinfo'
29
29
 
30
- 7:05:00 AM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/index.ts' is older than output '../common/tsconfig.tsbuildinfo'
30
+ 8:07:49 AM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/index.ts' is older than output '../common/tsconfig.tsbuildinfo'
31
31
 
32
- 7:05:00 AM - Project '../api-route/tsconfig.json' is up to date because newest input '../api-route/src/index.ts' is older than output '../api-route/tsconfig.tsbuildinfo'
32
+ 8:07:49 AM - Project '../api-route/tsconfig.json' is up to date because newest input '../api-route/src/apiRoutes.ts' is older than output '../api-route/tsconfig.tsbuildinfo'
33
33
 
34
- 7:05:00 AM - Project '../redis-client/tsconfig.json' is up to date because newest input '../redis-client/src/index.ts' is older than output '../redis-client/tsconfig.tsbuildinfo'
34
+ 8:07:49 AM - Project '../redis-client/tsconfig.json' is up to date because newest input '../redis-client/src/index.ts' is older than output '../redis-client/tsconfig.tsbuildinfo'
35
35
 
36
- 7:05:00 AM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/tests/api.test-d.ts' is older than output '../api/tsconfig.tsbuildinfo'
36
+ 8:07:49 AM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/tsconfig.tsbuildinfo'
37
37
 
38
- 7:05:00 AM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
38
+ 8:07:49 AM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
39
39
 
40
- 7:05:00 AM - Building project '/home/runner/work/captcha/captcha/packages/user-access-policy/tsconfig.json'...
40
+ 8:07:49 AM - Building project '/home/runner/work/captcha/captcha/packages/user-access-policy/tsconfig.json'...
41
41
 
@@ -1,9 +1,9 @@
1
1
 
2
- > @prosopo/user-access-policy@3.12.14 build
2
+ > @prosopo/user-access-policy@3.12.16 build
3
3
  > npm run build:cross-env -- --mode ${NODE_ENV:-development}
4
4
 
5
5
 
6
- > @prosopo/user-access-policy@3.12.14 build:cross-env
6
+ > @prosopo/user-access-policy@3.12.16 build:cross-env
7
7
  > vite build --config vite.esm.config.ts --mode production
8
8
 
9
9
  ViteEsmConfig: .
@@ -37,7 +37,7 @@ ViteEsmConfig: .
37
37
  vite v8.1.5 building ssr environment for production...
38
38
  Bundle build started
39
39
  
40
- ✓ 37 modules transformed.
40
+ ✓ 38 modules transformed.
41
41
  rendering chunks...
42
42
  computing gzip size...
43
43
  dist/_virtual/_rolldown/runtime.js 0.04 kB │ gzip: 0.06 kB
@@ -53,7 +53,7 @@ dist/api/.export.js 0.31 kB │ gzip: 0.16 kB
53
53
  dist/rule.js 0.36 kB │ gzip: 0.23 kB
54
54
  dist/ruleRecord.js 0.66 kB │ gzip: 0.33 kB
55
55
  dist/api/delete/deleteAllRules.js 0.73 kB │ gzip: 0.37 kB
56
- dist/.export.js 0.91 kB │ gzip: 0.29 kB
56
+ dist/.export.js 0.98 kB │ gzip: 0.31 kB
57
57
  dist/api/read/getMissingIds.js 1.02 kB │ gzip: 0.48 kB
58
58
  dist/api/read/fetchRules.js 1.07 kB │ gzip: 0.49 kB
59
59
  dist/redis/redisRulesStorage.js 1.22 kB │ gzip: 0.45 kB
@@ -68,6 +68,7 @@ dist/ruleInput/policyInput.js 1.84 kB │ gzip: 0.73 kB
68
68
  dist/classifyOs.js 1.98 kB │ gzip: 1.03 kB
69
69
  dist/ruleInput/userScopeInput.js 2.09 kB │ gzip: 0.67 kB
70
70
  dist/api/rulesApiClient.js 2.12 kB │ gzip: 0.62 kB
71
+ dist/matchedRule.js 2.22 kB │ gzip: 1.00 kB
71
72
  dist/redis/reader/redisAggregate.js 2.35 kB │ gzip: 0.99 kB
72
73
  dist/transformRule.js 2.40 kB │ gzip: 0.94 kB
73
74
  dist/redis/redisRuleIndex.js 2.44 kB │ gzip: 0.73 kB
@@ -78,4 +79,4 @@ dist/redis/reader/redisRulesSplitQuery.js 4.18 kB │ gzip: 1.89 kB
78
79
  dist/redis/reader/redisRulesQuery.js 4.30 kB │ gzip: 1.47 kB
79
80
  dist/redis/reader/redisRulesReader.js 10.19 kB │ gzip: 2.68 kB
80
81
 
81
- ✓ built in 110ms
82
+ ✓ built in 165ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @prosopo/user-access-policy
2
2
 
3
+ ## 3.12.16
4
+ ### Patch Changes
5
+
6
+ - Updated dependencies [0def557]
7
+ - @prosopo/types@5.1.0
8
+ - @prosopo/api@4.0.5
9
+
10
+ ## 3.12.15
11
+ ### Patch Changes
12
+
13
+ - 216f8cd: Record the access rule that actually fired on the record it acted on, so the
14
+ audit page can name the exact policy behind a block rather than echoing its
15
+ optional free-text description.
16
+
17
+ Access rules are ephemeral — client rules carry a TTL and are reaped by
18
+ Mongo's `expiry` index — so an audit row can't answer "which policy blocked
19
+ me?" by joining to the live rules collection: by the time anyone looks, the
20
+ rule is usually gone. `describeMatchedRule` snapshots the matched rule (policy
21
+ type, captcha type, `deferToVerify`, description, rule group, and its scope
22
+ conditions in record form) onto `Session.matchedRule` at enforcement time.
23
+
24
+ Previously only the request-time block middleware recorded any rule identity,
25
+ and only as a hash, a field-name list and a description. It is now written by
26
+ every access-policy path: the block middleware, the frictionless entry (block,
27
+ auto-ban, forced captcha type, and score-only restrict alike), and the
28
+ verify-time hard-block check in the PoW / image / puzzle flows — which is where
29
+ `deferToVerify` rules land, and where "why was I rejected?" was least obvious.
30
+
31
+ `checkForHardBlock` now returns the whole `AccessRule` rather than just its
32
+ policy half; the runtime value was always the full rule.
33
+ - Updated dependencies [216f8cd]
34
+ - @prosopo/types@5.0.4
35
+ - @prosopo/api@4.0.4
36
+
3
37
  ## 3.12.14
4
38
  ### Patch Changes
5
39
 
package/dist/.export.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./ruleInput/.export.js";
2
2
  export { makeAccessRuleHash, transformAccessRuleRecordIntoRule, transformAccessRuleIntoRecord, } from "./transformRule.js";
3
3
  export { type AccessRule, type AccessPolicy, type PolicyScope, type UserScope, AccessPolicyType, } from "./rule.js";
4
+ export { describeMatchedRule } from "./matchedRule.js";
4
5
  export { classifyOs, OS_NAMES, type OsName } from "./classifyOs.js";
5
6
  export { type AccessRulesFilter, type AccessRulesStorage, type AccessRuleEntry, FilterScopeMatch, } from "./rulesStorage.js";
6
7
  export { type AccessRuleRecord, type UserScopeRecord, type UserScopeRecordField, userScopeRecordFields, getUserScopeRecordFromAccessRuleRecord, } from "./ruleRecord.js";
@@ -1 +1 @@
1
- {"version":3,"file":".export.d.ts","sourceRoot":"","sources":["../src/.export.ts"],"names":[],"mappings":"AAcA,cAAc,wBAAwB,CAAC;AAEvC,OAAO,EACN,kBAAkB,EAClB,iCAAiC,EACjC,6BAA6B,GAC7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACN,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,gBAAgB,GAChB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,gBAAgB,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,sCAAsC,GACtC,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":".export.d.ts","sourceRoot":"","sources":["../src/.export.ts"],"names":[],"mappings":"AAcA,cAAc,wBAAwB,CAAC;AAEvC,OAAO,EACN,kBAAkB,EAClB,iCAAiC,EACjC,6BAA6B,GAC7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACN,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,gBAAgB,GAChB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,gBAAgB,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,sCAAsC,GACtC,MAAM,iBAAiB,CAAC"}
package/dist/.export.js CHANGED
@@ -5,6 +5,7 @@ import { accessPolicyInput, policyScopeInput } from "./ruleInput/policyInput.js"
5
5
  import { userScopeInput } from "./ruleInput/userScopeInput.js";
6
6
  import { accessRuleInput } from "./ruleInput/ruleInput.js";
7
7
  import { makeAccessRuleHash, transformAccessRuleIntoRecord, transformAccessRuleRecordIntoRule } from "./transformRule.js";
8
- import { OS_NAMES, classifyOs } from "./classifyOs.js";
9
8
  import { getUserScopeRecordFromAccessRuleRecord, userScopeRecordFields } from "./ruleRecord.js";
10
- export { AccessPolicyType, FilterScopeMatch, OS_NAMES, accessPolicyInput, accessRuleInput, classifyOs, getUserScopeRecordFromAccessRuleRecord, makeAccessRuleHash, policyScopeInput, transformAccessRuleIntoRecord, transformAccessRuleRecordIntoRule, userScopeInput, userScopeRecordFields };
9
+ import { describeMatchedRule } from "./matchedRule.js";
10
+ import { OS_NAMES, classifyOs } from "./classifyOs.js";
11
+ export { AccessPolicyType, FilterScopeMatch, OS_NAMES, accessPolicyInput, accessRuleInput, classifyOs, describeMatchedRule, getUserScopeRecordFromAccessRuleRecord, makeAccessRuleHash, policyScopeInput, transformAccessRuleIntoRecord, transformAccessRuleRecordIntoRule, userScopeInput, userScopeRecordFields };
@@ -1 +1 @@
1
- {"version":3,"file":".export.js","sourceRoot":"","sources":["../src/.export.ts"],"names":[],"mappings":"AAcA,cAAc,wBAAwB,CAAC;AAEvC,OAAO,EACN,kBAAkB,EAClB,iCAAiC,EACjC,6BAA6B,GAC7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAKN,gBAAgB,GAChB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAe,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAIN,gBAAgB,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAIN,qBAAqB,EACrB,sCAAsC,GACtC,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":".export.js","sourceRoot":"","sources":["../src/.export.ts"],"names":[],"mappings":"AAcA,cAAc,wBAAwB,CAAC;AAEvC,OAAO,EACN,kBAAkB,EAClB,iCAAiC,EACjC,6BAA6B,GAC7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAKN,gBAAgB,GAChB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAe,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAIN,gBAAgB,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAIN,qBAAqB,EACrB,sCAAsC,GACtC,MAAM,iBAAiB,CAAC"}
@@ -5,14 +5,16 @@ const require_ruleInput_policyInput = require("./ruleInput/policyInput.cjs");
5
5
  const require_ruleInput_userScopeInput = require("./ruleInput/userScopeInput.cjs");
6
6
  const require_ruleInput_ruleInput = require("./ruleInput/ruleInput.cjs");
7
7
  const require_transformRule = require("./transformRule.cjs");
8
- const require_classifyOs = require("./classifyOs.cjs");
9
8
  const require_ruleRecord = require("./ruleRecord.cjs");
9
+ const require_matchedRule = require("./matchedRule.cjs");
10
+ const require_classifyOs = require("./classifyOs.cjs");
10
11
  exports.AccessPolicyType = require_rule.AccessPolicyType;
11
12
  exports.FilterScopeMatch = require_rulesStorage.FilterScopeMatch;
12
13
  exports.OS_NAMES = require_classifyOs.OS_NAMES;
13
14
  exports.accessPolicyInput = require_ruleInput_policyInput.accessPolicyInput;
14
15
  exports.accessRuleInput = require_ruleInput_ruleInput.accessRuleInput;
15
16
  exports.classifyOs = require_classifyOs.classifyOs;
17
+ exports.describeMatchedRule = require_matchedRule.describeMatchedRule;
16
18
  exports.getUserScopeRecordFromAccessRuleRecord = require_ruleRecord.getUserScopeRecordFromAccessRuleRecord;
17
19
  exports.makeAccessRuleHash = require_transformRule.makeAccessRuleHash;
18
20
  exports.policyScopeInput = require_ruleInput_policyInput.policyScopeInput;
@@ -0,0 +1,59 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_transformRule = require("./transformRule.cjs");
3
+ const require_ruleRecord = require("./ruleRecord.cjs");
4
+ //#region src/matchedRule.ts
5
+ var MAX_CONDITION_VALUE_LENGTH = 256;
6
+ var toCondition = (field, value) => {
7
+ if (value === void 0 || value === null) return void 0;
8
+ const asString = typeof value === "string" ? value : String(value);
9
+ if (asString.length === 0) return void 0;
10
+ return asString.length > MAX_CONDITION_VALUE_LENGTH ? {
11
+ field,
12
+ value: `${asString.slice(0, MAX_CONDITION_VALUE_LENGTH)}…`,
13
+ truncated: true
14
+ } : {
15
+ field,
16
+ value: asString
17
+ };
18
+ };
19
+ /**
20
+ * Derive the rule's populated scope fields in record form.
21
+ *
22
+ * Goes through `transformAccessRuleIntoRecord` so the IP triple collapses back
23
+ * to the human-readable `ip` / `ipMask` the operator originally typed, rather
24
+ * than the numeric range the matcher works in, and so the field names match
25
+ * the vocabulary the portal's Access Control page already labels conditions
26
+ * with (`ip`, `ipMask`, `userAgent`, `ja4Hash`, …).
27
+ */
28
+ var deriveConditions = (rule) => {
29
+ let scope;
30
+ try {
31
+ scope = require_ruleRecord.getUserScopeRecordFromAccessRuleRecord(require_transformRule.transformAccessRuleIntoRecord(rule));
32
+ } catch {
33
+ return [];
34
+ }
35
+ const conditions = [];
36
+ for (const field of require_ruleRecord.userScopeRecordFields) {
37
+ const condition = toCondition(field, scope[field]);
38
+ if (condition) conditions.push(condition);
39
+ }
40
+ return conditions;
41
+ };
42
+ /**
43
+ * Snapshot a matched rule for persistence alongside the request it acted on.
44
+ *
45
+ * Total function: every rule shape yields a value, so callers can inline it
46
+ * into a record literal without a try/catch of their own.
47
+ */
48
+ var describeMatchedRule = (rule) => ({
49
+ ruleHash: require_transformRule.makeAccessRuleHash(rule),
50
+ policyType: rule.type,
51
+ conditions: deriveConditions(rule),
52
+ ...rule.description !== void 0 && { description: rule.description },
53
+ ...rule.captchaType !== void 0 && { captchaType: rule.captchaType },
54
+ ...rule.deferToVerify !== void 0 && { deferToVerify: rule.deferToVerify },
55
+ ...rule.groupId !== void 0 && { ruleGroupId: rule.groupId },
56
+ ...rule.clientId !== void 0 && { clientId: rule.clientId }
57
+ });
58
+ //#endregion
59
+ exports.describeMatchedRule = describeMatchedRule;
@@ -0,0 +1,4 @@
1
+ import type { MatchedAccessRule } from "@prosopo/types";
2
+ import type { AccessRule } from "#policy/rule.js";
3
+ export declare const describeMatchedRule: (rule: AccessRule) => MatchedAccessRule;
4
+ //# sourceMappingURL=matchedRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchedRule.d.ts","sourceRoot":"","sources":["../src/matchedRule.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,iBAAiB,EAAwB,MAAM,gBAAgB,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAwElD,eAAO,MAAM,mBAAmB,SAAU,UAAU,KAAG,iBAWrD,CAAC"}
@@ -0,0 +1,59 @@
1
+ import "./_virtual/_rolldown/runtime.js";
2
+ import { makeAccessRuleHash, transformAccessRuleIntoRecord } from "./transformRule.js";
3
+ import { getUserScopeRecordFromAccessRuleRecord, userScopeRecordFields } from "./ruleRecord.js";
4
+ //#region src/matchedRule.ts
5
+ var MAX_CONDITION_VALUE_LENGTH = 256;
6
+ var toCondition = (field, value) => {
7
+ if (value === void 0 || value === null) return void 0;
8
+ const asString = typeof value === "string" ? value : String(value);
9
+ if (asString.length === 0) return void 0;
10
+ return asString.length > MAX_CONDITION_VALUE_LENGTH ? {
11
+ field,
12
+ value: `${asString.slice(0, MAX_CONDITION_VALUE_LENGTH)}…`,
13
+ truncated: true
14
+ } : {
15
+ field,
16
+ value: asString
17
+ };
18
+ };
19
+ /**
20
+ * Derive the rule's populated scope fields in record form.
21
+ *
22
+ * Goes through `transformAccessRuleIntoRecord` so the IP triple collapses back
23
+ * to the human-readable `ip` / `ipMask` the operator originally typed, rather
24
+ * than the numeric range the matcher works in, and so the field names match
25
+ * the vocabulary the portal's Access Control page already labels conditions
26
+ * with (`ip`, `ipMask`, `userAgent`, `ja4Hash`, …).
27
+ */
28
+ var deriveConditions = (rule) => {
29
+ let scope;
30
+ try {
31
+ scope = getUserScopeRecordFromAccessRuleRecord(transformAccessRuleIntoRecord(rule));
32
+ } catch {
33
+ return [];
34
+ }
35
+ const conditions = [];
36
+ for (const field of userScopeRecordFields) {
37
+ const condition = toCondition(field, scope[field]);
38
+ if (condition) conditions.push(condition);
39
+ }
40
+ return conditions;
41
+ };
42
+ /**
43
+ * Snapshot a matched rule for persistence alongside the request it acted on.
44
+ *
45
+ * Total function: every rule shape yields a value, so callers can inline it
46
+ * into a record literal without a try/catch of their own.
47
+ */
48
+ var describeMatchedRule = (rule) => ({
49
+ ruleHash: makeAccessRuleHash(rule),
50
+ policyType: rule.type,
51
+ conditions: deriveConditions(rule),
52
+ ...rule.description !== void 0 && { description: rule.description },
53
+ ...rule.captchaType !== void 0 && { captchaType: rule.captchaType },
54
+ ...rule.deferToVerify !== void 0 && { deferToVerify: rule.deferToVerify },
55
+ ...rule.groupId !== void 0 && { ruleGroupId: rule.groupId },
56
+ ...rule.clientId !== void 0 && { clientId: rule.clientId }
57
+ });
58
+ //#endregion
59
+ export { describeMatchedRule };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchedRule.js","sourceRoot":"","sources":["../src/matchedRule.ts"],"names":[],"mappings":"AAgBA,OAAO,EAEN,sCAAsC,EACtC,qBAAqB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,kBAAkB,EAClB,6BAA6B,GAC7B,MAAM,0BAA0B,CAAC;AAMlC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAEvC,MAAM,WAAW,GAAG,CACnB,KAA2B,EAC3B,KAAc,EACqB,EAAE;IACrC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAE5D,MAAM,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,QAAQ,CAAC,MAAM,GAAG,0BAA0B;QAClD,CAAC,CAAC;YACA,KAAK;YACL,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,0BAA0B,CAAC,GAAG;YAC1D,SAAS,EAAE,IAAI;SACf;QACF,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC,CAAC;AAWF,MAAM,gBAAgB,GAAG,CAAC,IAAgB,EAA0B,EAAE;IACrE,IAAI,KAAqD,CAAC;IAC1D,IAAI,CAAC;QACJ,KAAK,GAAG,sCAAsC,CAC7C,6BAA6B,CAAC,IAAI,CAAC,CACnC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QAIR,OAAO,EAAE,CAAC;IACX,CAAC;IAED,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,qBAAqB,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACnD,IAAI,SAAS,EAAE,CAAC;YACf,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;IACF,CAAC;IACD,OAAO,UAAU,CAAC;AACnB,CAAC,CAAC;AAQF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAgB,EAAqB,EAAE,CAAC,CAAC;IAC5E,QAAQ,EAAE,kBAAkB,CAAC,IAAI,CAAC;IAClC,UAAU,EAAE,IAAI,CAAC,IAAI;IACrB,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC;IAClC,GAAG,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IACxE,GAAG,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IACxE,GAAG,CAAC,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI;QACvC,aAAa,EAAE,IAAI,CAAC,aAAa;KACjC,CAAC;IACF,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IAChE,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;CAC/D,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=matchedRule.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchedRule.unit.test.d.ts","sourceRoot":"","sources":["../../src/tests/matchedRule.unit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,142 @@
1
+ import { CaptchaType, MatchedAccessRuleSchema } from "@prosopo/types";
2
+ import { Address4 } from "ip-address";
3
+ import { describe, expect, it } from "vitest";
4
+ import { describeMatchedRule } from "#policy/matchedRule.js";
5
+ import { AccessPolicyType } from "#policy/rule.js";
6
+ import { userScopeRecordFields } from "#policy/ruleRecord.js";
7
+ import { makeAccessRuleHash } from "#policy/transformRule.js";
8
+ describe("describeMatchedRule", () => {
9
+ it("carries the policy half of the rule", () => {
10
+ const rule = {
11
+ type: AccessPolicyType.Restrict,
12
+ captchaType: CaptchaType.image,
13
+ description: "6 rounds for this ASN",
14
+ deferToVerify: true,
15
+ clientId: "site-key",
16
+ groupId: "group-1",
17
+ ja4Hash: "t13d1516h2_8daaf6152771_b186095e22b6",
18
+ };
19
+ expect(describeMatchedRule(rule)).toEqual({
20
+ ruleHash: makeAccessRuleHash(rule),
21
+ policyType: AccessPolicyType.Restrict,
22
+ captchaType: CaptchaType.image,
23
+ description: "6 rounds for this ASN",
24
+ deferToVerify: true,
25
+ clientId: "site-key",
26
+ ruleGroupId: "group-1",
27
+ conditions: [
28
+ {
29
+ field: "ja4Hash",
30
+ value: "t13d1516h2_8daaf6152771_b186095e22b6",
31
+ },
32
+ ],
33
+ });
34
+ });
35
+ it("omits policy fields the rule did not set rather than emitting undefined", () => {
36
+ const described = describeMatchedRule({ type: AccessPolicyType.Block });
37
+ expect(described).toEqual({
38
+ ruleHash: makeAccessRuleHash({ type: AccessPolicyType.Block }),
39
+ policyType: AccessPolicyType.Block,
40
+ conditions: [],
41
+ });
42
+ expect(Object.keys(described)).not.toContain("description");
43
+ expect(Object.keys(described)).not.toContain("ruleGroupId");
44
+ });
45
+ it("reports a single IP in the form the operator typed, not the numeric one", () => {
46
+ const { conditions } = describeMatchedRule({
47
+ type: AccessPolicyType.Block,
48
+ numericIp: new Address4("192.0.2.44").bigInt(),
49
+ });
50
+ expect(conditions).toEqual([{ field: "ip", value: "192.0.2.44" }]);
51
+ });
52
+ it("collapses an IP range back to its CIDR", () => {
53
+ const { conditions } = describeMatchedRule({
54
+ type: AccessPolicyType.Block,
55
+ numericIpMaskMin: new Address4("198.51.100.64").bigInt(),
56
+ numericIpMaskMax: new Address4("198.51.100.127").bigInt(),
57
+ });
58
+ expect(conditions).toEqual([
59
+ { field: "ipMask", value: "198.51.100.64/26" },
60
+ ]);
61
+ });
62
+ it("stringifies a numeric asn", () => {
63
+ const { conditions } = describeMatchedRule({
64
+ type: AccessPolicyType.Block,
65
+ asn: 205016,
66
+ });
67
+ expect(conditions).toEqual([{ field: "asn", value: "205016" }]);
68
+ });
69
+ it("reports every populated scope field, in record vocabulary", () => {
70
+ const { conditions } = describeMatchedRule({
71
+ type: AccessPolicyType.Block,
72
+ userId: "user",
73
+ ja4Hash: "ja4",
74
+ headersHash: "headers",
75
+ userAgentHash: "ua",
76
+ headHash: "head",
77
+ coords: "[[1,2]]",
78
+ countryCode: "GB",
79
+ asn: 1,
80
+ os: "macos",
81
+ numericIp: new Address4("203.0.113.5").bigInt(),
82
+ });
83
+ expect(conditions.map((condition) => condition.field)).toEqual([
84
+ "userId",
85
+ "ja4Hash",
86
+ "headersHash",
87
+ "userAgent",
88
+ "headHash",
89
+ "coords",
90
+ "countryCode",
91
+ "asn",
92
+ "os",
93
+ "ip",
94
+ ]);
95
+ for (const condition of conditions) {
96
+ expect(userScopeRecordFields).toContain(condition.field);
97
+ }
98
+ });
99
+ it("truncates an oversized coords polygon and flags it", () => {
100
+ const coords = JSON.stringify([Array.from({ length: 200 }, () => [1, 2])]);
101
+ const { conditions } = describeMatchedRule({
102
+ type: AccessPolicyType.Block,
103
+ coords,
104
+ });
105
+ const [condition] = conditions;
106
+ expect(condition?.truncated).toBe(true);
107
+ expect(condition?.value.length).toBe(257);
108
+ expect(coords.startsWith(condition?.value.slice(0, -1) ?? "")).toBe(true);
109
+ });
110
+ it("leaves a value at the cap untruncated", () => {
111
+ const coords = "x".repeat(256);
112
+ const { conditions } = describeMatchedRule({
113
+ type: AccessPolicyType.Block,
114
+ coords,
115
+ });
116
+ expect(conditions).toEqual([{ field: "coords", value: coords }]);
117
+ });
118
+ it("still describes a rule whose scope cannot be transformed", () => {
119
+ const rule = {
120
+ type: AccessPolicyType.Block,
121
+ description: "unrepresentable range",
122
+ numericIpMaskMin: new Address4("198.51.100.200").bigInt(),
123
+ numericIpMaskMax: new Address4("198.51.100.1").bigInt(),
124
+ };
125
+ expect(() => describeMatchedRule(rule)).not.toThrow();
126
+ expect(describeMatchedRule(rule)).toEqual({
127
+ ruleHash: makeAccessRuleHash(rule),
128
+ policyType: AccessPolicyType.Block,
129
+ description: "unrepresentable range",
130
+ conditions: [],
131
+ });
132
+ });
133
+ it("produces a value the persisted schema accepts", () => {
134
+ const described = describeMatchedRule({
135
+ type: AccessPolicyType.Restrict,
136
+ captchaType: CaptchaType.pow,
137
+ countryCode: "CN",
138
+ });
139
+ expect(MatchedAccessRuleSchema.safeParse(described).success).toBe(true);
140
+ });
141
+ });
142
+ //# sourceMappingURL=matchedRule.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchedRule.unit.test.js","sourceRoot":"","sources":["../../src/tests/matchedRule.unit.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prosopo/user-access-policy",
3
- "version": "3.12.14",
3
+ "version": "3.12.16",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": "^24",
@@ -43,12 +43,12 @@
43
43
  "test": "npm run test:unit && npm run test:integration"
44
44
  },
45
45
  "dependencies": {
46
- "@prosopo/api": "4.0.3",
46
+ "@prosopo/api": "4.0.5",
47
47
  "@prosopo/api-route": "2.6.55",
48
48
  "@prosopo/common": "3.1.50",
49
49
  "@prosopo/logger": "2.0.6",
50
50
  "@prosopo/redis-client": "1.0.32",
51
- "@prosopo/types": "5.0.3",
51
+ "@prosopo/types": "5.1.0",
52
52
  "@prosopo/util": "3.3.6",
53
53
  "@redis/search": "5.0.0",
54
54
  "cidr-calc": "1.0.4",
@@ -58,7 +58,7 @@
58
58
  "zod": "3.23.8"
59
59
  },
60
60
  "devDependencies": {
61
- "@prosopo/config": "3.3.7",
61
+ "@prosopo/config": "3.3.8",
62
62
  "@prosopo/util-crypto": "13.5.30",
63
63
  "@types/node": "22.10.2",
64
64
  "fast-glob": "3.3.2",
package/src/.export.ts CHANGED
@@ -28,6 +28,8 @@ export {
28
28
  AccessPolicyType,
29
29
  } from "./rule.js";
30
30
 
31
+ export { describeMatchedRule } from "./matchedRule.js";
32
+
31
33
  export { classifyOs, OS_NAMES, type OsName } from "./classifyOs.js";
32
34
 
33
35
  export {