@clossys/launcher 0.3.1 → 0.5.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/README.md +1373 -60
- package/contracts/conversation-contract.md +2 -2
- package/contracts/product-ci-workflow.yml +74 -0
- package/contracts/repository-inventory.json +53 -0
- package/dist/admission-fixture.d.ts +168 -0
- package/dist/admission-fixture.d.ts.map +1 -0
- package/dist/admission-fixture.js +467 -0
- package/dist/admission-fixture.js.map +1 -0
- package/dist/admission.d.ts +124 -0
- package/dist/admission.d.ts.map +1 -0
- package/dist/admission.js +804 -0
- package/dist/admission.js.map +1 -0
- package/dist/agents-guide.d.ts +9 -0
- package/dist/agents-guide.d.ts.map +1 -0
- package/dist/agents-guide.js +26 -0
- package/dist/agents-guide.js.map +1 -0
- package/dist/apply-command-options.check.d.ts +12 -0
- package/dist/apply-command-options.check.d.ts.map +1 -0
- package/dist/apply-command-options.check.js +20 -0
- package/dist/apply-command-options.check.js.map +1 -0
- package/dist/apply-plan-cli.d.ts +39 -1
- package/dist/apply-plan-cli.d.ts.map +1 -1
- package/dist/apply-plan-cli.js +432 -15
- package/dist/apply-plan-cli.js.map +1 -1
- package/dist/apply-plan.d.ts +46 -59
- package/dist/apply-plan.d.ts.map +1 -1
- package/dist/apply-plan.js +112 -97
- package/dist/apply-plan.js.map +1 -1
- package/dist/apply-step-fixture.d.ts +87 -0
- package/dist/apply-step-fixture.d.ts.map +1 -0
- package/dist/apply-step-fixture.js +199 -0
- package/dist/apply-step-fixture.js.map +1 -0
- package/dist/apply-store.d.ts +93 -0
- package/dist/apply-store.d.ts.map +1 -0
- package/dist/apply-store.js +625 -0
- package/dist/apply-store.js.map +1 -0
- package/dist/approval-sheet.d.ts +21 -0
- package/dist/approval-sheet.d.ts.map +1 -0
- package/dist/approval-sheet.js +163 -0
- package/dist/approval-sheet.js.map +1 -0
- package/dist/body-command.d.ts +42 -0
- package/dist/body-command.d.ts.map +1 -0
- package/dist/body-command.js +143 -0
- package/dist/body-command.js.map +1 -0
- package/dist/change-set-contract.d.ts +403 -0
- package/dist/change-set-contract.d.ts.map +1 -0
- package/dist/change-set-contract.js +781 -0
- package/dist/change-set-contract.js.map +1 -0
- package/dist/change-set-digest.d.ts +28 -0
- package/dist/change-set-digest.d.ts.map +1 -0
- package/dist/change-set-digest.js +65 -0
- package/dist/change-set-digest.js.map +1 -0
- package/dist/check-cli.d.ts.map +1 -1
- package/dist/check-cli.js +14 -3
- package/dist/check-cli.js.map +1 -1
- package/dist/cli.d.ts +17 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +84 -23
- package/dist/cli.js.map +1 -1
- package/dist/core.d.ts +79 -22
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +843 -268
- package/dist/core.js.map +1 -1
- package/dist/dry-materialize.d.ts +63 -0
- package/dist/dry-materialize.d.ts.map +1 -0
- package/dist/dry-materialize.js +330 -0
- package/dist/dry-materialize.js.map +1 -0
- package/dist/existing-declaration-adoption.check.d.ts +2 -0
- package/dist/existing-declaration-adoption.check.d.ts.map +1 -0
- package/dist/existing-declaration-adoption.check.js +10 -0
- package/dist/existing-declaration-adoption.check.js.map +1 -0
- package/dist/generated/contract-schema.generated.d.ts +97 -0
- package/dist/generated/contract-schema.generated.d.ts.map +1 -0
- package/dist/generated/contract-schema.generated.js +496 -0
- package/dist/generated/contract-schema.generated.js.map +1 -0
- package/dist/generated/package-scope.generated.d.ts +6 -0
- package/dist/generated/package-scope.generated.d.ts.map +1 -0
- package/dist/generated/package-scope.generated.js +10 -0
- package/dist/generated/package-scope.generated.js.map +1 -0
- package/dist/generated/plan-contracts.generated.d.ts +3 -0
- package/dist/generated/plan-contracts.generated.d.ts.map +1 -0
- package/dist/generated/plan-contracts.generated.js +3101 -0
- package/dist/generated/plan-contracts.generated.js.map +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +11 -0
- package/dist/host.js.map +1 -1
- package/dist/identity.d.ts +15 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +48 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +35 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/inventory-adoption.d.ts +24 -5
- package/dist/inventory-adoption.d.ts.map +1 -1
- package/dist/inventory-adoption.js +70 -25
- package/dist/inventory-adoption.js.map +1 -1
- package/dist/inventory-choice.d.ts +40 -0
- package/dist/inventory-choice.d.ts.map +1 -0
- package/dist/inventory-choice.js +156 -0
- package/dist/inventory-choice.js.map +1 -0
- package/dist/inventory-contract.d.ts +89 -0
- package/dist/inventory-contract.d.ts.map +1 -0
- package/dist/inventory-contract.js +121 -0
- package/dist/inventory-contract.js.map +1 -0
- package/dist/key-editor.d.ts +30 -0
- package/dist/key-editor.d.ts.map +1 -0
- package/dist/key-editor.js +445 -0
- package/dist/key-editor.js.map +1 -0
- package/dist/ledger-contract.d.ts +190 -0
- package/dist/ledger-contract.d.ts.map +1 -0
- package/dist/ledger-contract.js +555 -0
- package/dist/ledger-contract.js.map +1 -0
- package/dist/ledger-trust.d.ts +90 -0
- package/dist/ledger-trust.d.ts.map +1 -0
- package/dist/ledger-trust.js +203 -0
- package/dist/ledger-trust.js.map +1 -0
- package/dist/lockfile-invariants.d.ts +48 -0
- package/dist/lockfile-invariants.d.ts.map +1 -0
- package/dist/lockfile-invariants.js +375 -0
- package/dist/lockfile-invariants.js.map +1 -0
- package/dist/lockfile-readers.d.ts +72 -0
- package/dist/lockfile-readers.d.ts.map +1 -0
- package/dist/lockfile-readers.js +713 -0
- package/dist/lockfile-readers.js.map +1 -0
- package/dist/lockfile-regen.d.ts +106 -0
- package/dist/lockfile-regen.d.ts.map +1 -0
- package/dist/lockfile-regen.js +760 -0
- package/dist/lockfile-regen.js.map +1 -0
- package/dist/lockfile-tool-env.d.ts +29 -0
- package/dist/lockfile-tool-env.d.ts.map +1 -0
- package/dist/lockfile-tool-env.js +111 -0
- package/dist/lockfile-tool-env.js.map +1 -0
- package/dist/materialize.d.ts +113 -0
- package/dist/materialize.d.ts.map +1 -0
- package/dist/materialize.js +881 -0
- package/dist/materialize.js.map +1 -0
- package/dist/observe-repository.d.ts +90 -0
- package/dist/observe-repository.d.ts.map +1 -0
- package/dist/observe-repository.js +1367 -0
- package/dist/observe-repository.js.map +1 -0
- package/dist/plan-bundle-setup-fixture.d.ts +68 -0
- package/dist/plan-bundle-setup-fixture.d.ts.map +1 -0
- package/dist/plan-bundle-setup-fixture.js +167 -0
- package/dist/plan-bundle-setup-fixture.js.map +1 -0
- package/dist/plan-bundle.d.ts +256 -0
- package/dist/plan-bundle.d.ts.map +1 -0
- package/dist/plan-bundle.js +882 -0
- package/dist/plan-bundle.js.map +1 -0
- package/dist/plan-command.d.ts +29 -0
- package/dist/plan-command.d.ts.map +1 -0
- package/dist/plan-command.js +523 -0
- package/dist/plan-command.js.map +1 -0
- package/dist/plan-contract.d.ts +153 -0
- package/dist/plan-contract.d.ts.map +1 -0
- package/dist/plan-contract.js +61 -0
- package/dist/plan-contract.js.map +1 -0
- package/dist/plan-digest.d.ts +25 -0
- package/dist/plan-digest.d.ts.map +1 -0
- package/dist/plan-digest.js +106 -0
- package/dist/plan-digest.js.map +1 -0
- package/dist/plan-rules.d.ts +23 -0
- package/dist/plan-rules.d.ts.map +1 -0
- package/dist/plan-rules.js +177 -0
- package/dist/plan-rules.js.map +1 -0
- package/dist/planned-bundle.d.ts +20 -0
- package/dist/planned-bundle.d.ts.map +1 -0
- package/dist/planned-bundle.js +191 -0
- package/dist/planned-bundle.js.map +1 -0
- package/dist/product-repository.d.ts +4 -0
- package/dist/product-repository.d.ts.map +1 -1
- package/dist/product-repository.js +9 -1
- package/dist/product-repository.js.map +1 -1
- package/dist/provenance-gate.d.ts +48 -0
- package/dist/provenance-gate.d.ts.map +1 -0
- package/dist/provenance-gate.js +324 -0
- package/dist/provenance-gate.js.map +1 -0
- package/dist/pull-request-body.d.ts +45 -0
- package/dist/pull-request-body.d.ts.map +1 -0
- package/dist/pull-request-body.js +232 -0
- package/dist/pull-request-body.js.map +1 -0
- package/dist/registry-snapshot.d.ts +141 -0
- package/dist/registry-snapshot.d.ts.map +1 -0
- package/dist/registry-snapshot.js +483 -0
- package/dist/registry-snapshot.js.map +1 -0
- package/dist/release-age-edit.d.ts +52 -0
- package/dist/release-age-edit.d.ts.map +1 -0
- package/dist/release-age-edit.js +413 -0
- package/dist/release-age-edit.js.map +1 -0
- package/dist/root-entries.d.ts +36 -0
- package/dist/root-entries.d.ts.map +1 -0
- package/dist/root-entries.js +80 -0
- package/dist/root-entries.js.map +1 -0
- package/dist/setup-template-scripts.d.ts +36 -0
- package/dist/setup-template-scripts.d.ts.map +1 -0
- package/dist/setup-template-scripts.js +568 -0
- package/dist/setup-template-scripts.js.map +1 -0
- package/dist/setup-templates.d.ts +55 -0
- package/dist/setup-templates.d.ts.map +1 -0
- package/dist/setup-templates.js +438 -0
- package/dist/setup-templates.js.map +1 -0
- package/dist/skills.d.ts +34 -1
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +129 -17
- package/dist/skills.js.map +1 -1
- package/dist/status.d.ts +63 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +539 -0
- package/dist/status.js.map +1 -0
- package/dist/types.d.ts +151 -13
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/skeleton/README.md +14 -9
- package/skeleton/package.json +2 -1
- package/skill/SKILL.md +23 -7
- package/skill-catalogue/advisor/SKILL.md +59 -6
- package/skill-catalogue/architect/SKILL.md +2 -2
- package/skill-catalogue/bouncer/SKILL.md +2 -2
- package/skill-catalogue/builder/SKILL.md +2 -2
- package/skill-catalogue/butler/SKILL.md +2 -2
- package/skill-catalogue/controller/SKILL.md +2 -2
- package/skill-catalogue/customer/SKILL.md +2 -2
- package/skill-catalogue/designer/SKILL.md +4 -2
- package/skill-catalogue/giver/SKILL.md +2 -2
- package/skill-catalogue/influencer/SKILL.md +2 -2
- package/skill-catalogue/inspector/SKILL.md +2 -2
- package/skill-catalogue/integrator/SKILL.md +2 -2
- package/skill-catalogue/keeper/SKILL.md +2 -2
- package/skill-catalogue/launcher/SKILL.md +23 -7
- package/skill-catalogue/locksmith/SKILL.md +2 -2
- package/skill-catalogue/messenger/SKILL.md +2 -2
- package/skill-catalogue/observer/SKILL.md +2 -2
- package/skill-catalogue/publisher/SKILL.md +2 -2
- package/skill-catalogue/starter/SKILL.md +3 -2
- package/skill-catalogue/strategist/SKILL.md +12 -4
- package/skill-catalogue/writer/SKILL.md +2 -2
- package/src/admission-fixture.ts +585 -0
- package/src/admission.ts +819 -0
- package/src/agents-guide.ts +29 -0
- package/src/apply-command-options.check.ts +27 -0
- package/src/apply-plan-cli.ts +454 -14
- package/src/apply-plan.ts +112 -124
- package/src/apply-step-fixture.ts +236 -0
- package/src/apply-store.ts +584 -0
- package/src/approval-sheet.ts +170 -0
- package/src/body-command.ts +162 -0
- package/src/change-set-contract.ts +987 -0
- package/src/change-set-digest.ts +70 -0
- package/src/check-cli.ts +14 -3
- package/src/cli.ts +90 -22
- package/src/core.ts +973 -275
- package/src/dry-materialize.ts +353 -0
- package/src/existing-declaration-adoption.check.ts +12 -0
- package/src/generated/contract-schema.generated.ts +520 -0
- package/src/generated/package-scope.generated.ts +10 -0
- package/src/generated/plan-contracts.generated.ts +3101 -0
- package/src/host.ts +10 -0
- package/src/identity.ts +51 -0
- package/src/index.ts +74 -3
- package/src/inventory-adoption.ts +107 -29
- package/src/inventory-choice.ts +172 -0
- package/src/inventory-contract.ts +166 -0
- package/src/key-editor.ts +446 -0
- package/src/ledger-contract.ts +660 -0
- package/src/ledger-trust.ts +272 -0
- package/src/lockfile-invariants.ts +421 -0
- package/src/lockfile-readers.ts +749 -0
- package/src/lockfile-regen.ts +851 -0
- package/src/lockfile-tool-env.ts +131 -0
- package/src/materialize.ts +915 -0
- package/src/observe-repository.ts +1365 -0
- package/src/plan-bundle-setup-fixture.ts +200 -0
- package/src/plan-bundle.ts +1014 -0
- package/src/plan-command.ts +532 -0
- package/src/plan-contract.ts +179 -0
- package/src/plan-digest.ts +102 -0
- package/src/plan-rules.ts +188 -0
- package/src/planned-bundle.ts +211 -0
- package/src/product-repository.ts +10 -1
- package/src/provenance-gate.ts +352 -0
- package/src/pull-request-body.ts +261 -0
- package/src/registry-snapshot.ts +534 -0
- package/src/release-age-edit.ts +430 -0
- package/src/root-entries.ts +81 -0
- package/src/setup-template-scripts.ts +580 -0
- package/src/setup-templates.ts +479 -0
- package/src/skills.ts +161 -18
- package/src/status.ts +557 -0
- package/src/types.ts +148 -13
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ApplyBundle, RepositoryChangeSet } from "./change-set-contract.js";
|
|
2
|
+
/** Why a sheet was not rendered. The token is the whole message. */
|
|
3
|
+
export type ApprovalSheetRefusal = "bundle-invalid" | "change-set-invalid" | "set-mismatch" | "value-unsafe";
|
|
4
|
+
export declare class ApprovalSheetError extends Error {
|
|
5
|
+
readonly token: ApprovalSheetRefusal;
|
|
6
|
+
constructor(token: ApprovalSheetRefusal);
|
|
7
|
+
}
|
|
8
|
+
export interface ApprovalSheetInput {
|
|
9
|
+
readonly bundle: ApplyBundle;
|
|
10
|
+
/** The change set of every bundle repository that has one, in any order. */
|
|
11
|
+
readonly changeSets: readonly RepositoryChangeSet[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Renders the approval sheet of `bundle`, LF-terminated. Throws an
|
|
15
|
+
* ApprovalSheetError, a fixed token that names no value, when the bundle or a
|
|
16
|
+
* set does not validate (the validators recompute each digest, so one that
|
|
17
|
+
* does not recompute is refused there), the sets are not exactly
|
|
18
|
+
* the bundle's, or any printed value fails its pattern.
|
|
19
|
+
*/
|
|
20
|
+
export declare function renderApprovalSheet(input: ApprovalSheetInput): string;
|
|
21
|
+
//# sourceMappingURL=approval-sheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-sheet.d.ts","sourceRoot":"","sources":["../src/approval-sheet.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,WAAW,EAAwC,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEvH,oEAAoE;AACpE,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG,oBAAoB,GAAG,cAAc,GAAG,cAAc,CAAC;AAE7G,qBAAa,kBAAmB,SAAQ,KAAK;IAC/B,QAAQ,CAAC,KAAK,EAAE,oBAAoB;gBAA3B,KAAK,EAAE,oBAAoB;CAIjD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACrD;AAuED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAwDrE"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// The approval sheet (issue #1178, RFC section 12.7): what a client reads
|
|
2
|
+
// before approving an apply bundle, rendered from ids and digests only. It is
|
|
3
|
+
// a pure function of a bundle and the change sets the bundle names -- it reads
|
|
4
|
+
// no file, runs no process and reads no clock -- so the same inputs always
|
|
5
|
+
// give the same bytes.
|
|
6
|
+
//
|
|
7
|
+
// The sheet never carries brief or plan prose, the `texts` a set stores, a
|
|
8
|
+
// package.json key's value, or any file's contents (V5). Every value it does
|
|
9
|
+
// print is checked against a strict pattern first, and a value that fails one,
|
|
10
|
+
// or holds one of the characters that could make a row read as something
|
|
11
|
+
// else, refuses the whole sheet. A refusal is a fixed token and echoes
|
|
12
|
+
// nothing: a bundle can come from a plan a hostile author wrote, and the
|
|
13
|
+
// sheet is read by people and agents.
|
|
14
|
+
//
|
|
15
|
+
// The sheet asks for one approval: the line `Approve subjectDigest: <bundle
|
|
16
|
+
// digest>`. It computes and records no approval; that is the plan's decision,
|
|
17
|
+
// made in the hub.
|
|
18
|
+
import { validateApplyBundle, validateRepositoryChangeSet } from "./change-set-contract.js";
|
|
19
|
+
export class ApprovalSheetError extends Error {
|
|
20
|
+
token;
|
|
21
|
+
constructor(token) {
|
|
22
|
+
super(token);
|
|
23
|
+
this.token = token;
|
|
24
|
+
this.name = "ApprovalSheetError";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const REPOSITORY = /^[A-Za-z0-9._-]{1,100}(?:\/[A-Za-z0-9._-]{1,100})?$/u;
|
|
28
|
+
const TOKEN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
29
|
+
const CHECK = /^V[1-9]$/u;
|
|
30
|
+
const DIGEST = /^sha256:[0-9a-f]{64}$/u;
|
|
31
|
+
const ITEM = /^[A-Za-z0-9._@/:~+-]{1,300}$/u;
|
|
32
|
+
const PATH = /^[A-Za-z0-9._@/~+-]{1,300}$/u;
|
|
33
|
+
const PACKAGE_NAME = /^(?:@[a-z0-9._~-]{1,100}\/)?[a-z0-9._~-]{1,100}$/u;
|
|
34
|
+
const VERSION = /^[0-9A-Za-z.+-]{1,100}$/u;
|
|
35
|
+
const DATE_TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/u;
|
|
36
|
+
const FORBIDDEN = /[<>`|\r\n]/u;
|
|
37
|
+
function safe(value, pattern) {
|
|
38
|
+
if (typeof value !== "string" || FORBIDDEN.test(value) || !pattern.test(value))
|
|
39
|
+
throw new ApprovalSheetError("value-unsafe");
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
/** The first 12 hex digits of a digest, as RFC 12.7 names the Digest column. */
|
|
43
|
+
function short(digest) {
|
|
44
|
+
return safe(digest, DIGEST).slice("sha256:".length, "sha256:".length + 12);
|
|
45
|
+
}
|
|
46
|
+
function isPackageAct(item) {
|
|
47
|
+
return item.act === "install" || item.act === "pin-starter";
|
|
48
|
+
}
|
|
49
|
+
function change(set, item) {
|
|
50
|
+
if (isPackageAct(item))
|
|
51
|
+
return `${safe(item.package.name, PACKAGE_NAME)}@${safe(item.package.version, VERSION)}`;
|
|
52
|
+
const count = set.files.filter((file) => file.item === item.id).length;
|
|
53
|
+
return `${count} ${count === 1 ? "path" : "paths"}`;
|
|
54
|
+
}
|
|
55
|
+
function yesNo(value) {
|
|
56
|
+
if (value === true)
|
|
57
|
+
return "yes";
|
|
58
|
+
if (value === false)
|
|
59
|
+
return "no";
|
|
60
|
+
throw new ApprovalSheetError("value-unsafe");
|
|
61
|
+
}
|
|
62
|
+
function row(cells) {
|
|
63
|
+
return `| ${cells.join(" | ")} |`;
|
|
64
|
+
}
|
|
65
|
+
function checkedBundle(input) {
|
|
66
|
+
const { bundle, changeSets } = input;
|
|
67
|
+
if (!validateApplyBundle(bundle).valid)
|
|
68
|
+
throw new ApprovalSheetError("bundle-invalid");
|
|
69
|
+
const sets = new Map();
|
|
70
|
+
for (const set of changeSets) {
|
|
71
|
+
if (!validateRepositoryChangeSet(set).valid)
|
|
72
|
+
throw new ApprovalSheetError("change-set-invalid");
|
|
73
|
+
if (set.bundle !== bundle.bundleDigest || set.planDigest !== bundle.plan.digest)
|
|
74
|
+
throw new ApprovalSheetError("set-mismatch");
|
|
75
|
+
if (sets.has(set.changeSetDigest))
|
|
76
|
+
throw new ApprovalSheetError("set-mismatch");
|
|
77
|
+
sets.set(set.changeSetDigest, set);
|
|
78
|
+
}
|
|
79
|
+
const held = bundle.repositories.flatMap((entry) => ("changeSet" in entry ? [{ id: entry.id, changeSetDigest: entry.changeSet }] : []));
|
|
80
|
+
// Exactly the sets the bundle names: none missing, none extra, each under its own repository.
|
|
81
|
+
if (held.length !== sets.size)
|
|
82
|
+
throw new ApprovalSheetError("set-mismatch");
|
|
83
|
+
for (const entry of held) {
|
|
84
|
+
const set = sets.get(entry.changeSetDigest);
|
|
85
|
+
if (set === undefined || set.repository.id !== entry.id)
|
|
86
|
+
throw new ApprovalSheetError("set-mismatch");
|
|
87
|
+
}
|
|
88
|
+
return { bundle, sets };
|
|
89
|
+
}
|
|
90
|
+
function repositoryRows(entry, sets) {
|
|
91
|
+
if (!("changeSet" in entry))
|
|
92
|
+
return [];
|
|
93
|
+
const set = sets.get(entry.changeSet);
|
|
94
|
+
const repository = safe(entry.id, REPOSITORY);
|
|
95
|
+
const digest = short(set.changeSetDigest);
|
|
96
|
+
return set.items.map((item) => row([repository, safe(item.act, TOKEN), safe(item.id, ITEM), change(set, item), digest]));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Renders the approval sheet of `bundle`, LF-terminated. Throws an
|
|
100
|
+
* ApprovalSheetError, a fixed token that names no value, when the bundle or a
|
|
101
|
+
* set does not validate (the validators recompute each digest, so one that
|
|
102
|
+
* does not recompute is refused there), the sets are not exactly
|
|
103
|
+
* the bundle's, or any printed value fails its pattern.
|
|
104
|
+
*/
|
|
105
|
+
export function renderApprovalSheet(input) {
|
|
106
|
+
const { bundle, sets } = checkedBundle(input);
|
|
107
|
+
const authorization = bundle.authorization === null
|
|
108
|
+
? "none"
|
|
109
|
+
: `plan ${safe(bundle.authorization.planDigest, DIGEST)} expires ${safe(bundle.authorization.expiresAt, DATE_TIME)}`;
|
|
110
|
+
const lines = [
|
|
111
|
+
"Clossys apply plan: approval sheet",
|
|
112
|
+
`Mode: ${safe(bundle.mode, TOKEN)}`,
|
|
113
|
+
`Plan digest: ${safe(bundle.plan.digest, DIGEST)}`,
|
|
114
|
+
`Plan committed: ${yesNo(bundle.plan.committed)}`,
|
|
115
|
+
`Bundle digest: ${safe(bundle.bundleDigest, DIGEST)}`,
|
|
116
|
+
`Authorization: ${authorization}`,
|
|
117
|
+
`Approve subjectDigest: ${safe(bundle.bundleDigest, DIGEST)}`,
|
|
118
|
+
"",
|
|
119
|
+
row(["Repository", "Kind", "Item", "Change", "Digest"]),
|
|
120
|
+
row(["---", "---", "---", "---", "---"]),
|
|
121
|
+
...bundle.repositories.flatMap((entry) => repositoryRows(entry, sets)),
|
|
122
|
+
];
|
|
123
|
+
const deferred = [];
|
|
124
|
+
const adoptions = [];
|
|
125
|
+
const refused = [];
|
|
126
|
+
const skipped = [];
|
|
127
|
+
const unsatisfied = [];
|
|
128
|
+
for (const entry of bundle.repositories) {
|
|
129
|
+
const id = safe(entry.id, REPOSITORY);
|
|
130
|
+
if (!("changeSet" in entry)) {
|
|
131
|
+
skipped.push(`- ${id} ${safe(entry.verdict, TOKEN)} ${safe(entry.reason, TOKEN)}`);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const set = sets.get(entry.changeSet);
|
|
135
|
+
for (const proof of set.existingDeclarationAdoptions ?? []) {
|
|
136
|
+
// The schema already closes literal syntax; never print arbitrary caller prose.
|
|
137
|
+
adoptions.push(`- ${id} ${safe(proof.desired.planItem, ITEM)} ${safe(proof.placement, TOKEN)} ${safe(proof.beforeVersion, /^[~^]?[0-9A-Za-z.+-]{1,100}$/u)} (${safe(proof.beforeResolved.version, VERSION)}, ${safe(proof.beforeResolved.integrity, /^sha512-[A-Za-z0-9+/]{86}==$/u)}) -> ${safe(proof.desired.version, VERSION)} (${safe(proof.desired.integrity, /^sha512-[A-Za-z0-9+/]{86}==$/u)}); explicit adoption consent; observed base ${safe(proof.observedBaseCommit, /^[0-9a-f]{40}([0-9a-f]{24})?$/u)}; desired snapshot ${safe(proof.desiredSnapshotDigest, DIGEST)}`);
|
|
138
|
+
}
|
|
139
|
+
for (const item of set.deferred)
|
|
140
|
+
deferred.push(`- ${id} ${safe(item.planItem, ITEM)} ${safe(item.reason, TOKEN)}`);
|
|
141
|
+
for (const item of set.refused) {
|
|
142
|
+
const where = "path" in item ? safe(item.path, PATH) : `${safe(item.file, PATH)}#${safe(item.pointer, PATH)}`;
|
|
143
|
+
refused.push(`- ${id} ${where} ${safe(item.reason, TOKEN)}`);
|
|
144
|
+
}
|
|
145
|
+
for (const check of entry.checks) {
|
|
146
|
+
if (check.verdict === "satisfied")
|
|
147
|
+
continue;
|
|
148
|
+
unsatisfied.push(`- ${id} ${safe(check.check, CHECK)} ${safe(check.verdict, TOKEN)}${check.rule === undefined ? "" : ` ${safe(check.rule, TOKEN)}`}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
for (const [title, entries] of [
|
|
152
|
+
["Deferred", deferred],
|
|
153
|
+
["Existing declaration adoption consent", adoptions],
|
|
154
|
+
["Refused", refused],
|
|
155
|
+
["Skipped", skipped],
|
|
156
|
+
["Checks not satisfied", unsatisfied],
|
|
157
|
+
]) {
|
|
158
|
+
if (entries.length > 0)
|
|
159
|
+
lines.push("", `${title}:`, ...entries);
|
|
160
|
+
}
|
|
161
|
+
return `${lines.join("\n")}\n`;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=approval-sheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-sheet.js","sourceRoot":"","sources":["../src/approval-sheet.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ReadinessRunner } from "./admission.js";
|
|
2
|
+
import type { RepositoryChangeSet } from "./change-set-contract.js";
|
|
3
|
+
/** What `body` reads: no member can carry a binding. */
|
|
4
|
+
export interface BodyInput {
|
|
5
|
+
readonly clone: string;
|
|
6
|
+
readonly hub: string;
|
|
7
|
+
readonly set: RepositoryChangeSet;
|
|
8
|
+
readonly heldChangeSets: readonly RepositoryChangeSet[];
|
|
9
|
+
/** The number of the task-record issue in the target repository. */
|
|
10
|
+
readonly taskRecord: number;
|
|
11
|
+
/** The numbers of the pull requests of older change sets this one replaces. */
|
|
12
|
+
readonly supersedes?: readonly number[];
|
|
13
|
+
readonly now?: () => Date;
|
|
14
|
+
readonly runReadiness?: ReadinessRunner;
|
|
15
|
+
}
|
|
16
|
+
export type BodyOutcome = {
|
|
17
|
+
readonly exitCode: 0;
|
|
18
|
+
readonly body: string;
|
|
19
|
+
} | {
|
|
20
|
+
readonly exitCode: 1 | 2;
|
|
21
|
+
readonly reason: string;
|
|
22
|
+
};
|
|
23
|
+
export declare class BodyUsageError extends Error {
|
|
24
|
+
}
|
|
25
|
+
export declare const BODY_USAGE = "launcher-apply-plan body --repo <id> --task-record <n> [--supersedes <n>]...";
|
|
26
|
+
export interface BodyArgs {
|
|
27
|
+
readonly help: false;
|
|
28
|
+
readonly id: string;
|
|
29
|
+
readonly taskRecord: number;
|
|
30
|
+
readonly supersedes: readonly number[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Reads `--repo`, `--task-record` and any number of `--supersedes`. A usage error carries no message: nothing the caller typed is
|
|
34
|
+
* ever echoed. A number is digits only, so a sign, an exponent, a space or a leading zero is a usage error; whether it is a
|
|
35
|
+
* positive number that is not the task record is the renderer's judgment (`supersedes-invalid`, `task-record-invalid`).
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseBodyArgs(argv: readonly string[]): {
|
|
38
|
+
help: true;
|
|
39
|
+
} | BodyArgs;
|
|
40
|
+
/** Renders, binds and returns the body; never throws. */
|
|
41
|
+
export declare function bodyRepository(input: BodyInput): Promise<BodyOutcome>;
|
|
42
|
+
//# sourceMappingURL=body-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-command.d.ts","sourceRoot":"","sources":["../src/body-command.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,KAAK,EAAmB,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAOrF,wDAAwD;AACxD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,mBAAmB,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxD,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,eAAe,CAAC;CACzC;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,qBAAa,cAAe,SAAQ,KAAK;CAAG;AAE5C,eAAO,MAAM,UAAU,iFAAiF,CAAC;AAEzG,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAYD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,QAAQ,CAkBhF;AAkBD,yDAAyD;AACzD,wBAAsB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAkD3E"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// `launcher-apply-plan body` (issue #1716, RFC apply-approved-plan section 6): the body of the pull request for one stored
|
|
2
|
+
// change set, bound by what the hub decides now, with the hash of exactly the printed bytes recorded as the set's
|
|
3
|
+
// `pullRequest.bodySha256`. An approval must bind exactly the body that is opened: any ambiguity refuses, and a refusal prints
|
|
4
|
+
// nothing on standard output and one line of fixed tokens on standard error.
|
|
5
|
+
//
|
|
6
|
+
// B1. The binding is what runPreconditions decides now, from the hub. It is never an option, an argument or a stored value; a
|
|
7
|
+
// refusal of the preconditions keeps its own token and its own exit code.
|
|
8
|
+
// B2. A stored planned bundle that lists this set holds a binding for it; that binding must be exactly B1's, else
|
|
9
|
+
// `binding-mismatch`. A bundle that is absent, not planned, or does not list the set records no binding to hold it to.
|
|
10
|
+
// B3. The body is renderPullRequest over the stored set (read again here, so what is rendered is what is stored), B1's binding,
|
|
11
|
+
// the task record and the superseded numbers: nothing else.
|
|
12
|
+
// B4. `bodySha256` is the SHA-256 of exactly the bytes printed, recorded after rendering by bindChangeSetBody, which replaces
|
|
13
|
+
// the one stored file atomically, refuses a symbolic link, and changes nothing else. Another recorded value is
|
|
14
|
+
// `body-bound`; the same value is a no-op.
|
|
15
|
+
// B5. `--supersedes` numbers are distinct positive safe integers other than the task record (the renderer refuses the rest as
|
|
16
|
+
// `supersedes-invalid`), and the set must have another stored set of its repository to replace, else `supersedes-unfounded`.
|
|
17
|
+
// B6. Every refusal is empty standard output and one standard error line naming a fixed token, never an argument, a path, an id
|
|
18
|
+
// or tool output.
|
|
19
|
+
import { createHash } from "node:crypto";
|
|
20
|
+
import { realpathSync } from "node:fs";
|
|
21
|
+
import { BodyBoundError, bindChangeSetBody, readStoredApplyBundle, readStoredChangeSet } from "./apply-store.js";
|
|
22
|
+
import { validateRepositoryChangeSet } from "./change-set-contract.js";
|
|
23
|
+
import { changeSetDigest } from "./change-set-digest.js";
|
|
24
|
+
import { runPreconditions } from "./materialize.js";
|
|
25
|
+
import { renderPullRequest } from "./pull-request-body.js";
|
|
26
|
+
import { safeReason } from "./status.js";
|
|
27
|
+
export class BodyUsageError extends Error {
|
|
28
|
+
}
|
|
29
|
+
export const BODY_USAGE = "launcher-apply-plan body --repo <id> --task-record <n> [--supersedes <n>]...";
|
|
30
|
+
const REPO_ID_SHAPE = /^[^/]+\/[^/]+$/u;
|
|
31
|
+
const WHOLE_NUMBER = /^(?:0|[1-9][0-9]{0,15})$/u;
|
|
32
|
+
function wholeNumber(text) {
|
|
33
|
+
if (text === undefined || !WHOLE_NUMBER.test(text))
|
|
34
|
+
throw new BodyUsageError();
|
|
35
|
+
const value = Number(text);
|
|
36
|
+
if (!Number.isSafeInteger(value))
|
|
37
|
+
throw new BodyUsageError();
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Reads `--repo`, `--task-record` and any number of `--supersedes`. A usage error carries no message: nothing the caller typed is
|
|
42
|
+
* ever echoed. A number is digits only, so a sign, an exponent, a space or a leading zero is a usage error; whether it is a
|
|
43
|
+
* positive number that is not the task record is the renderer's judgment (`supersedes-invalid`, `task-record-invalid`).
|
|
44
|
+
*/
|
|
45
|
+
export function parseBodyArgs(argv) {
|
|
46
|
+
if (argv.length === 1 && (argv[0] === "--help" || argv[0] === "-h"))
|
|
47
|
+
return { help: true };
|
|
48
|
+
let id;
|
|
49
|
+
let taskRecord;
|
|
50
|
+
const supersedes = [];
|
|
51
|
+
for (let index = 0; index < argv.length; index += 2) {
|
|
52
|
+
const name = argv[index];
|
|
53
|
+
const value = argv[index + 1];
|
|
54
|
+
if (value === undefined)
|
|
55
|
+
throw new BodyUsageError();
|
|
56
|
+
if (name === "--repo" && id === undefined)
|
|
57
|
+
id = value;
|
|
58
|
+
else if (name === "--task-record" && taskRecord === undefined)
|
|
59
|
+
taskRecord = value;
|
|
60
|
+
else if (name === "--supersedes")
|
|
61
|
+
supersedes.push(wholeNumber(value));
|
|
62
|
+
else
|
|
63
|
+
throw new BodyUsageError();
|
|
64
|
+
}
|
|
65
|
+
if (id === undefined || taskRecord === undefined)
|
|
66
|
+
throw new BodyUsageError();
|
|
67
|
+
const name = id.slice(id.indexOf("/") + 1);
|
|
68
|
+
if (!REPO_ID_SHAPE.test(id) || name === "." || name === "..")
|
|
69
|
+
throw new BodyUsageError();
|
|
70
|
+
return { help: false, id, taskRecord: wholeNumber(taskRecord), supersedes };
|
|
71
|
+
}
|
|
72
|
+
const refuse = (reason) => ({ exitCode: 1, reason });
|
|
73
|
+
const indeterminate = (reason) => ({ exitCode: 2, reason });
|
|
74
|
+
const sameBinding = (left, right) => left.kind === right.kind &&
|
|
75
|
+
left.subjectDigest === right.subjectDigest &&
|
|
76
|
+
(left.kind !== "admitted" || (right.kind === "admitted" && left.setupChangeSet === right.setupChangeSet));
|
|
77
|
+
/** Whether the hub holds a set of this repository, other than this one, that verifies under its own digest. */
|
|
78
|
+
function hasAnotherSet(set, held) {
|
|
79
|
+
return held.some((other) => {
|
|
80
|
+
if (other.repository.id !== set.repository.id || other.changeSetDigest === set.changeSetDigest)
|
|
81
|
+
return false;
|
|
82
|
+
return validateRepositoryChangeSet(other).valid && changeSetDigest(other) === other.changeSetDigest;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/** Renders, binds and returns the body; never throws. */
|
|
86
|
+
export async function bodyRepository(input) {
|
|
87
|
+
try {
|
|
88
|
+
const hub = realpathSync(input.hub);
|
|
89
|
+
let stored;
|
|
90
|
+
try {
|
|
91
|
+
stored = readStoredChangeSet(hub, input.set.changeSetDigest);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return indeterminate("store-unreadable");
|
|
95
|
+
}
|
|
96
|
+
if (stored === null || stored.repository.id !== input.set.repository.id)
|
|
97
|
+
return indeterminate("change-set-absent");
|
|
98
|
+
// B1
|
|
99
|
+
const pre = await runPreconditions(input.clone, input.hub, stored, input.heldChangeSets, { now: input.now, runReadiness: input.runReadiness });
|
|
100
|
+
if ("exitCode" in pre)
|
|
101
|
+
return pre.exitCode === 1 ? refuse(safeReason(pre.reason)) : indeterminate(safeReason(pre.reason));
|
|
102
|
+
// B2
|
|
103
|
+
let bundle;
|
|
104
|
+
try {
|
|
105
|
+
bundle = readStoredApplyBundle(hub, stored.bundle);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return indeterminate("bundle-unreadable");
|
|
109
|
+
}
|
|
110
|
+
if (bundle !== null && bundle.mode === "planned") {
|
|
111
|
+
for (const entry of bundle.repositories) {
|
|
112
|
+
if (!("changeSet" in entry) || entry.changeSet !== stored.changeSetDigest)
|
|
113
|
+
continue;
|
|
114
|
+
const recorded = "binding" in entry ? entry.binding : undefined;
|
|
115
|
+
if (entry.id !== stored.repository.id || recorded === undefined || !sameBinding(recorded, pre.binding))
|
|
116
|
+
return refuse("binding-mismatch");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// B5
|
|
120
|
+
const supersedes = input.supersedes ?? [];
|
|
121
|
+
if (supersedes.length > 0 && !hasAnotherSet(stored, input.heldChangeSets))
|
|
122
|
+
return refuse("supersedes-unfounded");
|
|
123
|
+
// B3
|
|
124
|
+
const rendered = renderPullRequest({ set: stored, binding: pre.binding, taskRecord: input.taskRecord, ...(supersedes.length === 0 ? {} : { supersedes }) });
|
|
125
|
+
if (rendered.state === "refused")
|
|
126
|
+
return refuse(safeReason(rendered.reason));
|
|
127
|
+
// B4: the hash of exactly the bytes that will be printed.
|
|
128
|
+
const hash = `sha256:${createHash("sha256").update(Buffer.from(rendered.body, "utf8")).digest("hex")}`;
|
|
129
|
+
if (hash !== rendered.bodySha256)
|
|
130
|
+
return refuse("render-failed");
|
|
131
|
+
try {
|
|
132
|
+
bindChangeSetBody(hub, stored.changeSetDigest, hash);
|
|
133
|
+
}
|
|
134
|
+
catch (cause) {
|
|
135
|
+
return cause instanceof BodyBoundError ? refuse("body-bound") : indeterminate("store-failed");
|
|
136
|
+
}
|
|
137
|
+
return { exitCode: 0, body: rendered.body };
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return indeterminate("body-failed");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=body-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-command.js","sourceRoot":"","sources":["../src/body-command.ts"],"names":[],"mappings":"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"}
|