@ploaness/governance 1.0.0 → 1.2.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.
Files changed (222) hide show
  1. package/dist/a11y-hit-target.d.ts +35 -0
  2. package/dist/a11y-hit-target.d.ts.map +1 -0
  3. package/dist/a11y-hit-target.js +82 -0
  4. package/dist/a11y-hit-target.js.map +1 -0
  5. package/dist/a11y-incomplete.d.ts +18 -0
  6. package/dist/a11y-incomplete.d.ts.map +1 -0
  7. package/dist/a11y-incomplete.js +65 -0
  8. package/dist/a11y-incomplete.js.map +1 -0
  9. package/dist/access-boundary.d.ts +62 -6
  10. package/dist/access-boundary.d.ts.map +1 -1
  11. package/dist/access-boundary.js +201 -6
  12. package/dist/access-boundary.js.map +1 -1
  13. package/dist/admin-view-coverage.d.ts +25 -0
  14. package/dist/admin-view-coverage.d.ts.map +1 -0
  15. package/dist/admin-view-coverage.js +74 -0
  16. package/dist/admin-view-coverage.js.map +1 -0
  17. package/dist/asset-policy.d.ts.map +1 -1
  18. package/dist/asset-policy.js +1 -23
  19. package/dist/asset-policy.js.map +1 -1
  20. package/dist/axe-coverage.d.ts +40 -0
  21. package/dist/axe-coverage.d.ts.map +1 -0
  22. package/dist/axe-coverage.js +62 -0
  23. package/dist/axe-coverage.js.map +1 -0
  24. package/dist/banned-typography.d.ts.map +1 -1
  25. package/dist/banned-typography.js +26 -0
  26. package/dist/banned-typography.js.map +1 -1
  27. package/dist/blocklist-entries.d.ts +36 -0
  28. package/dist/blocklist-entries.d.ts.map +1 -0
  29. package/dist/blocklist-entries.js +338 -0
  30. package/dist/blocklist-entries.js.map +1 -0
  31. package/dist/blocklist.d.ts +91 -0
  32. package/dist/blocklist.d.ts.map +1 -0
  33. package/dist/blocklist.js +187 -0
  34. package/dist/blocklist.js.map +1 -0
  35. package/dist/build-diagnosis.d.ts +10 -0
  36. package/dist/build-diagnosis.d.ts.map +1 -0
  37. package/dist/build-diagnosis.js +38 -0
  38. package/dist/build-diagnosis.js.map +1 -0
  39. package/dist/container-failure.d.ts.map +1 -1
  40. package/dist/container-failure.js +1 -18
  41. package/dist/container-failure.js.map +1 -1
  42. package/dist/container-files.d.ts +16 -0
  43. package/dist/container-files.d.ts.map +1 -1
  44. package/dist/container-files.js +23 -8
  45. package/dist/container-files.js.map +1 -1
  46. package/dist/container-images.d.ts +43 -0
  47. package/dist/container-images.d.ts.map +1 -0
  48. package/dist/container-images.js +157 -0
  49. package/dist/container-images.js.map +1 -0
  50. package/dist/dependency-freshness.d.ts +8 -0
  51. package/dist/dependency-freshness.d.ts.map +1 -1
  52. package/dist/dependency-freshness.js +2 -18
  53. package/dist/dependency-freshness.js.map +1 -1
  54. package/dist/doc-blocks.d.ts.map +1 -1
  55. package/dist/doc-blocks.js +1 -13
  56. package/dist/doc-blocks.js.map +1 -1
  57. package/dist/document-references.d.ts.map +1 -1
  58. package/dist/document-references.js +7 -1
  59. package/dist/document-references.js.map +1 -1
  60. package/dist/editorconfig-policy.d.ts +7 -0
  61. package/dist/editorconfig-policy.d.ts.map +1 -1
  62. package/dist/editorconfig-policy.js +19 -12
  63. package/dist/editorconfig-policy.js.map +1 -1
  64. package/dist/environment-coherence.d.ts +87 -0
  65. package/dist/environment-coherence.d.ts.map +1 -0
  66. package/dist/environment-coherence.js +128 -0
  67. package/dist/environment-coherence.js.map +1 -0
  68. package/dist/environment-files.d.ts.map +1 -1
  69. package/dist/environment-files.js +1 -19
  70. package/dist/environment-files.js.map +1 -1
  71. package/dist/file-roles.d.ts +7 -2
  72. package/dist/file-roles.d.ts.map +1 -1
  73. package/dist/file-roles.js +10 -9
  74. package/dist/file-roles.js.map +1 -1
  75. package/dist/freshness-repair.d.ts +82 -0
  76. package/dist/freshness-repair.d.ts.map +1 -0
  77. package/dist/freshness-repair.js +91 -0
  78. package/dist/freshness-repair.js.map +1 -0
  79. package/dist/generated-denial.d.ts.map +1 -1
  80. package/dist/generated-denial.js +1 -9
  81. package/dist/generated-denial.js.map +1 -1
  82. package/dist/generated-drift.d.ts +18 -0
  83. package/dist/generated-drift.d.ts.map +1 -0
  84. package/dist/generated-drift.js +24 -0
  85. package/dist/generated-drift.js.map +1 -0
  86. package/dist/harness-package.d.ts +13 -0
  87. package/dist/harness-package.d.ts.map +1 -0
  88. package/dist/harness-package.js +20 -0
  89. package/dist/harness-package.js.map +1 -0
  90. package/dist/history-policy.d.ts.map +1 -1
  91. package/dist/history-policy.js +1 -7
  92. package/dist/history-policy.js.map +1 -1
  93. package/dist/image-assets.d.ts.map +1 -1
  94. package/dist/image-assets.js +1 -10
  95. package/dist/image-assets.js.map +1 -1
  96. package/dist/index.d.ts +22 -1
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +22 -1
  99. package/dist/index.js.map +1 -1
  100. package/dist/install-policy.d.ts +21 -0
  101. package/dist/install-policy.d.ts.map +1 -1
  102. package/dist/install-policy.js +53 -1
  103. package/dist/install-policy.js.map +1 -1
  104. package/dist/jsx-accessibility-scope.d.ts +17 -0
  105. package/dist/jsx-accessibility-scope.d.ts.map +1 -0
  106. package/dist/jsx-accessibility-scope.js +36 -0
  107. package/dist/jsx-accessibility-scope.js.map +1 -0
  108. package/dist/jsx-accessibility.d.ts +13 -0
  109. package/dist/jsx-accessibility.d.ts.map +1 -0
  110. package/dist/jsx-accessibility.js +188 -0
  111. package/dist/jsx-accessibility.js.map +1 -0
  112. package/dist/network-policy.d.ts.map +1 -1
  113. package/dist/network-policy.js +1 -12
  114. package/dist/network-policy.js.map +1 -1
  115. package/dist/oxlint-policy.d.ts +16 -0
  116. package/dist/oxlint-policy.d.ts.map +1 -0
  117. package/dist/oxlint-policy.js +28 -0
  118. package/dist/oxlint-policy.js.map +1 -0
  119. package/dist/oxlint-report.d.ts +29 -0
  120. package/dist/oxlint-report.d.ts.map +1 -0
  121. package/dist/oxlint-report.js +84 -0
  122. package/dist/oxlint-report.js.map +1 -0
  123. package/dist/oxlint-scope.d.ts +13 -0
  124. package/dist/oxlint-scope.d.ts.map +1 -0
  125. package/dist/oxlint-scope.js +46 -0
  126. package/dist/oxlint-scope.js.map +1 -0
  127. package/dist/oxlint-suppressions.d.ts +17 -0
  128. package/dist/oxlint-suppressions.d.ts.map +1 -0
  129. package/dist/oxlint-suppressions.js +72 -0
  130. package/dist/oxlint-suppressions.js.map +1 -0
  131. package/dist/paired-assets.d.ts.map +1 -1
  132. package/dist/paired-assets.js.map +1 -1
  133. package/dist/payload-access.d.ts +6 -0
  134. package/dist/payload-access.d.ts.map +1 -1
  135. package/dist/payload-access.js +188 -57
  136. package/dist/payload-access.js.map +1 -1
  137. package/dist/payload-configs.d.ts +23 -0
  138. package/dist/payload-configs.d.ts.map +1 -0
  139. package/dist/payload-configs.js +96 -0
  140. package/dist/payload-configs.js.map +1 -0
  141. package/dist/payload-defaults.d.ts +128 -0
  142. package/dist/payload-defaults.d.ts.map +1 -0
  143. package/dist/payload-defaults.js +295 -0
  144. package/dist/payload-defaults.js.map +1 -0
  145. package/dist/payload-field-access.d.ts +4 -0
  146. package/dist/payload-field-access.d.ts.map +1 -0
  147. package/dist/payload-field-access.js +51 -0
  148. package/dist/payload-field-access.js.map +1 -0
  149. package/dist/payload-policy.d.ts +13 -0
  150. package/dist/payload-policy.d.ts.map +1 -1
  151. package/dist/payload-policy.js +171 -32
  152. package/dist/payload-policy.js.map +1 -1
  153. package/dist/payload-source.js +2 -2
  154. package/dist/payload-source.js.map +1 -1
  155. package/dist/relationship-cleanup.d.ts +18 -0
  156. package/dist/relationship-cleanup.d.ts.map +1 -0
  157. package/dist/relationship-cleanup.js +96 -0
  158. package/dist/relationship-cleanup.js.map +1 -0
  159. package/dist/release-age.d.ts.map +1 -1
  160. package/dist/release-age.js +1 -16
  161. package/dist/release-age.js.map +1 -1
  162. package/dist/request-limits.d.ts.map +1 -1
  163. package/dist/request-limits.js +1 -11
  164. package/dist/request-limits.js.map +1 -1
  165. package/dist/route-coverage.d.ts +27 -0
  166. package/dist/route-coverage.d.ts.map +1 -0
  167. package/dist/route-coverage.js +57 -0
  168. package/dist/route-coverage.js.map +1 -0
  169. package/dist/route-map.d.ts +65 -0
  170. package/dist/route-map.d.ts.map +1 -0
  171. package/dist/route-map.js +168 -0
  172. package/dist/route-map.js.map +1 -0
  173. package/dist/run-plan.d.ts.map +1 -1
  174. package/dist/run-plan.js +1 -19
  175. package/dist/run-plan.js.map +1 -1
  176. package/dist/secret-policy.d.ts.map +1 -1
  177. package/dist/secret-policy.js +5 -15
  178. package/dist/secret-policy.js.map +1 -1
  179. package/dist/settings-layering.d.ts +8 -30
  180. package/dist/settings-layering.d.ts.map +1 -1
  181. package/dist/settings-layering.js +19 -48
  182. package/dist/settings-layering.js.map +1 -1
  183. package/dist/settings.d.ts +19 -2
  184. package/dist/settings.d.ts.map +1 -1
  185. package/dist/settings.js +5 -1
  186. package/dist/settings.js.map +1 -1
  187. package/dist/source-security.d.ts +4 -0
  188. package/dist/source-security.d.ts.map +1 -0
  189. package/dist/source-security.js +56 -0
  190. package/dist/source-security.js.map +1 -0
  191. package/dist/source-text.d.ts +16 -0
  192. package/dist/source-text.d.ts.map +1 -1
  193. package/dist/source-text.js +46 -16
  194. package/dist/source-text.js.map +1 -1
  195. package/dist/toolchain-pins.d.ts.map +1 -1
  196. package/dist/toolchain-pins.js +2 -19
  197. package/dist/toolchain-pins.js.map +1 -1
  198. package/dist/version-policy.d.ts +7 -8
  199. package/dist/version-policy.d.ts.map +1 -1
  200. package/dist/version-policy.js +46 -26
  201. package/dist/version-policy.js.map +1 -1
  202. package/dist/vulnerability-policy.d.ts.map +1 -1
  203. package/dist/vulnerability-policy.js +1 -11
  204. package/dist/vulnerability-policy.js.map +1 -1
  205. package/dist/wiring-policy.d.ts.map +1 -1
  206. package/dist/wiring-policy.js +4 -1
  207. package/dist/wiring-policy.js.map +1 -1
  208. package/dist/wiring-violation.d.ts.map +1 -1
  209. package/dist/wiring-violation.js +1 -6
  210. package/dist/wiring-violation.js.map +1 -1
  211. package/dist/workspace-policy.d.ts.map +1 -1
  212. package/dist/workspace-policy.js +3 -9
  213. package/dist/workspace-policy.js.map +1 -1
  214. package/dist/yaml-blocks.d.ts +10 -0
  215. package/dist/yaml-blocks.d.ts.map +1 -1
  216. package/dist/yaml-blocks.js +20 -0
  217. package/dist/yaml-blocks.js.map +1 -1
  218. package/package.json +2 -2
  219. package/dist/url-safety.d.ts +0 -12
  220. package/dist/url-safety.d.ts.map +0 -1
  221. package/dist/url-safety.js +0 -58
  222. package/dist/url-safety.js.map +0 -1
