@clossys/writer 0.3.9 → 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.
Files changed (136) hide show
  1. package/README.md +647 -6
  2. package/dist/addressability.d.ts +11 -1
  3. package/dist/addressability.d.ts.map +1 -1
  4. package/dist/addressability.js +169 -3
  5. package/dist/addressability.js.map +1 -1
  6. package/dist/approval-bypass.d.ts +120 -0
  7. package/dist/approval-bypass.d.ts.map +1 -0
  8. package/dist/approval-bypass.js +2318 -0
  9. package/dist/approval-bypass.js.map +1 -0
  10. package/dist/approval.d.ts +62 -0
  11. package/dist/approval.d.ts.map +1 -0
  12. package/dist/approval.js +421 -0
  13. package/dist/approval.js.map +1 -0
  14. package/dist/approve-cli.d.ts +82 -0
  15. package/dist/approve-cli.d.ts.map +1 -0
  16. package/dist/approve-cli.js +430 -0
  17. package/dist/approve-cli.js.map +1 -0
  18. package/dist/cli.d.ts +15 -0
  19. package/dist/cli.d.ts.map +1 -1
  20. package/dist/cli.js +264 -22
  21. package/dist/cli.js.map +1 -1
  22. package/dist/field-options.d.ts +59 -0
  23. package/dist/field-options.d.ts.map +1 -0
  24. package/dist/field-options.js +109 -0
  25. package/dist/field-options.js.map +1 -0
  26. package/dist/fold-wallpaper-gate.d.ts +7 -0
  27. package/dist/fold-wallpaper-gate.d.ts.map +1 -0
  28. package/dist/fold-wallpaper-gate.js +29 -0
  29. package/dist/fold-wallpaper-gate.js.map +1 -0
  30. package/dist/front-door.check.d.ts +2 -0
  31. package/dist/front-door.check.d.ts.map +1 -0
  32. package/dist/front-door.check.js +8 -0
  33. package/dist/front-door.check.js.map +1 -0
  34. package/dist/front-door.d.ts +82 -0
  35. package/dist/front-door.d.ts.map +1 -0
  36. package/dist/front-door.js +271 -0
  37. package/dist/front-door.js.map +1 -0
  38. package/dist/generated/advisor-plan-contract.generated.d.ts +3 -0
  39. package/dist/generated/advisor-plan-contract.generated.d.ts.map +1 -0
  40. package/dist/generated/advisor-plan-contract.generated.js +430 -0
  41. package/dist/generated/advisor-plan-contract.generated.js.map +1 -0
  42. package/dist/generated/contract-schema.generated.d.ts +97 -0
  43. package/dist/generated/contract-schema.generated.d.ts.map +1 -0
  44. package/dist/generated/contract-schema.generated.js +496 -0
  45. package/dist/generated/contract-schema.generated.js.map +1 -0
  46. package/dist/index.d.ts +18 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +26 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/live-copy-gate.d.ts +16 -0
  51. package/dist/live-copy-gate.d.ts.map +1 -0
  52. package/dist/live-copy-gate.js +135 -0
  53. package/dist/live-copy-gate.js.map +1 -0
  54. package/dist/messaging-kit.d.ts +113 -0
  55. package/dist/messaging-kit.d.ts.map +1 -0
  56. package/dist/messaging-kit.js +121 -0
  57. package/dist/messaging-kit.js.map +1 -0
  58. package/dist/passage.d.ts +2 -1
  59. package/dist/passage.d.ts.map +1 -1
  60. package/dist/passage.js +2 -1
  61. package/dist/passage.js.map +1 -1
  62. package/dist/plan-authority.d.ts +73 -0
  63. package/dist/plan-authority.d.ts.map +1 -0
  64. package/dist/plan-authority.js +126 -0
  65. package/dist/plan-authority.js.map +1 -0
  66. package/dist/plan-contract.d.ts +16 -0
  67. package/dist/plan-contract.d.ts.map +1 -0
  68. package/dist/plan-contract.js +33 -0
  69. package/dist/plan-contract.js.map +1 -0
  70. package/dist/plan-digest.d.ts +23 -0
  71. package/dist/plan-digest.d.ts.map +1 -0
  72. package/dist/plan-digest.js +82 -0
  73. package/dist/plan-digest.js.map +1 -0
  74. package/dist/plan-rules.d.ts +54 -0
  75. package/dist/plan-rules.d.ts.map +1 -0
  76. package/dist/plan-rules.js +145 -0
  77. package/dist/plan-rules.js.map +1 -0
  78. package/dist/render-registry-parity.d.ts +20 -0
  79. package/dist/render-registry-parity.d.ts.map +1 -0
  80. package/dist/render-registry-parity.js +45 -0
  81. package/dist/render-registry-parity.js.map +1 -0
  82. package/dist/resolve.d.ts +40 -6
  83. package/dist/resolve.d.ts.map +1 -1
  84. package/dist/resolve.js +144 -18
  85. package/dist/resolve.js.map +1 -1
  86. package/dist/scan.d.ts +32 -0
  87. package/dist/scan.d.ts.map +1 -1
  88. package/dist/scan.js +67 -6
  89. package/dist/scan.js.map +1 -1
  90. package/dist/schema.d.ts +1 -0
  91. package/dist/schema.d.ts.map +1 -1
  92. package/dist/schema.js +231 -5
  93. package/dist/schema.js.map +1 -1
  94. package/dist/site-identity.d.ts +88 -0
  95. package/dist/site-identity.d.ts.map +1 -0
  96. package/dist/site-identity.js +82 -0
  97. package/dist/site-identity.js.map +1 -0
  98. package/dist/treatment-word-budget.d.ts +31 -0
  99. package/dist/treatment-word-budget.d.ts.map +1 -0
  100. package/dist/treatment-word-budget.js +80 -0
  101. package/dist/treatment-word-budget.js.map +1 -0
  102. package/dist/types.d.ts +76 -7
  103. package/dist/types.d.ts.map +1 -1
  104. package/dist/types.js +9 -7
  105. package/dist/types.js.map +1 -1
  106. package/fit-signals.json +11 -0
  107. package/package.json +201 -11
  108. package/skill/SKILL.md +49 -0
  109. package/src/addressability.ts +186 -4
  110. package/src/approval-bypass.ts +2263 -0
  111. package/src/approval.ts +491 -0
  112. package/src/approve-cli.ts +474 -0
  113. package/src/cli.ts +274 -22
  114. package/src/field-options.ts +134 -0
  115. package/src/fold-wallpaper-gate.ts +29 -0
  116. package/src/front-door.check.ts +10 -0
  117. package/src/front-door.ts +312 -0
  118. package/src/generated/advisor-plan-contract.generated.ts +430 -0
  119. package/src/generated/contract-schema.generated.ts +520 -0
  120. package/src/index.ts +107 -1
  121. package/src/live-copy-gate.ts +150 -0
  122. package/src/messaging-kit.ts +195 -0
  123. package/src/passage.ts +2 -1
  124. package/src/plan-authority.ts +160 -0
  125. package/src/plan-contract.ts +45 -0
  126. package/src/plan-digest.ts +81 -0
  127. package/src/plan-rules.ts +179 -0
  128. package/src/render-registry-parity.ts +65 -0
  129. package/src/resolve.ts +185 -19
  130. package/src/scan.ts +97 -6
  131. package/src/schema.ts +247 -5
  132. package/src/site-identity.ts +125 -0
  133. package/src/treatment-word-budget.ts +100 -0
  134. package/src/types.ts +83 -7
  135. package/templates/front-door.en.json +426 -0
  136. package/CHANGELOG.md +0 -330
