@intentius/chant 0.53.1 → 0.54.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.
Files changed (59) hide show
  1. package/dist/audit/catalog.d.ts +4 -0
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/discover.d.ts +9 -0
  4. package/dist/audit/discover.d.ts.map +1 -1
  5. package/dist/audit/nginx.d.ts +53 -0
  6. package/dist/audit/nginx.d.ts.map +1 -0
  7. package/dist/audit/rules-doc.d.ts.map +1 -1
  8. package/dist/cli/commands/audit.d.ts.map +1 -1
  9. package/dist/cli/commands/carve-apply.d.ts.map +1 -1
  10. package/dist/cli/commands/carve-status.d.ts +56 -0
  11. package/dist/cli/commands/carve-status.d.ts.map +1 -0
  12. package/dist/cli/handlers/carve-status.d.ts +9 -0
  13. package/dist/cli/handlers/carve-status.d.ts.map +1 -0
  14. package/dist/cli/handlers/components.d.ts.map +1 -1
  15. package/dist/cli/handlers/run.d.ts.map +1 -1
  16. package/dist/cli/main.d.ts.map +1 -1
  17. package/dist/components/auto-release.d.ts +3 -1
  18. package/dist/components/auto-release.d.ts.map +1 -1
  19. package/dist/components/cli-support.d.ts +2 -0
  20. package/dist/components/cli-support.d.ts.map +1 -1
  21. package/dist/graph-ir.d.ts +7 -0
  22. package/dist/graph-ir.d.ts.map +1 -1
  23. package/dist/lexicon.d.ts +8 -0
  24. package/dist/lexicon.d.ts.map +1 -1
  25. package/dist/lifecycle/release-ledger.d.ts +55 -1
  26. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  27. package/dist/op/activity-contract.d.ts +15 -1
  28. package/dist/op/activity-contract.d.ts.map +1 -1
  29. package/dist/terraform/manifest.d.ts +31 -6
  30. package/dist/terraform/manifest.d.ts.map +1 -1
  31. package/package.json +1 -1
  32. package/src/audit/catalog.ts +35 -0
  33. package/src/audit/discover.ts +11 -0
  34. package/src/audit/edge-init-safety.test.ts +36 -3
  35. package/src/audit/nginx.test.ts +180 -0
  36. package/src/audit/nginx.ts +379 -0
  37. package/src/audit/rules-doc.ts +1 -0
  38. package/src/cli/commands/audit.test.ts +35 -0
  39. package/src/cli/commands/audit.ts +8 -3
  40. package/src/cli/commands/carve-apply.test.ts +4 -1
  41. package/src/cli/commands/carve-apply.ts +4 -2
  42. package/src/cli/commands/carve-bridge.test.ts +2 -1
  43. package/src/cli/commands/carve-emit-state.test.ts +3 -1
  44. package/src/cli/commands/carve-status.test.ts +116 -0
  45. package/src/cli/commands/carve-status.ts +163 -0
  46. package/src/cli/handlers/carve-status.ts +30 -0
  47. package/src/cli/handlers/components.ts +5 -1
  48. package/src/cli/handlers/graph.ts +3 -0
  49. package/src/cli/handlers/run.ts +4 -1
  50. package/src/cli/main.ts +8 -0
  51. package/src/components/auto-release.ts +4 -1
  52. package/src/components/cli-support.ts +4 -2
  53. package/src/graph-ir.ts +7 -0
  54. package/src/lexicon.ts +8 -0
  55. package/src/lifecycle/release-ledger.test.ts +64 -0
  56. package/src/lifecycle/release-ledger.ts +79 -1
  57. package/src/op/activity-contract.ts +14 -0
  58. package/src/terraform/manifest.test.ts +52 -0
  59. package/src/terraform/manifest.ts +72 -10
@@ -9,14 +9,23 @@
9
9
  */
10
10
 
11
11
  import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "fs";