@@ -0,0 +1,128 @@
1
+ /** The operations a collection must decide; the static rule holds a written config to the same list. */
2
+ export declare const COLLECTION_OPERATIONS: readonly string[];
3
+ /** The operations a global must decide. */
4
+ export declare const GLOBAL_OPERATIONS: readonly string[];
5
+ /** The operation an auth collection decides on top of the four: who may clear a locked account. */
6
+ export declare const UNLOCK_OPERATION: string;
7
+ /** The operation a versioned collection or global decides: who may read a stored version. */
8
+ export declare const READ_VERSIONS_OPERATION: string;
9
+ /** What an entity of the built configuration is, as far as the operations it owes depend on it. */
10
+ export interface PayloadSubjectTraits {
11
+ readonly kind: PayloadSubjectKind;
12
+ readonly hasAuth: boolean;
13
+ readonly hasVersions: boolean;
14
+ }
15
+ /**
16
+ * The access operations one entity owes a decision on. Two of them are conditional, and neither may be
17
+ * added to the lists above: Payload writes `unlock` onto EVERY collection during sanitisation, auth or
18
+ * not, so demanding it unconditionally would report the whole configuration, and `readVersions` means
19
+ * nothing on an entity that keeps no versions.
20
+ * @param traits what the entity is: its kind, and whether it authenticates or keeps versions.
21
+ * @returns the operations that entity must decide, in the order they are reported.
22
+ */
23
+ export declare const accessOperationsFor: (traits: PayloadSubjectTraits) => readonly string[];
24
+ /**
25
+ * The prefix the probe prints its report behind. A plugin may log on import, and a line the parser can
26
+ * name is what separates the report from that chatter.
27
+ */
28
+ export declare const INHERITED_ACCESS_REPORT_MARKER: string;
29
+ /** One entity of the built configuration and the operations it left to Payload's default. */
30
+ export interface InheritedAccessEntry {
31
+ readonly slug: string;
32
+ readonly inherited: readonly string[];
33
+ }
34
+ /**
35
+ * What a read rule answered an anonymous caller, as the probe observed it. `filtered` carries the
36
+ * query constraint the rule returned, which is the half `/api/access` reports and the anonymous sweep
37
+ * never opens; `undecidable` is a rule that threw when asked, which is reported rather than assumed
38
+ * safe.
39
+ */
40
+ export type AnonymousRead = {
41
+ readonly kind: 'denied';
42
+ } | {
43
+ readonly kind: 'filtered';
44
+ readonly where: unknown;
45
+ } | {
46
+ readonly kind: 'open';
47
+ } | {
48
+ readonly kind: 'undecidable';
49
+ readonly reason: string;
50
+ };
51
+ /** One entity that keeps drafts, and what its read rule answers a caller with no credentials. */
52
+ export interface DraftReadEntry {
53
+ readonly kind: PayloadSubjectKind;
54
+ readonly slug: string;
55
+ readonly anonymousRead: AnonymousRead;
56
+ }
57
+ /** What the probe reports: every collection and every global, decided ones included. */
58
+ export interface InheritedAccessReport {
59
+ readonly collections: readonly InheritedAccessEntry[];
60
+ readonly draftReads: readonly DraftReadEntry[];
61
+ readonly globals: readonly InheritedAccessEntry[];
62
+ }
63
+ /** The two kinds of entity a Payload configuration holds. */
64
+ export type PayloadSubjectKind = 'collection' | 'global';
65
+ /** One entity Payload builds for its own bookkeeping, which keeps the default access by design. */
66
+ export interface ExemptPayloadSubject {
67
+ readonly kind: PayloadSubjectKind;
68
+ readonly slug: string;
69
+ readonly reason: string;
70
+ }
71
+ /** The entities exempt from the rule, each with the reason. Nothing a project declares extends this. */
72
+ export declare const EXEMPT_PAYLOAD_SUBJECTS: readonly ExemptPayloadSubject[];
73
+ /**
74
+ * The saved-filter collection Payload builds behind `enableQueryPresets`.
75
+ *
76
+ * It is named here because the probe has to read its access from somewhere other than the collection.
77
+ * `getAccess` wraps EVERY operation of this one collection in a closure that calls the project's rule
78
+ * where there is one and Payload's own default where there is not, so the built collection carries four
79
+ * functions that match neither the default by reference nor its source text. Read there, a project that
80
+ * decided nothing is indistinguishable from one that decided everything - and undecided means an
81
+ * unconstrained `create` for any signed-in user, and a preset shared as `everyone` readable by every
82
+ * role that can log in, the ones a project keeps outside its editorial staff included.
83
+ */
84
+ export declare const QUERY_PRESETS_SLUG: string;
85
+ /**
86
+ * Every entity of the built configuration that still carries Payload's default access on a judged
87
+ * operation, in configuration order, each naming where the project decides it.
88
+ * @param report what the probe read from the built configuration.
89
+ * @returns one finding per entity, or nothing when every entity decides its access.
90
+ */
91
+ export declare const findInheritedAccess: (report: InheritedAccessReport) => readonly string[];
92
+ /**
93
+ * Whether a read filter admits published documents alone.
94
+ *
95
+ * A clause under `and` is enough on its own, because every conjunct holds. A clause under `or` counts
96
+ * only when EVERY branch carries one, because a single branch without it is a way in - which is the
97
+ * shape of the defect this rule exists for.
98
+ * @param where the query constraint the read rule returned.
99
+ * @returns whether every document the filter admits is a published one.
100
+ */
101
+ export declare const requiresPublishedStatus: (where: unknown) => boolean;
102
+ /**
103
+ * Every entity that keeps drafts and lets a stranger read something that was never approved, in
104
+ * configuration order.
105
+ * @param report what the probe read from the built configuration.
106
+ * @returns one finding per entity, or nothing when no drafts read admits an unapproved document.
107
+ */
108
+ export declare const findUnconstrainedDraftReads: (report: InheritedAccessReport) => readonly string[];
109
+ /**
110
+ * Read the probe's report out of everything the probe wrote to standard output.
111
+ *
112
+ * The LAST marker line is the report, so a plugin that logs during import cannot hide it, and a report
113
+ * that fails to parse or has the wrong shape is undefined rather than empty: a probe that printed a
114
+ * stack trace must fail the gate, never pass it as "no findings".
115
+ * @param text the probe's standard output.
116
+ * @returns the report, or undefined when no well-formed report was printed.
117
+ */
118
+ export declare const parseInheritedAccessReport: (text: string) => InheritedAccessReport | undefined;
119
+ /** Where a Payload member keeps its configuration when its tsconfig says nothing else. */
120
+ export declare const DEFAULT_PAYLOAD_CONFIG_PATH: string;
121
+ /**
122
+ * The path of the Payload configuration a member's tsconfig aliases as `@payload-config`, which is the
123
+ * alias `ploaness init` writes and Payload's own CLI resolves through.
124
+ * @param tsconfig the parsed tsconfig, or anything when it could not be read.
125
+ * @returns the configured path relative to the member root, or the default path.
126
+ */
127
+ export declare const payloadConfigPathOf: (tsconfig: unknown) => string;
128
+ //# sourceMappingURL=payload-defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-defaults.d.ts","sourceRoot":"","sources":["../src/payload-defaults.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,295 @@
1
+ // Whether every collection and global in a BUILT Payload configuration decides its own access.
2
+ //
3
+ // The static rule in payload-access.ts reads the access block a project wrote, and it can only read what
4
+ // the project wrote. Payload builds collections the project never writes: the folder tree behind
5
+ // `folders`, the job queue behind `jobs`, the saved filters behind `queryPresets`, and whatever a plugin
6
+ // adds. Each arrives with the access Payload gives an undeclared operation, `defaultAccess`, which admits
7
+ // every signed-in user to every operation. The anonymous sweep cannot see that either, because a
8
+ // signed-in stakeholder is not anonymous. So a probe imports the built configuration and reports, per
9
+ // entity, which operations still carry that function; this module decides what the report means.
10
+ //
11
+ // Payload's own bookkeeping keeps the default on purpose, and those entities are exempt by name here,
12
+ // with the reason each. No project setting widens the list: a rule a project can edit is not a rule, and
13
+ // the repair is always available - write the access explicitly, through the override the framework
14
+ // offers for the entity it built.
15
+ import { asRecord, asText, isArray, isRecord, readKey } from './json-shapes.js';
16
+ /** The operations a collection must decide; the static rule holds a written config to the same list. */
17
+ export const COLLECTION_OPERATIONS = ['create', 'read', 'update', 'delete'];
18
+ /** The operations a global must decide. */
19
+ export const GLOBAL_OPERATIONS = ['read', 'update'];
20
+ /** The operation an auth collection decides on top of the four: who may clear a locked account. */
21
+ export const UNLOCK_OPERATION = 'unlock';
22
+ /** The operation a versioned collection or global decides: who may read a stored version. */
23
+ export const READ_VERSIONS_OPERATION = 'readVersions';
24
+ /**
25
+ * The access operations one entity owes a decision on. Two of them are conditional, and neither may be
26
+ * added to the lists above: Payload writes `unlock` onto EVERY collection during sanitisation, auth or
27
+ * not, so demanding it unconditionally would report the whole configuration, and `readVersions` means
28
+ * nothing on an entity that keeps no versions.
29
+ * @param traits what the entity is: its kind, and whether it authenticates or keeps versions.
30
+ * @returns the operations that entity must decide, in the order they are reported.
31
+ */
32
+ export const accessOperationsFor = (traits) => [
33
+ ...(traits.kind === 'collection' ? COLLECTION_OPERATIONS : GLOBAL_OPERATIONS),
34
+ ...(traits.kind === 'collection' && traits.hasAuth ? [UNLOCK_OPERATION] : []),
35
+ ...(traits.hasVersions ? [READ_VERSIONS_OPERATION] : []),
36
+ ];
37
+ /**
38
+ * The prefix the probe prints its report behind. A plugin may log on import, and a line the parser can
39
+ * name is what separates the report from that chatter.
40
+ */
41
+ export const INHERITED_ACCESS_REPORT_MARKER = 'ploaness-inherited-access:';
42
+ /** The entities exempt from the rule, each with the reason. Nothing a project declares extends this. */
43
+ export const EXEMPT_PAYLOAD_SUBJECTS = [
44
+ {
45
+ kind: 'collection',
46
+ slug: 'payload-locked-documents',
47
+ reason: 'the document-lock ledger, which declares the default deliberately so that any signed-in editor ' +
48
+ 'can hold and release a lock',
49
+ },
50
+ {
51
+ kind: 'collection',
52
+ slug: 'payload-preferences',
53
+ reason: 'per-user admin preferences; Payload scopes read and delete to the owner, and leaves create and ' +
54
+ 'update to the default on purpose',
55
+ },
56
+ {
57
+ kind: 'collection',
58
+ slug: 'payload-migrations',
59
+ reason: 'the migration ledger, with no endpoint and no GraphQL surface; only the framework writes it',
60
+ },
61
+ {
62
+ kind: 'global',
63
+ slug: 'payload-jobs-stats',
64
+ reason: 'the scheduling counters Payload keeps beside the job queue; the framework offers no override ' +
65
+ 'for it, so no explicit access can be written, and the queue it counts is judged',
66
+ },
67
+ ];
68
+ /**
69
+ * The saved-filter collection Payload builds behind `enableQueryPresets`.
70
+ *
71
+ * It is named here because the probe has to read its access from somewhere other than the collection.
72
+ * `getAccess` wraps EVERY operation of this one collection in a closure that calls the project's rule
73
+ * where there is one and Payload's own default where there is not, so the built collection carries four
74
+ * functions that match neither the default by reference nor its source text. Read there, a project that
75
+ * decided nothing is indistinguishable from one that decided everything - and undecided means an
76
+ * unconstrained `create` for any signed-in user, and a preset shared as `everyone` readable by every
77
+ * role that can log in, the ones a project keeps outside its editorial staff included.
78
+ */
79
+ export const QUERY_PRESETS_SLUG = 'payload-query-presets';
80
+ // Where the framework lets a project decide the access of an entity it built. Anything else is either
81
+ // the project's own collection, which has an access block, or a plugin's, which has an override option.
82
+ const FRAMEWORK_REPAIRS = {
83
+ 'payload-folders': 'folders.collectionOverrides',
84
+ 'payload-jobs': 'jobs.jobsCollectionOverrides',
85
+ [QUERY_PRESETS_SLUG]: 'queryPresets.access',
86
+ };
87
+ const isExempt = (kind, slug) => EXEMPT_PAYLOAD_SUBJECTS.some((subject) => subject.kind === kind && subject.slug === slug);
88
+ const repairFor = (slug, pronoun) => {
89
+ const framework = FRAMEWORK_REPAIRS[slug];
90
+ return framework === undefined
91
+ ? `decide ${pronoun} in its access block, or in the override its plugin offers`
92
+ : `decide ${pronoun} in ${framework}`;
93
+ };
94
+ const describeInherited = (kind, entry) => {
95
+ const pronoun = entry.inherited.length === 1 ? 'it' : 'them';
96
+ return (`${kind} "${entry.slug}" leaves ${entry.inherited.join(', ')} to Payload's default access, ` +
97
+ `which admits every signed-in user; ${repairFor(entry.slug, pronoun)}`);
98
+ };
99
+ const judge = (kind, entries) => entries
100
+ .filter((entry) => entry.inherited.length > 0 && !isExempt(kind, entry.slug))
101
+ .map((entry) => describeInherited(kind, entry));
102
+ /**
103
+ * Every entity of the built configuration that still carries Payload's default access on a judged
104
+ * operation, in configuration order, each naming where the project decides it.
105
+ * @param report what the probe read from the built configuration.
106
+ * @returns one finding per entity, or nothing when every entity decides its access.
107
+ */
108
+ export const findInheritedAccess = (report) => [
109
+ ...judge('collection', report.collections),
110
+ ...judge('global', report.globals),
111
+ ];
112
+ // The read a drafts-enabled entity grants a stranger.
113
+ //
114
+ // A draft is a document nobody has approved. Payload writes an unpublished save to the versions table
115
+ // and leaves the main row alone, so a document that has never been published carries `_status: 'draft'`
116
+ // in the row a plain list reads - which means an unconstrained read serves unapproved content through
117
+ // the ordinary endpoint, not only through `?draft=true`.
118
+ //
119
+ // The static rule in payload-access.ts can only catch the inline spelling `read: (): boolean => true`,
120
+ // and the shipped ESLint config forbids exactly that spelling in a config file, so a conforming project
121
+ // writes `read: someHelper` and the static rule is blind to it. The anonymous sweep is blind too: it
122
+ // separates a grant that carries a query constraint from one that does not, and never opens the
123
+ // constraint to see what it constrains. Between the two, a read filtered by audience but not by status
124
+ // passed everything. This is the rule that reads the constraint.
125
+ /** The status Payload stamps on the version that is live. */
126
+ const PUBLISHED_STATUS = 'published';
127
+ /** The field Payload adds to an entity that keeps drafts. */
128
+ const STATUS_FIELD = '_status';
129
+ const declaresPublished = (where) => {
130
+ const status = where[STATUS_FIELD];
131
+ return isRecord(status) && status['equals'] === PUBLISHED_STATUS;
132
+ };
133
+ /**
134
+ * Whether a read filter admits published documents alone.
135
+ *
136
+ * A clause under `and` is enough on its own, because every conjunct holds. A clause under `or` counts
137
+ * only when EVERY branch carries one, because a single branch without it is a way in - which is the
138
+ * shape of the defect this rule exists for.
139
+ * @param where the query constraint the read rule returned.
140
+ * @returns whether every document the filter admits is a published one.
141
+ */
142
+ export const requiresPublishedStatus = (where) => {
143
+ if (!isRecord(where)) {
144
+ return false;
145
+ }
146
+ if (declaresPublished(where)) {
147
+ return true;
148
+ }
149
+ const conjuncts = where['and'];
150
+ if (isArray(conjuncts) &&
151
+ conjuncts.some((one) => requiresPublishedStatus(one))) {
152
+ return true;
153
+ }
154
+ const disjuncts = where['or'];
155
+ return (isArray(disjuncts) &&
156
+ disjuncts.length > 0 &&
157
+ disjuncts.every((one) => requiresPublishedStatus(one)));
158
+ };
159
+ const DRAFT_READ_REPAIR = 'a read that keeps unapproved work from a stranger either refuses them outright or filters on ' +
160
+ `${STATUS_FIELD} equals ${PUBLISHED_STATUS}`;
161
+ const describeDraftRead = (entry) => {
162
+ const subject = `${entry.kind} "${entry.slug}" keeps drafts and`;
163
+ const read = entry.anonymousRead;
164
+ if (read.kind === 'open') {
165
+ return (`${subject} grants an unconditional anonymous read, so every unapproved document in it is ` +
166
+ `served to anyone; ${DRAFT_READ_REPAIR}`);
167
+ }
168
+ if (read.kind === 'undecidable') {
169
+ return (`${subject} its read rule could not be decided from the request alone (${read.reason}); an ` +
170
+ 'access rule is a pure decision over the caller it is handed, so the harness can read it');
171
+ }
172
+ if (read.kind === 'filtered' && !requiresPublishedStatus(read.where)) {
173
+ return (`${subject} filters its anonymous read without constraining ${STATUS_FIELD}, so an ` +
174
+ `unapproved document is served to anyone the filter admits; ${DRAFT_READ_REPAIR}`);
175
+ }
176
+ return undefined;
177
+ };
178
+ /**
179
+ * Every entity that keeps drafts and lets a stranger read something that was never approved, in
180
+ * configuration order.
181
+ * @param report what the probe read from the built configuration.
182
+ * @returns one finding per entity, or nothing when no drafts read admits an unapproved document.
183
+ */
184
+ export const findUnconstrainedDraftReads = (report) => report.draftReads.flatMap((entry) => {
185
+ const finding = describeDraftRead(entry);
186
+ return finding === undefined ? [] : [finding];
187
+ });
188
+ const asEntry = (raw) => {
189
+ if (!isRecord(raw)) {
190
+ return undefined;
191
+ }
192
+ const slug = raw['slug'];
193
+ const inherited = raw['inherited'];
194
+ if (typeof slug !== 'string' || !isArray(inherited)) {
195
+ return undefined;
196
+ }
197
+ return inherited.every((operation) => typeof operation === 'string')
198
+ ? { slug, inherited: inherited.map((operation) => asText(operation)) }
199
+ : undefined;
200
+ };
201
+ const asEntries = (raw) => {
202
+ if (!isArray(raw)) {
203
+ return undefined;
204
+ }
205
+ const entries = raw.map((entry) => asEntry(entry));
206
+ return entries.every((entry) => entry !== undefined)
207
+ ? entries
208
+ : undefined;
209
+ };
210
+ const asAnonymousRead = (raw) => {
211
+ const kind = readKey(raw, 'kind');
212
+ if (kind === 'denied') {
213
+ return { kind };
214
+ }
215
+ if (kind === 'open') {
216
+ return { kind };
217
+ }
218
+ if (kind === 'filtered') {
219
+ return { kind, where: readKey(raw, 'where') };
220
+ }
221
+ return kind === 'undecidable' ? { kind, reason: asText(readKey(raw, 'reason')) } : undefined;
222
+ };
223
+ const asDraftRead = (raw) => {
224
+ const slug = readKey(raw, 'slug');
225
+ const kind = readKey(raw, 'kind');
226
+ const anonymousRead = asAnonymousRead(readKey(raw, 'anonymousRead'));
227
+ if (typeof slug !== 'string' || anonymousRead === undefined) {
228
+ return undefined;
229
+ }
230
+ return kind === 'collection' || kind === 'global' ? { kind, slug, anonymousRead } : undefined;
231
+ };
232
+ const asDraftReads = (raw) => {
233
+ if (!isArray(raw)) {
234
+ return undefined;
235
+ }
236
+ const entries = raw.map((entry) => asDraftRead(entry));
237
+ return entries.every((entry) => entry !== undefined)
238
+ ? entries
239
+ : undefined;
240
+ };
241
+ const parseJson = (text) => {
242
+ try {
243
+ return JSON.parse(text);
244
+ }
245
+ catch {
246
+ return undefined;
247
+ }
248
+ };
249
+ /**
250
+ * Read the probe's report out of everything the probe wrote to standard output.
251
+ *
252
+ * The LAST marker line is the report, so a plugin that logs during import cannot hide it, and a report
253
+ * that fails to parse or has the wrong shape is undefined rather than empty: a probe that printed a
254
+ * stack trace must fail the gate, never pass it as "no findings".
255
+ * @param text the probe's standard output.
256
+ * @returns the report, or undefined when no well-formed report was printed.
257
+ */
258
+ export const parseInheritedAccessReport = (text) => {
259
+ const line = text
260
+ .split('\n')
261
+ .map((candidate) => candidate.trim())
262
+ .findLast((candidate) => candidate.startsWith(INHERITED_ACCESS_REPORT_MARKER));
263
+ if (line === undefined) {
264
+ return undefined;
265
+ }
266
+ const parsed = parseJson(line.slice(INHERITED_ACCESS_REPORT_MARKER.length));
267
+ const collections = asEntries(readKey(parsed, 'collections'));
268
+ const globals = asEntries(readKey(parsed, 'globals'));
269
+ const draftReads = asDraftReads(readKey(parsed, 'draftReads'));
270
+ if (collections === undefined || globals === undefined || draftReads === undefined) {
271
+ return undefined;
272
+ }
273
+ return { collections, draftReads, globals };
274
+ };
275
+ /** Where a Payload member keeps its configuration when its tsconfig says nothing else. */
276
+ export const DEFAULT_PAYLOAD_CONFIG_PATH = 'src/payload.config.ts';
277
+ const CURRENT_DIRECTORY_PREFIX = './';
278
+ /**
279
+ * The path of the Payload configuration a member's tsconfig aliases as `@payload-config`, which is the
280
+ * alias `ploaness init` writes and Payload's own CLI resolves through.
281
+ * @param tsconfig the parsed tsconfig, or anything when it could not be read.
282
+ * @returns the configured path relative to the member root, or the default path.
283
+ */
284
+ export const payloadConfigPathOf = (tsconfig) => {
285
+ const paths = asRecord(readKey(readKey(tsconfig, 'compilerOptions'), 'paths'));
286
+ const alias = paths['@payload-config'];
287
+ const first = isArray(alias) ? alias[0] : undefined;
288
+ if (typeof first !== 'string' || first.length === 0) {
289
+ return DEFAULT_PAYLOAD_CONFIG_PATH;
290
+ }
291
+ return first.startsWith(CURRENT_DIRECTORY_PREFIX)
292
+ ? first.slice(CURRENT_DIRECTORY_PREFIX.length)
293
+ : first;
294
+ };
295
+ //# sourceMappingURL=payload-defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-defaults.js","sourceRoot":"","sources":["../src/payload-defaults.ts"],"names":[],"mappings":"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"}
@@ -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"}
@@ -15,4 +15,17 @@ export declare const findSourceViolations: (source: string) => readonly PayloadV
15
15
  * @returns one violation per offending line.
