@ploaness/governance 1.0.0 → 1.1.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/dist/a11y-hit-target.d.ts +35 -0
- package/dist/a11y-hit-target.d.ts.map +1 -0
- package/dist/a11y-hit-target.js +102 -0
- package/dist/a11y-hit-target.js.map +1 -0
- package/dist/a11y-incomplete.d.ts +18 -0
- package/dist/a11y-incomplete.d.ts.map +1 -0
- package/dist/a11y-incomplete.js +82 -0
- package/dist/a11y-incomplete.js.map +1 -0
- package/dist/access-boundary.d.ts +19 -5
- package/dist/access-boundary.d.ts.map +1 -1
- package/dist/access-boundary.js +58 -4
- package/dist/access-boundary.js.map +1 -1
- package/dist/admin-view-coverage.d.ts +25 -0
- package/dist/admin-view-coverage.d.ts.map +1 -0
- package/dist/admin-view-coverage.js +90 -0
- package/dist/admin-view-coverage.js.map +1 -0
- package/dist/axe-coverage.d.ts +41 -0
- package/dist/axe-coverage.d.ts.map +1 -0
- package/dist/axe-coverage.js +95 -0
- package/dist/axe-coverage.js.map +1 -0
- package/dist/banned-typography.d.ts.map +1 -1
- package/dist/banned-typography.js +26 -0
- package/dist/banned-typography.js.map +1 -1
- package/dist/build-diagnosis.d.ts +10 -0
- package/dist/build-diagnosis.d.ts.map +1 -0
- package/dist/build-diagnosis.js +38 -0
- package/dist/build-diagnosis.js.map +1 -0
- package/dist/document-references.d.ts.map +1 -1
- package/dist/document-references.js +7 -1
- package/dist/document-references.js.map +1 -1
- package/dist/environment-coherence.d.ts +87 -0
- package/dist/environment-coherence.d.ts.map +1 -0
- package/dist/environment-coherence.js +150 -0
- package/dist/environment-coherence.js.map +1 -0
- package/dist/generated-drift.d.ts +18 -0
- package/dist/generated-drift.d.ts.map +1 -0
- package/dist/generated-drift.js +35 -0
- package/dist/generated-drift.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/payload-access.d.ts.map +1 -1
- package/dist/payload-access.js +23 -49
- package/dist/payload-access.js.map +1 -1
- package/dist/payload-configs.d.ts +24 -0
- package/dist/payload-configs.d.ts.map +1 -0
- package/dist/payload-configs.js +77 -0
- package/dist/payload-configs.js.map +1 -0
- package/dist/payload-field-access.d.ts +4 -0
- package/dist/payload-field-access.d.ts.map +1 -0
- package/dist/payload-field-access.js +51 -0
- package/dist/payload-field-access.js.map +1 -0
- package/dist/payload-policy.d.ts.map +1 -1
- package/dist/payload-policy.js +111 -13
- package/dist/payload-policy.js.map +1 -1
- package/dist/payload-source.js +2 -2
- package/dist/payload-source.js.map +1 -1
- package/dist/relationship-cleanup.d.ts +18 -0
- package/dist/relationship-cleanup.d.ts.map +1 -0
- package/dist/relationship-cleanup.js +96 -0
- package/dist/relationship-cleanup.js.map +1 -0
- package/dist/route-coverage.d.ts +27 -0
- package/dist/route-coverage.d.ts.map +1 -0
- package/dist/route-coverage.js +57 -0
- package/dist/route-coverage.js.map +1 -0
- package/dist/route-map.d.ts +65 -0
- package/dist/route-map.d.ts.map +1 -0
- package/dist/route-map.js +183 -0
- package/dist/route-map.js.map +1 -0
- package/dist/secret-policy.js +4 -4
- package/dist/secret-policy.js.map +1 -1
- package/dist/settings.d.ts +10 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +5 -1
- package/dist/settings.js.map +1 -1
- package/dist/source-security.d.ts +4 -0
- package/dist/source-security.d.ts.map +1 -0
- package/dist/source-security.js +56 -0
- package/dist/source-security.js.map +1 -0
- package/dist/source-text.d.ts +14 -0
- package/dist/source-text.d.ts.map +1 -1
- package/dist/source-text.js +39 -0
- package/dist/source-text.js.map +1 -1
- package/dist/version-policy.d.ts.map +1 -1
- package/dist/version-policy.js +31 -0
- package/dist/version-policy.js.map +1 -1
- package/package.json +1 -1
- package/dist/url-safety.d.ts +0 -12
- package/dist/url-safety.d.ts.map +0 -1
- package/dist/url-safety.js +0 -58
- package/dist/url-safety.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
export * from './a11y-hit-target.js';
|
|
2
|
+
export * from './a11y-incomplete.js';
|
|
1
3
|
export * from './access-boundary.js';
|
|
4
|
+
export * from './admin-view-coverage.js';
|
|
2
5
|
export * from './agent-references.js';
|
|
3
6
|
export * from './architecture-layers.js';
|
|
4
7
|
export * from './asset-policy.js';
|
|
8
|
+
export * from './axe-coverage.js';
|
|
5
9
|
export * from './banned-typography.js';
|
|
10
|
+
export * from './build-diagnosis.js';
|
|
6
11
|
export * from './bundle-budget.js';
|
|
7
12
|
export * from './commit-message.js';
|
|
8
13
|
export * from './config-references.js';
|
|
@@ -13,9 +18,11 @@ export * from './dependency-freshness.js';
|
|
|
13
18
|
export * from './doc-blocks.js';
|
|
14
19
|
export * from './document-references.js';
|
|
15
20
|
export * from './editorconfig-policy.js';
|
|
21
|
+
export * from './environment-coherence.js';
|
|
16
22
|
export * from './environment-files.js';
|
|
17
23
|
export * from './file-roles.js';
|
|
18
24
|
export * from './generated-denial.js';
|
|
25
|
+
export * from './generated-drift.js';
|
|
19
26
|
export * from './history-policy.js';
|
|
20
27
|
export * from './image-assets.js';
|
|
21
28
|
export * from './install-policy.js';
|
|
@@ -26,8 +33,11 @@ export * from './paired-assets.js';
|
|
|
26
33
|
export * from './payload-access.js';
|
|
27
34
|
export * from './payload-policy.js';
|
|
28
35
|
export * from './payload-source.js';
|
|
36
|
+
export * from './relationship-cleanup.js';
|
|
29
37
|
export * from './release-age.js';
|
|
30
38
|
export * from './request-limits.js';
|
|
39
|
+
export * from './route-coverage.js';
|
|
40
|
+
export * from './route-map.js';
|
|
31
41
|
export * from './run-plan.js';
|
|
32
42
|
export * from './run-policy.js';
|
|
33
43
|
export * from './secret-policy.js';
|
|
@@ -39,7 +49,6 @@ export * from './suppression-ceiling.js';
|
|
|
39
49
|
export * from './tailwind-tokens.js';
|
|
40
50
|
export * from './text-escapes.js';
|
|
41
51
|
export * from './toolchain-pins.js';
|
|
42
|
-
export * from './url-safety.js';
|
|
43
52
|
export * from './version-policy.js';
|
|
44
53
|
export * from './vulnerability-policy.js';
|
|
45
54
|
export * from './wiring-policy.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA;AACtC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AACzC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AACzC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,kBAAkB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
// process, and network access. Every gate in the CLI is a thin I/O shell around a function exported
|
|
3
3
|
// here. The split is what makes the rules cheap to test exhaustively: a pure function over strings
|
|
4
4
|
// needs no fixture repository to exercise its edge cases.
|
|
5
|
+
export * from './a11y-hit-target.js';
|
|
6
|
+
export * from './a11y-incomplete.js';
|
|
5
7
|
export * from './access-boundary.js';
|
|
8
|
+
export * from './admin-view-coverage.js';
|
|
6
9
|
export * from './agent-references.js';
|
|
7
10
|
export * from './architecture-layers.js';
|
|
8
11
|
export * from './asset-policy.js';
|
|
12
|
+
export * from './axe-coverage.js';
|
|
9
13
|
export * from './banned-typography.js';
|
|
14
|
+
export * from './build-diagnosis.js';
|
|
10
15
|
export * from './bundle-budget.js';
|
|
11
16
|
export * from './commit-message.js';
|
|
12
17
|
export * from './config-references.js';
|
|
@@ -17,9 +22,11 @@ export * from './dependency-freshness.js';
|
|
|
17
22
|
export * from './doc-blocks.js';
|
|
18
23
|
export * from './document-references.js';
|
|
19
24
|
export * from './editorconfig-policy.js';
|
|
25
|
+
export * from './environment-coherence.js';
|
|
20
26
|
export * from './environment-files.js';
|
|
21
27
|
export * from './file-roles.js';
|
|
22
28
|
export * from './generated-denial.js';
|
|
29
|
+
export * from './generated-drift.js';
|
|
23
30
|
export * from './history-policy.js';
|
|
24
31
|
export * from './image-assets.js';
|
|
25
32
|
export * from './install-policy.js';
|
|
@@ -30,8 +37,11 @@ export * from './paired-assets.js';
|
|
|
30
37
|
export * from './payload-access.js';
|
|
31
38
|
export * from './payload-policy.js';
|
|
32
39
|
export * from './payload-source.js';
|
|
40
|
+
export * from './relationship-cleanup.js';
|
|
33
41
|
export * from './release-age.js';
|
|
34
42
|
export * from './request-limits.js';
|
|
43
|
+
export * from './route-coverage.js';
|
|
44
|
+
export * from './route-map.js';
|
|
35
45
|
export * from './run-plan.js';
|
|
36
46
|
export * from './run-policy.js';
|
|
37
47
|
export * from './secret-policy.js';
|
|
@@ -43,7 +53,6 @@ export * from './suppression-ceiling.js';
|
|
|
43
53
|
export * from './tailwind-tokens.js';
|
|
44
54
|
export * from './text-escapes.js';
|
|
45
55
|
export * from './toolchain-pins.js';
|
|
46
|
-
export * from './url-safety.js';
|
|
47
56
|
export * from './version-policy.js';
|
|
48
57
|
export * from './vulnerability-policy.js';
|
|
49
58
|
export * from './wiring-policy.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,oGAAoG;AACpG,mGAAmG;AACnG,0DAA0D;AAE1D,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,oGAAoG;AACpG,mGAAmG;AACnG,0DAA0D;AAE1D,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA;AACtC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AACzC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,eAAe,CAAA;AAC7B,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AACzC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,kBAAkB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload-access.d.ts","sourceRoot":"","sources":["../src/payload-access.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"payload-access.d.ts","sourceRoot":"","sources":["../src/payload-access.ts"],"names":[],"mappings":"AAaA,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAA;AAe5B,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,KAAG,SAAS,gBAAgB,EAqB5E,CAAA;AA8CH,uGAAuG;AACvG,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,KAAG,SAAS,gBAAgB,EAK1E,CAAA;AA2CH,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,GAAI,QAAQ,MAAM,KAAG,SAAS,gBAAgB,EAe/E,CAAA;AA6BH,4FAA4F;AAC5F,eAAO,MAAM,uBAAuB,GAAI,QAAQ,MAAM,KAAG,SAAS,gBAAgB,EAK/E,CAAA"}
|
package/dist/payload-access.js
CHANGED
|
@@ -5,45 +5,10 @@
|
|
|
5
5
|
// question the others do not ask - "which object literal IS this config" - and because together the two
|
|
6
6
|
// halves passed the file size cap. Every one of them is a security decision that Payload will silently
|
|
7
7
|
// make on the project's behalf if the project does not make it first.
|
|
8
|
+
import { payloadConfigsIn, } from './payload-configs.js';
|
|
8
9
|
import { configBody, depthOneBlockKeys, depthOneValue, } from './payload-source.js';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
//
|
|
12
|
-
// const Users: CollectionConfig = { ... } the annotation
|
|
13
|
-
// const Users: CollectionConfig<'users'> = { ... } the annotation, with the slug as a type argument
|
|
14
|
-
// const Users = { ... } satisfies CollectionConfig the inferred form
|
|
15
|
-
//
|
|
16
|
-
// Only the first was matched for a long time, because the lookahead that stopped `CollectionConfigs`
|
|
17
|
-
// from matching also excluded `<`, and nothing looked for `satisfies` at all. A collection written
|
|
18
|
-
// either of the other two ways passed every rule below without one of them ever reading it - which is
|
|
19
|
-
// the worst failure a gate can have, because it is indistinguishable from a pass.
|
|
20
|
-
const declarationPattern = (typeName) => new RegExp(String.raw `(:|satisfies)\s*${typeName}(?=[<=,)\s]|$)`, 'g');
|
|
21
|
-
/** The operations a collection must decide for itself rather than inherit. */
|
|
22
|
-
const COLLECTION_OPERATIONS = ['create', 'read', 'update', 'delete'];
|
|
23
|
-
/** A global has no create or delete: it exists from the moment it is configured. */
|
|
24
|
-
const GLOBAL_OPERATIONS = ['read', 'update'];
|
|
25
|
-
const CONFIG_KINDS = [
|
|
26
|
-
{
|
|
27
|
-
label: 'CollectionConfig',
|
|
28
|
-
declaration: declarationPattern('CollectionConfig'),
|
|
29
|
-
operations: COLLECTION_OPERATIONS,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
label: 'GlobalConfig',
|
|
33
|
-
declaration: declarationPattern('GlobalConfig'),
|
|
34
|
-
operations: GLOBAL_OPERATIONS,
|
|
35
|
-
},
|
|
36
|
-
];
|
|
37
|
-
const SATISFIES = 'satisfies';
|
|
38
|
-
// EVERY config in the file, not the first. `search` returned one offset, so a module exporting two
|
|
39
|
-
// collections - or a collection beside a global - had its second config judged by nothing at all. The
|
|
40
|
-
// Local API rules already iterated their matches; these did not, and the asymmetry was invisible
|
|
41
|
-
// because a file with one config, which is most of them, behaves identically either way.
|
|
42
|
-
const findConfigs = (source, kind) => [...source.matchAll(kind.declaration)].flatMap((match) => {
|
|
43
|
-
const body = configBody(source, match.index, match[1] === SATISFIES);
|
|
44
|
-
return body === undefined ? [] : [{ marker: match.index, body }];
|
|
45
|
-
});
|
|
46
|
-
const eachConfig = (source, judge) => CONFIG_KINDS.flatMap((kind) => findConfigs(source, kind).flatMap((found) => judge(kind, found)));
|
|
10
|
+
import { NOT_FOUND, topLevelKeys } from './source-text.js';
|
|
11
|
+
const eachConfig = (source, judge) => payloadConfigsIn(source).flatMap((found) => judge(found.kind, found));
|
|
47
12
|
// Payload fills the missing operations in during sanitisation, so a partial access block is invisible
|
|
48
13
|
// the moment the app boots - and its default for a non-auth collection is public read. Checking that
|
|
49
14
|
// the word `access` appears somewhere in the file, which is what this rule used to do, accepted a block
|
|
@@ -55,7 +20,7 @@ export const findUndeclaredAccess = (source) => eachConfig(source, (kind, found)
|
|
|
55
20
|
? []
|
|
56
21
|
: [
|
|
57
22
|
{
|
|
58
|
-
line:
|
|
23
|
+
line: found.line,
|
|
59
24
|
rule: 'require-complete-access',
|
|
60
25
|
reason: `a ${kind.label} must declare access for ${kind.operations.join(', ')}; ` +
|
|
61
26
|
`${missing.join(', ')} ${missing.length === 1 ? 'is' : 'are'} left to the Payload ` +
|
|
@@ -68,7 +33,11 @@ export const findUndeclaredAccess = (source) => eachConfig(source, (kind, found)
|
|
|
68
33
|
// the case this rule most needs to catch.
|
|
69
34
|
const AUTH_HARDENING_KEYS = ['maxLoginAttempts', 'lockTime'];
|
|
70
35
|
const COLLECTION = 'CollectionConfig';
|
|
71
|
-
const
|
|
36
|
+
const leadingNumber = (value) => {
|
|
37
|
+
const match = /^\s*(-?\d[\d_]*(?:\.\d[\d_]*)?)\s*(?=[,}])/.exec(value ?? '');
|
|
38
|
+
return match === null ? undefined : Number((match[1] ?? '').replaceAll('_', ''));
|
|
39
|
+
};
|
|
40
|
+
const unhardenedAuthIn = (found) => {
|
|
72
41
|
const value = depthOneValue(found.body, 'auth');
|
|
73
42
|
if (value === undefined) {
|
|
74
43
|
return [];
|
|
@@ -77,20 +46,25 @@ const unhardenedAuthIn = (source, found) => {
|
|
|
77
46
|
? topLevelKeys(value, 0)
|
|
78
47
|
: [];
|
|
79
48
|
const missing = AUTH_HARDENING_KEYS.filter((key) => !declared.includes(key));
|
|
80
|
-
|
|
49
|
+
const disabled = AUTH_HARDENING_KEYS.filter((key) => {
|
|
50
|
+
const numeric = leadingNumber(depthOneValue(value, key));
|
|
51
|
+
return numeric !== undefined && numeric <= 0;
|
|
52
|
+
});
|
|
53
|
+
return missing.length === 0 && disabled.length === 0
|
|
81
54
|
? []
|
|
82
55
|
: [
|
|
83
56
|
{
|
|
84
|
-
line:
|
|
57
|
+
line: found.line,
|
|
85
58
|
rule: 'require-auth-hardening',
|
|
86
59
|
reason: `an auth collection must declare ${AUTH_HARDENING_KEYS.join(' and ')}; ` +
|
|
87
|
-
`${missing.join(' and ')}
|
|
88
|
-
'
|
|
60
|
+
(missing.length === 0 ? '' : `${missing.join(' and ')} is missing; `) +
|
|
61
|
+
(disabled.length === 0 ? '' : `${disabled.join(' and ')} is not positive; `) +
|
|
62
|
+
'without a positive attempt cap and lock time, login guesses are not bounded',
|
|
89
63
|
},
|
|
90
64
|
];
|
|
91
65
|
};
|
|
92
66
|
/** Report an auth collection that leaves the login-attempt cap and lock time to Payload's defaults. */
|
|
93
|
-
export const findUnhardenedAuth = (source) => eachConfig(source, (kind, found) => kind.label === COLLECTION ? unhardenedAuthIn(
|
|
67
|
+
export const findUnhardenedAuth = (source) => eachConfig(source, (kind, found) => kind.label === COLLECTION ? unhardenedAuthIn(found) : []);
|
|
94
68
|
// A draft is unpublished content. With versions.drafts enabled, `?draft=true` serves it to whoever the
|
|
95
69
|
// read rule admits - so a read that is unconditionally true publishes every draft to anyone.
|
|
96
70
|
const DRAFTS_ENABLED = /drafts\s*:\s*(?:true|\{)/;
|
|
@@ -132,7 +106,7 @@ const isDraftExposed = (body) => {
|
|
|
132
106
|
export const findAnonymousDraftReads = (source) => eachConfig(source, (kind, found) => isDraftExposed(found.body)
|
|
133
107
|
? [
|
|
134
108
|
{
|
|
135
|
-
line:
|
|
109
|
+
line: found.line,
|
|
136
110
|
rule: 'no-anonymous-draft-reads',
|
|
137
111
|
reason: `a ${kind.label} with drafts enabled must not grant an unconditionally true read; ` +
|
|
138
112
|
'an unauthenticated client would fetch unpublished drafts through ?draft=true',
|
|
@@ -144,7 +118,7 @@ export const findAnonymousDraftReads = (source) => eachConfig(source, (kind, fou
|
|
|
144
118
|
// as the site, which is why the restriction is required rather than advised. No size cap is asked for
|
|
145
119
|
// here: Payload takes that at the config root rather than on the collection.
|
|
146
120
|
const UPLOAD_RESTRICTION = 'mimeTypes';
|
|
147
|
-
const unrestrictedUploadIn = (
|
|
121
|
+
const unrestrictedUploadIn = (found) => {
|
|
148
122
|
const value = depthOneValue(found.body, 'upload');
|
|
149
123
|
if (value === undefined) {
|
|
150
124
|
return [];
|
|
@@ -156,7 +130,7 @@ const unrestrictedUploadIn = (source, found) => {
|
|
|
156
130
|
? []
|
|
157
131
|
: [
|
|
158
132
|
{
|
|
159
|
-
line:
|
|
133
|
+
line: found.line,
|
|
160
134
|
rule: 'require-upload-restrictions',
|
|
161
135
|
reason: `an upload collection must declare ${UPLOAD_RESTRICTION}; left undeclared it accepts ` +
|
|
162
136
|
'any file, and an SVG served from this origin is script that runs as the site',
|
|
@@ -164,5 +138,5 @@ const unrestrictedUploadIn = (source, found) => {
|
|
|
164
138
|
];
|
|
165
139
|
};
|
|
166
140
|
/** Report an upload collection that accepts whatever file type Payload's defaults allow. */
|
|
167
|
-
export const findUnrestrictedUploads = (source) => eachConfig(source, (kind, found) => kind.label === COLLECTION ? unrestrictedUploadIn(
|
|
141
|
+
export const findUnrestrictedUploads = (source) => eachConfig(source, (kind, found) => kind.label === COLLECTION ? unrestrictedUploadIn(found) : []);
|
|
168
142
|
//# sourceMappingURL=payload-access.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload-access.js","sourceRoot":"","sources":["../src/payload-access.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,sCAAsC;AACtC,EAAE;AACF,iGAAiG;AACjG,wGAAwG;AACxG,uGAAuG;AACvG,sEAAsE;
|
|
1
|
+
{"version":3,"file":"payload-access.js","sourceRoot":"","sources":["../src/payload-access.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** The operations one Payload configuration kind must decide explicitly. */
|
|
2
|
+
export interface PayloadConfigKind {
|
|
3
|
+
readonly kind: 'collection' | 'global';
|
|
4
|
+
readonly label: string;
|
|
5
|
+
readonly operations: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
/** One Payload configuration literal, with the source position its body begins at. */
|
|
8
|
+
export interface FoundPayloadConfig {
|
|
9
|
+
readonly kind: PayloadConfigKind;
|
|
10
|
+
readonly marker: number;
|
|
11
|
+
readonly body: string;
|
|
12
|
+
readonly bodyStart: number;
|
|
13
|
+
readonly line: number;
|
|
14
|
+
}
|
|
15
|
+
/** One object written directly as an element of a configuration's `fields` array. */
|
|
16
|
+
export interface FoundFieldLiteral {
|
|
17
|
+
readonly body: string;
|
|
18
|
+
readonly line: number;
|
|
19
|
+
}
|
|
20
|
+
/** Every collection and global configuration literal the source declares. */
|
|
21
|
+
export declare const payloadConfigsIn: (source: string) => readonly FoundPayloadConfig[];
|
|
22
|
+
/** The field literals directly visible in one collection/global config. */
|
|
23
|
+
export declare const directFieldsIn: (source: string, config: FoundPayloadConfig) => readonly FoundFieldLiteral[];
|
|
24
|
+
//# sourceMappingURL=payload-configs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-configs.d.ts","sourceRoot":"","sources":["../src/payload-configs.ts"],"names":[],"mappings":"AAgBA,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAA;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CACvC;AAED,sFAAsF;AACtF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,qFAAqF;AACrF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AA2CD,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,SAAS,kBAAkB,EAI1E,CAAA;AAwCH,2EAA2E;AAC3E,eAAO,MAAM,cAAc,GACzB,QAAQ,MAAM,EACd,QAAQ,kBAAkB,KACzB,SAAS,iBAAiB,EAkB5B,CAAA"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// The shared catalogue of Payload configuration literals.
|
|
2
|
+
//
|
|
3
|
+
// Access policy and field policy ask different questions of the same object: whether a collection or
|
|
4
|
+
// global has declared its operation boundary, and whether a privilege-bearing field has declared its
|
|
5
|
+
// own. The declaration forms must therefore have one owner. A second regex beside the access rule was
|
|
6
|
+
// how generic annotations and `satisfies` configurations previously escaped every Payload check.
|
|
7
|
+
import { configBody, depthOneValue } from './payload-source.js';
|
|
8
|
+
import { balancedArguments, lineOf, NOT_FOUND, scanDelimited, } from './source-text.js';
|
|
9
|
+
const declarationPattern = (typeName) => new RegExp(String.raw `(:|satisfies)\s*${typeName}(?=[<=,)\s]|$)`, 'g');
|
|
10
|
+
const CONFIG_KINDS = [
|
|
11
|
+
{
|
|
12
|
+
kind: 'collection',
|
|
13
|
+
label: 'CollectionConfig',
|
|
14
|
+
declaration: declarationPattern('CollectionConfig'),
|
|
15
|
+
operations: ['create', 'read', 'update', 'delete'],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
kind: 'global',
|
|
19
|
+
label: 'GlobalConfig',
|
|
20
|
+
declaration: declarationPattern('GlobalConfig'),
|
|
21
|
+
operations: ['read', 'update'],
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
const SATISFIES = 'satisfies';
|
|
25
|
+
const bodyStartOf = (source, body, marker, isTrailing) => isTrailing ? source.lastIndexOf(body, marker) : source.indexOf(body, marker);
|
|
26
|
+
const configsOfKind = (source, kind) => [...source.matchAll(kind.declaration)].flatMap((match) => {
|
|
27
|
+
const isTrailing = match[1] === SATISFIES;
|
|
28
|
+
const body = configBody(source, match.index, isTrailing);
|
|
29
|
+
if (body === undefined) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
const bodyStart = bodyStartOf(source, body, match.index, isTrailing);
|
|
33
|
+
return bodyStart === NOT_FOUND
|
|
34
|
+
? []
|
|
35
|
+
: [{ kind, marker: match.index, body, bodyStart, line: lineOf(source, match.index) }];
|
|
36
|
+
});
|
|
37
|
+
/** Every collection and global configuration literal the source declares. */
|
|
38
|
+
export const payloadConfigsIn = (source) => CONFIG_KINDS.flatMap((kind) => configsOfKind(source, kind));
|
|
39
|
+
const DIRECT_FIELD_DEPTH = 2;
|
|
40
|
+
const closeLastSpan = (spans, close) => {
|
|
41
|
+
const last = spans.at(-1);
|
|
42
|
+
return last?.close === NOT_FOUND ? [...spans.slice(0, -1), { open: last.open, close }] : spans;
|
|
43
|
+
};
|
|
44
|
+
const opensDirectField = (step) => step.character === '{' && step.depth === DIRECT_FIELD_DEPTH;
|
|
45
|
+
const endsDirectField = (step) => step.character === '}' && step.depth === 1;
|
|
46
|
+
const endsFieldArray = (step) => step.character === ']' && step.depth === 0;
|
|
47
|
+
const afterFieldDelimiter = (spans, step) => {
|
|
48
|
+
if (opensDirectField(step)) {
|
|
49
|
+
return { state: [...spans, { open: step.index, close: NOT_FOUND }], stop: false };
|
|
50
|
+
}
|
|
51
|
+
if (endsDirectField(step)) {
|
|
52
|
+
return { state: closeLastSpan(spans, step.index), stop: false };
|
|
53
|
+
}
|
|
54
|
+
return { state: spans, stop: endsFieldArray(step) };
|
|
55
|
+
};
|
|
56
|
+
// Starting on the array opener puts its direct object elements at depth two. A nested object opens at
|
|
57
|
+
// depth three or more and is part of the field rather than another field beside it.
|
|
58
|
+
const directObjectSpans = (source, open) => scanDelimited(source, open, afterFieldDelimiter, []);
|
|
59
|
+
/** The field literals directly visible in one collection/global config. */
|
|
60
|
+
export const directFieldsIn = (source, config) => {
|
|
61
|
+
const fields = depthOneValue(config.body, 'fields');
|
|
62
|
+
if (fields === undefined) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
const open = fields.indexOf('[');
|
|
66
|
+
if (open === NOT_FOUND) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
const fieldsStart = config.bodyStart + config.body.length - fields.length;
|
|
70
|
+
return directObjectSpans(fields, open).flatMap((span) => {
|
|
71
|
+
const body = balancedArguments(fields, span.open);
|
|
72
|
+
return body === undefined
|
|
73
|
+
? []
|
|
74
|
+
: [{ body: `{${body}}`, line: lineOf(source, fieldsStart + span.open) }];
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=payload-configs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-configs.js","sourceRoot":"","sources":["../src/payload-configs.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,qGAAqG;AACrG,qGAAqG;AACrG,sGAAsG;AACtG,iGAAiG;AACjG,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EACL,iBAAiB,EAEjB,MAAM,EACN,SAAS,EAET,aAAa,GACd,MAAM,kBAAkB,CAAA;AAwBzB,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAU,EAAE,CACtD,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAA,mBAAmB,QAAQ,gBAAgB,EAAE,GAAG,CAAC,CAAA;AAExE,MAAM,YAAY,GAAsE;IACtF;QACE,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,kBAAkB,CAAC,kBAAkB,CAAC;QACnD,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;KACnD;IACD;QACE,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,kBAAkB,CAAC,cAAc,CAAC;QAC/C,UAAU,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;KAC/B;CACF,CAAA;AAED,MAAM,SAAS,GAAW,WAAW,CAAA;AAErC,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,IAAY,EAAE,MAAc,EAAE,UAAmB,EAAU,EAAE,CAChG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAE9E,MAAM,aAAa,GAAG,CACpB,MAAc,EACd,IAA0D,EAC3B,EAAE,CACjC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAC5C,CAAC,KAAsB,EAAiC,EAAE;IACxD,MAAM,UAAU,GAAY,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAA;IAClD,MAAM,IAAI,GAAuB,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IAC5E,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,MAAM,SAAS,GAAW,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IAC5E,OAAO,SAAS,KAAK,SAAS;QAC5B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;AACzF,CAAC,CACF,CAAA;AAEH,6EAA6E;AAC7E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAc,EAAiC,EAAE,CAChF,YAAY,CAAC,OAAO,CAClB,CAAC,IAA0D,EAAiC,EAAE,CAC5F,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAC9B,CAAA;AAQH,MAAM,kBAAkB,GAAW,CAAC,CAAA;AAEpC,MAAM,aAAa,GAAG,CAAC,KAA2B,EAAE,KAAa,EAAwB,EAAE;IACzF,MAAM,IAAI,GAA0B,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAChD,OAAO,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AAChG,CAAC,CAAA;AAED,MAAM,gBAAgB,GAAG,CAAC,IAAc,EAAW,EAAE,CACnD,IAAI,CAAC,SAAS,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,KAAK,kBAAkB,CAAA;AAE7D,MAAM,eAAe,GAAG,CAAC,IAAc,EAAW,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,CAAA;AAE/F,MAAM,cAAc,GAAG,CAAC,IAAc,EAAW,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,CAAA;AAE9F,MAAM,mBAAmB,GAAG,CAC1B,KAA2B,EAC3B,IAAc,EACgB,EAAE;IAChC,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;IACnF,CAAC;IACD,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;IACjE,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,CAAA;AACrD,CAAC,CAAA;AAED,sGAAsG;AACtG,oFAAoF;AACpF,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAE,IAAY,EAAwB,EAAE,CAC/E,aAAa,CAAuB,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAA;AAE5E,2EAA2E;AAC3E,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,MAAc,EACd,MAA0B,EACI,EAAE;IAChC,MAAM,MAAM,GAAuB,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACvE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,MAAM,IAAI,GAAW,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACxC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,MAAM,WAAW,GAAW,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IACjF,OAAO,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,OAAO,CAC5C,CAAC,IAAe,EAAgC,EAAE;QAChD,MAAM,IAAI,GAAuB,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACrE,OAAO,IAAI,KAAK,SAAS;YACvB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC5E,CAAC,CACF,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type PayloadViolation } from './payload-source.js';
|
|
2
|
+
/** Report privilege-bearing auth fields without explicit create and update access. */
|
|
3
|
+
export declare const findUnprotectedPrivilegedFields: (source: string) => readonly PayloadViolation[];
|
|
4
|
+
//# sourceMappingURL=payload-field-access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-field-access.d.ts","sourceRoot":"","sources":["../src/payload-field-access.ts"],"names":[],"mappings":"AASA,OAAO,EAAoC,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AA+C7F,sFAAsF;AACtF,eAAO,MAAM,+BAA+B,GAAI,QAAQ,MAAM,KAAG,SAAS,gBAAgB,EAUrF,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Field-level access decisions that protect an account's authority.
|
|
2
|
+
//
|
|
3
|
+
// A collection access rule and a field access rule defend different boundaries. The collection rule
|
|
4
|
+
// decides who may update an account at all; the field rule decides whether that caller may change the
|
|
5
|
+
// part which grants authority. Requiring both prevents a later widening of collection access from
|
|
6
|
+
// silently turning an ordinary profile update into privilege escalation.
|
|
7
|
+
import { directFieldsIn, payloadConfigsIn } from './payload-configs.js';
|
|
8
|
+
import { depthOneBlockKeys, depthOneValue } from './payload-source.js';
|
|
9
|
+
const PRIVILEGED_FIELD_NAMES = new Set([
|
|
10
|
+
'role',
|
|
11
|
+
'roles',
|
|
12
|
+
'isAdmin',
|
|
13
|
+
'isStaff',
|
|
14
|
+
'permission',
|
|
15
|
+
'permissions',
|
|
16
|
+
'capability',
|
|
17
|
+
'capabilities',
|
|
18
|
+
]);
|
|
19
|
+
const REQUIRED_OPERATIONS = ['create', 'update'];
|
|
20
|
+
const quotedValue = (value) => /^\s*['"`]([^'"`]+)['"`]/.exec(value ?? '')?.[1];
|
|
21
|
+
const isAuthCollection = (config) => {
|
|
22
|
+
if (config.kind.kind !== 'collection') {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const auth = depthOneValue(config.body, 'auth');
|
|
26
|
+
return /^\s*(?:true\b|\{)/.test(auth ?? '');
|
|
27
|
+
};
|
|
28
|
+
const violationFor = (field) => {
|
|
29
|
+
const name = quotedValue(depthOneValue(field.body, 'name'));
|
|
30
|
+
if (name === undefined || !PRIVILEGED_FIELD_NAMES.has(name)) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const declared = depthOneBlockKeys(field.body, 'access');
|
|
34
|
+
const missing = REQUIRED_OPERATIONS.filter((operation) => !declared.includes(operation));
|
|
35
|
+
return missing.length === 0
|
|
36
|
+
? undefined
|
|
37
|
+
: {
|
|
38
|
+
line: field.line,
|
|
39
|
+
rule: 'require-privileged-field-access',
|
|
40
|
+
reason: `the privilege-bearing field "${name}" must declare field access for create and update; ` +
|
|
41
|
+
`${missing.join(' and ')} is not protected from assignment by a caller who can write ` +
|
|
42
|
+
'the auth collection',
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
/** Report privilege-bearing auth fields without explicit create and update access. */
|
|
46
|
+
export const findUnprotectedPrivilegedFields = (source) => payloadConfigsIn(source)
|
|
47
|
+
.filter((config) => isAuthCollection(config))
|
|
48
|
+
.flatMap((config) => directFieldsIn(source, config))
|
|
49
|
+
.map((field) => violationFor(field))
|
|
50
|
+
.filter((violation) => violation !== undefined);
|
|
51
|
+
//# sourceMappingURL=payload-field-access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-field-access.js","sourceRoot":"","sources":["../src/payload-field-access.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,oGAAoG;AACpG,sGAAsG;AACtG,kGAAkG;AAClG,yEAAyE;AAGzE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAyB,MAAM,qBAAqB,CAAA;AAE7F,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC;IAC1D,MAAM;IACN,OAAO;IACP,SAAS;IACT,SAAS;IACT,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,cAAc;CACf,CAAC,CAAA;AAEF,MAAM,mBAAmB,GAAsB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;AAEnE,MAAM,WAAW,GAAG,CAAC,KAAyB,EAAsB,EAAE,CACpE,yBAAyB,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAElD,MAAM,gBAAgB,GAAG,CAAC,MAA0B,EAAW,EAAE;IAC/D,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACtC,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,IAAI,GAAuB,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACnE,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,YAAY,GAAG,CAAC,KAAwB,EAAgC,EAAE;IAC9E,MAAM,IAAI,GAAuB,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/E,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5D,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,QAAQ,GAAsB,iBAAiB,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IAC3E,MAAM,OAAO,GAAsB,mBAAmB,CAAC,MAAM,CAC3D,CAAC,SAAiB,EAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAC9D,CAAA;IACD,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC;QACzB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC;YACE,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,iCAAiC;YACvC,MAAM,EACJ,gCAAgC,IAAI,qDAAqD;gBACzF,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,8DAA8D;gBACtF,qBAAqB;SACxB,CAAA;AACP,CAAC,CAAA;AAED,sFAAsF;AACtF,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,MAAc,EAA+B,EAAE,CAC7F,gBAAgB,CAAC,MAAM,CAAC;KACrB,MAAM,CAAC,CAAC,MAA0B,EAAW,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;KACzE,OAAO,CAAC,CAAC,MAA0B,EAAgC,EAAE,CACpE,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAC/B;KACA,GAAG,CAAC,CAAC,KAAwB,EAAgC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;KACpF,MAAM,CACL,CAAC,SAAuC,EAAiC,EAAE,CACzE,SAAS,KAAK,SAAS,CAC1B,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload-policy.d.ts","sourceRoot":"","sources":["../src/payload-policy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"payload-policy.d.ts","sourceRoot":"","sources":["../src/payload-policy.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAqR3D;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,KAAG,SAAS,gBAAgB,EAG9E,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,KAAG,SAAS,gBAAgB,EAe/E,CAAA"}
|