12
- import { join } from "path";
12
+ import { isAbsolute, join, relative } from "path";
13
13
  import type { CarveReport } from "./carve";
14
14
  import type { OwnershipMarker } from "../ownership";
15
15
 
16
16
  export const CARVE_MANIFEST_SUFFIX = ".carve.json";
17
17
 
18
+ /**
19
+ * Version 2 (#2039): `emit.files`, `bridge.written`, `bridge.patch` and
20
+ * `apply.stampedFiles` are recorded relative to the manifest's own directory,
21
+ * so the manifest stays true when the tree is copied, moved, or checked out
22
+ * elsewhere. Version-1 manifests recorded them absolute; readers resolve
23
+ * either through `resolveManifestFilePath`.
24
+ */
25
+ export const CARVE_MANIFEST_VERSION = 2;
26
+
18
27
  export interface CarveManifest {
19
- version: 1;
28
+ version: 1 | 2;
20
29
  /** Terraform address of the carved resource, e.g. `aws_s3_bucket.assets`. */
21
30
  target: string;
22
31
  /** Terraform resource type, when known. */
@@ -30,7 +39,13 @@ export interface CarveManifest {
30
39
  /** Recorded by `carve emit`. */
31
40
  emit?: {
32
41
  source: "tfstate" | "live";
33
- /** Emitted chant source file path(s). */
42
+ /**
43
+ * Emitted chant source file path(s), relative to the manifest's directory
44
+ * (absolute in version-1 manifests). The manifest sits at the scaffolded
45
+ * project's root, so these are also project-root-relative — the same base
46
+ * `chant graph --format ir` uses for `sourceLoc.file`, which is the join
47
+ * from a carved Terraform address to the chant entity it became (#2040).
48
+ */
34
49
  files: string[];
35
50
  /**
36
51
  * Deferred outbound inputs declared as build parameters in the emitted
@@ -53,9 +68,10 @@ export interface CarveManifest {
53
68
  };
54
69
  /** Recorded by `carve bridge`. */
55
70
  bridge?: {
71
+ /** Files written, relative to the manifest's directory (absolute in version-1 manifests). */
56
72
  written: string[];
57
73
  appliedInPlace: boolean;
58
- /** The git-applyable `.patch` carrying the whole survivor edit. */
74
+ /** The git-applyable `.patch` carrying the whole survivor edit, relative to the manifest's directory (absolute in version-1 manifests). */
59
75
  patch?: string;
60
76
  /** Carved addresses whose own `.tf` block the rewrites remove (#998). */
61
77
  excised?: string[];
@@ -65,7 +81,7 @@ export interface CarveManifest {
65
81
  apply?: {
66
82
  marker: OwnershipMarker;
67
83
  ownershipTags: Record<string, string>;
68
- /** Emitted files the marker was stamped into (`--write-source`). */
84
+ /** Emitted files the marker was stamped into (`--write-source`), relative to the manifest's directory (absolute in version-1 manifests). */
69
85
  stampedFiles?: string[];
70
86
  at: string;
71
87
  };
@@ -81,20 +97,62 @@ export function carveManifestPath(outDir: string, target: string): string {
81
97
  return join(outDir, `${carveSlug(target)}${CARVE_MANIFEST_SUFFIX}`);
82
98
  }
83
99
 
100
+ /**
101
+ * Relative-to-`outDir` spelling of a recorded file path. Absolute entries
102
+ * (the run-time spelling every step naturally produces, and every version-1
103
+ * manifest on disk) are rewritten; already-relative entries pass through.
104
+ */
105
+ function relativizePath(outDir: string, p: string): string {
106
+ return isAbsolute(p) ? relative(outDir, p) : p;
107
+ }
108
+
109
+ /**
110
+ * Normalize a manifest to the version-2 on-disk contract: recorded file
111
+ * paths relative to the manifest's own directory (#2039). `from` and
112
+ * `statePath` stay absolute — they locate the Terraform estate, a different
113
+ * tree the manifest does not travel with.
114
+ */
115
+ function normalizeManifest(outDir: string, manifest: CarveManifest): CarveManifest {
116
+ const out: CarveManifest = { ...manifest, version: CARVE_MANIFEST_VERSION };
117
+ if (manifest.emit) {
118
+ out.emit = { ...manifest.emit, files: manifest.emit.files.map((f) => relativizePath(outDir, f)) };
119
+ }
120
+ if (manifest.bridge) {
121
+ out.bridge = {
122
+ ...manifest.bridge,
123
+ written: manifest.bridge.written.map((f) => relativizePath(outDir, f)),
124
+ ...(manifest.bridge.patch !== undefined ? { patch: relativizePath(outDir, manifest.bridge.patch) } : {}),
125
+ };
126
+ }
127
+ if (manifest.apply?.stampedFiles) {
128
+ out.apply = { ...manifest.apply, stampedFiles: manifest.apply.stampedFiles.map((f) => relativizePath(outDir, f)) };
129
+ }
130
+ return out;
131
+ }
132
+
133
+ /**
134
+ * Resolve a manifest-recorded file path against the manifest's directory.
135
+ * Absolute paths (version-1 manifests) pass through untouched, so both
136
+ * on-disk spellings read the same.
137
+ */
138
+ export function resolveManifestFilePath(manifestDir: string, p: string): string {
139
+ return isAbsolute(p) ? p : join(manifestDir, p);
140
+ }
141
+
84
142
  /** Write (or overwrite) a manifest into the output dir. Returns the path. */
85
143
  export function writeCarveManifest(outDir: string, manifest: CarveManifest): string {
86
144
  mkdirSync(outDir, { recursive: true });
87
145
  const path = carveManifestPath(outDir, manifest.target);
88
- writeFileSync(path, JSON.stringify(manifest, null, 2) + "\n");
146
+ writeFileSync(path, JSON.stringify(normalizeManifest(outDir, manifest), null, 2) + "\n");
89
147
  return path;
90
148
  }
91
149
 
92
- /** Read a manifest, or null when absent/unreadable/not a v1 manifest. */
150
+ /** Read a manifest, or null when absent/unreadable/not a known-version manifest. */
93
151
  export function readCarveManifest(path: string): CarveManifest | null {
94
152
  if (!existsSync(path)) return null;
95
153
  try {
96
154
  const parsed = JSON.parse(readFileSync(path, "utf-8")) as CarveManifest;
97
- if (parsed?.version !== 1) return null;
155
+ if (parsed?.version !== 1 && parsed?.version !== 2) return null;
98
156
  if (typeof parsed.target !== "string" || typeof parsed.boundary !== "object") return null;
99
157
  return parsed;
100
158
  } catch {
@@ -147,7 +205,11 @@ export function resolveCarveManifest(outDir: string, select?: string): ResolvedM
147
205
  return { manifest: manifests[0].manifest, path: manifests[0].path };
148
206
  }
149
207
 
150
- /** Read-modify-write a section of an existing manifest. No-op when absent. */
208
+ /**
209
+ * Read-modify-write a section of an existing manifest. No-op when absent.
210
+ * The whole manifest is re-normalized on write, so updating a version-1
211
+ * manifest also migrates its recorded paths to the relative contract.
212
+ */
151
213
  export function updateCarveManifest(
152
214
  outDir: string,
153
215
  target: string,
@@ -157,6 +219,6 @@ export function updateCarveManifest(
157
219
  const manifest = readCarveManifest(path);
158
220
  if (!manifest) return undefined;
159
221
  Object.assign(manifest, patch);
160
- writeFileSync(path, JSON.stringify(manifest, null, 2) + "\n");
222
+ writeFileSync(path, JSON.stringify(normalizeManifest(outDir, manifest), null, 2) + "\n");
161
223
  return path;
162
224
  }