16
16
  */
17
17
  export declare const findPayloadViolations: (source: string) => readonly PayloadViolation[];
18
+ /**
19
+ * The access decision a route handler has to state rather than inherit.
20
+ *
21
+ * The two rules that already read `overrideAccess` judge a value that is written down: one bans `true`,
22
+ * the other requires `false` beside a `user`. Neither can see an absent property, and absent is the
23
+ * dangerous spelling - Payload defaults `overrideAccess` to `true`, so the call that says nothing is
24
+ * the call that runs as an administrator. Under `src/endpoints` the omission is therefore the
25
+ * violation, which is why this rule reads the path and the others do not.
26
+ * @param filePath the repository-relative path of the file, which decides whether the rule applies.
27
+ * @param source the file's text.
28
+ * @returns one violation per Local API call that leaves the decision to the default.
29
+ */
30
+ export declare const findEndpointViolations: (filePath: string, source: string) => readonly PayloadViolation[];
18
31
  //# sourceMappingURL=payload-policy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"payload-policy.d.ts","sourceRoot":"","sources":["../src/payload-policy.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AA6H3D;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,KAAG,SAAS,gBAAgB,EAC/B,CAAA;AAEhD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,KAAG,SAAS,gBAAgB,EAY/E,CAAA"}
1
+ {"version":3,"file":"payload-policy.d.ts","sourceRoot":"","sources":["../src/payload-policy.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAqT3D;;;;;;;;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,EAmB/E,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,GACjC,UAAU,MAAM,EAChB,QAAQ,MAAM,KACb,SAAS,gBAAgB,EAiB3B,CAAA"}