package/dist/resolve.d.ts CHANGED
@@ -7,14 +7,47 @@
7
7
  * source provenance, and an approved entry. The result exposes every one of
8
8
  * those inputs so `@example/surface` can place them in its output
9
9
  * manifest without knowing how a consumer stores copy.
10
+ *
11
+ * Target policy: an owner-approved entry resolves on both `"preview"` and
12
+ * `"production"` (the default target). A delegate-approved entry resolves
13
+ * freely on `"preview"`, but on `"production"` is refused
14
+ * (`delegate-approval-refused`) unless the caller opts in with
15
+ * `acceptDelegateInProduction: true`, or passes `approvalPlan`, the bytes of
16
+ * a plan whose latest approval names that plan's own digest and which
17
+ * declares `delegatedCopyApproval` covering the entry — a delegate's sign-off
18
+ * is not, by itself, sufficient evidence to publish, only to preview.
10
19
  */
11
20
  import type { CopyRef, CopyRegistry, CopyResolution, CopyResolver } from "./types.js";
12
- export type CopyResolveIssueReason = "invalid-registry" | "invalid-ref" | "locale-mismatch" | "unknown-copy-id" | "copy-not-approved" | "missing-placeholder-value" | "unexpected-placeholder-value";
21
+ import type { PlanDelegateCopyRefusal } from "./plan-authority.js";
22
+ export type CopyResolveIssueReason = "invalid-registry" | "invalid-ref" | "locale-mismatch" | "unknown-copy-id" | "copy-not-approved" | "missing-placeholder-value" | "unexpected-placeholder-value" | "invalid-options" | "approval-stale" | "approval-expired" | "delegate-approval-refused";
23
+ /** Which audience a resolution is for — see this file's top doc comment for the policy difference. */
24
+ export type CopyResolveTarget = "preview" | "production";
25
+ /** Options controlling how strictly `resolveCopyRef`/`createCopyResolver` treat an entry's approval record. */
26
+ export interface CopyResolveOptions {
27
+ /** Defaults to `"production"`. */
28
+ target?: CopyResolveTarget;
29
+ /** Defaults to `false`. Only meaningful when `target` is `"production"`. */
30
+ acceptDelegateInProduction?: boolean;
31
+ /** Defaults to `new Date()`, evaluated per call. */
32
+ now?: Date;
33
+ /**
34
+ * The bytes of an Advisor plan record (a `Uint8Array`; Node's `Buffer` is
35
+ * one), read by the caller. Consulted only for a delegate-approved entry on
36
+ * `"production"` when `acceptDelegateInProduction` is not `true`: see
37
+ * `planDelegateCopyAuthority()`. Not a `Uint8Array`, or given together with
38
+ * `acceptDelegateInProduction: true`, is `"invalid-options"`.
39
+ */
40
+ approvalPlan?: Uint8Array;
41
+ }
42
+ /** Why an `approvalPlan` did not authorize an entry: the plan's own refusal, or that the entry is outside the scopes the plan declares. */
43
+ export type CopyResolvePlanRefusal = PlanDelegateCopyRefusal | "entry-outside-plan-scopes";
13
44
  export interface CopyResolveIssue {
14
45
  reason: CopyResolveIssueReason;
15
46
  message: string;
16
47
  id?: string;
17
48
  placeholder?: string;
49
+ /** Only on `"delegate-approval-refused"` when an `approvalPlan` was given: why it did not authorize this entry. */
50
+ planRefusal?: CopyResolvePlanRefusal;
18
51
  }
