@ploaness/governance 1.0.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/LICENSE +21 -0
- package/README.md +13 -0
- package/dist/access-boundary.d.ts +41 -0
- package/dist/access-boundary.d.ts.map +1 -0
- package/dist/access-boundary.js +26 -0
- package/dist/access-boundary.js.map +1 -0
- package/dist/agent-references.d.ts +12 -0
- package/dist/agent-references.d.ts.map +1 -0
- package/dist/agent-references.js +53 -0
- package/dist/agent-references.js.map +1 -0
- package/dist/architecture-layers.d.ts +11 -0
- package/dist/architecture-layers.d.ts.map +1 -0
- package/dist/architecture-layers.js +47 -0
- package/dist/architecture-layers.js.map +1 -0
- package/dist/asset-policy.d.ts +138 -0
- package/dist/asset-policy.d.ts.map +1 -0
- package/dist/asset-policy.js +312 -0
- package/dist/asset-policy.js.map +1 -0
- package/dist/banned-typography.d.ts +13 -0
- package/dist/banned-typography.d.ts.map +1 -0
- package/dist/banned-typography.js +78 -0
- package/dist/banned-typography.js.map +1 -0
- package/dist/bundle-budget.d.ts +16 -0
- package/dist/bundle-budget.d.ts.map +1 -0
- package/dist/bundle-budget.js +37 -0
- package/dist/bundle-budget.js.map +1 -0
- package/dist/commit-message.d.ts +37 -0
- package/dist/commit-message.d.ts.map +1 -0
- package/dist/commit-message.js +144 -0
- package/dist/commit-message.js.map +1 -0
- package/dist/config-references.d.ts +17 -0
- package/dist/config-references.d.ts.map +1 -0
- package/dist/config-references.js +54 -0
- package/dist/config-references.js.map +1 -0
- package/dist/container-failure.d.ts +40 -0
- package/dist/container-failure.d.ts.map +1 -0
- package/dist/container-failure.js +154 -0
- package/dist/container-failure.js.map +1 -0
- package/dist/container-files.d.ts +36 -0
- package/dist/container-files.d.ts.map +1 -0
- package/dist/container-files.js +74 -0
- package/dist/container-files.js.map +1 -0
- package/dist/container-freshness.d.ts +102 -0
- package/dist/container-freshness.d.ts.map +1 -0
- package/dist/container-freshness.js +129 -0
- package/dist/container-freshness.js.map +1 -0
- package/dist/dependency-freshness.d.ts +129 -0
- package/dist/dependency-freshness.d.ts.map +1 -0
- package/dist/dependency-freshness.js +161 -0
- package/dist/dependency-freshness.js.map +1 -0
- package/dist/doc-blocks.d.ts +13 -0
- package/dist/doc-blocks.d.ts.map +1 -0
- package/dist/doc-blocks.js +75 -0
- package/dist/doc-blocks.js.map +1 -0
- package/dist/document-references.d.ts +44 -0
- package/dist/document-references.d.ts.map +1 -0
- package/dist/document-references.js +94 -0
- package/dist/document-references.js.map +1 -0
- package/dist/editorconfig-policy.d.ts +24 -0
- package/dist/editorconfig-policy.d.ts.map +1 -0
- package/dist/editorconfig-policy.js +106 -0
- package/dist/editorconfig-policy.js.map +1 -0
- package/dist/environment-files.d.ts +42 -0
- package/dist/environment-files.d.ts.map +1 -0
- package/dist/environment-files.js +76 -0
- package/dist/environment-files.js.map +1 -0
- package/dist/file-roles.d.ts +39 -0
- package/dist/file-roles.d.ts.map +1 -0
- package/dist/file-roles.js +82 -0
- package/dist/file-roles.js.map +1 -0
- package/dist/generated-denial.d.ts +42 -0
- package/dist/generated-denial.d.ts.map +1 -0
- package/dist/generated-denial.js +87 -0
- package/dist/generated-denial.js.map +1 -0
- package/dist/history-policy.d.ts +32 -0
- package/dist/history-policy.d.ts.map +1 -0
- package/dist/history-policy.js +50 -0
- package/dist/history-policy.js.map +1 -0
- package/dist/image-assets.d.ts +14 -0
- package/dist/image-assets.d.ts.map +1 -0
- package/dist/image-assets.js +205 -0
- package/dist/image-assets.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/install-policy.d.ts +35 -0
- package/dist/install-policy.d.ts.map +1 -0
- package/dist/install-policy.js +61 -0
- package/dist/install-policy.js.map +1 -0
- package/dist/json-shapes.d.ts +86 -0
- package/dist/json-shapes.d.ts.map +1 -0
- package/dist/json-shapes.js +124 -0
- package/dist/json-shapes.js.map +1 -0
- package/dist/license-allowlist.d.ts +15 -0
- package/dist/license-allowlist.d.ts.map +1 -0
- package/dist/license-allowlist.js +157 -0
- package/dist/license-allowlist.js.map +1 -0
- package/dist/network-policy.d.ts +69 -0
- package/dist/network-policy.d.ts.map +1 -0
- package/dist/network-policy.js +173 -0
- package/dist/network-policy.js.map +1 -0
- package/dist/paired-assets.d.ts +34 -0
- package/dist/paired-assets.d.ts.map +1 -0
- package/dist/paired-assets.js +63 -0
- package/dist/paired-assets.js.map +1 -0
- package/dist/payload-access.d.ts +9 -0
- package/dist/payload-access.d.ts.map +1 -0
- package/dist/payload-access.js +168 -0
- package/dist/payload-access.js.map +1 -0
- package/dist/payload-policy.d.ts +18 -0
- package/dist/payload-policy.d.ts.map +1 -0
- package/dist/payload-policy.js +124 -0
- package/dist/payload-policy.js.map +1 -0
- package/dist/payload-source.d.ts +29 -0
- package/dist/payload-source.d.ts.map +1 -0
- package/dist/payload-source.js +84 -0
- package/dist/payload-source.js.map +1 -0
- package/dist/release-age.d.ts +23 -0
- package/dist/release-age.d.ts.map +1 -0
- package/dist/release-age.js +38 -0
- package/dist/release-age.js.map +1 -0
- package/dist/request-limits.d.ts +39 -0
- package/dist/request-limits.d.ts.map +1 -0
- package/dist/request-limits.js +57 -0
- package/dist/request-limits.js.map +1 -0
- package/dist/run-plan.d.ts +32 -0
- package/dist/run-plan.d.ts.map +1 -0
- package/dist/run-plan.js +43 -0
- package/dist/run-plan.js.map +1 -0
- package/dist/run-policy.d.ts +32 -0
- package/dist/run-policy.d.ts.map +1 -0
- package/dist/run-policy.js +37 -0
- package/dist/run-policy.js.map +1 -0
- package/dist/secret-policy.d.ts +13 -0
- package/dist/secret-policy.d.ts.map +1 -0
- package/dist/secret-policy.js +69 -0
- package/dist/secret-policy.js.map +1 -0
- package/dist/settings-layering.d.ts +45 -0
- package/dist/settings-layering.d.ts.map +1 -0
- package/dist/settings-layering.js +134 -0
- package/dist/settings-layering.js.map +1 -0
- package/dist/settings.d.ts +238 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +378 -0
- package/dist/settings.js.map +1 -0
- package/dist/skill-manifest.d.ts +18 -0
- package/dist/skill-manifest.d.ts.map +1 -0
- package/dist/skill-manifest.js +125 -0
- package/dist/skill-manifest.js.map +1 -0
- package/dist/source-text.d.ts +83 -0
- package/dist/source-text.d.ts.map +1 -0
- package/dist/source-text.js +310 -0
- package/dist/source-text.js.map +1 -0
- package/dist/suppression-ceiling.d.ts +48 -0
- package/dist/suppression-ceiling.d.ts.map +1 -0
- package/dist/suppression-ceiling.js +115 -0
- package/dist/suppression-ceiling.js.map +1 -0
- package/dist/tailwind-tokens.d.ts +16 -0
- package/dist/tailwind-tokens.d.ts.map +1 -0
- package/dist/tailwind-tokens.js +70 -0
- package/dist/tailwind-tokens.js.map +1 -0
- package/dist/text-escapes.d.ts +7 -0
- package/dist/text-escapes.d.ts.map +1 -0
- package/dist/text-escapes.js +14 -0
- package/dist/text-escapes.js.map +1 -0
- package/dist/toolchain-pins.d.ts +42 -0
- package/dist/toolchain-pins.d.ts.map +1 -0
- package/dist/toolchain-pins.js +99 -0
- package/dist/toolchain-pins.js.map +1 -0
- package/dist/url-safety.d.ts +12 -0
- package/dist/url-safety.d.ts.map +1 -0
- package/dist/url-safety.js +58 -0
- package/dist/url-safety.js.map +1 -0
- package/dist/version-policy.d.ts +99 -0
- package/dist/version-policy.d.ts.map +1 -0
- package/dist/version-policy.js +306 -0
- package/dist/version-policy.js.map +1 -0
- package/dist/vulnerability-policy.d.ts +66 -0
- package/dist/vulnerability-policy.d.ts.map +1 -0
- package/dist/vulnerability-policy.js +106 -0
- package/dist/vulnerability-policy.js.map +1 -0
- package/dist/wiring-policy.d.ts +226 -0
- package/dist/wiring-policy.d.ts.map +1 -0
- package/dist/wiring-policy.js +458 -0
- package/dist/wiring-policy.js.map +1 -0
- package/dist/wiring-violation.d.ts +6 -0
- package/dist/wiring-violation.d.ts.map +1 -0
- package/dist/wiring-violation.js +8 -0
- package/dist/wiring-violation.js.map +1 -0
- package/dist/workspace-policy.d.ts +177 -0
- package/dist/workspace-policy.d.ts.map +1 -0
- package/dist/workspace-policy.js +228 -0
- package/dist/workspace-policy.js.map +1 -0
- package/dist/yaml-blocks.d.ts +43 -0
- package/dist/yaml-blocks.d.ts.map +1 -0
- package/dist/yaml-blocks.js +87 -0
- package/dist/yaml-blocks.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Write denial for generated files.
|
|
2
|
+
//
|
|
3
|
+
// A generated file changes only as the output of its generator, and the regeneration check already
|
|
4
|
+
// fails on a hand edit. That check reports the damage after the fact; the denial stops the edit from
|
|
5
|
+
// being made, which is the difference between a build that fails and work that was never wasted.
|
|
6
|
+
//
|
|
7
|
+
// The standard scopes this to "where the runtime used by AI agents supports the denial", so a rule here
|
|
8
|
+
// binds one runtime and cannot bind them all. That is conformance rather than a shortfall, and the gate
|
|
9
|
+
// says so rather than implying a guarantee it does not have.
|
|
10
|
+
import { asRecord, isArray, readKey } from './json-shapes.js';
|
|
11
|
+
/** The artefacts Payload derives from the configuration. Declared once and consumed by every rule. */
|
|
12
|
+
export const GENERATED_ARTEFACTS = [
|
|
13
|
+
'src/payload-types.ts',
|
|
14
|
+
'src/app/(payload)/admin/importMap.js',
|
|
15
|
+
'src/payload-generated-schema.ts',
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* The deny rules a runtime must carry for a set of generated artefacts.
|
|
19
|
+
*
|
|
20
|
+
* The artefacts are a parameter rather than the constant above so the rule stays a statement about a
|
|
21
|
+
* SET of generated paths rather than about Payload's three. What ploaness governs is one such set; the
|
|
22
|
+
* ploaness repository denies its own regenerated asset bodies through the same shaped list, written by
|
|
23
|
+
* hand in `.claude/settings.json` because nothing here runs `ploaness sync`. Closing over the constant
|
|
24
|
+
* would have made the rule untestable against any set but that one.
|
|
25
|
+
* @param artefacts the repo-relative paths a generator owns.
|
|
26
|
+
* @returns the Edit and Write denials the runtime settings must carry.
|
|
27
|
+
*/
|
|
28
|
+
export const requiredDenyRules = (artefacts) => artefacts.flatMap((artefact) => [
|
|
29
|
+
`Edit(${artefact})`,
|
|
30
|
+
`Write(${artefact})`,
|
|
31
|
+
]);
|
|
32
|
+
const stringsAt = (settings, section, key) => {
|
|
33
|
+
const inner = readKey(readKey(settings, section), key);
|
|
34
|
+
return isArray(inner)
|
|
35
|
+
? inner.filter((entry) => typeof entry === 'string')
|
|
36
|
+
: [];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Merge the required deny rules into an existing runtime settings object.
|
|
40
|
+
* @param existing the parsed settings, or undefined when the file does not exist.
|
|
41
|
+
* @param artefacts the repo-relative paths a generator owns.
|
|
42
|
+
* @returns the settings to write, preserving every key the project owns.
|
|
43
|
+
*/
|
|
44
|
+
export const applyDenyRules = (existing, artefacts) => {
|
|
45
|
+
const base = { ...asRecord(existing) };
|
|
46
|
+
const permissions = { ...asRecord(base['permissions']) };
|
|
47
|
+
const deny = stringsAt(base, 'permissions', 'deny');
|
|
48
|
+
const merged = [
|
|
49
|
+
...deny,
|
|
50
|
+
...requiredDenyRules(artefacts).filter((rule) => !deny.includes(rule)),
|
|
51
|
+
];
|
|
52
|
+
return { ...base, permissions: { ...permissions, deny: merged } };
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Report every required denial the runtime settings do not carry, and every re-permission of one.
|
|
56
|
+
* @param settings the parsed runtime settings, or undefined when absent.
|
|
57
|
+
* @param localSettings the parsed machine-local overrides, or undefined when absent.
|
|
58
|
+
* @param artefacts the repo-relative paths a generator owns.
|
|
59
|
+
* @returns one message per missing denial or re-permitted artefact.
|
|
60
|
+
*/
|
|
61
|
+
export const findDenialViolations = (settings, localSettings, artefacts) => {
|
|
62
|
+
const required = requiredDenyRules(artefacts);
|
|
63
|
+
const deny = stringsAt(settings, 'permissions', 'deny');
|
|
64
|
+
const missing = required
|
|
65
|
+
.filter((rule) => !deny.includes(rule))
|
|
66
|
+
.map((rule) => `no write denial for ${rule}; run \`ploaness sync\` to add it`);
|
|
67
|
+
// A local override that re-permits a denied artefact undoes the denial on the one machine where it
|
|
68
|
+
// matters most, and it is untracked, so nothing else would ever report it.
|
|
69
|
+
const allowed = stringsAt(localSettings, 'permissions', 'allow');
|
|
70
|
+
const rePermitted = allowed
|
|
71
|
+
.filter((rule) => required.includes(rule))
|
|
72
|
+
.map((rule) => `local settings re-permit ${rule}, which the project denies; remove the local allow entry`);
|
|
73
|
+
return [...missing, ...rePermitted];
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* The generated paths a repository denies, across every member that has any.
|
|
77
|
+
*
|
|
78
|
+
* The runtime reads one settings file, at the repository root, while the artefacts are named relative
|
|
79
|
+
* to the member that generates them. A rule written for one member would therefore bind nothing in a
|
|
80
|
+
* workspace. For a single member at the root the union is the artefact list unchanged, which is what
|
|
81
|
+
* keeps a single-package project's settings file byte-identical.
|
|
82
|
+
* @param memberPaths the repo-relative paths of the members that own generated artefacts.
|
|
83
|
+
* @param artefacts the member-relative paths a generator owns.
|
|
84
|
+
* @returns every repo-relative path the runtime must deny, in member order.
|
|
85
|
+
*/
|
|
86
|
+
export const deniedPathsFor = (memberPaths, artefacts) => memberPaths.flatMap((memberPath) => artefacts.map((artefact) => memberPath === '.' ? artefact : `${memberPath}/${artefact}`));
|
|
87
|
+
//# sourceMappingURL=generated-denial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generated-denial.js","sourceRoot":"","sources":["../src/generated-denial.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** One commit reduced to the facts the history-shape rule needs. */
|
|
2
|
+
export interface CommitShape {
|
|
3
|
+
readonly sha: string;
|
|
4
|
+
readonly subject: string;
|
|
5
|
+
readonly parentCount: number;
|
|
6
|
+
}
|
|
7
|
+
/** A commit that breaks the linear-history rule. */
|
|
8
|
+
export interface HistoryViolation {
|
|
9
|
+
readonly sha: string;
|
|
10
|
+
readonly reason: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Return every merge commit reachable from the tip.
|
|
14
|
+
* @param commits the history, each with the number of parents git recorded.
|
|
15
|
+
* @returns one violation per merge commit; empty means the history is linear.
|
|
16
|
+
*/
|
|
17
|
+
export declare const findMergeCommits: (commits: readonly CommitShape[]) => readonly HistoryViolation[];
|
|
18
|
+
/**
|
|
19
|
+
* Report the ref namespaces a revision argument reaches.
|
|
20
|
+
* @param revision one revision argument, as passed to `git log`.
|
|
21
|
+
* @returns the namespaces it selects; empty when the argument names no namespace.
|
|
22
|
+
*/
|
|
23
|
+
export declare const namespacesReachedBy: (revision: string) => readonly string[];
|
|
24
|
+
/**
|
|
25
|
+
* Decide whether a ref namespace holds history this repository owns.
|
|
26
|
+
* @param namespace a ref namespace, slash-terminated.
|
|
27
|
+
* @returns true when a commit there is the repository's to rewrite.
|
|
28
|
+
*/
|
|
29
|
+
export declare const isOwnedNamespace: (namespace: string) => boolean;
|
|
30
|
+
/** The revisions a history gate walks: every commit this repository owns, and no other. */
|
|
31
|
+
export declare const OWNED_HISTORY_REVISIONS: readonly string[];
|
|
32
|
+
//# sourceMappingURL=history-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-policy.d.ts","sourceRoot":"","sources":["../src/history-policy.ts"],"names":[],"mappings":"AAQA,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,SAAS,WAAW,EAAE,KAAG,SAAS,gBAAgB,EAUvF,CAAA;AAqBL;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,KAAG,SAAS,MAAM,EAC9B,CAAA;AAExC;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,WAAW,MAAM,KAAG,OAA6C,CAAA;AAElG,2FAA2F;AAC3F,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAAqC,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// History-shape policy. The history is linear, so a merge commit is prohibited
|
|
2
|
+
// wherever it sits, including between two side branches: a branch takes the work of another by rebase or
|
|
3
|
+
// cherry-pick. The check counts the parents git recorded rather than reading the subject, so a commit
|
|
4
|
+
// that merely mentions merging is an ordinary commit, and rewording a merge does not hide it.
|
|
5
|
+
//
|
|
6
|
+
// The rule reaches back to the first commit and has no exception. Avoid a merge rather than plan to
|
|
7
|
+
// repair one: once it is published, only a fresh history satisfies the rule.
|
|
8
|
+
/**
|
|
9
|
+
* Return every merge commit reachable from the tip.
|
|
10
|
+
* @param commits the history, each with the number of parents git recorded.
|
|
11
|
+
* @returns one violation per merge commit; empty means the history is linear.
|
|
12
|
+
*/
|
|
13
|
+
export const findMergeCommits = (commits) => commits
|
|
14
|
+
.filter((commit) => commit.parentCount > 1)
|
|
15
|
+
.map((commit) => ({
|
|
16
|
+
sha: commit.sha,
|
|
17
|
+
reason: `merge commit with ${String(commit.parentCount)} parents ` +
|
|
18
|
+
`("${commit.subject}"); rebase or cherry-pick instead`,
|
|
19
|
+
}));
|
|
20
|
+
// Which refs a history gate may judge. `--all` was the obvious spelling and the wrong one: git defines it
|
|
21
|
+
// as every ref under `refs/` plus HEAD, so it also walks `refs/remotes/`, which mirrors branches on a
|
|
22
|
+
// server this repository cannot rewrite, and `refs/notes/`, whose commit messages git writes rather than
|
|
23
|
+
// an author. Failing there asks a project to force-push a teammate's unmerged topic branch, and a fetch
|
|
24
|
+
// restores whatever it rewrote. Narrowing loses no violation: work on such a branch reaches a local branch
|
|
25
|
+
// the moment it lands, and is judged there.
|
|
26
|
+
/** The ref namespaces a revision argument reaches, as git defines them. */
|
|
27
|
+
const NAMESPACES_BY_REVISION = {
|
|
28
|
+
'--all': ['refs/heads/', 'refs/tags/', 'refs/remotes/', 'refs/notes/'],
|
|
29
|
+
'--branches': ['refs/heads/'],
|
|
30
|
+
'--remotes': ['refs/remotes/'],
|
|
31
|
+
'--tags': ['refs/tags/'],
|
|
32
|
+
HEAD: ['refs/heads/'],
|
|
33
|
+
};
|
|
34
|
+
/** Namespaces holding history this repository cannot rewrite, or did not write. */
|
|
35
|
+
const UNOWNED_NAMESPACES = new Set(['refs/notes/', 'refs/remotes/']);
|
|
36
|
+
/**
|
|
37
|
+
* Report the ref namespaces a revision argument reaches.
|
|
38
|
+
* @param revision one revision argument, as passed to `git log`.
|
|
39
|
+
* @returns the namespaces it selects; empty when the argument names no namespace.
|
|
40
|
+
*/
|
|
41
|
+
export const namespacesReachedBy = (revision) => NAMESPACES_BY_REVISION[revision] ?? [];
|
|
42
|
+
/**
|
|
43
|
+
* Decide whether a ref namespace holds history this repository owns.
|
|
44
|
+
* @param namespace a ref namespace, slash-terminated.
|
|
45
|
+
* @returns true when a commit there is the repository's to rewrite.
|
|
46
|
+
*/
|
|
47
|
+
export const isOwnedNamespace = (namespace) => !UNOWNED_NAMESPACES.has(namespace);
|
|
48
|
+
/** The revisions a history gate walks: every commit this repository owns, and no other. */
|
|
49
|
+
export const OWNED_HISTORY_REVISIONS = ['--branches', '--tags', 'HEAD'];
|
|
50
|
+
//# sourceMappingURL=history-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-policy.js","sourceRoot":"","sources":["../src/history-policy.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,yGAAyG;AACzG,sGAAsG;AACtG,8FAA8F;AAC9F,EAAE;AACF,oGAAoG;AACpG,6EAA6E;AAe7E;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAA+B,EAA+B,EAAE,CAC/F,OAAO;KACJ,MAAM,CAAC,CAAC,MAAmB,EAAW,EAAE,CAAC,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC;KAChE,GAAG,CACF,CAAC,MAAmB,EAAoB,EAAE,CAAC,CAAC;IAC1C,GAAG,EAAE,MAAM,CAAC,GAAG;IACf,MAAM,EACJ,qBAAqB,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW;QAC1D,KAAK,MAAM,CAAC,OAAO,mCAAmC;CACzD,CAAC,CACH,CAAA;AAEL,0GAA0G;AAC1G,sGAAsG;AACtG,yGAAyG;AACzG,wGAAwG;AACxG,2GAA2G;AAC3G,4CAA4C;AAE5C,2EAA2E;AAC3E,MAAM,sBAAsB,GAAgD;IAC1E,OAAO,EAAE,CAAC,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,CAAC;IACtE,YAAY,EAAE,CAAC,aAAa,CAAC;IAC7B,WAAW,EAAE,CAAC,eAAe,CAAC;IAC9B,QAAQ,EAAE,CAAC,YAAY,CAAC;IACxB,IAAI,EAAE,CAAC,aAAa,CAAC;CACtB,CAAA;AAED,mFAAmF;AACnF,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAS,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,CAAA;AAEjG;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAgB,EAAqB,EAAE,CACzE,sBAAsB,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;AAExC;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,SAAiB,EAAW,EAAE,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;AAElG,2FAA2F;AAC3F,MAAM,CAAC,MAAM,uBAAuB,GAAsB,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** The lowercased file extensions the image-asset gate validates. */
|
|
2
|
+
export declare const SUPPORTED_IMAGE_EXTENSIONS: readonly string[];
|
|
3
|
+
/** Whether a path is an image asset this gate validates (by extension). */
|
|
4
|
+
export declare const isSupportedImagePath: (filePath: string) => boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Validate the bytes of one image, dispatched by the path's extension. Returns a human-readable reason
|
|
7
|
+
* when the image is structurally broken (corrupt, truncated, or empty), or null when it is intact. A
|
|
8
|
+
* path whose extension is not a supported image returns null (the caller filters to supported paths).
|
|
9
|
+
* @param filePath the image's path, used only to pick the validator by extension.
|
|
10
|
+
* @param bytes the raw file contents.
|
|
11
|
+
* @returns the failure reason, or null when the image is intact.
|
|
12
|
+
*/
|
|
13
|
+
export declare const validateImageBytes: (filePath: string, bytes: Uint8Array) => string | null;
|
|
14
|
+
//# sourceMappingURL=image-assets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-assets.d.ts","sourceRoot":"","sources":["../src/image-assets.ts"],"names":[],"mappings":"AA8NA,qEAAqE;AACrE,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAA4B,CAAA;AAOpF,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,GAAI,UAAU,MAAM,KAAG,OACN,CAAA;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,EAAE,OAAO,UAAU,KAAG,MAAM,GAAG,IAUjF,CAAA"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
// Image-asset integrity policy: the pure, unit-tested logic behind the repo-wide gate
|
|
2
|
+
// (`image-assets`, in packages/cli/src/checks/integrity.ts). Given the bytes of a
|
|
3
|
+
// tracked image, it reports whether the image is structurally broken - corrupt or truncated - so a
|
|
4
|
+
// committed asset that will not render cannot ship. This is the class of defect that a 200 response and
|
|
5
|
+
// a passing a11y sweep both miss: the original failure was a seeded PNG whose header parsed but whose
|
|
6
|
+
// compressed image data was truncated, so it served fine yet rendered as "Image corrupt or truncated".
|
|
7
|
+
//
|
|
8
|
+
// PNG (the format that broke, and the one the CMS stores) gets a REAL decode: its IDAT stream is fully
|
|
9
|
+
// inflated with zlib, which throws exactly on that truncation. The other formats get a structural
|
|
10
|
+
// signature-and-trailer check that catches truncation cheaply and dependency-free.
|
|
11
|
+
import { inflateSync } from 'node:zlib';
|
|
12
|
+
const LATIN1 = new TextDecoder('latin1');
|
|
13
|
+
const dataView = (bytes) => new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
14
|
+
// Read a run of bytes as a Latin-1 string (each byte maps 1:1 to a code point), for magic-number headers.
|
|
15
|
+
const asciiSlice = (bytes, start, end) => LATIN1.decode(bytes.subarray(start, end));
|
|
16
|
+
// The PNG signature, written as the byte string the format specification defines rather than as eight
|
|
17
|
+
// bare numbers: a high bit, "PNG", then a CRLF/EOF/LF run that detects a transfer which mangled line
|
|
18
|
+
// endings. Spelling it this way makes the bytes readable and leaves no unexplained number behind.
|
|
19
|
+
const PNG_SIGNATURE_BYTES = '\u{89}PNG\r\n\u{1A}\n';
|
|
20
|
+
const PNG_SIGNATURE = Array.from(PNG_SIGNATURE_BYTES, (character) => character.codePointAt(0) ?? 0);
|
|
21
|
+
const PNG_HEADER_BYTES = 8;
|
|
22
|
+
// Every chunk carries a 4-byte length, a 4-byte type, and a 4-byte CRC around its payload.
|
|
23
|
+
const CHUNK_LENGTH_BYTES = 4;
|
|
24
|
+
const CHUNK_TYPE_BYTES = 4;
|
|
25
|
+
const CHUNK_CRC_BYTES = 4;
|
|
26
|
+
const CHUNK_OVERHEAD_BYTES = CHUNK_LENGTH_BYTES + CHUNK_TYPE_BYTES + CHUNK_CRC_BYTES;
|
|
27
|
+
// The payload begins after the length and the type.
|
|
28
|
+
const CHUNK_PAYLOAD_OFFSET = CHUNK_LENGTH_BYTES + CHUNK_TYPE_BYTES;
|
|
29
|
+
const hasPngSignature = (bytes) => PNG_SIGNATURE.every((byte, index) => bytes[index] === byte);
|
|
30
|
+
// Walk the PNG chunk stream from the end of the signature, collecting IDAT payloads and stopping at
|
|
31
|
+
// IEND. Any chunk whose declared length runs past the file, or a missing IEND, means a truncated image.
|
|
32
|
+
const walkPngChunks = (bytes, view) => {
|
|
33
|
+
/* eslint-disable functional/no-let -- a PNG can carry thousands of chunks, so recursion would risk
|
|
34
|
+
the stack; the cursor and the payloads it collects escape only as the returned value */
|
|
35
|
+
let parts = [];
|
|
36
|
+
let offset = PNG_HEADER_BYTES;
|
|
37
|
+
/* eslint-enable functional/no-let -- the walk above is the only place this file mutates */
|
|
38
|
+
while (offset + CHUNK_OVERHEAD_BYTES <= bytes.length) {
|
|
39
|
+
const length = view.getUint32(offset);
|
|
40
|
+
const type = asciiSlice(bytes, offset + CHUNK_LENGTH_BYTES, offset + CHUNK_PAYLOAD_OFFSET);
|
|
41
|
+
const dataEnd = offset + CHUNK_PAYLOAD_OFFSET + length;
|
|
42
|
+
if (dataEnd + CHUNK_CRC_BYTES > bytes.length) {
|
|
43
|
+
return { parts, error: `truncated PNG (chunk "${type}" runs past end of file)` };
|
|
44
|
+
}
|
|
45
|
+
if (type === 'IDAT') {
|
|
46
|
+
parts = [...parts, bytes.subarray(offset + CHUNK_PAYLOAD_OFFSET, dataEnd)];
|
|
47
|
+
}
|
|
48
|
+
else if (type === 'IEND') {
|
|
49
|
+
return { parts, error: null };
|
|
50
|
+
}
|
|
51
|
+
offset = dataEnd + CHUNK_CRC_BYTES;
|
|
52
|
+
}
|
|
53
|
+
return { parts, error: 'truncated PNG (no IEND chunk)' };
|
|
54
|
+
};
|
|
55
|
+
const inflatePng = (parts) => {
|
|
56
|
+
try {
|
|
57
|
+
inflateSync(Buffer.concat([...parts]));
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return 'corrupt PNG (image data failed to inflate)';
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const validatePng = (bytes) => {
|
|
65
|
+
if (bytes.length < PNG_HEADER_BYTES || !hasPngSignature(bytes)) {
|
|
66
|
+
return 'not a valid PNG (bad signature)';
|
|
67
|
+
}
|
|
68
|
+
const walk = walkPngChunks(bytes, dataView(bytes));
|
|
69
|
+
if (walk.error !== null) {
|
|
70
|
+
return walk.error;
|
|
71
|
+
}
|
|
72
|
+
if (walk.parts.length === 0) {
|
|
73
|
+
return 'invalid PNG (no IDAT image data)';
|
|
74
|
+
}
|
|
75
|
+
return inflatePng(walk.parts);
|
|
76
|
+
};
|
|
77
|
+
// JPEG brackets its data with a start-of-image and an end-of-image marker, each two bytes.
|
|
78
|
+
const JPEG_MARKER_PREFIX = 0xff;
|
|
79
|
+
const JPEG_START_OF_IMAGE = 0xd8;
|
|
80
|
+
const JPEG_END_OF_IMAGE = 0xd9;
|
|
81
|
+
const JPEG_MARKER_BYTES = 2;
|
|
82
|
+
// A JPEG must carry at least its start-of-image and end-of-image markers.
|
|
83
|
+
const JPEG_MARKER_COUNT = 2;
|
|
84
|
+
const JPEG_MINIMUM_BYTES = JPEG_MARKER_BYTES * JPEG_MARKER_COUNT;
|
|
85
|
+
const SECOND_BYTE = 1;
|
|
86
|
+
const LAST_BYTE = -1;
|
|
87
|
+
const SECOND_TO_LAST_BYTE = -2;
|
|
88
|
+
const validateJpeg = (bytes) => {
|
|
89
|
+
if (bytes.length < JPEG_MINIMUM_BYTES ||
|
|
90
|
+
bytes[0] !== JPEG_MARKER_PREFIX ||
|
|
91
|
+
bytes[SECOND_BYTE] !== JPEG_START_OF_IMAGE) {
|
|
92
|
+
return 'not a valid JPEG (bad SOI marker)';
|
|
93
|
+
}
|
|
94
|
+
if (bytes.at(SECOND_TO_LAST_BYTE) !== JPEG_MARKER_PREFIX ||
|
|
95
|
+
bytes.at(LAST_BYTE) !== JPEG_END_OF_IMAGE) {
|
|
96
|
+
return 'truncated JPEG (missing EOI marker)';
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
};
|
|
100
|
+
const GIF_HEADER_BYTES = 6;
|
|
101
|
+
const GIF_TRAILER = 0x3b;
|
|
102
|
+
const validateGif = (bytes) => {
|
|
103
|
+
const header = asciiSlice(bytes, 0, GIF_HEADER_BYTES);
|
|
104
|
+
if (header !== 'GIF87a' && header !== 'GIF89a') {
|
|
105
|
+
return 'not a valid GIF (bad header)';
|
|
106
|
+
}
|
|
107
|
+
if (bytes.at(LAST_BYTE) !== GIF_TRAILER) {
|
|
108
|
+
return 'truncated GIF (missing trailer byte)';
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
};
|
|
112
|
+
// A WebP file is a RIFF container: the tag, a 32-bit size, then the form type.
|
|
113
|
+
const RIFF_TAG_BYTES = 4;
|
|
114
|
+
const RIFF_SIZE_OFFSET = RIFF_TAG_BYTES;
|
|
115
|
+
const RIFF_FORM_OFFSET = 8;
|
|
116
|
+
const WEBP_HEADER_BYTES = 12;
|
|
117
|
+
// The declared size counts everything after the tag and the size field itself.
|
|
118
|
+
const RIFF_SIZE_EXCLUDES_BYTES = 8;
|
|
119
|
+
const validateWebp = (bytes) => {
|
|
120
|
+
if (bytes.length < WEBP_HEADER_BYTES ||
|
|
121
|
+
asciiSlice(bytes, 0, RIFF_TAG_BYTES) !== 'RIFF' ||
|
|
122
|
+
asciiSlice(bytes, RIFF_FORM_OFFSET, WEBP_HEADER_BYTES) !== 'WEBP') {
|
|
123
|
+
return 'not a valid WebP (bad RIFF/WEBP header)';
|
|
124
|
+
}
|
|
125
|
+
const declaredLength = dataView(bytes).getUint32(RIFF_SIZE_OFFSET, true) + RIFF_SIZE_EXCLUDES_BYTES;
|
|
126
|
+
if (declaredLength > bytes.length) {
|
|
127
|
+
return 'truncated WebP (RIFF size exceeds file length)';
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
};
|
|
131
|
+
const ICO_HEADER_BYTES = 6;
|
|
132
|
+
const ICO_DIR_ENTRY_BYTES = 16;
|
|
133
|
+
// Within a directory entry: the payload size, then the offset the payload begins at.
|
|
134
|
+
const ICO_ENTRY_SIZE_OFFSET = 8;
|
|
135
|
+
const ICO_ENTRY_DATA_OFFSET = 12;
|
|
136
|
+
// The ICO header is a zero reserved field, an image type of 1, then the entry count.
|
|
137
|
+
const ICO_RESERVED_OFFSET = 0;
|
|
138
|
+
const ICO_TYPE_OFFSET = 2;
|
|
139
|
+
const ICO_COUNT_OFFSET = 4;
|
|
140
|
+
const ICO_ICON_TYPE = 1;
|
|
141
|
+
const validateIcoEntries = (bytes, view, count) => {
|
|
142
|
+
const entryIndexes = Array.from({ length: count }, (_, at) => at);
|
|
143
|
+
for (const index of entryIndexes) {
|
|
144
|
+
const entry = ICO_HEADER_BYTES + index * ICO_DIR_ENTRY_BYTES;
|
|
145
|
+
if (entry + ICO_DIR_ENTRY_BYTES > bytes.length) {
|
|
146
|
+
return 'truncated ICO (directory runs past end of file)';
|
|
147
|
+
}
|
|
148
|
+
const imageSize = view.getUint32(entry + ICO_ENTRY_SIZE_OFFSET, true);
|
|
149
|
+
const imageOffset = view.getUint32(entry + ICO_ENTRY_DATA_OFFSET, true);
|
|
150
|
+
if (imageOffset + imageSize > bytes.length) {
|
|
151
|
+
return 'truncated ICO (image data runs past end of file)';
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
};
|
|
156
|
+
const validateIco = (bytes) => {
|
|
157
|
+
const view = dataView(bytes);
|
|
158
|
+
if (bytes.length < ICO_HEADER_BYTES ||
|
|
159
|
+
view.getUint16(ICO_RESERVED_OFFSET, true) !== 0 ||
|
|
160
|
+
view.getUint16(ICO_TYPE_OFFSET, true) !== ICO_ICON_TYPE) {
|
|
161
|
+
return 'not a valid ICO (bad header)';
|
|
162
|
+
}
|
|
163
|
+
const count = view.getUint16(ICO_COUNT_OFFSET, true);
|
|
164
|
+
if (count === 0) {
|
|
165
|
+
return 'invalid ICO (no image entries)';
|
|
166
|
+
}
|
|
167
|
+
return validateIcoEntries(bytes, view, count);
|
|
168
|
+
};
|
|
169
|
+
// The image extensions this gate understands, each mapped to its byte validator. A tracked file with any
|
|
170
|
+
// other extension is not an image this gate checks.
|
|
171
|
+
const VALIDATORS = {
|
|
172
|
+
png: validatePng,
|
|
173
|
+
jpg: validateJpeg,
|
|
174
|
+
jpeg: validateJpeg,
|
|
175
|
+
gif: validateGif,
|
|
176
|
+
webp: validateWebp,
|
|
177
|
+
ico: validateIco,
|
|
178
|
+
};
|
|
179
|
+
/** The lowercased file extensions the image-asset gate validates. */
|
|
180
|
+
export const SUPPORTED_IMAGE_EXTENSIONS = Object.keys(VALIDATORS);
|
|
181
|
+
const extensionOf = (filePath) => {
|
|
182
|
+
const lastDot = filePath.lastIndexOf('.');
|
|
183
|
+
return lastDot === -1 ? '' : filePath.slice(lastDot + 1).toLowerCase();
|
|
184
|
+
};
|
|
185
|
+
/** Whether a path is an image asset this gate validates (by extension). */
|
|
186
|
+
export const isSupportedImagePath = (filePath) => Object.hasOwn(VALIDATORS, extensionOf(filePath));
|
|
187
|
+
/**
|
|
188
|
+
* Validate the bytes of one image, dispatched by the path's extension. Returns a human-readable reason
|
|
189
|
+
* when the image is structurally broken (corrupt, truncated, or empty), or null when it is intact. A
|
|
190
|
+
* path whose extension is not a supported image returns null (the caller filters to supported paths).
|
|
191
|
+
* @param filePath the image's path, used only to pick the validator by extension.
|
|
192
|
+
* @param bytes the raw file contents.
|
|
193
|
+
* @returns the failure reason, or null when the image is intact.
|
|
194
|
+
*/
|
|
195
|
+
export const validateImageBytes = (filePath, bytes) => {
|
|
196
|
+
const validator = VALIDATORS[extensionOf(filePath)];
|
|
197
|
+
if (validator === undefined) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
if (bytes.length === 0) {
|
|
201
|
+
return 'empty file';
|
|
202
|
+
}
|
|
203
|
+
return validator(bytes);
|
|
204
|
+
};
|
|
205
|
+
//# sourceMappingURL=image-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-assets.js","sourceRoot":"","sources":["../src/image-assets.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export * from './access-boundary.js';
|
|
2
|
+
export * from './agent-references.js';
|
|
3
|
+
export * from './architecture-layers.js';
|
|
4
|
+
export * from './asset-policy.js';
|
|
5
|
+
export * from './banned-typography.js';
|
|
6
|
+
export * from './bundle-budget.js';
|
|
7
|
+
export * from './commit-message.js';
|
|
8
|
+
export * from './config-references.js';
|
|
9
|
+
export * from './container-failure.js';
|
|
10
|
+
export * from './container-files.js';
|
|
11
|
+
export * from './container-freshness.js';
|
|
12
|
+
export * from './dependency-freshness.js';
|
|
13
|
+
export * from './doc-blocks.js';
|
|
14
|
+
export * from './document-references.js';
|
|
15
|
+
export * from './editorconfig-policy.js';
|
|
16
|
+
export * from './environment-files.js';
|
|
17
|
+
export * from './file-roles.js';
|
|
18
|
+
export * from './generated-denial.js';
|
|
19
|
+
export * from './history-policy.js';
|
|
20
|
+
export * from './image-assets.js';
|
|
21
|
+
export * from './install-policy.js';
|
|
22
|
+
export * from './json-shapes.js';
|
|
23
|
+
export * from './license-allowlist.js';
|
|
24
|
+
export * from './network-policy.js';
|
|
25
|
+
export * from './paired-assets.js';
|
|
26
|
+
export * from './payload-access.js';
|
|
27
|
+
export * from './payload-policy.js';
|
|
28
|
+
export * from './payload-source.js';
|
|
29
|
+
export * from './release-age.js';
|
|
30
|
+
export * from './request-limits.js';
|
|
31
|
+
export * from './run-plan.js';
|
|
32
|
+
export * from './run-policy.js';
|
|
33
|
+
export * from './secret-policy.js';
|
|
34
|
+
export * from './settings.js';
|
|
35
|
+
export * from './settings-layering.js';
|
|
36
|
+
export * from './skill-manifest.js';
|
|
37
|
+
export * from './source-text.js';
|
|
38
|
+
export * from './suppression-ceiling.js';
|
|
39
|
+
export * from './tailwind-tokens.js';
|
|
40
|
+
export * from './text-escapes.js';
|
|
41
|
+
export * from './toolchain-pins.js';
|
|
42
|
+
export * from './url-safety.js';
|
|
43
|
+
export * from './version-policy.js';
|
|
44
|
+
export * from './vulnerability-policy.js';
|
|
45
|
+
export * from './wiring-policy.js';
|
|
46
|
+
export * from './wiring-violation.js';
|
|
47
|
+
export * from './workspace-policy.js';
|
|
48
|
+
export * from './yaml-blocks.js';
|
|
49
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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,iBAAiB,CAAA;AAC/B,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
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Public surface of the ploaness governance layer: the pure, unit-tested rules, free of filesystem,
|
|
2
|
+
// process, and network access. Every gate in the CLI is a thin I/O shell around a function exported
|
|
3
|
+
// here. The split is what makes the rules cheap to test exhaustively: a pure function over strings
|
|
4
|
+
// needs no fixture repository to exercise its edge cases.
|
|
5
|
+
export * from './access-boundary.js';
|
|
6
|
+
export * from './agent-references.js';
|
|
7
|
+
export * from './architecture-layers.js';
|
|
8
|
+
export * from './asset-policy.js';
|
|
9
|
+
export * from './banned-typography.js';
|
|
10
|
+
export * from './bundle-budget.js';
|
|
11
|
+
export * from './commit-message.js';
|
|
12
|
+
export * from './config-references.js';
|
|
13
|
+
export * from './container-failure.js';
|
|
14
|
+
export * from './container-files.js';
|
|
15
|
+
export * from './container-freshness.js';
|
|
16
|
+
export * from './dependency-freshness.js';
|
|
17
|
+
export * from './doc-blocks.js';
|
|
18
|
+
export * from './document-references.js';
|
|
19
|
+
export * from './editorconfig-policy.js';
|
|
20
|
+
export * from './environment-files.js';
|
|
21
|
+
export * from './file-roles.js';
|
|
22
|
+
export * from './generated-denial.js';
|
|
23
|
+
export * from './history-policy.js';
|
|
24
|
+
export * from './image-assets.js';
|
|
25
|
+
export * from './install-policy.js';
|
|
26
|
+
export * from './json-shapes.js';
|
|
27
|
+
export * from './license-allowlist.js';
|
|
28
|
+
export * from './network-policy.js';
|
|
29
|
+
export * from './paired-assets.js';
|
|
30
|
+
export * from './payload-access.js';
|
|
31
|
+
export * from './payload-policy.js';
|
|
32
|
+
export * from './payload-source.js';
|
|
33
|
+
export * from './release-age.js';
|
|
34
|
+
export * from './request-limits.js';
|
|
35
|
+
export * from './run-plan.js';
|
|
36
|
+
export * from './run-policy.js';
|
|
37
|
+
export * from './secret-policy.js';
|
|
38
|
+
export * from './settings.js';
|
|
39
|
+
export * from './settings-layering.js';
|
|
40
|
+
export * from './skill-manifest.js';
|
|
41
|
+
export * from './source-text.js';
|
|
42
|
+
export * from './suppression-ceiling.js';
|
|
43
|
+
export * from './tailwind-tokens.js';
|
|
44
|
+
export * from './text-escapes.js';
|
|
45
|
+
export * from './toolchain-pins.js';
|
|
46
|
+
export * from './url-safety.js';
|
|
47
|
+
export * from './version-policy.js';
|
|
48
|
+
export * from './vulnerability-policy.js';
|
|
49
|
+
export * from './wiring-policy.js';
|
|
50
|
+
export * from './wiring-violation.js';
|
|
51
|
+
export * from './workspace-policy.js';
|
|
52
|
+
export * from './yaml-blocks.js';
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AACzC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The install-config keys that can redefine a resolved version.
|
|
3
|
+
*
|
|
4
|
+
* Exported because `version-policy.ts` reads the same four keys out of package.json, where they are an
|
|
5
|
+
* escape from a pin rather than a workspace-wide one. It carried its own copy of this list, in a module
|
|
6
|
+
* that already imports this one - two arrays that had to stay equal, in the same gate.
|
|
7
|
+
*/
|
|
8
|
+
export declare const OVERRIDE_KEYS: readonly string[];
|
|
9
|
+
/** A dependency whose resolved version a project has redefined. */
|
|
10
|
+
export interface OverrideEntry {
|
|
11
|
+
readonly key: string;
|
|
12
|
+
readonly packageName: string;
|
|
13
|
+
/** What the override resolves to, which decides whether it redefines a version or an artefact. */
|
|
14
|
+
readonly specifier: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Read the package names whose resolved version an install config redefines.
|
|
18
|
+
* @param workspaceFile the contents of pnpm-workspace.yaml, or an empty string when absent.
|
|
19
|
+
* @returns one entry per redefined package, naming the block it came from.
|
|
20
|
+
*/
|
|
21
|
+
export declare const findOverrides: (workspaceFile: string) => readonly OverrideEntry[];
|
|
22
|
+
/**
|
|
23
|
+
* Decide whether an install config names the dependencies allowed to run an install script.
|
|
24
|
+
* @param workspaceFile the contents of pnpm-workspace.yaml, or an empty string when absent.
|
|
25
|
+
* @param packageJson the parsed package.json, where pnpm also accepts the key.
|
|
26
|
+
* @returns true when the allowlist is declared in either place.
|
|
27
|
+
*/
|
|
28
|
+
export declare const declaresInstallScriptAllowlist: (workspaceFile: string, packageJson: unknown) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Report an audit configuration that would silence the vulnerability gate.
|
|
31
|
+
* @param packageJson the parsed package.json.
|
|
32
|
+
* @returns one message per silencing key found.
|
|
33
|
+
*/
|
|
34
|
+
export declare const findSilencedAdvisories: (packageJson: unknown) => readonly string[];
|
|
35
|
+
//# sourceMappingURL=install-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-policy.d.ts","sourceRoot":"","sources":["../src/install-policy.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAK1C,CAAA;AAQD,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,kGAAkG;IAClG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,eAAe,MAAM,KAAG,SAAS,aAAa,EASzE,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GACzC,eAAe,MAAM,EACrB,aAAa,OAAO,KACnB,OAKF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,aAAa,OAAO,KAAG,SAAS,MAAM,EAG5E,CAAA"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Install-time configuration: the surface a project can use to undo what the harness pinned.
|
|
2
|
+
//
|
|
3
|
+
// A pinned version is only a pin while nothing else can change it. `checkTestLibraries` requires an
|
|
4
|
+
// exact version in package.json, but an `overrides` entry installs a different one and leaves that
|
|
5
|
+
// declaration untouched - so the gate passes while the code runs against a version ploaness never saw.
|
|
6
|
+
// The same shape of escape silences the vulnerability gate through `pnpm.auditConfig`.
|
|
7
|
+
//
|
|
8
|
+
// The reader lives in `yaml-blocks.ts`. It is deliberately small and not a YAML parser: it looks for the
|
|
9
|
+
// block keys pnpm reads at the top level of a workspace file, which is where they must appear to take
|
|
10
|
+
// effect.
|
|
11
|
+
import { readKey } from './json-shapes.js';
|
|
12
|
+
import { declaresTopLevelKey, topLevelMappingEntries } from './yaml-blocks.js';
|
|
13
|
+
/**
|
|
14
|
+
* The install-config keys that can redefine a resolved version.
|
|
15
|
+
*
|
|
16
|
+
* Exported because `version-policy.ts` reads the same four keys out of package.json, where they are an
|
|
17
|
+
* escape from a pin rather than a workspace-wide one. It carried its own copy of this list, in a module
|
|
18
|
+
* that already imports this one - two arrays that had to stay equal, in the same gate.
|
|
19
|
+
*/
|
|
20
|
+
export const OVERRIDE_KEYS = [
|
|
21
|
+
'overrides',
|
|
22
|
+
'resolutions',
|
|
23
|
+
'patchedDependencies',
|
|
24
|
+
'packageExtensions',
|
|
25
|
+
];
|
|
26
|
+
/** The key naming the dependencies permitted to run an install script. */
|
|
27
|
+
const ALLOWLIST_KEY = 'onlyBuiltDependencies';
|
|
28
|
+
/** The `pnpm.auditConfig` keys that drop an advisory the vulnerability gate would otherwise report. */
|
|
29
|
+
const SILENCING_KEYS = ['ignoreCves', 'ignoreGhsas'];
|
|
30
|
+
/**
|
|
31
|
+
* Read the package names whose resolved version an install config redefines.
|
|
32
|
+
* @param workspaceFile the contents of pnpm-workspace.yaml, or an empty string when absent.
|
|
33
|
+
* @returns one entry per redefined package, naming the block it came from.
|
|
34
|
+
*/
|
|
35
|
+
export const findOverrides = (workspaceFile) => OVERRIDE_KEYS.flatMap((key) => topLevelMappingEntries(workspaceFile, key).map(([packageName, specifier]) => ({
|
|
36
|
+
key,
|
|
37
|
+
packageName,
|
|
38
|
+
specifier,
|
|
39
|
+
})));
|
|
40
|
+
/**
|
|
41
|
+
* Decide whether an install config names the dependencies allowed to run an install script.
|
|
42
|
+
* @param workspaceFile the contents of pnpm-workspace.yaml, or an empty string when absent.
|
|
43
|
+
* @param packageJson the parsed package.json, where pnpm also accepts the key.
|
|
44
|
+
* @returns true when the allowlist is declared in either place.
|
|
45
|
+
*/
|
|
46
|
+
export const declaresInstallScriptAllowlist = (workspaceFile, packageJson) => {
|
|
47
|
+
if (declaresTopLevelKey(workspaceFile, ALLOWLIST_KEY)) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return Array.isArray(readKey(readKey(packageJson, 'pnpm'), ALLOWLIST_KEY));
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Report an audit configuration that would silence the vulnerability gate.
|
|
54
|
+
* @param packageJson the parsed package.json.
|
|
55
|
+
* @returns one message per silencing key found.
|
|
56
|
+
*/
|
|
57
|
+
export const findSilencedAdvisories = (packageJson) => {
|
|
58
|
+
const auditConfig = readKey(readKey(packageJson, 'pnpm'), 'auditConfig');
|
|
59
|
+
return SILENCING_KEYS.filter((key) => Array.isArray(readKey(auditConfig, key)));
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=install-policy.js.map
|