@clossys/writer 0.4.0 → 0.5.1
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 +592 -2
- package/dist/approval-bypass.d.ts +120 -0
- package/dist/approval-bypass.d.ts.map +1 -0
- package/dist/approval-bypass.js +2318 -0
- package/dist/approval-bypass.js.map +1 -0
- package/dist/approval.d.ts +62 -0
- package/dist/approval.d.ts.map +1 -0
- package/dist/approval.js +421 -0
- package/dist/approval.js.map +1 -0
- package/dist/approve-cli.d.ts +82 -0
- package/dist/approve-cli.d.ts.map +1 -0
- package/dist/approve-cli.js +430 -0
- package/dist/approve-cli.js.map +1 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +48 -13
- package/dist/cli.js.map +1 -1
- package/dist/field-options.d.ts +59 -0
- package/dist/field-options.d.ts.map +1 -0
- package/dist/field-options.js +109 -0
- package/dist/field-options.js.map +1 -0
- package/dist/front-door-browser.d.ts +5 -0
- package/dist/front-door-browser.d.ts.map +1 -0
- package/dist/front-door-browser.js +30 -0
- package/dist/front-door-browser.js.map +1 -0
- package/dist/front-door-core.d.ts +45 -0
- package/dist/front-door-core.d.ts.map +1 -0
- package/dist/front-door-core.js +224 -0
- package/dist/front-door-core.js.map +1 -0
- package/dist/front-door.check.d.ts +2 -0
- package/dist/front-door.check.d.ts.map +1 -0
- package/dist/front-door.check.js +8 -0
- package/dist/front-door.check.js.map +1 -0
- package/dist/front-door.d.ts +46 -0
- package/dist/front-door.d.ts.map +1 -0
- package/dist/front-door.js +61 -0
- package/dist/front-door.js.map +1 -0
- package/dist/generated/advisor-plan-contract.generated.d.ts +3 -0
- package/dist/generated/advisor-plan-contract.generated.d.ts.map +1 -0
- package/dist/generated/advisor-plan-contract.generated.js +430 -0
- package/dist/generated/advisor-plan-contract.generated.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/index.d.ts +14 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/messaging-kit.d.ts +113 -0
- package/dist/messaging-kit.d.ts.map +1 -0
- package/dist/messaging-kit.js +121 -0
- package/dist/messaging-kit.js.map +1 -0
- package/dist/passage.d.ts +2 -1
- package/dist/passage.d.ts.map +1 -1
- package/dist/passage.js +2 -1
- package/dist/passage.js.map +1 -1
- package/dist/plan-authority.d.ts +73 -0
- package/dist/plan-authority.d.ts.map +1 -0
- package/dist/plan-authority.js +126 -0
- package/dist/plan-authority.js.map +1 -0
- package/dist/plan-contract.d.ts +16 -0
- package/dist/plan-contract.d.ts.map +1 -0
- package/dist/plan-contract.js +33 -0
- package/dist/plan-contract.js.map +1 -0
- package/dist/plan-digest.d.ts +23 -0
- package/dist/plan-digest.d.ts.map +1 -0
- package/dist/plan-digest.js +82 -0
- package/dist/plan-digest.js.map +1 -0
- package/dist/plan-rules.d.ts +54 -0
- package/dist/plan-rules.d.ts.map +1 -0
- package/dist/plan-rules.js +145 -0
- package/dist/plan-rules.js.map +1 -0
- package/dist/resolve.d.ts +40 -6
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +144 -18
- package/dist/resolve.js.map +1 -1
- package/dist/scan.d.ts +32 -0
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +67 -6
- package/dist/scan.js.map +1 -1
- package/dist/schema.d.ts +1 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +209 -5
- package/dist/schema.js.map +1 -1
- package/dist/site-identity.d.ts +88 -0
- package/dist/site-identity.d.ts.map +1 -0
- package/dist/site-identity.js +82 -0
- package/dist/site-identity.js.map +1 -0
- package/dist/types.d.ts +65 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -7
- package/dist/types.js.map +1 -1
- package/package.json +11 -6
- package/skill/SKILL.md +2 -2
- package/src/approval-bypass.ts +2263 -0
- package/src/approval.ts +491 -0
- package/src/approve-cli.ts +474 -0
- package/src/cli.ts +46 -13
- package/src/field-options.ts +134 -0
- package/src/front-door-browser.ts +31 -0
- package/src/front-door-core.ts +265 -0
- package/src/front-door.check.ts +10 -0
- package/src/front-door.ts +65 -0
- package/src/generated/advisor-plan-contract.generated.ts +430 -0
- package/src/generated/contract-schema.generated.ts +520 -0
- package/src/index.ts +97 -1
- package/src/messaging-kit.ts +195 -0
- package/src/passage.ts +2 -1
- package/src/plan-authority.ts +160 -0
- package/src/plan-contract.ts +45 -0
- package/src/plan-digest.ts +81 -0
- package/src/plan-rules.ts +179 -0
- package/src/resolve.ts +185 -19
- package/src/scan.ts +97 -6
- package/src/schema.ts +223 -5
- package/src/site-identity.ts +125 -0
- package/src/types.ts +72 -7
- package/templates/front-door.en.json +423 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The messaging-kit copy kind: a pitch and a boilerplate, each in three
|
|
3
|
+
* lengths, resolved from a `CopyRegistry` under six reserved entry ids.
|
|
4
|
+
*
|
|
5
|
+
* A consumer reuses the same "about us" text in press, footers and email,
|
|
6
|
+
* and needs it to carry the same approval evidence as any other rendered
|
|
7
|
+
* copy. This module is a reserved copy kind, not a second text store or a
|
|
8
|
+
* second approval path: it asks `resolveCopyRef` for each id, so everything
|
|
9
|
+
* that resolver refuses is refused here for the same reason.
|
|
10
|
+
*
|
|
11
|
+
* Invariants:
|
|
12
|
+
*
|
|
13
|
+
* - K1: every `resolveCopyRef` refusal is reported with its own reason,
|
|
14
|
+
* tagged with the field it belongs to.
|
|
15
|
+
* - K2: `"messaging-placeholder"` when an entry declares placeholders or its
|
|
16
|
+
* text is one the resolver would rewrite; `"messaging-blank"` when the
|
|
17
|
+
* resolved text is empty after trimming. These are literal texts, not
|
|
18
|
+
* templates.
|
|
19
|
+
* - K3: `"messaging-ladder-order"` when `countCopyWords` does not strictly
|
|
20
|
+
* increase within a ladder (pitch: one-liner, elevator, paragraph; then
|
|
21
|
+
* boilerplate: short, medium, long). It is reported on the later field,
|
|
22
|
+
* and only between two fields that both resolved.
|
|
23
|
+
* - K4: all six are attempted on every call. `kit` and `resolutions` exist
|
|
24
|
+
* only when `issues` is empty, so there is no partial kit. `options.now`
|
|
25
|
+
* is fixed once per call. Nothing here throws for any input.
|
|
26
|
+
* - K5: no word targets beyond K3. An FAQ and a tagline are out of scope
|
|
27
|
+
* (`site.tagline` is already a reserved site-identity id).
|
|
28
|
+
*
|
|
29
|
+
* No real copy ships here. The ids are reserved names; the words are the
|
|
30
|
+
* consumer's own.
|
|
31
|
+
*/
|
|
32
|
+
import type { CopyResolveIssue, CopyResolveIssueReason, CopyResolveOptions } from "./resolve.js";
|
|
33
|
+
import type { CopyRegistry, CopyResolution } from "./types.js";
|
|
34
|
+
/** Reserved copy id for the shortest pitch. */
|
|
35
|
+
export declare const MESSAGING_PITCH_ONE_LINER_COPY_ID = "messaging.pitch.one-liner";
|
|
36
|
+
/** Reserved copy id for the elevator pitch. */
|
|
37
|
+
export declare const MESSAGING_PITCH_ELEVATOR_COPY_ID = "messaging.pitch.elevator";
|
|
38
|
+
/** Reserved copy id for the paragraph-length pitch. */
|
|
39
|
+
export declare const MESSAGING_PITCH_PARAGRAPH_COPY_ID = "messaging.pitch.paragraph";
|
|
40
|
+
/** Reserved copy id for the short boilerplate. */
|
|
41
|
+
export declare const MESSAGING_BOILERPLATE_SHORT_COPY_ID = "messaging.boilerplate.short";
|
|
42
|
+
/** Reserved copy id for the medium boilerplate. */
|
|
43
|
+
export declare const MESSAGING_BOILERPLATE_MEDIUM_COPY_ID = "messaging.boilerplate.medium";
|
|
44
|
+
/** Reserved copy id for the long boilerplate. */
|
|
45
|
+
export declare const MESSAGING_BOILERPLATE_LONG_COPY_ID = "messaging.boilerplate.long";
|
|
46
|
+
/** All six reserved messaging-kit copy ids: the pitch ladder, then the boilerplate ladder. */
|
|
47
|
+
export declare const MESSAGING_KIT_COPY_IDS: readonly ["messaging.pitch.one-liner", "messaging.pitch.elevator", "messaging.pitch.paragraph", "messaging.boilerplate.short", "messaging.boilerplate.medium", "messaging.boilerplate.long"];
|
|
48
|
+
/** Which entry of the kit an issue is about. */
|
|
49
|
+
export type MessagingKitField = "pitch.oneLiner" | "pitch.elevator" | "pitch.paragraph" | "boilerplate.short" | "boilerplate.medium" | "boilerplate.long";
|
|
50
|
+
/**
|
|
51
|
+
* Every reason `resolveMessagingKit` can report: whatever `resolveCopyRef`
|
|
52
|
+
* refuses, plus the three refusals specific to the kit.
|
|
53
|
+
*/
|
|
54
|
+
export type MessagingKitIssueReason = CopyResolveIssueReason | "messaging-blank" | "messaging-placeholder" | "messaging-ladder-order";
|
|
55
|
+
/** One reason the kit could not be resolved, tagged with its field. */
|
|
56
|
+
export interface MessagingKitIssue extends Omit<CopyResolveIssue, "reason"> {
|
|
57
|
+
reason: MessagingKitIssueReason;
|
|
58
|
+
field: MessagingKitField;
|
|
59
|
+
}
|
|
60
|
+
/** The resolved text of the kit, by ladder. */
|
|
61
|
+
export interface MessagingKit {
|
|
62
|
+
pitch: {
|
|
63
|
+
oneLiner: string;
|
|
64
|
+
elevator: string;
|
|
65
|
+
paragraph: string;
|
|
66
|
+
};
|
|
67
|
+
boilerplate: {
|
|
68
|
+
short: string;
|
|
69
|
+
medium: string;
|
|
70
|
+
long: string;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** Each entry's `CopyResolution`, shaped like `MessagingKit`. */
|
|
74
|
+
export interface MessagingKitResolutions {
|
|
75
|
+
pitch: {
|
|
76
|
+
oneLiner: CopyResolution;
|
|
77
|
+
elevator: CopyResolution;
|
|
78
|
+
paragraph: CopyResolution;
|
|
79
|
+
};
|
|
80
|
+
boilerplate: {
|
|
81
|
+
short: CopyResolution;
|
|
82
|
+
medium: CopyResolution;
|
|
83
|
+
long: CopyResolution;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The outcome of `resolveMessagingKit`. `kit` and `resolutions` are present
|
|
88
|
+
* only when `complete` is `true`; `issues` is empty exactly then.
|
|
89
|
+
*/
|
|
90
|
+
export interface MessagingKitResolution {
|
|
91
|
+
complete: boolean;
|
|
92
|
+
kit?: MessagingKit;
|
|
93
|
+
resolutions?: MessagingKitResolutions;
|
|
94
|
+
issues: MessagingKitIssue[];
|
|
95
|
+
}
|
|
96
|
+
/** `CopyResolveOptions` plus the requested locale, which is a ref field for the underlying resolver. */
|
|
97
|
+
export type MessagingKitOptions = CopyResolveOptions & {
|
|
98
|
+
locale?: string;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Resolves the messaging kit from `registry`, under the six ids in
|
|
102
|
+
* `MESSAGING_KIT_COPY_IDS`. All six are attempted on every call and every
|
|
103
|
+
* issue is reported in id order, tagged with its `field`; `kit` and
|
|
104
|
+
* `resolutions` are returned only when there are no issues.
|
|
105
|
+
*
|
|
106
|
+
* `options` are `resolveCopyRef`'s (`target`, `acceptDelegateInProduction`,
|
|
107
|
+
* `now`) plus an optional `locale`, which is forwarded as the ref's locale
|
|
108
|
+
* rather than as an option. Malformed options produce an `"invalid-options"`
|
|
109
|
+
* issue per field. Pure apart from the clock read that `now` defaults to;
|
|
110
|
+
* the registry is not modified and no input makes this throw.
|
|
111
|
+
*/
|
|
112
|
+
export declare function resolveMessagingKit(registry: CopyRegistry | unknown, options?: MessagingKitOptions | unknown): MessagingKitResolution;
|
|
113
|
+
//# sourceMappingURL=messaging-kit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging-kit.d.ts","sourceRoot":"","sources":["../src/messaging-kit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEjG,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D,+CAA+C;AAC/C,eAAO,MAAM,iCAAiC,8BAA8B,CAAC;AAE7E,+CAA+C;AAC/C,eAAO,MAAM,gCAAgC,6BAA6B,CAAC;AAE3E,uDAAuD;AACvD,eAAO,MAAM,iCAAiC,8BAA8B,CAAC;AAE7E,kDAAkD;AAClD,eAAO,MAAM,mCAAmC,gCAAgC,CAAC;AAEjF,mDAAmD;AACnD,eAAO,MAAM,oCAAoC,iCAAiC,CAAC;AAEnF,iDAAiD;AACjD,eAAO,MAAM,kCAAkC,+BAA+B,CAAC;AAE/E,8FAA8F;AAC9F,eAAO,MAAM,sBAAsB,8LAOzB,CAAC;AAEX,gDAAgD;AAChD,MAAM,MAAM,iBAAiB,GACzB,gBAAgB,GAChB,gBAAgB,GAChB,iBAAiB,GACjB,mBAAmB,GACnB,oBAAoB,GACpB,kBAAkB,CAAC;AAEvB;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAC/B,sBAAsB,GACtB,iBAAiB,GACjB,uBAAuB,GACvB,wBAAwB,CAAC;AAE7B,uEAAuE;AACvE,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC;IACzE,MAAM,EAAE,uBAAuB,CAAC;IAChC,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9D;AAED,iEAAiE;AACjE,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE;QAAE,QAAQ,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,cAAc,CAAC;QAAC,SAAS,EAAE,cAAc,CAAA;KAAE,CAAC;IACzF,WAAW,EAAE;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,MAAM,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,CAAC;CACtF;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED,wGAAwG;AACxG,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAkB3E;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,YAAY,GAAG,OAAO,EAChC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,GACtC,sBAAsB,CA8CxB"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The messaging-kit copy kind: a pitch and a boilerplate, each in three
|
|
3
|
+
* lengths, resolved from a `CopyRegistry` under six reserved entry ids.
|
|
4
|
+
*
|
|
5
|
+
* A consumer reuses the same "about us" text in press, footers and email,
|
|
6
|
+
* and needs it to carry the same approval evidence as any other rendered
|
|
7
|
+
* copy. This module is a reserved copy kind, not a second text store or a
|
|
8
|
+
* second approval path: it asks `resolveCopyRef` for each id, so everything
|
|
9
|
+
* that resolver refuses is refused here for the same reason.
|
|
10
|
+
*
|
|
11
|
+
* Invariants:
|
|
12
|
+
*
|
|
13
|
+
* - K1: every `resolveCopyRef` refusal is reported with its own reason,
|
|
14
|
+
* tagged with the field it belongs to.
|
|
15
|
+
* - K2: `"messaging-placeholder"` when an entry declares placeholders or its
|
|
16
|
+
* text is one the resolver would rewrite; `"messaging-blank"` when the
|
|
17
|
+
* resolved text is empty after trimming. These are literal texts, not
|
|
18
|
+
* templates.
|
|
19
|
+
* - K3: `"messaging-ladder-order"` when `countCopyWords` does not strictly
|
|
20
|
+
* increase within a ladder (pitch: one-liner, elevator, paragraph; then
|
|
21
|
+
* boilerplate: short, medium, long). It is reported on the later field,
|
|
22
|
+
* and only between two fields that both resolved.
|
|
23
|
+
* - K4: all six are attempted on every call. `kit` and `resolutions` exist
|
|
24
|
+
* only when `issues` is empty, so there is no partial kit. `options.now`
|
|
25
|
+
* is fixed once per call. Nothing here throws for any input.
|
|
26
|
+
* - K5: no word targets beyond K3. An FAQ and a tagline are out of scope
|
|
27
|
+
* (`site.tagline` is already a reserved site-identity id).
|
|
28
|
+
*
|
|
29
|
+
* No real copy ships here. The ids are reserved names; the words are the
|
|
30
|
+
* consumer's own.
|
|
31
|
+
*/
|
|
32
|
+
import { prepareOptions, resolveField } from "./field-options.js";
|
|
33
|
+
import { countCopyWords } from "./treatment-word-budget.js";
|
|
34
|
+
/** Reserved copy id for the shortest pitch. */
|
|
35
|
+
export const MESSAGING_PITCH_ONE_LINER_COPY_ID = "messaging.pitch.one-liner";
|
|
36
|
+
/** Reserved copy id for the elevator pitch. */
|
|
37
|
+
export const MESSAGING_PITCH_ELEVATOR_COPY_ID = "messaging.pitch.elevator";
|
|
38
|
+
/** Reserved copy id for the paragraph-length pitch. */
|
|
39
|
+
export const MESSAGING_PITCH_PARAGRAPH_COPY_ID = "messaging.pitch.paragraph";
|
|
40
|
+
/** Reserved copy id for the short boilerplate. */
|
|
41
|
+
export const MESSAGING_BOILERPLATE_SHORT_COPY_ID = "messaging.boilerplate.short";
|
|
42
|
+
/** Reserved copy id for the medium boilerplate. */
|
|
43
|
+
export const MESSAGING_BOILERPLATE_MEDIUM_COPY_ID = "messaging.boilerplate.medium";
|
|
44
|
+
/** Reserved copy id for the long boilerplate. */
|
|
45
|
+
export const MESSAGING_BOILERPLATE_LONG_COPY_ID = "messaging.boilerplate.long";
|
|
46
|
+
/** All six reserved messaging-kit copy ids: the pitch ladder, then the boilerplate ladder. */
|
|
47
|
+
export const MESSAGING_KIT_COPY_IDS = [
|
|
48
|
+
MESSAGING_PITCH_ONE_LINER_COPY_ID,
|
|
49
|
+
MESSAGING_PITCH_ELEVATOR_COPY_ID,
|
|
50
|
+
MESSAGING_PITCH_PARAGRAPH_COPY_ID,
|
|
51
|
+
MESSAGING_BOILERPLATE_SHORT_COPY_ID,
|
|
52
|
+
MESSAGING_BOILERPLATE_MEDIUM_COPY_ID,
|
|
53
|
+
MESSAGING_BOILERPLATE_LONG_COPY_ID,
|
|
54
|
+
];
|
|
55
|
+
const FIELDS = [
|
|
56
|
+
{ field: "pitch.oneLiner", id: MESSAGING_KIT_COPY_IDS[0], ladder: "pitch" },
|
|
57
|
+
{ field: "pitch.elevator", id: MESSAGING_KIT_COPY_IDS[1], ladder: "pitch" },
|
|
58
|
+
{ field: "pitch.paragraph", id: MESSAGING_KIT_COPY_IDS[2], ladder: "pitch" },
|
|
59
|
+
{ field: "boilerplate.short", id: MESSAGING_KIT_COPY_IDS[3], ladder: "boilerplate" },
|
|
60
|
+
{ field: "boilerplate.medium", id: MESSAGING_KIT_COPY_IDS[4], ladder: "boilerplate" },
|
|
61
|
+
{ field: "boilerplate.long", id: MESSAGING_KIT_COPY_IDS[5], ladder: "boilerplate" },
|
|
62
|
+
];
|
|
63
|
+
const LABELS = {
|
|
64
|
+
optionsSubject: "Messaging kit",
|
|
65
|
+
entrySubject: (id) => `Messaging kit entry "${id}"`,
|
|
66
|
+
placeholderReason: "messaging-placeholder",
|
|
67
|
+
blankReason: "messaging-blank",
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Resolves the messaging kit from `registry`, under the six ids in
|
|
71
|
+
* `MESSAGING_KIT_COPY_IDS`. All six are attempted on every call and every
|
|
72
|
+
* issue is reported in id order, tagged with its `field`; `kit` and
|
|
73
|
+
* `resolutions` are returned only when there are no issues.
|
|
74
|
+
*
|
|
75
|
+
* `options` are `resolveCopyRef`'s (`target`, `acceptDelegateInProduction`,
|
|
76
|
+
* `now`) plus an optional `locale`, which is forwarded as the ref's locale
|
|
77
|
+
* rather than as an option. Malformed options produce an `"invalid-options"`
|
|
78
|
+
* issue per field. Pure apart from the clock read that `now` defaults to;
|
|
79
|
+
* the registry is not modified and no input makes this throw.
|
|
80
|
+
*/
|
|
81
|
+
export function resolveMessagingKit(registry, options) {
|
|
82
|
+
const prepared = prepareOptions(options);
|
|
83
|
+
const issues = [];
|
|
84
|
+
const resolved = [];
|
|
85
|
+
const words = [];
|
|
86
|
+
FIELDS.forEach(({ field, id, ladder }, index) => {
|
|
87
|
+
const outcome = resolveField(registry, field, id, prepared, LABELS);
|
|
88
|
+
issues.push(...outcome.issues);
|
|
89
|
+
const resolution = outcome.resolution;
|
|
90
|
+
if (resolution)
|
|
91
|
+
resolved[index] = resolution;
|
|
92
|
+
words[index] = resolution ? countCopyWords(resolution.text) : undefined;
|
|
93
|
+
const previous = index - 1;
|
|
94
|
+
const before = previous >= 0 && FIELDS[previous].ladder === ladder ? words[previous] : undefined;
|
|
95
|
+
const current = words[index];
|
|
96
|
+
if (before !== undefined && current !== undefined && !(current > before)) {
|
|
97
|
+
issues.push({
|
|
98
|
+
reason: "messaging-ladder-order",
|
|
99
|
+
field,
|
|
100
|
+
id,
|
|
101
|
+
message: `Messaging kit entry "${id}" has ${current} words, which is not more than the ${before} of "${FIELDS[previous].id}".`,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
if (issues.length > 0 || resolved.length !== FIELDS.length)
|
|
106
|
+
return { complete: false, issues };
|
|
107
|
+
const [oneLiner, elevator, paragraph, short, medium, long] = resolved;
|
|
108
|
+
return {
|
|
109
|
+
complete: true,
|
|
110
|
+
kit: {
|
|
111
|
+
pitch: { oneLiner: oneLiner.text, elevator: elevator.text, paragraph: paragraph.text },
|
|
112
|
+
boilerplate: { short: short.text, medium: medium.text, long: long.text },
|
|
113
|
+
},
|
|
114
|
+
resolutions: {
|
|
115
|
+
pitch: { oneLiner, elevator, paragraph },
|
|
116
|
+
boilerplate: { short, medium, long },
|
|
117
|
+
},
|
|
118
|
+
issues: [],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=messaging-kit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging-kit.js","sourceRoot":"","sources":["../src/messaging-kit.ts"],"names":[],"mappings":"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"}
|
package/dist/passage.d.ts
CHANGED
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
*
|
|
38
38
|
* This file ships no example content of anyone's real copy — the same
|
|
39
39
|
* "vocabulary layer, never a source of real words" constraint `types.ts`
|
|
40
|
-
* documents for `CopyEntry`/`CopyRecord
|
|
40
|
+
* documents for `CopyEntry`/`CopyRecord` (its one exemption is the shipped
|
|
41
|
+
* front-door defaults, which this file does not touch). Every fixture in this package's
|
|
41
42
|
* own tests is structural placeholder text, never something a product
|
|
42
43
|
* would actually show a user.
|
|
43
44
|
*
|
package/dist/passage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passage.d.ts","sourceRoot":"","sources":["../src/passage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"passage.d.ts","sourceRoot":"","sources":["../src/passage.ts"],"names":[],"mappings":"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"}
|
package/dist/passage.js
CHANGED
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
*
|
|
38
38
|
* This file ships no example content of anyone's real copy — the same
|
|
39
39
|
* "vocabulary layer, never a source of real words" constraint `types.ts`
|
|
40
|
-
* documents for `CopyEntry`/`CopyRecord
|
|
40
|
+
* documents for `CopyEntry`/`CopyRecord` (its one exemption is the shipped
|
|
41
|
+
* front-door defaults, which this file does not touch). Every fixture in this package's
|
|
41
42
|
* own tests is structural placeholder text, never something a product
|
|
42
43
|
* would actually show a user.
|
|
43
44
|
*
|
package/dist/passage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passage.js","sourceRoot":"","sources":["../src/passage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"passage.js","sourceRoot":"","sources":["../src/passage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Why a plan's bytes did not authorize delegate-approved copy on production. */
|
|
2
|
+
export type PlanDelegateCopyRefusal =
|
|
3
|
+
/** The argument is not a `Uint8Array` (a Node `Buffer` is one). */
|
|
4
|
+
"plan-not-bytes"
|
|
5
|
+
/** The bytes are not strict JSON: not valid UTF-8, a byte order mark, a syntax error, or a key repeated at any depth. */
|
|
6
|
+
| "plan-unreadable"
|
|
7
|
+
/** The plan does not validate against the plan contract, schema and code rules. */
|
|
8
|
+
| "plan-invalid"
|
|
9
|
+
/** The plan does not declare `delegatedCopyApproval`. */
|
|
10
|
+
| "delegated-copy-approval-absent" | "no-decisions"
|
|
11
|
+
/** Defence in depth: a valid plan's decision times always parse. */
|
|
12
|
+
| "decision-time-unparseable"
|
|
13
|
+
/** A decision at the latest instant has not chosen "approved". */
|
|
14
|
+
| "latest-decision-not-approved"
|
|
15
|
+
/** A decision at the latest instant is an approval that names no sha256 digest. */
|
|
16
|
+
| "approval-without-subject-digest"
|
|
17
|
+
/** Decisions at the latest instant name different digests. */
|
|
18
|
+
| "latest-decisions-disagree"
|
|
19
|
+
/** The latest approval names a digest other than this plan's own. */
|
|
20
|
+
| "subject-digest-mismatch";
|
|
21
|
+
/** What `planDelegateCopyAuthority()` decided. Frozen, and carries no plan text. */
|
|
22
|
+
export type PlanDelegateCopyAuthority = {
|
|
23
|
+
readonly authorized: true;
|
|
24
|
+
/** The plan's canonical digest, which the latest approval names. */
|
|
25
|
+
readonly planDigest: string;
|
|
26
|
+
/** The plan's `delegatedCopyApproval.scopes`, copied; absent when the plan declares none, which covers every entry. */
|
|
27
|
+
readonly scopes?: readonly string[];
|
|
28
|
+
} | {
|
|
29
|
+
readonly authorized: false;
|
|
30
|
+
readonly refusal: PlanDelegateCopyRefusal;
|
|
31
|
+
/** Only with "plan-invalid": each violation's rule and position, never a value. */
|
|
32
|
+
readonly violations?: readonly {
|
|
33
|
+
readonly rule: string;
|
|
34
|
+
readonly path: string;
|
|
35
|
+
}[];
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* The positions of the decisions made at the latest instant, by `at` and
|
|
39
|
+
* never by array position, in array order. Times are compared as instants
|
|
40
|
+
* (`Date.parse`), so `2026-09-21T00:00:00Z` and `2026-09-21T02:00:00+02:00`
|
|
41
|
+
* tie. Null when there are no decisions, or when any `at` does not parse to a
|
|
42
|
+
* finite time, because then time cannot say which is latest. Exported for
|
|
43
|
+
* tests, not from the package entry point.
|
|
44
|
+
*/
|
|
45
|
+
export declare function latestDecisionIndices(decisions: readonly {
|
|
46
|
+
readonly at: string;
|
|
47
|
+
}[]): number[] | null;
|
|
48
|
+
/** True for a real `Uint8Array` (a Node `Buffer` is one), never a `DataView`, another typed array or a proxy. */
|
|
49
|
+
export declare function isPlanBytes(value: unknown): value is Uint8Array;
|
|
50
|
+
/**
|
|
51
|
+
* Whether the bytes of a plan record authorize delegate-approved copy on
|
|
52
|
+
* production. Checks run in this order and the first that fails refuses:
|
|
53
|
+
*
|
|
54
|
+
* 1. the argument is a `Uint8Array` (`plan-not-bytes`);
|
|
55
|
+
* 2. the bytes are strict JSON (`plan-unreadable`);
|
|
56
|
+
* 3. the plan validates against the plan contract, R1-R12 included
|
|
57
|
+
* (`plan-invalid`, with each violation's rule and position);
|
|
58
|
+
* 4. the plan declares `delegatedCopyApproval` (`delegated-copy-approval-absent`);
|
|
59
|
+
* 5-9. the plan's latest decision, found by time and never by array
|
|
60
|
+
* position, has chosen "approved" and names one sha256 `subjectDigest`.
|
|
61
|
+
* When several decisions share the latest instant, every one is examined:
|
|
62
|
+
* the outcome does not depend on their order;
|
|
63
|
+
* 10. that digest equals the plan's own canonical digest, computed here from
|
|
64
|
+
* the same bytes (`subject-digest-mismatch`). The digest covers
|
|
65
|
+
* `delegatedCopyApproval`, so a declaration added, removed or edited after
|
|
66
|
+
* the approval leaves the plan unapproved for this purpose.
|
|
67
|
+
*
|
|
68
|
+
* Never throws for a bad argument and never echoes plan text. The result and
|
|
69
|
+
* everything in it is frozen, and copied from the bytes, which are copied
|
|
70
|
+
* before they are read.
|
|
71
|
+
*/
|
|
72
|
+
export declare function planDelegateCopyAuthority(planBytes: Uint8Array | unknown): PlanDelegateCopyAuthority;
|
|
73
|
+
//# sourceMappingURL=plan-authority.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-authority.d.ts","sourceRoot":"","sources":["../src/plan-authority.ts"],"names":[],"mappings":"AAuBA,iFAAiF;AACjF,MAAM,MAAM,uBAAuB;AACjC,mEAAmE;AACjE,gBAAgB;AAClB,yHAAyH;GACvH,iBAAiB;AACnB,mFAAmF;GACjF,cAAc;AAChB,yDAAyD;GACvD,gCAAgC,GAChC,cAAc;AAChB,oEAAoE;GAClE,2BAA2B;AAC7B,kEAAkE;GAChE,8BAA8B;AAChC,mFAAmF;GACjF,iCAAiC;AACnC,8DAA8D;GAC5D,2BAA2B;AAC7B,qEAAqE;GACnE,yBAAyB,CAAC;AAE9B,oFAAoF;AACpF,MAAM,MAAM,yBAAyB,GACjC;IACE,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,uHAAuH;IACvH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC,GACD;IACE,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC1C,mFAAmF;IACnF,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACnF,CAAC;AASN;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAWpG;AAED,iHAAiH;AACjH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAM/D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,GAAG,yBAAyB,CAuCpG"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Whether the bytes of an Advisor plan record authorize copy a delegate
|
|
2
|
+
// approved on production (issue #1586). The plan's optional
|
|
3
|
+
// `delegatedCopyApproval` declares that grant, and an approval binds the plan
|
|
4
|
+
// it grants for: this reads the field only through a latest decision that
|
|
5
|
+
// names the plan's own canonical digest. Two files define what is read, both
|
|
6
|
+
// in the public repository, not shipped in this package: the plan contract,
|
|
7
|
+
// docs/contracts/advisor-plan.json (see its DELEGATED COPY APPROVAL and
|
|
8
|
+
// APPROVAL BINDING sections), and the digest definition,
|
|
9
|
+
// docs/contracts/advisor-plan-digest.md.
|
|
10
|
+
//
|
|
11
|
+
// It is a pure function of the bytes: it reads no file, keeps nothing between
|
|
12
|
+
// calls and never looks at the clock, because a plan approval has no expiry
|
|
13
|
+
// of its own. It takes bytes, not a parsed object, because the digest is
|
|
14
|
+
// defined only over a plan that was read strictly, and an object a caller
|
|
15
|
+
// built can carry getters or proxies that answer validation, the digest and
|
|
16
|
+
// the scope check differently. What it does not prove is who wrote the
|
|
17
|
+
// decision, or where the bytes came from: see this package's README.
|
|
18
|
+
import { readContractDocument } from "./generated/contract-schema.generated.js";
|
|
19
|
+
import { planViolations } from "./plan-contract.js";
|
|
20
|
+
import { digestOfValidPlan } from "./plan-digest.js";
|
|
21
|
+
const SUBJECT_DIGEST = /^sha256:[0-9a-f]{64}$/;
|
|
22
|
+
function refuse(refusal, violations) {
|
|
23
|
+
if (violations === undefined)
|
|
24
|
+
return Object.freeze({ authorized: false, refusal });
|
|
25
|
+
return Object.freeze({ authorized: false, refusal, violations: Object.freeze(violations.map((violation) => Object.freeze({ rule: violation.rule, path: violation.path }))) });
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The positions of the decisions made at the latest instant, by `at` and
|
|
29
|
+
* never by array position, in array order. Times are compared as instants
|
|
30
|
+
* (`Date.parse`), so `2026-09-21T00:00:00Z` and `2026-09-21T02:00:00+02:00`
|
|
31
|
+
* tie. Null when there are no decisions, or when any `at` does not parse to a
|
|
32
|
+
* finite time, because then time cannot say which is latest. Exported for
|
|
33
|
+
* tests, not from the package entry point.
|
|
34
|
+
*/
|
|
35
|
+
export function latestDecisionIndices(decisions) {
|
|
36
|
+
if (decisions.length === 0)
|
|
37
|
+
return null;
|
|
38
|
+
const times = decisions.map((decision) => Date.parse(decision.at));
|
|
39
|
+
if (!times.every(Number.isFinite))
|
|
40
|
+
return null;
|
|
41
|
+
// A reduce, not Math.max(...times): spreading a very long list into arguments throws a RangeError.
|
|
42
|
+
const latest = times.reduce((highest, time) => (time > highest ? time : highest), Number.NEGATIVE_INFINITY);
|
|
43
|
+
const indices = [];
|
|
44
|
+
times.forEach((time, index) => {
|
|
45
|
+
if (time === latest)
|
|
46
|
+
indices.push(index);
|
|
47
|
+
});
|
|
48
|
+
return indices;
|
|
49
|
+
}
|
|
50
|
+
/** True for a real `Uint8Array` (a Node `Buffer` is one), never a `DataView`, another typed array or a proxy. */
|
|
51
|
+
export function isPlanBytes(value) {
|
|
52
|
+
try {
|
|
53
|
+
return value instanceof Uint8Array && ArrayBuffer.isView(value);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false; // instanceof throws on a revoked proxy
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Whether the bytes of a plan record authorize delegate-approved copy on
|
|
61
|
+
* production. Checks run in this order and the first that fails refuses:
|
|
62
|
+
*
|
|
63
|
+
* 1. the argument is a `Uint8Array` (`plan-not-bytes`);
|
|
64
|
+
* 2. the bytes are strict JSON (`plan-unreadable`);
|
|
65
|
+
* 3. the plan validates against the plan contract, R1-R12 included
|
|
66
|
+
* (`plan-invalid`, with each violation's rule and position);
|
|
67
|
+
* 4. the plan declares `delegatedCopyApproval` (`delegated-copy-approval-absent`);
|
|
68
|
+
* 5-9. the plan's latest decision, found by time and never by array
|
|
69
|
+
* position, has chosen "approved" and names one sha256 `subjectDigest`.
|
|
70
|
+
* When several decisions share the latest instant, every one is examined:
|
|
71
|
+
* the outcome does not depend on their order;
|
|
72
|
+
* 10. that digest equals the plan's own canonical digest, computed here from
|
|
73
|
+
* the same bytes (`subject-digest-mismatch`). The digest covers
|
|
74
|
+
* `delegatedCopyApproval`, so a declaration added, removed or edited after
|
|
75
|
+
* the approval leaves the plan unapproved for this purpose.
|
|
76
|
+
*
|
|
77
|
+
* Never throws for a bad argument and never echoes plan text. The result and
|
|
78
|
+
* everything in it is frozen, and copied from the bytes, which are copied
|
|
79
|
+
* before they are read.
|
|
80
|
+
*/
|
|
81
|
+
export function planDelegateCopyAuthority(planBytes) {
|
|
82
|
+
if (!isPlanBytes(planBytes))
|
|
83
|
+
return refuse("plan-not-bytes");
|
|
84
|
+
// A copy, so nothing the caller does to its buffer during or after this call changes what is read.
|
|
85
|
+
const bytes = new Uint8Array(planBytes);
|
|
86
|
+
let value;
|
|
87
|
+
try {
|
|
88
|
+
value = readContractDocument(bytes);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return refuse("plan-unreadable");
|
|
92
|
+
}
|
|
93
|
+
const violations = planViolations(value);
|
|
94
|
+
if (violations.length > 0)
|
|
95
|
+
return refuse("plan-invalid", violations);
|
|
96
|
+
const plan = value;
|
|
97
|
+
if (!Object.hasOwn(plan, "delegatedCopyApproval"))
|
|
98
|
+
return refuse("delegated-copy-approval-absent");
|
|
99
|
+
if (plan.decisions.length === 0)
|
|
100
|
+
return refuse("no-decisions");
|
|
101
|
+
const latestIndices = latestDecisionIndices(plan.decisions);
|
|
102
|
+
if (latestIndices === null)
|
|
103
|
+
return refuse("decision-time-unparseable");
|
|
104
|
+
const latest = latestIndices.map((index) => plan.decisions[index]);
|
|
105
|
+
if (latest.some((decision) => decision.chosen !== "approved"))
|
|
106
|
+
return refuse("latest-decision-not-approved");
|
|
107
|
+
const subjects = latest.map((decision) => (Object.hasOwn(decision, "subjectDigest") ? decision.subjectDigest : undefined));
|
|
108
|
+
if (subjects.some((subject) => typeof subject !== "string" || !SUBJECT_DIGEST.test(subject)))
|
|
109
|
+
return refuse("approval-without-subject-digest");
|
|
110
|
+
if (subjects.some((subject) => subject !== subjects[0]))
|
|
111
|
+
return refuse("latest-decisions-disagree");
|
|
112
|
+
let digest;
|
|
113
|
+
try {
|
|
114
|
+
digest = digestOfValidPlan(plan);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return refuse("plan-invalid", []);
|
|
118
|
+
}
|
|
119
|
+
if (subjects[0] !== digest)
|
|
120
|
+
return refuse("subject-digest-mismatch");
|
|
121
|
+
const declaration = plan.delegatedCopyApproval;
|
|
122
|
+
if (!Object.hasOwn(declaration, "scopes") || declaration.scopes === undefined)
|
|
123
|
+
return Object.freeze({ authorized: true, planDigest: digest });
|
|
124
|
+
return Object.freeze({ authorized: true, planDigest: digest, scopes: Object.freeze([...declaration.scopes]) });
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=plan-authority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-authority.js","sourceRoot":"","sources":["../src/plan-authority.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PlanRuleId } from "./plan-rules.js";
|
|
2
|
+
/** One reason a plan is refused: `rule` is "schema" for the contract's keywords, else the code rule's id. */
|
|
3
|
+
export interface PlanViolation {
|
|
4
|
+
readonly rule: "schema" | PlanRuleId;
|
|
5
|
+
/** The field at fault, like `staffing[1].repository`, or "" for the document itself. */
|
|
6
|
+
readonly path: string;
|
|
7
|
+
/** The whole message, starting with `plan` and the path; it never quotes a value. */
|
|
8
|
+
readonly message: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Every reason `value` is not a valid plan: the plan contract's schema, then,
|
|
12
|
+
* once that passes, its code rules R1-R12. Empty means valid. Never throws
|
|
13
|
+
* for a bad value, and no message echoes a value from the plan.
|
|
14
|
+
*/
|
|
15
|
+
export declare function planViolations(value: unknown): PlanViolation[];
|
|
16
|
+
//# sourceMappingURL=plan-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-contract.d.ts","sourceRoot":"","sources":["../src/plan-contract.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhE,6GAA6G;AAC7G,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IACrC,wFAAwF;IACxF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAOD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,EAAE,CAW9D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Reads a plan record (issue #1586) against the shared plan contract
|
|
2
|
+
// docs/contracts/advisor-plan.json -- in the public repository, not shipped in
|
|
3
|
+
// this package. This package's build packs that contract into src/generated/
|
|
4
|
+
// as plain data, with a generated copy of the one contract checker every
|
|
5
|
+
// other reader of a plan also uses (packages/advisor/src/contract-schema.ts,
|
|
6
|
+
// likewise in the public repository, not shipped in this package), so
|
|
7
|
+
// Writer validates against the same definition with no runtime dependency on
|
|
8
|
+
// any other package.
|
|
9
|
+
import { ADVISOR_PLAN_CONTRACT } from "./generated/advisor-plan-contract.generated.js";
|
|
10
|
+
import { formatContractViolation, validateAgainstContract } from "./generated/contract-schema.generated.js";
|
|
11
|
+
import { planRuleViolations } from "./plan-rules.js";
|
|
12
|
+
/** The plan contract refers to no other contract file, so every name is refused. */
|
|
13
|
+
function refuseEveryName(name) {
|
|
14
|
+
throw new Error(`the plan contract refers to no other contract, but the checker asked for ${JSON.stringify(name)}`);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Every reason `value` is not a valid plan: the plan contract's schema, then,
|
|
18
|
+
* once that passes, its code rules R1-R12. Empty means valid. Never throws
|
|
19
|
+
* for a bad value, and no message echoes a value from the plan.
|
|
20
|
+
*/
|
|
21
|
+
export function planViolations(value) {
|
|
22
|
+
const schema = validateAgainstContract(ADVISOR_PLAN_CONTRACT, value, refuseEveryName);
|
|
23
|
+
if (schema.length > 0) {
|
|
24
|
+
return schema.map((violation) => ({ rule: "schema", path: violation.path, message: formatContractViolation("plan", violation) }));
|
|
25
|
+
}
|
|
26
|
+
// The code rules relate fields to one another, so they run only on a plan whose shape is known good.
|
|
27
|
+
return planRuleViolations(value).map((violation) => ({
|
|
28
|
+
rule: violation.rule,
|
|
29
|
+
path: violation.path,
|
|
30
|
+
message: `plan.${violation.path} ${violation.message} (rule ${violation.rule})`,
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=plan-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-contract.js","sourceRoot":"","sources":["../src/plan-contract.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,+EAA+E;AAC/E,6EAA6E;AAC7E,yEAAyE;AACzE,6EAA6E;AAC7E,sEAAsE;AACtE,6EAA6E;AAC7E,qBAAqB;AAErB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAC5G,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAYrD,oFAAoF;AACpF,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,IAAI,KAAK,CAAC,4EAA4E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACtH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,MAAM,MAAM,GAAG,uBAAuB,CAAC,qBAAqB,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;IACtF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,uBAAuB,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACpI,CAAC;IACD,qGAAqG;IACrG,OAAO,kBAAkB,CAAC,KAAqB,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACnE,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,OAAO,EAAE,QAAQ,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,OAAO,UAAU,SAAS,CAAC,IAAI,GAAG;KAChF,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** The top-level plan members the digest leaves out: when the file was written, and the decisions an approval is recorded in. */
|
|
2
|
+
export declare const PLAN_DIGEST_EXCLUDED_FIELDS: readonly string[];
|
|
3
|
+
/**
|
|
4
|
+
* RFC 8785 (JSON Canonicalization Scheme) serialization: no whitespace,
|
|
5
|
+
* object members sorted by UTF-16 code units, strings escaped only where
|
|
6
|
+
* JSON requires, numbers as ECMAScript writes them. Throws on anything JSON
|
|
7
|
+
* cannot carry (undefined, a function, a bigint, a non-finite number, a hole
|
|
8
|
+
* in an array) and on a lone surrogate, rather than silently dropping or
|
|
9
|
+
* repairing it.
|
|
10
|
+
*/
|
|
11
|
+
export declare function canonicalJson(value: unknown): string;
|
|
12
|
+
/**
|
|
13
|
+
* `sha256:` and the lowercase hex SHA-256 of the canonical JSON of a plan
|
|
14
|
+
* without `asOf` and `decisions`. Assumes `plan` already passed
|
|
15
|
+
* `planViolations()`: it checks nothing itself.
|
|
16
|
+
*/
|
|
17
|
+
export declare function digestOfValidPlan(plan: Readonly<Record<string, unknown>>): string;
|
|
18
|
+
/**
|
|
19
|
+
* The plan digest. Throws when the plan does not validate against the plan
|
|
20
|
+
* contract, rules included: an invalid plan has no digest.
|
|
21
|
+
*/
|
|
22
|
+
export declare function planDigest(plan: unknown): string;
|
|
23
|
+
//# sourceMappingURL=plan-digest.d.ts.map
|