19
52
  export interface CopyResolveResult {
20
53
  resolution?: CopyResolution;
@@ -23,11 +56,12 @@ export interface CopyResolveResult {
23
56
  }
24
57
  /**
25
58
  * Resolves a `CopyRef` against one locale-specific registry. Any absence,
26
- * lifecycle failure, locale mismatch, or placeholder mismatch produces no
27
- * text and a non-complete result. Consumers may log `issues`; renderers must
28
- * treat a missing `resolution` as an unresolved required input.
59
+ * lifecycle failure, locale mismatch, staleness/expiry, delegate-in-production
60
+ * refusal, or placeholder mismatch produces no text and a non-complete
61
+ * result. Consumers may log `issues`; renderers must treat a missing
62
+ * `resolution` as an unresolved required input.
29
63
  */
30
- export declare function resolveCopyRef(registry: CopyRegistry | unknown, ref: CopyRef | unknown): CopyResolveResult;
64
+ export declare function resolveCopyRef(registry: CopyRegistry | unknown, ref: CopyRef | unknown, options?: CopyResolveOptions | unknown): CopyResolveResult;
31
65
  /** Creates the narrow resolver callback for presentation code. */
32
- export declare function createCopyResolver(registry: CopyRegistry | unknown): CopyResolver;
66
+ export declare function createCopyResolver(registry: CopyRegistry | unknown, options?: CopyResolveOptions | unknown): CopyResolver;
33
67
  //# sourceMappingURL=resolve.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,cAAc,EACd,YAAY,EAEb,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,sBAAsB,GAC9B,kBAAkB,GAClB,aAAa,GACb,iBAAiB,GACjB,iBAAiB,GACjB,mBAAmB,GACnB,2BAA2B,GAC3B,8BAA8B,CAAC;AAEnC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAkBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,GAAG,iBAAiB,CAsG1G;AAED,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,GAAG,YAAY,CAEjF"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,cAAc,EAEd,YAAY,EAEb,MAAM,YAAY,CAAC;AAIpB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE,MAAM,MAAM,sBAAsB,GAC9B,kBAAkB,GAClB,aAAa,GACb,iBAAiB,GACjB,iBAAiB,GACjB,mBAAmB,GACnB,2BAA2B,GAC3B,8BAA8B,GAC9B,iBAAiB,GACjB,gBAAgB,GAChB,kBAAkB,GAClB,2BAA2B,CAAC;AAEhC,sGAAsG;AACtG,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC;AAEzD,+GAA+G;AAC/G,MAAM,WAAW,kBAAkB;IACjC,kCAAkC;IAClC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,4EAA4E;IAC5E,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,oDAAoD;IACpD,GAAG,CAAC,EAAE,IAAI,CAAC;IACX;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,UAAU,CAAC;CAC3B;AAED,2IAA2I;AAC3I,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,GAAG,2BAA2B,CAAC;AAE3F,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mHAAmH;IACnH,WAAW,CAAC,EAAE,sBAAsB,CAAC;CACtC;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAmDD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,YAAY,GAAG,OAAO,EAChC,GAAG,EAAE,OAAO,GAAG,OAAO,EACtB,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,GACrC,iBAAiB,CA2LnB;AAED,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,GAAG,YAAY,CAEzH"}
package/dist/resolve.js CHANGED
@@ -7,8 +7,19 @@
7
7
  * source provenance, and an approved entry. The result exposes every one of
8
8
  * those inputs so `@example/surface` can place them in its output
9
9
  * manifest without knowing how a consumer stores copy.
10
+ *
11
+ * Target policy: an owner-approved entry resolves on both `"preview"` and
12
+ * `"production"` (the default target). A delegate-approved entry resolves
13
+ * freely on `"preview"`, but on `"production"` is refused
14
+ * (`delegate-approval-refused`) unless the caller opts in with
15
+ * `acceptDelegateInProduction: true`, or passes `approvalPlan`, the bytes of
16
+ * a plan whose latest approval names that plan's own digest and which
17
+ * declares `delegatedCopyApproval` covering the entry — a delegate's sign-off
18
+ * is not, by itself, sufficient evidence to publish, only to preview.
10
19
  */
11
20
  import { validateCopyRegistryShape } from "./schema.js";
21
+ import { isApprovalExpired, isApprovalStale, isEntryInDelegateScope } from "./approval.js";
22
+ import { isPlanBytes, planDelegateCopyAuthority } from "./plan-authority.js";
12
23
  function isNonEmptyString(value) {
13
24
  return typeof value === "string" && value.trim().length > 0;
14
25
  }
@@ -21,13 +32,53 @@ function isCopyValue(value) {
21
32
  function interpolate(text, values) {
22
33
  return text.replace(/\{([^{}]+)\}/g, (_match, name) => String(values[name]));
23
34
  }
35
+ /**
36
+ * Reads a well-formed `CopyResolveOptions`, or returns null — checked before
37
+ * anything else so a malformed caller-supplied options object fails closed
38
+ * rather than silently falling back to defaults. Each property is read
39
+ * exactly once, into a local that is validated and then used, so a getter
40
+ * cannot answer differently at validation and at use.
41
+ */
42
+ function readResolveOptions(value) {
43
+ if (value === undefined)
44
+ return { target: "production", acceptDelegateInProduction: false, now: new Date(), approvalPlan: undefined };
45
+ if (!isPlainObject(value))
46
+ return null;
47
+ const { target, acceptDelegateInProduction, now, approvalPlan } = value;
48
+ if (target !== undefined && target !== "preview" && target !== "production")
49
+ return null;
50
+ if (acceptDelegateInProduction !== undefined && typeof acceptDelegateInProduction !== "boolean")
51
+ return null;
52
+ if (now !== undefined && !(now instanceof Date && Number.isFinite(now.getTime())))
53
+ return null;
54
+ if (approvalPlan !== undefined && !isPlanBytes(approvalPlan))
55
+ return null;
56
+ // Two authorities for one decision is an ambiguity, so it is refused: no precedence needs defining.
57
+ if (approvalPlan !== undefined && acceptDelegateInProduction === true)
58
+ return null;
59
+ return {
60
+ target: target ?? "production",
61
+ acceptDelegateInProduction: acceptDelegateInProduction ?? false,
62
+ now: now ?? new Date(),
63
+ approvalPlan,
64
+ };
65
+ }
24
66
  /**
25
67
  * Resolves a `CopyRef` against one locale-specific registry. Any absence,
26
- * lifecycle failure, locale mismatch, or placeholder mismatch produces no
27
- * text and a non-complete result. Consumers may log `issues`; renderers must
28
- * treat a missing `resolution` as an unresolved required input.
68
+ * lifecycle failure, locale mismatch, staleness/expiry, delegate-in-production
69
+ * refusal, or placeholder mismatch produces no text and a non-complete
70
+ * result. Consumers may log `issues`; renderers must treat a missing
71
+ * `resolution` as an unresolved required input.
29
72
  */
30
- export function resolveCopyRef(registry, ref) {
73
+ export function resolveCopyRef(registry, ref, options) {
74
+ const settings = readResolveOptions(options);
75
+ if (settings === null) {
76
+ return {
77
+ issues: [{ reason: "invalid-options", message: "CopyResolveOptions is malformed." }],
78
+ complete: false,
79
+ };
80
+ }
81
+ const { target, acceptDelegateInProduction, now, approvalPlan } = settings;
31
82
  const registryFindings = validateCopyRegistryShape(registry);
32
83
  if (registryFindings.length > 0) {
33
84
  return {
@@ -79,6 +130,70 @@ export function resolveCopyRef(registry, ref) {
79
130
  complete: false,
80
131
  };
81
132
  }
133
+ const approval = entry.approval;
134
+ // Set only when an approvalPlan, not the flag, authorized a delegate entry on production.
135
+ let authorizingPlanDigest;
136
+ if (approval) {
137
+ if (isApprovalStale(entry)) {
138
+ return {
139
+ issues: [
140
+ {
141
+ reason: "approval-stale",
142
+ id: validRef.id,
143
+ message: `CopyRef "${validRef.id}"'s approval record no longer matches its current text.`,
144
+ },
145
+ ],
146
+ complete: false,
147
+ };
148
+ }
149
+ if (isApprovalExpired(approval, now)) {
150
+ return {
151
+ issues: [
152
+ {
153
+ reason: "approval-expired",
154
+ id: validRef.id,
155
+ message: `CopyRef "${validRef.id}"'s approval expired at ${approval.expiresAt}.`,
156
+ },
157
+ ],
158
+ complete: false,
159
+ };
160
+ }
161
+ if (approval.approvedBy === "delegate" && target === "production" && acceptDelegateInProduction !== true) {
162
+ // The flag did not authorize this entry, so only a plan can. The plan is
163
+ // read here and nowhere else: never for preview, an owner entry, a
164
+ // record-less entry, or once the flag is true, and never before the
165
+ // entry's own staleness and expiry, which outrank it.
166
+ if (approvalPlan === undefined) {
167
+ return {
168
+ issues: [
169
+ {
170
+ reason: "delegate-approval-refused",
171
+ id: validRef.id,
172
+ message: `CopyRef "${validRef.id}" was approved by a delegate; production resolution requires acceptDelegateInProduction: true.`,
173
+ },
174
+ ],
175
+ complete: false,
176
+ };
177
+ }
178
+ const planRefused = (code) => ({
179
+ issues: [
180
+ {
181
+ reason: "delegate-approval-refused",
182
+ id: validRef.id,
183
+ planRefusal: code,
184
+ message: `CopyRef "${validRef.id}" was approved by a delegate; the approvalPlan given does not authorize it on production (${code}).`,
185
+ },
186
+ ],
187
+ complete: false,
188
+ });
189
+ const authority = planDelegateCopyAuthority(approvalPlan);
190
+ if (!authority.authorized)
191
+ return planRefused(authority.refusal);
192
+ if (authority.scopes !== undefined && !isEntryInDelegateScope(entry.id, authority.scopes))
193
+ return planRefused("entry-outside-plan-scopes");
194
+ authorizingPlanDigest = authority.planDigest;
195
+ }
196
+ }
82
197
  const values = validRef.values ?? {};
83
198
  const issues = [];
84
199
  const declared = new Set(entry.placeholders ?? []);
@@ -112,22 +227,33 @@ export function resolveCopyRef(registry, ref) {
112
227
  }
113
228
  if (issues.length > 0)
114
229
  return { issues, complete: false };
115
- return {
116
- resolution: {
117
- ref: validRef,
118
- text: interpolate(entry.text, values),
119
- recordId: validRegistry.id,
120
- revision: validRegistry.revision,
121
- locale: validRegistry.locale,
122
- source: validRegistry.source,
123
- entryId: entry.id,
124
- },
125
- issues: [],
126
- complete: true,
230
+ const resolution = {
231
+ ref: validRef,
232
+ text: interpolate(entry.text, values),
233
+ recordId: validRegistry.id,
234
+ revision: validRegistry.revision,
235
+ locale: validRegistry.locale,
236
+ source: validRegistry.source,
237
+ entryId: entry.id,
127
238
  };
239
+ // Only set when the entry actually carries a record — an approved entry
240
+ // with no record resolves exactly as it did before this field existed,
241
+ // with no `approval` key on the resolution at all.
242
+ if (approval) {
243
+ // Built explicitly, so the digest key exists only when a plan authorized the entry.
244
+ const facts = approval.approvedBy === "owner"
245
+ ? { approvedBy: "owner", pendingOwnerReview: false }
246
+ : {
247
+ approvedBy: "delegate",
248
+ pendingOwnerReview: approval.pendingOwnerReview === true,
249
+ ...(authorizingPlanDigest === undefined ? {} : { authorizingPlanDigest }),
250
+ };
251
+ resolution.approval = facts;
252
+ }
253
+ return { resolution, issues: [], complete: true };
128
254
  }
129
255
  /** Creates the narrow resolver callback for presentation code. */
130
- export function createCopyResolver(registry) {
131
- return (ref) => resolveCopyRef(registry, ref).resolution;
256
+ export function createCopyResolver(registry, options) {
257
+ return (ref) => resolveCopyRef(registry, ref, options).resolution;
132
258
  }
133
259
  //# sourceMappingURL=resolve.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"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"}
package/dist/scan.d.ts CHANGED
@@ -454,4 +454,36 @@ interface ExtractResult {
454
454
  * source-text fixture.
455
455
  */
456
456
  export declare function extractCopyCandidates(content: string, filePath: string): ExtractResult;
457
+ /** One string or template literal `maskNonCode` found, with its position in the original content. */
458
+ export interface MaskedLiteral {
459
+ kind: "string" | "template";
460
+ line: number;
461
+ /** Index of the opening quote/backtick. */
462
+ start: number;
463
+ /** Index one past the closing quote/backtick. */
464
+ end: number;
465
+ raw: string;
466
+ /** The literal's static text, unescaped; a template's interpolations are dropped. */
467
+ text: string;
468
+ }
469
+ /** `maskNonCode`'s result. `code` has the same length and line breaks as the input. */
470
+ export interface CodeMask {
471
+ code: string;
472
+ literals: MaskedLiteral[];
473
+ failure?: string;
474
+ }
475
+ /**
476
+ * Pure. Runs this file's tokenizer over `content` and returns a copy of it in
477
+ * which every comment, string literal, template static segment, regex literal
478
+ * and (in a `.tsx`/`.jsx` file) JSX text run is replaced by spaces, keeping
479
+ * every newline and every character offset. A caller can then match code
480
+ * patterns against `code` without a comment or a string ever matching, and
481
+ * look up the literal at a given offset through `literals`. A template's
482
+ * `${...}` interpolations stay visible in `code`, because they are code.
483
+ *
484
+ * Exported for `approval-bypass.ts` so it delegates literal and comment
485
+ * boundaries to this tokenizer instead of growing a second one. Deliberately
486
+ * not re-exported from `index.ts`: it is an internal helper, not package API.
487
+ */
488
+ export declare function maskNonCode(content: string, filePath: string): CodeMask;
457
489
  //# sourceMappingURL=scan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"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"}
package/dist/scan.js CHANGED
@@ -479,6 +479,7 @@ function tokenize(content, isJsxFile) {
479
479
  const literals = [];
480
480
  const jsxTexts = [];
481
481
  const unchecked = [];
482
+ const opaque = [];
482
483
  const n = content.length;
483
484
  let i = 0;
484
485
  let line = 1;
@@ -536,6 +537,7 @@ function tokenize(content, isJsxFile) {
536
537
  }
537
538
  if (ck === '"' || ck === "'") {
538
539
  const q = ck;
540
+ const stringStart = j;
539
541
  j++;
540
542
  while (j < n && content[j] !== q) {
541
543
  if (content[j] === "\\")
@@ -545,6 +547,7 @@ function tokenize(content, isJsxFile) {
545
547
  j++;
546
548
  }
547
549
  j++; // consume closing quote, or run past EOF — caught by the outer unterminated-template check
550
+ opaque.push([stringStart, Math.min(j, n)]);
548
551
  continue;
549
552
  }
550
553
  if (ck === "`") {
@@ -556,6 +559,7 @@ function tokenize(content, isJsxFile) {
556
559
  }
557
560
  if (ck === "/" && content[j + 1] === "/") {
558
561
  const nl = content.indexOf("\n", j);
562
+ opaque.push([j, nl === -1 ? n : nl]);
559
563
  j = nl === -1 ? n : nl;
560
564
  continue;
561
565
  }
@@ -564,6 +568,7 @@ function tokenize(content, isJsxFile) {
564
568
  if (close === -1)
565
569
  return -1;
566
570
  advanceLine(j, close + 2);
571
+ opaque.push([j, close + 2]);
567
572
  j = close + 2;
568
573
  continue;
569
574
  }
@@ -574,24 +579,29 @@ function tokenize(content, isJsxFile) {
574
579
  /** Skips an entire template literal starting at `pos` (`content[pos] === "\`"`), including every interpolation it contains, recursively. Returns the index one past its closing backtick, or `-1` if unterminated. */
575
580
  function skipTemplateFrom(pos) {
576
581
  let j = pos + 1;
582
+ let segmentStart = pos;
577
583
  while (j < n) {
578
584
  const cj = content[j];
579
585
  if (cj === "\\" && j + 1 < n) {
580
586
  j += 2;
581
587
  continue;
582
588
  }
583
- if (cj === "`")
589
+ if (cj === "`") {
590
+ opaque.push([segmentStart, j + 1]);
584
591
  return j + 1;
592
+ }
585
593
  if (cj === "\n") {
586
594
  line++;
587
595
  j++;
588
596
  continue;
589
597
  }
590
598
  if (cj === "$" && content[j + 1] === "{") {
599
+ opaque.push([segmentStart, j]);
591
600
  const next = skipInterpolation(j + 2);
592
601
  if (next === -1)
593
602
  return -1;
594
603
  j = next;
604
+ segmentStart = j;
595
605
  continue;
596
606
  }
597
607
  j++;
@@ -653,6 +663,7 @@ function tokenize(content, isJsxFile) {
653
663
  literalFailure = `unterminated string starting at line ${startLine}`;
654
664
  return -1;
655
665
  }
666
+ opaque.push([start, j]);
656
667
  literals.push({
657
668
  kind: "string",
658
669
  line: startLine,
@@ -686,6 +697,7 @@ function tokenize(content, isJsxFile) {
686
697
  let j = pos + 1;
687
698
  let current = "";
688
699
  let closed = false;
700
+ let segmentStart = pos;
689
701
  while (j < n) {
690
702
  const cj = content[j];
691
703
  if (cj === "\\" && j + 1 < n) {
@@ -699,6 +711,7 @@ function tokenize(content, isJsxFile) {
699
711
  break;
700
712
  }
701
713
  if (cj === "$" && content[j + 1] === "{") {
714
+ opaque.push([segmentStart, j]);
702
715
  staticParts.push(unescape(current));
703
716
  current = "";
704
717
  placeholderCount++;
@@ -714,6 +727,7 @@ function tokenize(content, isJsxFile) {
714
727
  return -1;
715
728
  }
716
729
  j = next;
730
+ segmentStart = j;
717
731
  continue;
718
732
  }
719
733
  if (cj === "\n")
@@ -726,6 +740,7 @@ function tokenize(content, isJsxFile) {
726
740
  return -1;
727
741
  }
728
742
  staticParts.push(unescape(current));
743
+ opaque.push([segmentStart, j]);
729
744
  literals.push({
730
745
  kind: "template",
731
746
  line: startLine,
@@ -775,6 +790,7 @@ function tokenize(content, isJsxFile) {
775
790
  }
776
791
  if (cj === "/" && content[j + 1] === "/") {
777
792
  const nl = content.indexOf("\n", j);
793
+ opaque.push([j, nl === -1 ? n : nl]);
778
794
  j = nl === -1 ? n : nl;
779
795
  continue;
780
796
  }
@@ -783,6 +799,7 @@ function tokenize(content, isJsxFile) {
783
799
  if (close === -1)
784
800
  return -1;
785
801
  advanceLine(j, close + 2);
802
+ opaque.push([j, close + 2]);
786
803
  j = close + 2;
787
804
  continue;
788
805
  }
@@ -881,6 +898,7 @@ function tokenize(content, isJsxFile) {
881
898
  let m = found + 1;
882
899
  while (m < n && /[a-z]/i.test(content[m]))
883
900
  m++;
901
+ opaque.push([j, m]);
884
902
  j = m;
885
903
  localLast = "value";
886
904
  continue;
@@ -916,8 +934,10 @@ function tokenize(content, isJsxFile) {
916
934
  const flush = () => {
917
935
  if (j > runStart) {
918
936
  const raw = content.slice(runStart, j);
919
- if (raw.trim().length > 0)
937
+ if (raw.trim().length > 0) {
920
938
  jsxTexts.push({ line: runStartLine, raw });
939
+ opaque.push([runStart, j]);
940
+ }
921
941
  }
922
942
  };
923
943
  while (j < n) {
@@ -1052,11 +1072,13 @@ function tokenize(content, isJsxFile) {
1052
1072
  const entryLiteralsCount = literals.length;
1053
1073
  const entryJsxTextsCount = jsxTexts.length;
1054
1074
  const entryUncheckedCount = unchecked.length;
1075
+ const entryOpaqueCount = opaque.length;
1055
1076
  function backtrack() {
1056
1077
  line = entryLine;
1057
1078
  literals.length = entryLiteralsCount;
1058
1079
  jsxTexts.length = entryJsxTextsCount;
1059
1080
  unchecked.length = entryUncheckedCount;
1081
+ opaque.length = entryOpaqueCount;
1060
1082
  return null;
1061
1083
  }
1062
1084
  if (depth > MAX_JSX_DEPTH) {
@@ -1118,6 +1140,7 @@ function tokenize(content, isJsxFile) {
1118
1140
  // above.
1119
1141
  if (cj === "/" && content[j + 1] === "/") {
1120
1142
  const nl = content.indexOf("\n", j);
1143
+ opaque.push([j, nl === -1 ? n : nl]);
1121
1144
  j = nl === -1 ? n : nl;
1122
1145
  continue;
1123
1146
  }
@@ -1126,6 +1149,7 @@ function tokenize(content, isJsxFile) {
1126
1149
  if (close === -1)
1127
1150
  return backtrack(); // unterminated block comment — not committed, silently not-JSX
1128
1151
  advanceLine(j, close + 2);
1152
+ opaque.push([j, close + 2]);
1129
1153
  j = close + 2;
1130
1154
  continue;
1131
1155
  }
@@ -1226,6 +1250,7 @@ function tokenize(content, isJsxFile) {
1226
1250
  // line comment
1227
1251
  if (c === "/" && content[i + 1] === "/") {
1228
1252
  const nl = content.indexOf("\n", i);
1253
+ opaque.push([i, nl === -1 ? n : nl]);
1229
1254
  i = nl === -1 ? n : nl;
1230
1255
  continue;
1231
1256
  }
@@ -1233,8 +1258,9 @@ function tokenize(content, isJsxFile) {
1233
1258
  if (c === "/" && content[i + 1] === "*") {
1234
1259
  const close = content.indexOf("*/", i + 2);
1235
1260
  if (close === -1)
1236
- return { literals, jsxTexts, unchecked, failure: `unterminated block comment starting at line ${line}` };
1261
+ return { literals, jsxTexts, unchecked, opaque, failure: `unterminated block comment starting at line ${line}` };
1237
1262
  advanceLine(i, close + 2);
1263
+ opaque.push([i, close + 2]);
1238
1264
  i = close + 2;
1239
1265
  continue;
1240
1266
  }
@@ -1242,7 +1268,7 @@ function tokenize(content, isJsxFile) {
1242
1268
  if (c === '"' || c === "'") {
1243
1269
  const end = scanStringLiteral(i);
1244
1270
  if (end === -1)
1245
- return { literals, jsxTexts, unchecked, failure: literalFailure };
1271
+ return { literals, jsxTexts, unchecked, opaque, failure: literalFailure };
1246
1272
  lastTokenType = "value";
1247
1273
  i = end;
1248
1274
  continue;
@@ -1251,7 +1277,7 @@ function tokenize(content, isJsxFile) {
1251
1277
  if (c === "`") {
1252
1278
  const end = scanTemplateLiteral(i);
1253
1279
  if (end === -1)
1254
- return { literals, jsxTexts, unchecked, failure: literalFailure };
1280
+ return { literals, jsxTexts, unchecked, opaque, failure: literalFailure };
1255
1281
  lastTokenType = "value";
1256
1282
  i = end;
1257
1283
  continue;
@@ -1311,6 +1337,7 @@ function tokenize(content, isJsxFile) {
1311
1337
  let k = found + 1;
1312
1338
  while (k < n && /[a-z]/i.test(content[k]))
1313
1339
  k++;
1340
+ opaque.push([i, k]);
1314
1341
  i = k;
1315
1342
  lastTokenType = "value";
1316
1343
  continue;
@@ -1351,7 +1378,7 @@ function tokenize(content, isJsxFile) {
1351
1378
  lastTokenType = "other";
1352
1379
  i++;
1353
1380
  }
1354
- return { literals, jsxTexts, unchecked };
1381
+ return { literals, jsxTexts, unchecked, opaque };
1355
1382
  }
1356
1383
  // ---------------------------------------------------------- classification
1357
1384
  const ARIA_DATA_ATTR_RE = /^(aria|data)[-A-Z]/i;
@@ -1725,4 +1752,38 @@ export function extractCopyCandidates(content, filePath) {
1725
1752
  const unchecked = rawUnchecked.map((u) => ({ file: filePath, line: u.line, kind: u.kind, detail: u.detail }));
1726
1753
  return { candidates, excluded, citations, unchecked };
1727
1754
  }
1755
+ /**
1756
+ * Pure. Runs this file's tokenizer over `content` and returns a copy of it in
1757
+ * which every comment, string literal, template static segment, regex literal
1758
+ * and (in a `.tsx`/`.jsx` file) JSX text run is replaced by spaces, keeping
1759
+ * every newline and every character offset. A caller can then match code
1760
+ * patterns against `code` without a comment or a string ever matching, and
1761
+ * look up the literal at a given offset through `literals`. A template's
1762
+ * `${...}` interpolations stay visible in `code`, because they are code.
1763
+ *
1764
+ * Exported for `approval-bypass.ts` so it delegates literal and comment
1765
+ * boundaries to this tokenizer instead of growing a second one. Deliberately
1766
+ * not re-exported from `index.ts`: it is an internal helper, not package API.
1767
+ */
1768
+ export function maskNonCode(content, filePath) {
1769
+ const { literals, opaque, failure } = tokenize(content, JSX_FILE_RE.test(filePath));
1770
+ const masked = content.split("");
1771
+ if (!failure) {
1772
+ for (const [start, end] of opaque) {
1773
+ for (let k = start; k < end && k < masked.length; k++) {
1774
+ if (masked[k] !== "\n")
1775
+ masked[k] = " ";
1776
+ }
1777
+ }
1778
+ }
1779
+ const out = literals.map((lit) => ({
1780
+ kind: lit.kind,
1781
+ line: lit.line,
1782
+ start: lit.start,
1783
+ end: lit.end,
1784
+ raw: lit.raw,
1785
+ text: lit.staticParts.join(""),
1786
+ }));
1787
+ return failure ? { code: masked.join(""), literals: out, failure } : { code: masked.join(""), literals: out };
1788
+ }
1728
1789
  //# sourceMappingURL=scan.js.map