@truefoundry/tfy-infra-engine 0.1.3 → 0.1.4-canary.c56f92d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -100,15 +100,21 @@ if (!result.driftReport.valid) {
100
100
 
101
101
  ### `engine.upgrade(envelope, currentFiles, previousManifest)`
102
102
 
103
- Update platform files to new template versions. Performs pre-upgrade drift detection and source mismatch blocking.
103
+ Update platform files to new template versions. Always renders new files and returns a pre-upgrade drift report. The `sourceBlocked` flag indicates a template source mismatch -- callers enforce blocking policy (FR-029).
104
104
 
105
105
  ```typescript
106
106
  const result = await engine.upgrade(envelope, currentFiles, previousManifest);
107
+
107
108
  if (result.sourceBlocked) {
108
- console.log('Upgrade blocked: template source mismatch');
109
- } else if (!result.driftReport.valid) {
109
+ // Template source changed -- caller decides whether to proceed
110
+ console.log('Source mismatch detected');
111
+ }
112
+ if (!result.driftReport.valid) {
113
+ // Managed files were modified since last render
110
114
  console.log('Pre-upgrade drift detected');
111
115
  }
116
+
117
+ // result.files always contains newly rendered files, even when sourceBlocked
112
118
  ```
113
119
 
114
120
  ### `engine.hashOnly(envelope)`
@@ -146,15 +152,15 @@ if (!result.valid) {
146
152
  // inputs now has defaults applied in-place
147
153
  ```
148
154
 
149
- ### Template JSON Validation
155
+ ### Bundle Validation
150
156
 
151
- Validate the top-level structure of a `template.json` file:
157
+ Validate the top-level structure of a `bundle.json` file:
152
158
 
153
159
  ```typescript
154
- import { validateTemplateJson } from '@truefoundry/tfy-infra-engine';
160
+ import { validateBundle } from '@truefoundry/tfy-infra-engine';
155
161
 
156
- const parsed = JSON.parse(fs.readFileSync('template.json', 'utf-8'));
157
- const { metadata, jsonSchema } = validateTemplateJson(parsed);
162
+ const parsed = JSON.parse(fs.readFileSync('bundle.json', 'utf-8'));
163
+ const { metadata, jsonSchema } = validateBundle(parsed);
158
164
  // metadata: { name, version, description? }
159
165
  // jsonSchema: the raw JSON Schema object
160
166
  ```
@@ -269,11 +275,11 @@ try {
269
275
  case EngineErrorCode.INPUT_VALIDATION_FAILED:
270
276
  console.log('Invalid inputs:', error.details);
271
277
  break;
272
- case EngineErrorCode.TEMPLATE_JSON_NOT_FOUND:
273
- console.log('template.json not found in template directory');
278
+ case EngineErrorCode.BUNDLE_NOT_FOUND:
279
+ console.log('bundle.json not found in template directory');
274
280
  break;
275
- case EngineErrorCode.TEMPLATE_JSON_INVALID:
276
- console.log('template.json has invalid structure:', error.message);
281
+ case EngineErrorCode.BUNDLE_INVALID:
282
+ console.log('bundle.json has invalid structure:', error.message);
277
283
  break;
278
284
  case EngineErrorCode.TOFU_NOT_FOUND:
279
285
  console.log('Install OpenTofu or use skipFormat option');
package/dist/index.d.mts CHANGED
@@ -4,14 +4,12 @@
4
4
  declare enum EngineErrorCode {
5
5
  TEMPLATE_NOT_FOUND = "TEMPLATE_NOT_FOUND",
6
6
  NETWORK_ERROR = "NETWORK_ERROR",
7
- GITHUB_NOT_FOUND = "GITHUB_NOT_FOUND",
8
- GITHUB_RATE_LIMITED = "GITHUB_RATE_LIMITED",
9
7
  FILE_NOT_FOUND = "FILE_NOT_FOUND",
10
8
  HTTPS_AUTH_FAILED = "HTTPS_AUTH_FAILED",
11
9
  SCHEMA_INVALID = "SCHEMA_INVALID",
12
10
  INPUT_VALIDATION_FAILED = "INPUT_VALIDATION_FAILED",
13
- TEMPLATE_JSON_NOT_FOUND = "TEMPLATE_JSON_NOT_FOUND",
14
- TEMPLATE_JSON_INVALID = "TEMPLATE_JSON_INVALID",
11
+ BUNDLE_NOT_FOUND = "BUNDLE_NOT_FOUND",
12
+ BUNDLE_INVALID = "BUNDLE_INVALID",
15
13
  TEMPLATE_SYNTAX_ERROR = "TEMPLATE_SYNTAX_ERROR",
16
14
  TOFU_NOT_FOUND = "TOFU_NOT_FOUND",
17
15
  TOFU_FMT_FAILED = "TOFU_FMT_FAILED",
@@ -42,7 +40,7 @@ declare class EngineError extends Error {
42
40
  *
43
41
  * CHANGE (008): All Zod-based converter functions and zod-to-json-schema
44
42
  * import removed. Only the JSONSchema7 type interface remains.
45
- * Templates provide JSON Schema directly via template.json.
43
+ * Templates provide JSON Schema directly via bundle.json.
46
44
  */
47
45
  /**
48
46
  * JSON Schema Draft-07 type.
@@ -174,7 +172,7 @@ interface RenderOptions {
174
172
  skipFormat?: boolean;
175
173
  }
176
174
  /**
177
- * Metadata about a template, sourced from the "template" key in template.json.
175
+ * Metadata about a template, sourced from the "metadata" key in bundle.json.
178
176
  */
179
177
  interface TemplateMetadata {
180
178
  /** Template name */
@@ -188,12 +186,12 @@ interface TemplateMetadata {
188
186
  * A remote template package containing source files and schema.
189
187
  *
190
188
  * CHANGE (008): Replaced `schema: TemplateSchema` with `metadata` + `jsonSchema`.
191
- * Metadata comes from template.json "template" key; schema from "schema" key.
189
+ * Metadata comes from bundle.json "metadata" key; schema from "jsonSchema" key.
192
190
  */
193
191
  interface Template {
194
- /** Template metadata from template.json → "template" key */
192
+ /** Template metadata from bundle.json → "metadata" key */
195
193
  metadata: TemplateMetadata;
196
- /** JSON Schema Draft-07 from template.json → "schema" key */
194
+ /** JSON Schema Draft-07 from bundle.json → "jsonSchema" key */
197
195
  jsonSchema: JSONSchema7;
198
196
  /** Map of output paths to HBS content (rendered via Handlebars) */
199
197
  files: Map<string, string>;
@@ -423,36 +421,36 @@ interface HclEngine {
423
421
  }
424
422
 
425
423
  /**
426
- * Template JSON structure validation using AJV.
424
+ * Bundle structure validation using AJV.
427
425
  *
428
- * Validates the top-level structure of template.json against the
429
- * templateJsonSchema (JSON Schema Draft-07) defined in template-json-schema.ts.
426
+ * Validates the top-level structure of a bundle against the
427
+ * bundleSchema (JSON Schema Draft-07) defined in bundle-schema.ts.
430
428
  *
431
429
  * Reference: R-006, data-model.md validator.ts
432
430
  */
433
431
 
434
432
  /**
435
- * Result of validating a template.json file.
433
+ * Result of validating a bundle.
436
434
  */
437
- interface TemplateJsonResult {
435
+ interface BundleValidationResult {
438
436
  metadata: TemplateMetadata;
439
437
  jsonSchema: JSONSchema7;
440
438
  }
441
439
  /**
442
- * Validate the structure of a parsed template.json file.
440
+ * Validate the structure of a parsed bundle.
443
441
  *
444
442
  * Checks:
445
- * - Data is an object with "template" and "schema" keys
446
- * - template.name is a non-empty string
447
- * - template.version is a semver string (x.y.z)
448
- * - template.description is an optional string
449
- * - schema is a non-null object with type: "object" and properties
443
+ * - Data is an object with "metadata" and "jsonSchema" keys
444
+ * - metadata.name is a non-empty string
445
+ * - metadata.version is a semver string (x.y.z)
446
+ * - metadata.description is an optional string
447
+ * - jsonSchema is a non-null object with type: "object" and properties
450
448
  *
451
- * @param data - Parsed JSON content from template.json
449
+ * @param data - Parsed JSON content from a bundle
452
450
  * @returns Validated metadata and JSON Schema
453
- * @throws EngineError with TEMPLATE_JSON_INVALID on failure
451
+ * @throws EngineError with BUNDLE_INVALID on failure
454
452
  */
455
- declare function validateTemplateJson(data: unknown): TemplateJsonResult;
453
+ declare function validateBundle(data: unknown): BundleValidationResult;
456
454
 
457
455
  /**
458
456
  * AJV-based JSON Schema input validation.
@@ -480,20 +478,20 @@ declare function validateTemplateJson(data: unknown): TemplateJsonResult;
480
478
  declare function validateJsonSchemaStructure(schema: JSONSchema7): void;
481
479
 
482
480
  /**
483
- * JSON Schema (Draft-07) for template.json files.
481
+ * JSON Schema (Draft-07) for bundle.json files.
484
482
  *
485
- * This is the source of truth for template.json validation.
483
+ * This is the source of truth for bundle structure validation.
486
484
  * Used by validator.ts via AJV for runtime validation.
487
485
  *
488
486
  * Validates:
489
- * - "template" key: name (required, non-empty), version (semver, required), description (optional string)
490
- * - "schema" key: must be a JSON Schema object with type: "object" and a properties key
487
+ * - "metadata" key: name (required, non-empty), version (semver, required), description (optional string)
488
+ * - "jsonSchema" key: must be a JSON Schema object with type: "object" and a properties key
491
489
  *
492
- * Note: No additionalProperties: false at root level extra top-level keys are allowed
493
- * for forward compatibility.
490
+ * Note: No additionalProperties: false at root level -- extra top-level keys are allowed
491
+ * for forward compatibility (e.g., uiSchema, files, staticFiles, version).
494
492
  */
495
493
 
496
- declare const templateJsonSchema: JSONSchema7;
494
+ declare const bundleSchema: JSONSchema7;
497
495
 
498
496
  /**
499
497
  * Check if tofu is available in the system.
@@ -627,4 +625,4 @@ declare function parseHeader(content: string): TfyStatusHeader | undefined;
627
625
  */
628
626
  declare function createEngine(): HclEngine;
629
627
 
630
- export { DEFAULT_PREFIX, type DriftReport, type DriftType, EngineError, EngineErrorCode, type Envelope, type FileEntry, type FileMap, type HashOnlyResult, type InstallResult, type JSONSchema7, type Manifest, type Resolver, type ResolverOptions, type Template, type UpgradeResult, type VerifyResult, type VersionInfo, canonicalHash, classifyFile, createEngine, getCanonicalHashScriptPath, isTofuAvailable, parseHeader, templateJsonSchema, validateJsonSchemaStructure, validateTemplateJson };
628
+ export { type BundleValidationResult, DEFAULT_PREFIX, type DriftReport, type DriftType, EngineError, EngineErrorCode, type Envelope, type FileEntry, type FileMap, type HashOnlyResult, type InstallResult, type JSONSchema7, type Manifest, type Resolver, type ResolverOptions, type Template, type TemplateMetadata, type UpgradeResult, type VerifyResult, type VersionInfo, bundleSchema, canonicalHash, classifyFile, createEngine, getCanonicalHashScriptPath, isTofuAvailable, parseHeader, validateBundle, validateJsonSchemaStructure };
package/dist/index.d.ts CHANGED
@@ -4,14 +4,12 @@
4
4
  declare enum EngineErrorCode {
5
5
  TEMPLATE_NOT_FOUND = "TEMPLATE_NOT_FOUND",
6
6
  NETWORK_ERROR = "NETWORK_ERROR",
7
- GITHUB_NOT_FOUND = "GITHUB_NOT_FOUND",
8
- GITHUB_RATE_LIMITED = "GITHUB_RATE_LIMITED",
9
7
  FILE_NOT_FOUND = "FILE_NOT_FOUND",
10
8
  HTTPS_AUTH_FAILED = "HTTPS_AUTH_FAILED",
11
9
  SCHEMA_INVALID = "SCHEMA_INVALID",
12
10
  INPUT_VALIDATION_FAILED = "INPUT_VALIDATION_FAILED",
13
- TEMPLATE_JSON_NOT_FOUND = "TEMPLATE_JSON_NOT_FOUND",
14
- TEMPLATE_JSON_INVALID = "TEMPLATE_JSON_INVALID",
11
+ BUNDLE_NOT_FOUND = "BUNDLE_NOT_FOUND",
12
+ BUNDLE_INVALID = "BUNDLE_INVALID",
15
13
  TEMPLATE_SYNTAX_ERROR = "TEMPLATE_SYNTAX_ERROR",
16
14
  TOFU_NOT_FOUND = "TOFU_NOT_FOUND",
17
15
  TOFU_FMT_FAILED = "TOFU_FMT_FAILED",
@@ -42,7 +40,7 @@ declare class EngineError extends Error {
42
40
  *
43
41
  * CHANGE (008): All Zod-based converter functions and zod-to-json-schema
44
42
  * import removed. Only the JSONSchema7 type interface remains.
45
- * Templates provide JSON Schema directly via template.json.
43
+ * Templates provide JSON Schema directly via bundle.json.
46
44
  */
47
45
  /**
48
46
  * JSON Schema Draft-07 type.
@@ -174,7 +172,7 @@ interface RenderOptions {
174
172
  skipFormat?: boolean;
175
173
  }
176
174
  /**
177
- * Metadata about a template, sourced from the "template" key in template.json.
175
+ * Metadata about a template, sourced from the "metadata" key in bundle.json.
178
176
  */
179
177
  interface TemplateMetadata {
180
178
  /** Template name */
@@ -188,12 +186,12 @@ interface TemplateMetadata {
188
186
  * A remote template package containing source files and schema.
189
187
  *
190
188
  * CHANGE (008): Replaced `schema: TemplateSchema` with `metadata` + `jsonSchema`.
191
- * Metadata comes from template.json "template" key; schema from "schema" key.
189
+ * Metadata comes from bundle.json "metadata" key; schema from "jsonSchema" key.
192
190
  */
193
191
  interface Template {
194
- /** Template metadata from template.json → "template" key */
192
+ /** Template metadata from bundle.json → "metadata" key */
195
193
  metadata: TemplateMetadata;
196
- /** JSON Schema Draft-07 from template.json → "schema" key */
194
+ /** JSON Schema Draft-07 from bundle.json → "jsonSchema" key */
197
195
  jsonSchema: JSONSchema7;
198
196
  /** Map of output paths to HBS content (rendered via Handlebars) */
199
197
  files: Map<string, string>;
@@ -423,36 +421,36 @@ interface HclEngine {
423
421
  }
424
422
 
425
423
  /**
426
- * Template JSON structure validation using AJV.
424
+ * Bundle structure validation using AJV.
427
425
  *
428
- * Validates the top-level structure of template.json against the
429
- * templateJsonSchema (JSON Schema Draft-07) defined in template-json-schema.ts.
426
+ * Validates the top-level structure of a bundle against the
427
+ * bundleSchema (JSON Schema Draft-07) defined in bundle-schema.ts.
430
428
  *
431
429
  * Reference: R-006, data-model.md validator.ts
432
430
  */
433
431
 
434
432
  /**
435
- * Result of validating a template.json file.
433
+ * Result of validating a bundle.
436
434
  */
437
- interface TemplateJsonResult {
435
+ interface BundleValidationResult {
438
436
  metadata: TemplateMetadata;
439
437
  jsonSchema: JSONSchema7;
440
438
  }
441
439
  /**
442
- * Validate the structure of a parsed template.json file.
440
+ * Validate the structure of a parsed bundle.
443
441
  *
444
442
  * Checks:
445
- * - Data is an object with "template" and "schema" keys
446
- * - template.name is a non-empty string
447
- * - template.version is a semver string (x.y.z)
448
- * - template.description is an optional string
449
- * - schema is a non-null object with type: "object" and properties
443
+ * - Data is an object with "metadata" and "jsonSchema" keys
444
+ * - metadata.name is a non-empty string
445
+ * - metadata.version is a semver string (x.y.z)
446
+ * - metadata.description is an optional string
447
+ * - jsonSchema is a non-null object with type: "object" and properties
450
448
  *
451
- * @param data - Parsed JSON content from template.json
449
+ * @param data - Parsed JSON content from a bundle
452
450
  * @returns Validated metadata and JSON Schema
453
- * @throws EngineError with TEMPLATE_JSON_INVALID on failure
451
+ * @throws EngineError with BUNDLE_INVALID on failure
454
452
  */
455
- declare function validateTemplateJson(data: unknown): TemplateJsonResult;
453
+ declare function validateBundle(data: unknown): BundleValidationResult;
456
454
 
457
455
  /**
458
456
  * AJV-based JSON Schema input validation.
@@ -480,20 +478,20 @@ declare function validateTemplateJson(data: unknown): TemplateJsonResult;
480
478
  declare function validateJsonSchemaStructure(schema: JSONSchema7): void;
481
479
 
482
480
  /**
483
- * JSON Schema (Draft-07) for template.json files.
481
+ * JSON Schema (Draft-07) for bundle.json files.
484
482
  *
485
- * This is the source of truth for template.json validation.
483
+ * This is the source of truth for bundle structure validation.
486
484
  * Used by validator.ts via AJV for runtime validation.
487
485
  *
488
486
  * Validates:
489
- * - "template" key: name (required, non-empty), version (semver, required), description (optional string)
490
- * - "schema" key: must be a JSON Schema object with type: "object" and a properties key
487
+ * - "metadata" key: name (required, non-empty), version (semver, required), description (optional string)
488
+ * - "jsonSchema" key: must be a JSON Schema object with type: "object" and a properties key
491
489
  *
492
- * Note: No additionalProperties: false at root level extra top-level keys are allowed
493
- * for forward compatibility.
490
+ * Note: No additionalProperties: false at root level -- extra top-level keys are allowed
491
+ * for forward compatibility (e.g., uiSchema, files, staticFiles, version).
494
492
  */
495
493
 
496
- declare const templateJsonSchema: JSONSchema7;
494
+ declare const bundleSchema: JSONSchema7;
497
495
 
498
496
  /**
499
497
  * Check if tofu is available in the system.
@@ -627,4 +625,4 @@ declare function parseHeader(content: string): TfyStatusHeader | undefined;
627
625
  */
628
626
  declare function createEngine(): HclEngine;
629
627
 
630
- export { DEFAULT_PREFIX, type DriftReport, type DriftType, EngineError, EngineErrorCode, type Envelope, type FileEntry, type FileMap, type HashOnlyResult, type InstallResult, type JSONSchema7, type Manifest, type Resolver, type ResolverOptions, type Template, type UpgradeResult, type VerifyResult, type VersionInfo, canonicalHash, classifyFile, createEngine, getCanonicalHashScriptPath, isTofuAvailable, parseHeader, templateJsonSchema, validateJsonSchemaStructure, validateTemplateJson };
628
+ export { type BundleValidationResult, DEFAULT_PREFIX, type DriftReport, type DriftType, EngineError, EngineErrorCode, type Envelope, type FileEntry, type FileMap, type HashOnlyResult, type InstallResult, type JSONSchema7, type Manifest, type Resolver, type ResolverOptions, type Template, type TemplateMetadata, type UpgradeResult, type VerifyResult, type VersionInfo, bundleSchema, canonicalHash, classifyFile, createEngine, getCanonicalHashScriptPath, isTofuAvailable, parseHeader, validateBundle, validateJsonSchemaStructure };
package/dist/index.js CHANGED
@@ -33,15 +33,15 @@ __export(index_exports, {
33
33
  DEFAULT_PREFIX: () => DEFAULT_PREFIX,
34
34
  EngineError: () => EngineError,
35
35
  EngineErrorCode: () => EngineErrorCode,
36
+ bundleSchema: () => bundleSchema,
36
37
  canonicalHash: () => canonicalHash,
37
38
  classifyFile: () => classifyFile,
38
39
  createEngine: () => createEngine,
39
40
  getCanonicalHashScriptPath: () => getCanonicalHashScriptPath,
40
41
  isTofuAvailable: () => isTofuAvailable,
41
42
  parseHeader: () => parseHeader,
42
- templateJsonSchema: () => templateJsonSchema,
43
- validateJsonSchemaStructure: () => validateJsonSchemaStructure,
44
- validateTemplateJson: () => validateTemplateJson
43
+ validateBundle: () => validateBundle,
44
+ validateJsonSchemaStructure: () => validateJsonSchemaStructure
45
45
  });
46
46
  module.exports = __toCommonJS(index_exports);
47
47
 
@@ -49,14 +49,12 @@ module.exports = __toCommonJS(index_exports);
49
49
  var EngineErrorCode = /* @__PURE__ */ ((EngineErrorCode2) => {
50
50
  EngineErrorCode2["TEMPLATE_NOT_FOUND"] = "TEMPLATE_NOT_FOUND";
51
51
  EngineErrorCode2["NETWORK_ERROR"] = "NETWORK_ERROR";
52
- EngineErrorCode2["GITHUB_NOT_FOUND"] = "GITHUB_NOT_FOUND";
53
- EngineErrorCode2["GITHUB_RATE_LIMITED"] = "GITHUB_RATE_LIMITED";
54
52
  EngineErrorCode2["FILE_NOT_FOUND"] = "FILE_NOT_FOUND";
55
53
  EngineErrorCode2["HTTPS_AUTH_FAILED"] = "HTTPS_AUTH_FAILED";
56
54
  EngineErrorCode2["SCHEMA_INVALID"] = "SCHEMA_INVALID";
57
55
  EngineErrorCode2["INPUT_VALIDATION_FAILED"] = "INPUT_VALIDATION_FAILED";
58
- EngineErrorCode2["TEMPLATE_JSON_NOT_FOUND"] = "TEMPLATE_JSON_NOT_FOUND";
59
- EngineErrorCode2["TEMPLATE_JSON_INVALID"] = "TEMPLATE_JSON_INVALID";
56
+ EngineErrorCode2["BUNDLE_NOT_FOUND"] = "BUNDLE_NOT_FOUND";
57
+ EngineErrorCode2["BUNDLE_INVALID"] = "BUNDLE_INVALID";
60
58
  EngineErrorCode2["TEMPLATE_SYNTAX_ERROR"] = "TEMPLATE_SYNTAX_ERROR";
61
59
  EngineErrorCode2["TOFU_NOT_FOUND"] = "TOFU_NOT_FOUND";
62
60
  EngineErrorCode2["TOFU_FMT_FAILED"] = "TOFU_FMT_FAILED";
@@ -101,12 +99,12 @@ var EngineError = class _EngineError extends Error {
101
99
  // src/schema/validator.ts
102
100
  var import_ajv = __toESM(require("ajv"));
103
101
 
104
- // src/schema/template-json-schema.ts
105
- var templateJsonSchema = {
102
+ // src/schema/bundle-schema.ts
103
+ var bundleSchema = {
106
104
  $schema: "http://json-schema.org/draft-07/schema#",
107
105
  type: "object",
108
106
  properties: {
109
- template: {
107
+ metadata: {
110
108
  type: "object",
111
109
  properties: {
112
110
  name: { type: "string", minLength: 1 },
@@ -116,7 +114,7 @@ var templateJsonSchema = {
116
114
  required: ["name", "version"],
117
115
  additionalProperties: false
118
116
  },
119
- schema: {
117
+ jsonSchema: {
120
118
  type: "object",
121
119
  description: "JSON Schema Draft-07 defining template inputs",
122
120
  properties: {
@@ -127,7 +125,7 @@ var templateJsonSchema = {
127
125
  required: ["type", "properties"]
128
126
  }
129
127
  },
130
- required: ["template", "schema"]
128
+ required: ["metadata", "jsonSchema"]
131
129
  };
132
130
 
133
131
  // src/schema/validator.ts
@@ -136,54 +134,51 @@ var ajv = new import_ajv.default({
136
134
  strict: false,
137
135
  validateSchema: false
138
136
  });
139
- var validate = ajv.compile(templateJsonSchema);
140
- function validateTemplateJson(data) {
137
+ var validate = ajv.compile(bundleSchema);
138
+ function validateBundle(data) {
141
139
  if (!data || typeof data !== "object" || Array.isArray(data)) {
142
- throw new EngineError(
143
- "template.json must be a JSON object",
144
- "TEMPLATE_JSON_INVALID" /* TEMPLATE_JSON_INVALID */
145
- );
140
+ throw new EngineError("bundle must be a JSON object", "BUNDLE_INVALID" /* BUNDLE_INVALID */);
146
141
  }
147
142
  const valid = validate(data);
148
143
  if (!valid) {
149
144
  const message = formatAjvErrors(validate.errors ?? []);
150
- throw new EngineError(message, "TEMPLATE_JSON_INVALID" /* TEMPLATE_JSON_INVALID */);
145
+ throw new EngineError(message, "BUNDLE_INVALID" /* BUNDLE_INVALID */);
151
146
  }
152
147
  const record = data;
153
- const templateBlock = record["template"];
148
+ const metadataBlock = record["metadata"];
154
149
  const metadata = {
155
- name: templateBlock["name"],
156
- version: templateBlock["version"],
157
- ...templateBlock["description"] !== void 0 ? { description: templateBlock["description"] } : {}
150
+ name: metadataBlock["name"],
151
+ version: metadataBlock["version"],
152
+ ...metadataBlock["description"] !== void 0 ? { description: metadataBlock["description"] } : {}
158
153
  };
159
- const jsonSchema = record["schema"];
154
+ const jsonSchema = record["jsonSchema"];
160
155
  return { metadata, jsonSchema };
161
156
  }
162
157
  function formatAjvErrors(errors) {
163
158
  const first = errors[0];
164
159
  if (!first) {
165
- return "template.json validation failed";
160
+ return "bundle validation failed";
166
161
  }
167
162
  const path = first.instancePath || "";
168
163
  if (first.keyword === "required") {
169
164
  const prop = first.params["missingProperty"];
170
- return `template.json must have a "${prop}" key`;
165
+ return `bundle must have a "${prop}" key`;
171
166
  }
172
167
  if (first.keyword === "type") {
173
168
  const expected = first.params["type"];
174
- return `template.json${path ? ` "${dotPath(path)}"` : ""} must be ${expected}`;
169
+ return `bundle${path ? ` "${dotPath(path)}"` : ""} must be ${expected}`;
175
170
  }
176
- if (first.keyword === "pattern" && path === "/template/version") {
177
- return `template.json "template.version" must be semver format (x.y.z)`;
171
+ if (first.keyword === "pattern" && path === "/metadata/version") {
172
+ return `bundle "metadata.version" must be semver format (x.y.z)`;
178
173
  }
179
- if (first.keyword === "minLength" && path === "/template/name") {
180
- return `template.json "template.name" must be a non-empty string`;
174
+ if (first.keyword === "minLength" && path === "/metadata/name") {
175
+ return `bundle "metadata.name" must be a non-empty string`;
181
176
  }
182
177
  if (first.keyword === "const") {
183
178
  const expected = first.params["allowedValue"];
184
- return `template.json "${dotPath(path)}" must be ${JSON.stringify(expected)}`;
179
+ return `bundle "${dotPath(path)}" must be ${JSON.stringify(expected)}`;
185
180
  }
186
- return `template.json validation failed at ${path || "/"}: ${first.message ?? "unknown error"}`;
181
+ return `bundle validation failed at ${path || "/"}: ${first.message ?? "unknown error"}`;
187
182
  }
188
183
  function dotPath(jsonPointer) {
189
184
  return jsonPointer.replace(/^\//, "").replace(/\//g, ".");
@@ -701,7 +696,7 @@ function computeAggregateHash(files) {
701
696
  }
702
697
 
703
698
  // src/render/manifest.ts
704
- var ENGINE_VERSION = "0.1.3";
699
+ var ENGINE_VERSION = "0.1.4-canary.c56f92d";
705
700
  function generateManifest(opts) {
706
701
  const { files, template, inputs, formatted, intentId, platformPrefix = "tfy_" } = opts;
707
702
  const manifestFiles = [];
@@ -1006,8 +1001,11 @@ var HclEngineImpl = class {
1006
1001
  /**
1007
1002
  * Upgrade: Update an existing cluster to new templates.
1008
1003
  *
1009
- * Pipeline: validate envelope → drift detection (FR-028) → if source mismatch,
1010
- * short-circuit → validate inputs → render → format → hash + manifest.
1004
+ * Pipeline: validate envelope → drift detection (FR-028) → validate inputs
1005
+ * render → format → hash + manifest.
1006
+ *
1007
+ * The engine always renders new files regardless of source mismatch.
1008
+ * Callers (CLI/Server) enforce blocking policy via `sourceBlocked` flag (FR-029).
1011
1009
  */
1012
1010
  async upgrade(envelope, currentFiles, previousManifest) {
1013
1011
  const validatedEnvelope = this.validateEnvelopeOrThrow(envelope);
@@ -1016,14 +1014,6 @@ var HclEngineImpl = class {
1016
1014
  const incomingSource = validatedEnvelope.template.source;
1017
1015
  const driftReport = buildDriftReport(currentFiles, previousManifest, prefix, incomingSource);
1018
1016
  const sourceBlocked = driftReport.summary.sourceMismatches > 0;
1019
- if (sourceBlocked) {
1020
- return {
1021
- files: currentFiles,
1022
- manifest: previousManifest,
1023
- driftReport,
1024
- sourceBlocked: true
1025
- };
1026
- }
1027
1017
  const { renderedFiles, template, formatted, inputsWithDefaults } = await this.renderPipeline(
1028
1018
  validatedEnvelope,
1029
1019
  options
@@ -1036,7 +1026,7 @@ var HclEngineImpl = class {
1036
1026
  formatted,
1037
1027
  prefix
1038
1028
  );
1039
- return { files: fileMap, manifest, driftReport, sourceBlocked: false };
1029
+ return { files: fileMap, manifest, driftReport, sourceBlocked };
1040
1030
  }
1041
1031
  /**
1042
1032
  * Verify: Check integrity of existing files against a Manifest.
@@ -1195,14 +1185,14 @@ function createEngine() {
1195
1185
  DEFAULT_PREFIX,
1196
1186
  EngineError,
1197
1187
  EngineErrorCode,
1188
+ bundleSchema,
1198
1189
  canonicalHash,
1199
1190
  classifyFile,
1200
1191
  createEngine,
1201
1192
  getCanonicalHashScriptPath,
1202
1193
  isTofuAvailable,
1203
1194
  parseHeader,
1204
- templateJsonSchema,
1205
- validateJsonSchemaStructure,
1206
- validateTemplateJson
1195
+ validateBundle,
1196
+ validateJsonSchemaStructure
1207
1197
  });
1208
1198
  //# sourceMappingURL=index.js.map