@telorun/analyzer 0.62.0 → 0.63.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 (146) hide show
  1. package/dist/analysis-registry.d.ts.map +1 -1
  2. package/dist/analysis-registry.js +6 -0
  3. package/dist/analyzer.d.ts +1 -1
  4. package/dist/analyzer.d.ts.map +1 -1
  5. package/dist/analyzer.js +343 -13
  6. package/dist/call-graph.d.ts.map +1 -1
  7. package/dist/call-graph.js +2 -7
  8. package/dist/flatten-for-analyzer.js +1 -1
  9. package/dist/import-resolution-diagnostics.d.ts +9 -2
  10. package/dist/import-resolution-diagnostics.d.ts.map +1 -1
  11. package/dist/import-resolution-diagnostics.js +26 -7
  12. package/dist/index.d.ts +15 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +13 -1
  15. package/dist/invocation-contract.d.ts +6 -1
  16. package/dist/invocation-contract.d.ts.map +1 -1
  17. package/dist/invocation-contract.js +27 -4
  18. package/dist/loaded-types.d.ts +12 -3
  19. package/dist/loaded-types.d.ts.map +1 -1
  20. package/dist/manifest-loader.d.ts +0 -1
  21. package/dist/manifest-loader.d.ts.map +1 -1
  22. package/dist/manifest-loader.js +62 -41
  23. package/dist/manifest-schemas.d.ts +699 -0
  24. package/dist/manifest-schemas.d.ts.map +1 -1
  25. package/dist/manifest-schemas.js +306 -14
  26. package/dist/module-compatibility.d.ts +40 -0
  27. package/dist/module-compatibility.d.ts.map +1 -0
  28. package/dist/module-compatibility.js +52 -0
  29. package/dist/ref-slot-reading.d.ts +30 -0
  30. package/dist/ref-slot-reading.d.ts.map +1 -0
  31. package/dist/ref-slot-reading.js +139 -0
  32. package/dist/referrer-rule.d.ts +67 -0
  33. package/dist/referrer-rule.d.ts.map +1 -0
  34. package/dist/referrer-rule.js +96 -0
  35. package/dist/release/index.d.ts +1 -1
  36. package/dist/release/index.d.ts.map +1 -1
  37. package/dist/release/index.js +1 -1
  38. package/dist/release/payload-digest.d.ts +7 -3
  39. package/dist/release/payload-digest.d.ts.map +1 -1
  40. package/dist/release/payload-digest.js +7 -3
  41. package/dist/release/version-stamp.d.ts +16 -0
  42. package/dist/release/version-stamp.d.ts.map +1 -1
  43. package/dist/release/version-stamp.js +52 -0
  44. package/dist/release/workspace-config.d.ts +10 -6
  45. package/dist/release/workspace-config.d.ts.map +1 -1
  46. package/dist/release/workspace-config.js +10 -6
  47. package/dist/resolve-schema-ref-kinds.d.ts +4 -3
  48. package/dist/resolve-schema-ref-kinds.d.ts.map +1 -1
  49. package/dist/resolve-schema-ref-kinds.js +16 -0
  50. package/dist/resolve-throws-union.d.ts.map +1 -1
  51. package/dist/resolve-throws-union.js +4 -3
  52. package/dist/resolve-zone-containment.d.ts +99 -0
  53. package/dist/resolve-zone-containment.d.ts.map +1 -0
  54. package/dist/resolve-zone-containment.js +212 -0
  55. package/dist/resolve-zone-requirements.d.ts +5 -0
  56. package/dist/resolve-zone-requirements.d.ts.map +1 -1
  57. package/dist/resolve-zone-requirements.js +48 -7
  58. package/dist/resource-rule.d.ts +106 -0
  59. package/dist/resource-rule.d.ts.map +1 -0
  60. package/dist/resource-rule.js +236 -0
  61. package/dist/rule-condition.d.ts +50 -0
  62. package/dist/rule-condition.d.ts.map +1 -0
  63. package/dist/rule-condition.js +108 -0
  64. package/dist/schema-keywords.d.ts.map +1 -1
  65. package/dist/schema-keywords.js +20 -0
  66. package/dist/schema-projection.d.ts +171 -0
  67. package/dist/schema-projection.d.ts.map +1 -0
  68. package/dist/schema-projection.js +317 -0
  69. package/dist/step-slot.d.ts +39 -0
  70. package/dist/step-slot.d.ts.map +1 -0
  71. package/dist/step-slot.js +49 -0
  72. package/dist/telo-version.d.ts +1 -1
  73. package/dist/telo-version.js +1 -1
  74. package/dist/validate-cel-context.d.ts.map +1 -1
  75. package/dist/validate-cel-context.js +17 -3
  76. package/dist/validate-durable-regions.d.ts +15 -0
  77. package/dist/validate-durable-regions.d.ts.map +1 -0
  78. package/dist/validate-durable-regions.js +336 -0
  79. package/dist/validate-references.d.ts.map +1 -1
  80. package/dist/validate-references.js +44 -2
  81. package/dist/validate-referrer-rules.d.ts +120 -0
  82. package/dist/validate-referrer-rules.d.ts.map +1 -0
  83. package/dist/validate-referrer-rules.js +255 -0
  84. package/dist/validate-resource-rules.d.ts +114 -0
  85. package/dist/validate-resource-rules.d.ts.map +1 -0
  86. package/dist/validate-resource-rules.js +283 -0
  87. package/dist/validate-schema-projection.d.ts +32 -0
  88. package/dist/validate-schema-projection.d.ts.map +1 -0
  89. package/dist/validate-schema-projection.js +110 -0
  90. package/dist/validate-step-inputs.d.ts +2 -1
  91. package/dist/validate-step-inputs.d.ts.map +1 -1
  92. package/dist/validate-step-inputs.js +5 -3
  93. package/dist/validate-throws-coverage.d.ts.map +1 -1
  94. package/dist/validate-throws-coverage.js +11 -5
  95. package/dist/validate-zone-slots.d.ts +2 -2
  96. package/dist/validate-zone-slots.d.ts.map +1 -1
  97. package/dist/validate-zone-slots.js +202 -6
  98. package/dist/validate-zone-violations.d.ts +12 -0
  99. package/dist/validate-zone-violations.d.ts.map +1 -0
  100. package/dist/validate-zone-violations.js +169 -0
  101. package/dist/value-type-keyword.d.ts +1 -1
  102. package/dist/value-type-keyword.d.ts.map +1 -1
  103. package/dist/value-type-keyword.js +4 -0
  104. package/dist/zone-slot.d.ts +61 -0
  105. package/dist/zone-slot.d.ts.map +1 -1
  106. package/dist/zone-slot.js +86 -5
  107. package/package.json +2 -2
  108. package/src/analysis-registry.ts +6 -0
  109. package/src/analyzer.ts +395 -14
  110. package/src/call-graph.ts +2 -8
  111. package/src/flatten-for-analyzer.ts +1 -1
  112. package/src/import-resolution-diagnostics.ts +25 -7
  113. package/src/index.ts +73 -0
  114. package/src/invocation-contract.ts +45 -2
  115. package/src/loaded-types.ts +12 -3
  116. package/src/manifest-loader.ts +87 -55
  117. package/src/manifest-schemas.ts +328 -14
  118. package/src/module-compatibility.ts +72 -0
  119. package/src/ref-slot-reading.ts +156 -0
  120. package/src/referrer-rule.ts +116 -0
  121. package/src/release/index.ts +1 -0
  122. package/src/release/payload-digest.ts +7 -3
  123. package/src/release/version-stamp.ts +58 -0
  124. package/src/release/workspace-config.ts +10 -6
  125. package/src/resolve-schema-ref-kinds.ts +28 -4
  126. package/src/resolve-throws-union.ts +4 -3
  127. package/src/resolve-zone-containment.ts +329 -0
  128. package/src/resolve-zone-requirements.ts +67 -7
  129. package/src/resource-rule.ts +252 -0
  130. package/src/rule-condition.ts +126 -0
  131. package/src/schema-keywords.ts +24 -0
  132. package/src/schema-projection.ts +403 -0
  133. package/src/step-slot.ts +64 -0
  134. package/src/telo-version.ts +1 -1
  135. package/src/validate-cel-context.ts +17 -3
  136. package/src/validate-durable-regions.ts +401 -0
  137. package/src/validate-references.ts +57 -2
  138. package/src/validate-referrer-rules.ts +373 -0
  139. package/src/validate-resource-rules.ts +401 -0
  140. package/src/validate-schema-projection.ts +184 -0
  141. package/src/validate-step-inputs.ts +5 -3
  142. package/src/validate-throws-coverage.ts +12 -5
  143. package/src/validate-zone-slots.ts +192 -8
  144. package/src/validate-zone-violations.ts +190 -0
  145. package/src/value-type-keyword.ts +4 -0
  146. package/src/zone-slot.ts +114 -5
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The single reader for `x-telo-referrer-rules` — a kind declaring, as data,
3
+ * what must be true of whoever REFERENCES one of its resources.
4
+ *
5
+ * `x-telo-resource-rules` relates the fields of one resource; this relates a
6
+ * resource to the one that reached it. `Http.Reference` renders the OpenAPI
7
+ * document its server collects, so a server mounting it without an `openapi:`
8
+ * block has nothing to render — a disagreement neither kind can state alone,
9
+ * and one that otherwise surfaces only at boot, after the port is bound.
10
+ *
11
+ * Declared by the kind that HAS the requirement, never by the kind that must
12
+ * satisfy it. That is what lets a third-party mount carry its own requirement
13
+ * without `Http.Server` knowing the kind exists — and it is what keeps the rule
14
+ * free of a kind literal on the subject side, where the spelling would be the
15
+ * consumer's import alias rather than anything the rule author controls.
16
+ *
17
+ * The CEL scope is `self` (the declaring resource) and `referrer` (the one that
18
+ * references it). Deliberately NOT `this`: in a resource rule `this` is an
19
+ * ELEMENT of a collection, and binding it to a whole foreign manifest would give
20
+ * one word two meanings across the two families.
21
+ *
22
+ * Lenient by design, the `ref-slot.ts` precedent: anything unreadable here reads
23
+ * as absent, and `validate-referrer-rules.ts` is the strict half that reports it.
24
+ *
25
+ * Browser-safe: no Node built-ins.
26
+ */
27
+ import { type ResourceRuleSeverity } from "./resource-rule.js";
28
+ export declare const REFERRER_RULES_ANNOTATION = "x-telo-referrer-rules";
29
+ export interface ReferrerRule {
30
+ /**
31
+ * Kind the referring resource must be for this rule to apply, in the
32
+ * alias-qualified grammar `extends:` and `x-telo-ref` use — canonicalized in
33
+ * the declaring module's scope at registration, so evaluation never sees an
34
+ * alias. Absent = any referrer, which conflates "references me" with the
35
+ * relation the rule is about, so a kind should write it.
36
+ */
37
+ readonly referrer?: string;
38
+ /** CEL source. TRUE when the rule holds. */
39
+ readonly condition: string;
40
+ /** The rule's own name, carried in `data.rule`. Never a diagnostic code —
41
+ * every violation reports under the analyzer-owned envelope. */
42
+ readonly code: string;
43
+ readonly message: string;
44
+ readonly severity: ResourceRuleSeverity;
45
+ /** Position in the annotation array — the anchor for a declaration defect. */
46
+ readonly index: number;
47
+ }
48
+ /** The annotation exactly as written, for the strict half. `undefined` when the
49
+ * kind declares none; a non-array is returned as-is so the shape can be
50
+ * reported rather than silently skipped. */
51
+ export declare function readRawReferrerRules(schema: unknown): unknown;
52
+ /** Every rule this kind declares that is well-formed enough to run. */
53
+ export declare function readReferrerRules(schema: unknown): ReferrerRule[];
54
+ /** True when this node carries the annotation — the recognizer the schema-kind
55
+ * canonicalization walk tests, so shape knowledge stays in this file. */
56
+ export declare function hasReferrerRules(node: Record<string, unknown>): boolean;
57
+ /**
58
+ * Rewrite each rule's `referrer:` kind through `rewrite`, in place.
59
+ *
60
+ * The mirror of `rewriteRequiresZoneKind`: the alias→canonical rule lives in
61
+ * `resolve-schema-ref-kinds.ts` and the shape lives here, so a filter is
62
+ * canonical everywhere downstream and a name that resolves to nothing is
63
+ * reported once, at the kind that wrote it. A rewrite returning `undefined`
64
+ * leaves the value as written — the caller reports it.
65
+ */
66
+ export declare function rewriteReferrerRuleKinds(node: Record<string, unknown>, rewrite: (kind: string) => string | undefined): void;
67
+ //# sourceMappingURL=referrer-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"referrer-rule.d.ts","sourceRoot":"","sources":["../src/referrer-rule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAe,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AAEjE,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;qEACiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAMD;;6CAE6C;AAC7C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAG7D;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,EAAE,CAwBjE;AAED;0EAC0E;AAC1E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAEvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAC5C,IAAI,CAQN"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * The single reader for `x-telo-referrer-rules` — a kind declaring, as data,
3
+ * what must be true of whoever REFERENCES one of its resources.
4
+ *
5
+ * `x-telo-resource-rules` relates the fields of one resource; this relates a
6
+ * resource to the one that reached it. `Http.Reference` renders the OpenAPI
7
+ * document its server collects, so a server mounting it without an `openapi:`
8
+ * block has nothing to render — a disagreement neither kind can state alone,
9
+ * and one that otherwise surfaces only at boot, after the port is bound.
10
+ *
11
+ * Declared by the kind that HAS the requirement, never by the kind that must
12
+ * satisfy it. That is what lets a third-party mount carry its own requirement
13
+ * without `Http.Server` knowing the kind exists — and it is what keeps the rule
14
+ * free of a kind literal on the subject side, where the spelling would be the
15
+ * consumer's import alias rather than anything the rule author controls.
16
+ *
17
+ * The CEL scope is `self` (the declaring resource) and `referrer` (the one that
18
+ * references it). Deliberately NOT `this`: in a resource rule `this` is an
19
+ * ELEMENT of a collection, and binding it to a whole foreign manifest would give
20
+ * one word two meanings across the two families.
21
+ *
22
+ * Lenient by design, the `ref-slot.ts` precedent: anything unreadable here reads
23
+ * as absent, and `validate-referrer-rules.ts` is the strict half that reports it.
24
+ *
25
+ * Browser-safe: no Node built-ins.
26
+ */
27
+ import { celSourceOf } from "./resource-rule.js";
28
+ export const REFERRER_RULES_ANNOTATION = "x-telo-referrer-rules";
29
+ function isObject(value) {
30
+ return !!value && typeof value === "object" && !Array.isArray(value);
31
+ }
32
+ /** The annotation exactly as written, for the strict half. `undefined` when the
33
+ * kind declares none; a non-array is returned as-is so the shape can be
34
+ * reported rather than silently skipped. */
35
+ export function readRawReferrerRules(schema) {
36
+ if (!isObject(schema))
37
+ return undefined;
38
+ return schema[REFERRER_RULES_ANNOTATION];
39
+ }
40
+ /** Every rule this kind declares that is well-formed enough to run. */
41
+ export function readReferrerRules(schema) {
42
+ const raw = readRawReferrerRules(schema);
43
+ if (!Array.isArray(raw))
44
+ return [];
45
+ const rules = [];
46
+ raw.forEach((entry, index) => {
47
+ if (!isObject(entry))
48
+ return;
49
+ const condition = celSourceOf(entry.condition);
50
+ const { code, message, referrer } = entry;
51
+ if (!condition || typeof code !== "string" || typeof message !== "string")
52
+ return;
53
+ if (code.length === 0 || message.length === 0)
54
+ return;
55
+ if (referrer !== undefined && typeof referrer !== "string")
56
+ return;
57
+ if (entry.severity !== undefined && entry.severity !== "warning" && entry.severity !== "error") {
58
+ return;
59
+ }
60
+ rules.push({
61
+ ...(referrer === undefined ? {} : { referrer }),
62
+ condition,
63
+ code,
64
+ message,
65
+ severity: entry.severity === "warning" ? "warning" : "error",
66
+ index,
67
+ });
68
+ });
69
+ return rules;
70
+ }
71
+ /** True when this node carries the annotation — the recognizer the schema-kind
72
+ * canonicalization walk tests, so shape knowledge stays in this file. */
73
+ export function hasReferrerRules(node) {
74
+ return Array.isArray(node[REFERRER_RULES_ANNOTATION]);
75
+ }
76
+ /**
77
+ * Rewrite each rule's `referrer:` kind through `rewrite`, in place.
78
+ *
79
+ * The mirror of `rewriteRequiresZoneKind`: the alias→canonical rule lives in
80
+ * `resolve-schema-ref-kinds.ts` and the shape lives here, so a filter is
81
+ * canonical everywhere downstream and a name that resolves to nothing is
82
+ * reported once, at the kind that wrote it. A rewrite returning `undefined`
83
+ * leaves the value as written — the caller reports it.
84
+ */
85
+ export function rewriteReferrerRuleKinds(node, rewrite) {
86
+ const raw = node[REFERRER_RULES_ANNOTATION];
87
+ if (!Array.isArray(raw))
88
+ return;
89
+ for (const entry of raw) {
90
+ if (!isObject(entry) || typeof entry.referrer !== "string")
91
+ continue;
92
+ const rewritten = rewrite(entry.referrer);
93
+ if (rewritten !== undefined)
94
+ entry.referrer = rewritten;
95
+ }
96
+ }
@@ -20,7 +20,7 @@ export { LOCALLY_DERIVED_LAYERS, MANIFEST_LAYER, diffLayerDigests, layerDigestKe
20
20
  export type { LayerChange, LayerDigests } from "./payload-digest.js";
21
21
  export { orderByImports, planRelease } from "./release-plan.js";
22
22
  export type { ArtifactKind, BumpReason, ChangelogEntry, ModuleEvidence, PlannedModule, ReleaseDiagnostic, ReleaseEvidence, ReleasePlan, } from "./release-plan.js";
23
- export { VersionStampError, readManifestVersion, stampCrateVersion, stampManifestVersion, stampPackageVersion, } from "./version-stamp.js";
23
+ export { VersionStampError, readManifestVersion, stampCrateVersion, stampManifestVersion, stampSelfNpmPins, stampPackageVersion, } from "./version-stamp.js";
24
24
  export { WORKSPACE_FILENAME, WorkspaceConfigError, parseWorkspaceConfig } from "./workspace-config.js";
25
25
  export type { WorkspaceConfig } from "./workspace-config.js";
26
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpG,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnG,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,YAAY,EACV,YAAY,EACZ,UAAU,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACvG,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpG,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnG,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,YAAY,EACV,YAAY,EACZ,UAAU,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACvG,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -14,5 +14,5 @@ export { FragmentError, normalizeModuleKey, parseFragment, serializeFragment } f
14
14
  export { EMPTY_LEDGER, LEDGER_PATH, LedgerError, parseLedger, serializeLedger } from "./ledger.js";
15
15
  export { LOCALLY_DERIVED_LAYERS, MANIFEST_LAYER, diffLayerDigests, layerDigestKey, } from "./payload-digest.js";
16
16
  export { orderByImports, planRelease } from "./release-plan.js";
17
- export { VersionStampError, readManifestVersion, stampCrateVersion, stampManifestVersion, stampPackageVersion, } from "./version-stamp.js";
17
+ export { VersionStampError, readManifestVersion, stampCrateVersion, stampManifestVersion, stampSelfNpmPins, stampPackageVersion, } from "./version-stamp.js";
18
18
  export { WORKSPACE_FILENAME, WorkspaceConfigError, parseWorkspaceConfig } from "./workspace-config.js";
@@ -25,9 +25,13 @@ export declare const MANIFEST_LAYER = "manifest";
25
25
  * Exactly one today, and for a structural reason rather than an omission: the
26
26
  * published `layers:` index lives *inside* `telo.yaml`, so it cannot carry that
27
27
  * file's own digest — the entry would have to be computed over bytes containing
28
- * it. Nor can the digest be recovered by hashing what the registry serves, since
29
- * the transport injects the index at push time and the published text is
30
- * therefore not the text the payload builder produced.
28
+ * it. `readPublishedDigests` reads that index, so it has no answer for this key.
29
+ *
30
+ * It is no longer *unknowable*, though, only absent from the index: the payload
31
+ * builder now writes the index, so its manifest is the published text and this
32
+ * digest is what hashing the served `telo.yaml` yields. Reconciling it would
33
+ * mean fetching the manifest per module rather than reading one index — worth
34
+ * doing, and a separate change from the one that made it possible.
31
35
  *
32
36
  * It stays in the ledger regardless, because it is the only thing that sees a
33
37
  * **manifest-only change**: a schema edit, a new kind, a description, a
@@ -1 +1 @@
1
- {"version":3,"file":"payload-digest.d.ts","sourceRoot":"","sources":["../../src/release/payload-digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAiB,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAE/F,sDAAsD;AACtD,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5D,yDAAyD;AACzD,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAA6B,CAAC;AAErF;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAM5F;AAED;;;mBAGmB;AACnB,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;mCACmC;AACnC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,WAAW,EAAE,CAQzF"}
1
+ {"version":3,"file":"payload-digest.d.ts","sourceRoot":"","sources":["../../src/release/payload-digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAiB,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAE/F,sDAAsD;AACtD,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5D,yDAAyD;AACzD,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAA6B,CAAC;AAErF;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAM5F;AAED;;;mBAGmB;AACnB,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;mCACmC;AACnC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,WAAW,EAAE,CAQzF"}
@@ -23,9 +23,13 @@ export const MANIFEST_LAYER = "manifest";
23
23
  * Exactly one today, and for a structural reason rather than an omission: the
24
24
  * published `layers:` index lives *inside* `telo.yaml`, so it cannot carry that
25
25
  * file's own digest — the entry would have to be computed over bytes containing
26
- * it. Nor can the digest be recovered by hashing what the registry serves, since
27
- * the transport injects the index at push time and the published text is
28
- * therefore not the text the payload builder produced.
26
+ * it. `readPublishedDigests` reads that index, so it has no answer for this key.
27
+ *
28
+ * It is no longer *unknowable*, though, only absent from the index: the payload
29
+ * builder now writes the index, so its manifest is the published text and this
30
+ * digest is what hashing the served `telo.yaml` yields. Reconciling it would
31
+ * mean fetching the manifest per module rather than reading one index — worth
32
+ * doing, and a separate change from the one that made it possible.
29
33
  *
30
34
  * It stays in the ledger regardless, because it is the only thing that sees a
31
35
  * **manifest-only change**: a schema edit, a new kind, a description, a
@@ -25,6 +25,22 @@ export declare class VersionStampError extends Error {
25
25
  * of how many lines it was allowed to hit.
26
26
  */
27
27
  export declare function stampManifestVersion(text: string, version: string, where: string): string | undefined;
28
+ /**
29
+ * `pkg:npm/<name>@<version>` candidates naming the module's OWN package.
30
+ *
31
+ * A module has one version, and its manifest pins the package it ships itself —
32
+ * so the pin has to move with the rest of it. Left behind, the manifest names a
33
+ * tarball older than the module describing it, which is exactly how an
34
+ * npm-delivered module came to point at a years-old version of itself.
35
+ *
36
+ * Anchored on the `controllers:` SCALARS the YAML actually holds, not on a free
37
+ * text match: this file's whole rule is find the scalar, splice its span, touch
38
+ * nothing else, and a bare regex over the document would also reach a PURL
39
+ * written in a description, an example or a comment. Matched by exact package
40
+ * name, so a PURL naming a DIFFERENT package — a real dependency, pinned
41
+ * deliberately — is untouched.
42
+ */
43
+ export declare function stampSelfNpmPins(text: string, packageName: string, version: string, where?: string): string;
28
44
  /** Read the module doc's `metadata.version` without rewriting it. */
29
45
  export declare function readManifestVersion(text: string): string | undefined;
30
46
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"version-stamp.d.ts","sourceRoot":"","sources":["../../src/release/version-stamp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAqB/C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAYpB;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CA+BpB"}
1
+ {"version":3,"file":"version-stamp.d.ts","sourceRoot":"","sources":["../../src/release/version-stamp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAqB/C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAYpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,KAAK,SAAgB,GACpB,MAAM,CAoCR;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CA+BpB"}
@@ -56,6 +56,58 @@ export function stampManifestVersion(text, version, where) {
56
56
  return undefined;
57
57
  return spliceScalar(text, node, version, where);
58
58
  }
59
+ /**
60
+ * `pkg:npm/<name>@<version>` candidates naming the module's OWN package.
61
+ *
62
+ * A module has one version, and its manifest pins the package it ships itself —
63
+ * so the pin has to move with the rest of it. Left behind, the manifest names a
64
+ * tarball older than the module describing it, which is exactly how an
65
+ * npm-delivered module came to point at a years-old version of itself.
66
+ *
67
+ * Anchored on the `controllers:` SCALARS the YAML actually holds, not on a free
68
+ * text match: this file's whole rule is find the scalar, splice its span, touch
69
+ * nothing else, and a bare regex over the document would also reach a PURL
70
+ * written in a description, an example or a comment. Matched by exact package
71
+ * name, so a PURL naming a DIFFERENT package — a real dependency, pinned
72
+ * deliberately — is untouched.
73
+ */
74
+ export function stampSelfNpmPins(text, packageName, version, where = "controllers") {
75
+ const docs = parseAllDocuments(text, { customTags: defaultCustomTags() });
76
+ const prefix = `pkg:npm/${packageName}@`;
77
+ const edits = [];
78
+ for (const doc of docs) {
79
+ const controllers = doc.get("controllers", true);
80
+ const items = controllers?.items;
81
+ if (!Array.isArray(items))
82
+ continue;
83
+ for (const item of items) {
84
+ if (!isScalar(item) || typeof item.value !== "string")
85
+ continue;
86
+ const purl = item.value;
87
+ if (!purl.startsWith(prefix))
88
+ continue;
89
+ // Everything from the version up to the first qualifier or fragment is the
90
+ // pin; the rest of the PURL (`?local_path=…#Export`) is carried through.
91
+ const rest = purl.slice(prefix.length);
92
+ const tail = rest.search(/[?#]/);
93
+ const rewritten = `${prefix}${version}${tail === -1 ? "" : rest.slice(tail)}`;
94
+ if (rewritten === purl)
95
+ continue;
96
+ const range = item.range;
97
+ if (!range) {
98
+ throw new VersionStampError(`${where}: a controller PURL carries no source range.`);
99
+ }
100
+ const [start, end] = range;
101
+ const replacement = renderFixReplacement(text.slice(start, end), rewritten);
102
+ if (replacement === undefined) {
103
+ throw new VersionStampError(`${where}: the controller PURL '${purl}' cannot be rewritten in place. ` +
104
+ `Write it as a plain or quoted scalar on one line.`);
105
+ }
106
+ edits.push({ start, end, newText: replacement });
107
+ }
108
+ }
109
+ return edits.length === 0 ? text : applyTextEdits(text, edits);
110
+ }
59
111
  /** Read the module doc's `metadata.version` without rewriting it. */
60
112
  export function readManifestVersion(text) {
61
113
  const docs = parseAllDocuments(text, { customTags: defaultCustomTags() });
@@ -8,12 +8,16 @@
8
8
  * would read every example and every cached `.telo/manifests` copy as a released
9
9
  * module).
10
10
  *
11
- * The file is **optional and read only by `telo release`**. Nothing else — not
12
- * `run`, `check`, `publish`, `install`, `upgrade`, `migrate`, `module`, and not
13
- * the kernellooks for it, so a single-manifest repo, a bare `examples/`
14
- * directory and a third-party module checkout keep working with nothing added.
15
- * Any field added later must be true of the whole tree, not derivable from it,
16
- * and harmless by its absence.
11
+ * The file is **optional**, and everything reading it is harmless without one.
12
+ * `telo release` requires one. `telo run` uses its LOCATION — never `modules:`,
13
+ * which is release scope as the bound on the walk-up that collects `.env` /
14
+ * `.env.local`, and with no marker reads the manifest's own directory alone, as
15
+ * it did before this file existed; a bound is what keeps that walk out of a
16
+ * user's home directory. Nothing else — not `check`, `publish`, `install`,
17
+ * `upgrade`, `migrate`, `module`, and not the kernel — looks for it, so a
18
+ * single-manifest repo, a bare `examples/` directory and a third-party module
19
+ * checkout keep working with nothing added. Any field added later must be true
20
+ * of the whole tree, not derivable from it, and harmless by its absence.
17
21
  *
18
22
  * Parsing lives here, in the browser-safe half, because the editor answers
19
23
  * "what does changing this library bump?" from the same model. Finding the file
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-config.d.ts","sourceRoot":"","sources":["../../src/release/workspace-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,qBAAa,oBAAqB,SAAQ,KAAK;CAAG;AAElD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAoCjF"}
1
+ {"version":3,"file":"workspace-config.d.ts","sourceRoot":"","sources":["../../src/release/workspace-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,qBAAa,oBAAqB,SAAQ,KAAK;CAAG;AAElD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAoCjF"}
@@ -8,12 +8,16 @@
8
8
  * would read every example and every cached `.telo/manifests` copy as a released
9
9
  * module).
10
10
  *
11
- * The file is **optional and read only by `telo release`**. Nothing else — not
12
- * `run`, `check`, `publish`, `install`, `upgrade`, `migrate`, `module`, and not
13
- * the kernellooks for it, so a single-manifest repo, a bare `examples/`
14
- * directory and a third-party module checkout keep working with nothing added.
15
- * Any field added later must be true of the whole tree, not derivable from it,
16
- * and harmless by its absence.
11
+ * The file is **optional**, and everything reading it is harmless without one.
12
+ * `telo release` requires one. `telo run` uses its LOCATION — never `modules:`,
13
+ * which is release scope as the bound on the walk-up that collects `.env` /
14
+ * `.env.local`, and with no marker reads the manifest's own directory alone, as
15
+ * it did before this file existed; a bound is what keeps that walk out of a
16
+ * user's home directory. Nothing else — not `check`, `publish`, `install`,
17
+ * `upgrade`, `migrate`, `module`, and not the kernel — looks for it, so a
18
+ * single-manifest repo, a bare `examples/` directory and a third-party module
19
+ * checkout keep working with nothing added. Any field added later must be true
20
+ * of the whole tree, not derivable from it, and harmless by its absence.
17
21
  *
18
22
  * Parsing lives here, in the browser-safe half, because the editor answers
19
23
  * "what does changing this library bump?" from the same model. Finding the file
@@ -21,9 +21,10 @@ export interface RefConstraintIssue {
21
21
  manifest: ResourceManifest;
22
22
  reason: RefConstraintReason;
23
23
  /** Which annotation carried the unresolved name: an `x-telo-ref` constraint
24
- * (the default) or an `x-telo-requires-zone` provider kind the caller
25
- * reports the latter as ZONE_PROVIDER_UNRESOLVED. */
26
- annotation?: "ref" | "zone";
24
+ * (the default), an `x-telo-requires-zone` provider kind, or an
25
+ * `x-telo-referrer-rules` `referrer:` filter — the caller reports those as
26
+ * ZONE_PROVIDER_UNRESOLVED and REFERRER_RULE_INVALID. */
27
+ annotation?: "ref" | "zone" | "referrer";
27
28
  /** For `gated`: the target module and the kinds it does export. */
28
29
  gate?: {
29
30
  module: string;
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-schema-ref-kinds.d.ts","sourceRoot":"","sources":["../src/resolve-schema-ref-kinds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMzD;;;;;;;;sDAQsD;AACtD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAEjE,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ;sFACkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,mBAAmB,CAAC;IAC5B;;0DAEsD;IACtD,UAAU,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC5B,mEAAmE;IACnE,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9C;+BAC2B;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,mBAAmB,GAAG,cAAc,CAAC,GAClE,kBAAkB,EAAE,CAsEtB"}
1
+ {"version":3,"file":"resolve-schema-ref-kinds.d.ts","sourceRoot":"","sources":["../src/resolve-schema-ref-kinds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAWzD;;;;;;;;sDAQsD;AACtD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAEjE,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ;sFACkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,mBAAmB,CAAC;IAC5B;;;8DAG0D;IAC1D,UAAU,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;IACzC,mEAAmE;IACnE,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9C;+BAC2B;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,mBAAmB,GAAG,cAAc,CAAC,GAClE,kBAAkB,EAAE,CAwFtB"}
@@ -1,4 +1,5 @@
1
1
  import { rewriteRefSlotKinds } from "./ref-slot.js";
2
+ import { REFERRER_RULES_ANNOTATION, hasReferrerRules, rewriteReferrerRuleKinds, } from "./referrer-rule.js";
2
3
  import { hasRequiresZone, rewriteRequiresZoneKind } from "./zone-slot.js";
3
4
  const REF_ANNOTATION = "x-telo-ref";
4
5
  /** True for the legacy identity form, which is split on `#` by the identity table. */
@@ -95,6 +96,21 @@ export function resolveSchemaRefKinds(definition, resolver) {
95
96
  return undefined;
96
97
  });
97
98
  }
99
+ if (hasReferrerRules(obj)) {
100
+ // A referrer rule's `referrer:` filter names a kind through the identical
101
+ // alias-qualified grammar, resolved in the same declaring scope — so the
102
+ // evaluation pass compares canonical kinds and never has to know which
103
+ // alias the CONSUMER happened to import the kind under. That is the whole
104
+ // reason such a rule can be sound where the same test written on the
105
+ // referring kind cannot.
106
+ rewriteReferrerRuleKinds(obj, (kind) => {
107
+ const result = resolver.resolveKindResult(kind);
108
+ if (result.status === "ok")
109
+ return result.kind;
110
+ record(kind, `${path}.${REFERRER_RULES_ANNOTATION}`, "referrer");
111
+ return undefined;
112
+ });
113
+ }
98
114
  for (const key of Object.keys(obj)) {
99
115
  walk(obj[key], path ? `${path}.${key}` : key);
100
116
  }
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-throws-union.d.ts","sourceRoot":"","sources":["../src/resolve-throws-union.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED;;gFAEgF;AAChF,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,gFAAgF;IAChF,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACnC;;;8EAG0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB;;;;gDAI4C;IAC5C,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC;IACvB;;;wFAGoF;IACpF,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC5C,0FAA0F;IAC1F,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC/B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,gBAAgB,EAAE,EAChC,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,aAAa,EACtB,eAAe,GAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAa,EACvD,WAAW,GAAE,GAAG,CAAC,MAAM,CAAa,GACnC,UAAU,CAUZ;AA6CD;;;;8CAI8C;AAC9C,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,EAAE,UAAU,GACd,WAAW,CAiDb"}
1
+ {"version":3,"file":"resolve-throws-union.d.ts","sourceRoot":"","sources":["../src/resolve-throws-union.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED;;gFAEgF;AAChF,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,gFAAgF;IAChF,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACnC;;;8EAG0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB;;;;gDAI4C;IAC5C,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC;IACvB;;;wFAGoF;IACpF,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC5C,0FAA0F;IAC1F,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC/B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,gBAAgB,EAAE,EAChC,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,aAAa,EACtB,eAAe,GAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAa,EACvD,WAAW,GAAE,GAAG,CAAC,MAAM,CAAa,GACnC,UAAU,CAUZ;AA6CD;;;;8CAI8C;AAC9C,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,EAAE,UAAU,GACd,WAAW,CAiDb"}
@@ -1,5 +1,6 @@
1
1
  import { isTaggedSentinel } from "@telorun/templating";
2
2
  import { scopeResolverForModule } from "./alias-resolver.js";
3
+ import { readStepSlot } from "./step-slot.js";
3
4
  /** Code a non-`InvokeError` failure surfaces as inside a `catch` block. Mirrors
4
5
  * `PLAIN_ERROR_CODE` in `@telorun/run`'s `toSequenceError`: any invoke can throw
5
6
  * a plain error, which the catch sees as `error.code === "INTERNAL_ERROR"`. */
@@ -114,8 +115,8 @@ function resolveInherited(manifest, definition, ctx, ownerModule) {
114
115
  if (!props)
115
116
  return result;
116
117
  for (const [fieldName, fieldSchema] of Object.entries(props)) {
117
- const stepCtx = fieldSchema["x-telo-step-context"];
118
- if (!stepCtx?.invoke)
118
+ const stepCtx = readStepSlot(fieldSchema);
119
+ if (!stepCtx)
119
120
  continue;
120
121
  const steps = manifest[fieldName];
121
122
  if (!Array.isArray(steps))
@@ -136,7 +137,7 @@ function collectStepArrayThrows(steps, invokeField, enclosingTryCodes, ctx, owne
136
137
  /** Walk one step, dispatching by shape. Generic for any Run.Sequence-style
137
138
  * composer: the step keys it recognises (`try` / `catch` / `finally` / `then`
138
139
  * / `else` / `elseif` / `do` / `cases` / `default`) are the same set already
139
- * traversed by the analyzer's `x-telo-step-context` schema builder, so future
140
+ * traversed by the analyzer's step-body walk, so future
140
141
  * composers that reuse those shape conventions work without changes here. */
141
142
  function collectStepThrows(step, invokeField, enclosingTryCodes, ctx, ownerModule) {
142
143
  if (step[invokeField]) {
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Zone containment — *what is inside this zone*, which is the opposite question
3
+ * from the one `resolve-zone-requirements.ts` answers.
4
+ *
5
+ * The landed projection propagates a requirement callee→caller and asks *is this
6
+ * requirement satisfied*. Every check built on zone ATTRIBUTES asks the reverse:
7
+ * a `noSuspend` region has to know what it contains before it can forbid parking
8
+ * inside it, a `replayed` region before it can reject a detached dispatch, an
9
+ * `idempotent` region before it can call impure CEL a broken promise. So this is
10
+ * a DOWNWARD walk from a providing slot to everything its body reaches.
11
+ *
12
+ * It is a second consumer of the shared call graph, not a second graph, and it
13
+ * is **parameterized over the attribute that opens the region** — so the durable
14
+ * zone (`replayed`) and the constraint zones (`noSuspend`, `atomic`,
15
+ * `idempotent`) share one traversal. It resolves an attribute NAME and nothing
16
+ * else: no kind is named here, which is what keeps `modules/durable` out of the
17
+ * analyzer's surface and satisfies the topology-driven constraint.
18
+ *
19
+ * **Two shapes of body slot, one region.** A slot may hold its body as a
20
+ * reference to an executable (`Sql.Transaction.steps`) or carry a step array
21
+ * natively (the shared `Step` fragment, which any kind may point at). Both are
22
+ * regions; the first is entered through the slot's edge, the second through the
23
+ * step nodes the slot declares. Handling only the first would have made the
24
+ * checks silently vacuous on exactly the kinds written after the grammar became
25
+ * shared vocabulary.
26
+ *
27
+ * **The walk under-approximates, and that is the safe direction — for a CHECK.**
28
+ * A dynamically dispatched edge is invisible here, so a check over the result
29
+ * may stay silent where it should have spoken, and the runtime enforcement is
30
+ * what closes it. A consumer at the OPPOSITE polarity — the durable manifest
31
+ * digest, whose blind spot is silent replay against changed code rather than a
32
+ * missed diagnostic — must not inherit this tolerance, and verifies its coverage
33
+ * against the journal instead of trusting this set.
34
+ *
35
+ * Browser-safe: no Node built-ins.
36
+ */
37
+ import type { ResourceDefinition, ResourceManifest } from "@telorun/sdk";
38
+ import type { CallGraph, CallGraphEdge, CallGraphNode, ResourceGraphNode } from "./call-graph.js";
39
+ /** One node the region reaches, with the route taken to it. */
40
+ export interface ContainedNode {
41
+ node: CallGraphNode;
42
+ /** Labels of the hops from the body slot to this node, for a diagnostic that
43
+ * names the path rather than only the endpoint. */
44
+ via: string[];
45
+ }
46
+ /** A dispatch that leaves the region without extending it.
47
+ *
48
+ * Recorded rather than followed, because the two facts are different and both
49
+ * are wanted: the zone's lifetime does NOT reach the target (so nothing inside
50
+ * it is contained), while the dispatch itself is a site inside the region that
51
+ * a check may forbid outright — `DURABLE_DETACH_FORBIDDEN` is exactly that. */
52
+ export interface RegionBoundary {
53
+ edge: CallGraphEdge;
54
+ /** The resource whose slot dispatches this way. */
55
+ from: ResourceGraphNode;
56
+ via: string[];
57
+ /** Why the zone stops here: the uses that do not extend it. */
58
+ escaping: string[];
59
+ }
60
+ /** A region opened by one providing slot carrying the requested attribute. */
61
+ export interface ZoneRegion {
62
+ /** The attribute that opened it — the one the walk was asked for. */
63
+ attribute: string;
64
+ /** The author's reason, quoted verbatim by every diagnostic over this region.
65
+ * Present by construction: an attribute's value IS the reason. */
66
+ reason: string;
67
+ /** The resource whose slot establishes the zone. */
68
+ provider: ResourceGraphNode;
69
+ /** Field-map path of the body slot (`steps`, `invoke`). */
70
+ slot: string;
71
+ /** Every attribute the slot declares, not only the requested one — a consumer
72
+ * deciding collapse reads `atomic` and `idempotent` off one region. */
73
+ attributes: Readonly<Record<string, string>>;
74
+ /** Everything control reaches from the body, keyed by node id. Includes the
75
+ * step nodes of a native body, since a step is where a check anchors. */
76
+ contents: ReadonlyMap<string, ContainedNode>;
77
+ /** Dispatches inside the region that the zone does not extend through. */
78
+ boundaries: readonly RegionBoundary[];
79
+ }
80
+ /** Resolves a kind name to its definition in the scope of the module that
81
+ * DECLARED it — the same resolver the projection takes, passed in rather than
82
+ * rebuilt so both walks agree about what a kind means. */
83
+ export type DefinitionLookup = (kind: string, module?: string) => ResourceDefinition | undefined;
84
+ /**
85
+ * Every region in the graph opened by a slot declaring `attribute`.
86
+ *
87
+ * The provider itself is NOT in `contents` — a zone constrains what runs inside
88
+ * its body, not the resource that establishes it. A transaction's own
89
+ * `connection:` dependency is outside the region it opens, and a rule that
90
+ * treated the provider as contained would report the provider against its own
91
+ * constraint.
92
+ */
93
+ export declare function findZoneRegions(graph: CallGraph, resolveDef: DefinitionLookup, attribute: string): ZoneRegion[];
94
+ /** Convenience for a consumer that only wants membership: every node id inside
95
+ * any region opened by `attribute`, mapped to the region that contains it. */
96
+ export declare function containmentIndex(regions: readonly ZoneRegion[]): ReadonlyMap<string, ZoneRegion>;
97
+ /** The manifests a region's contents belong to — what a diagnostic anchors on. */
98
+ export declare function regionManifests(region: ZoneRegion): ResourceManifest[];
99
+ //# sourceMappingURL=resolve-zone-containment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-zone-containment.d.ts","sourceRoot":"","sources":["../src/resolve-zone-containment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAKlG,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB;wDACoD;IACpD,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED;;;;;gFAKgF;AAChF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,mDAAmD;IACnD,IAAI,EAAE,iBAAiB,CAAC;IACxB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB;uEACmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb;4EACwE;IACxE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C;8EAC0E;IAC1E,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,0EAA0E;IAC1E,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;CACvC;AAED;;2DAE2D;AAC3D,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;AA4GjG;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,MAAM,GAChB,UAAU,EAAE,CA6Dd;AAoCD;+EAC+E;AAC/E,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,UAAU,EAAE,GAC7B,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAQjC;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAMtE"}