@apexops/capabilities 0.10.0-next.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 (130) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/bound-envelope-transport.d.ts +27 -0
  3. package/dist/bound-envelope-transport.d.ts.map +1 -0
  4. package/dist/bound-envelope-transport.js +96 -0
  5. package/dist/bound-envelope-transport.js.map +1 -0
  6. package/dist/capability.d.ts +36 -0
  7. package/dist/capability.d.ts.map +1 -0
  8. package/dist/capability.js +83 -0
  9. package/dist/capability.js.map +1 -0
  10. package/dist/command-plans.d.ts +49 -0
  11. package/dist/command-plans.d.ts.map +1 -0
  12. package/dist/command-plans.js +157 -0
  13. package/dist/command-plans.js.map +1 -0
  14. package/dist/design-capabilities.d.ts +23 -0
  15. package/dist/design-capabilities.d.ts.map +1 -0
  16. package/dist/design-capabilities.js +32 -0
  17. package/dist/design-capabilities.js.map +1 -0
  18. package/dist/encrypted-envelope-transport.d.ts +32 -0
  19. package/dist/encrypted-envelope-transport.d.ts.map +1 -0
  20. package/dist/encrypted-envelope-transport.js +138 -0
  21. package/dist/encrypted-envelope-transport.js.map +1 -0
  22. package/dist/iac-generation.d.ts +52 -0
  23. package/dist/iac-generation.d.ts.map +1 -0
  24. package/dist/iac-generation.js +645 -0
  25. package/dist/iac-generation.js.map +1 -0
  26. package/dist/iac-normalizers.d.ts +22 -0
  27. package/dist/iac-normalizers.d.ts.map +1 -0
  28. package/dist/iac-normalizers.js +198 -0
  29. package/dist/iac-normalizers.js.map +1 -0
  30. package/dist/iac.d.ts +83 -0
  31. package/dist/iac.d.ts.map +1 -0
  32. package/dist/iac.js +217 -0
  33. package/dist/iac.js.map +1 -0
  34. package/dist/index.d.ts +17 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +17 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/local-plan-transport.d.ts +29 -0
  39. package/dist/local-plan-transport.d.ts.map +1 -0
  40. package/dist/local-plan-transport.js +101 -0
  41. package/dist/local-plan-transport.js.map +1 -0
  42. package/dist/native-iac-providers.d.ts +96 -0
  43. package/dist/native-iac-providers.d.ts.map +1 -0
  44. package/dist/native-iac-providers.js +487 -0
  45. package/dist/native-iac-providers.js.map +1 -0
  46. package/dist/operations-placeholders.d.ts +5 -0
  47. package/dist/operations-placeholders.d.ts.map +1 -0
  48. package/dist/operations-placeholders.js +23 -0
  49. package/dist/operations-placeholders.js.map +1 -0
  50. package/dist/pack-manager.d.ts +95 -0
  51. package/dist/pack-manager.d.ts.map +1 -0
  52. package/dist/pack-manager.js +556 -0
  53. package/dist/pack-manager.js.map +1 -0
  54. package/dist/packs.d.ts +29 -0
  55. package/dist/packs.d.ts.map +1 -0
  56. package/dist/packs.js +51 -0
  57. package/dist/packs.js.map +1 -0
  58. package/dist/process-runner.d.ts +30 -0
  59. package/dist/process-runner.d.ts.map +1 -0
  60. package/dist/process-runner.js +97 -0
  61. package/dist/process-runner.js.map +1 -0
  62. package/dist/secret-redaction.d.ts +3 -0
  63. package/dist/secret-redaction.d.ts.map +1 -0
  64. package/dist/secret-redaction.js +48 -0
  65. package/dist/secret-redaction.js.map +1 -0
  66. package/dist/terraform-provider-schema.d.ts +75 -0
  67. package/dist/terraform-provider-schema.d.ts.map +1 -0
  68. package/dist/terraform-provider-schema.js +307 -0
  69. package/dist/terraform-provider-schema.js.map +1 -0
  70. package/dist/terraform-registry-client.d.ts +63 -0
  71. package/dist/terraform-registry-client.d.ts.map +1 -0
  72. package/dist/terraform-registry-client.js +388 -0
  73. package/dist/terraform-registry-client.js.map +1 -0
  74. package/dist/test/bound-envelope-transport.test.d.ts +2 -0
  75. package/dist/test/bound-envelope-transport.test.d.ts.map +1 -0
  76. package/dist/test/bound-envelope-transport.test.js +30 -0
  77. package/dist/test/bound-envelope-transport.test.js.map +1 -0
  78. package/dist/test/capabilities.test.d.ts +2 -0
  79. package/dist/test/capabilities.test.d.ts.map +1 -0
  80. package/dist/test/capabilities.test.js +86 -0
  81. package/dist/test/capabilities.test.js.map +1 -0
  82. package/dist/test/encrypted-envelope-transport.test.d.ts +2 -0
  83. package/dist/test/encrypted-envelope-transport.test.d.ts.map +1 -0
  84. package/dist/test/encrypted-envelope-transport.test.js +74 -0
  85. package/dist/test/encrypted-envelope-transport.test.js.map +1 -0
  86. package/dist/test/fixtures/terraform-provider-schema.d.ts +65 -0
  87. package/dist/test/fixtures/terraform-provider-schema.d.ts.map +1 -0
  88. package/dist/test/fixtures/terraform-provider-schema.js +29 -0
  89. package/dist/test/fixtures/terraform-provider-schema.js.map +1 -0
  90. package/dist/test/fixtures/terraform-registry.d.ts +54 -0
  91. package/dist/test/fixtures/terraform-registry.d.ts.map +1 -0
  92. package/dist/test/fixtures/terraform-registry.js +42 -0
  93. package/dist/test/fixtures/terraform-registry.js.map +1 -0
  94. package/dist/test/iac-generation.test.d.ts +2 -0
  95. package/dist/test/iac-generation.test.d.ts.map +1 -0
  96. package/dist/test/iac-generation.test.js +271 -0
  97. package/dist/test/iac-generation.test.js.map +1 -0
  98. package/dist/test/iac.test.d.ts +2 -0
  99. package/dist/test/iac.test.d.ts.map +1 -0
  100. package/dist/test/iac.test.js +161 -0
  101. package/dist/test/iac.test.js.map +1 -0
  102. package/dist/test/native-iac-providers.test.d.ts +2 -0
  103. package/dist/test/native-iac-providers.test.d.ts.map +1 -0
  104. package/dist/test/native-iac-providers.test.js +594 -0
  105. package/dist/test/native-iac-providers.test.js.map +1 -0
  106. package/dist/test/operations-placeholders.test.d.ts +2 -0
  107. package/dist/test/operations-placeholders.test.d.ts.map +1 -0
  108. package/dist/test/operations-placeholders.test.js +34 -0
  109. package/dist/test/operations-placeholders.test.js.map +1 -0
  110. package/dist/test/pack-manager.test.d.ts +2 -0
  111. package/dist/test/pack-manager.test.d.ts.map +1 -0
  112. package/dist/test/pack-manager.test.js +379 -0
  113. package/dist/test/pack-manager.test.js.map +1 -0
  114. package/dist/test/packs-and-commands.test.d.ts +2 -0
  115. package/dist/test/packs-and-commands.test.d.ts.map +1 -0
  116. package/dist/test/packs-and-commands.test.js +131 -0
  117. package/dist/test/packs-and-commands.test.js.map +1 -0
  118. package/dist/test/process-runner.test.d.ts +2 -0
  119. package/dist/test/process-runner.test.d.ts.map +1 -0
  120. package/dist/test/process-runner.test.js +42 -0
  121. package/dist/test/process-runner.test.js.map +1 -0
  122. package/dist/test/terraform-provider-schema.test.d.ts +2 -0
  123. package/dist/test/terraform-provider-schema.test.d.ts.map +1 -0
  124. package/dist/test/terraform-provider-schema.test.js +259 -0
  125. package/dist/test/terraform-provider-schema.test.js.map +1 -0
  126. package/dist/test/terraform-registry-client.test.d.ts +2 -0
  127. package/dist/test/terraform-registry-client.test.d.ts.map +1 -0
  128. package/dist/test/terraform-registry-client.test.js +321 -0
  129. package/dist/test/terraform-registry-client.test.js.map +1 -0
  130. package/package.json +41 -0
@@ -0,0 +1,17 @@
1
+ export * from "./capability.js";
2
+ export * from "./bound-envelope-transport.js";
3
+ export * from "./command-plans.js";
4
+ export * from "./design-capabilities.js";
5
+ export * from "./encrypted-envelope-transport.js";
6
+ export * from "./iac.js";
7
+ export * from "./iac-generation.js";
8
+ export * from "./iac-normalizers.js";
9
+ export * from "./local-plan-transport.js";
10
+ export * from "./native-iac-providers.js";
11
+ export * from "./operations-placeholders.js";
12
+ export * from "./pack-manager.js";
13
+ export * from "./packs.js";
14
+ export * from "./process-runner.js";
15
+ export * from "./terraform-provider-schema.js";
16
+ export * from "./terraform-registry-client.js";
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mCAAmC,CAAC;AAClD,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ export * from "./capability.js";
2
+ export * from "./bound-envelope-transport.js";
3
+ export * from "./command-plans.js";
4
+ export * from "./design-capabilities.js";
5
+ export * from "./encrypted-envelope-transport.js";
6
+ export * from "./iac.js";
7
+ export * from "./iac-generation.js";
8
+ export * from "./iac-normalizers.js";
9
+ export * from "./local-plan-transport.js";
10
+ export * from "./native-iac-providers.js";
11
+ export * from "./operations-placeholders.js";
12
+ export * from "./pack-manager.js";
13
+ export * from "./packs.js";
14
+ export * from "./process-runner.js";
15
+ export * from "./terraform-provider-schema.js";
16
+ export * from "./terraform-registry-client.js";
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mCAAmC,CAAC;AAClD,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC"}
@@ -0,0 +1,29 @@
1
+ export interface LocalEncryptedPlanMetadata {
2
+ readonly implementation: "local-reference";
3
+ readonly algorithm: "aes-256-gcm";
4
+ readonly digest: string;
5
+ readonly recipient: string;
6
+ readonly createdAt: string;
7
+ readonly expiresAt: string;
8
+ }
9
+ export interface LocalEncryptedPlan {
10
+ readonly metadata: LocalEncryptedPlanMetadata;
11
+ readonly iv: string;
12
+ readonly authTag: string;
13
+ readonly ciphertext: string;
14
+ }
15
+ export interface DecryptedPlanHandle {
16
+ readonly path: string;
17
+ dispose(): Promise<void>;
18
+ }
19
+ export declare class LocalEncryptedPlanTransport {
20
+ private readonly now;
21
+ constructor(now?: () => Date);
22
+ encrypt(plaintext: Uint8Array, key: Uint8Array, options: {
23
+ readonly recipient: string;
24
+ readonly ttlMs: number;
25
+ }): LocalEncryptedPlan;
26
+ decrypt(encrypted: LocalEncryptedPlan, key: Uint8Array, recipient: string): Buffer;
27
+ decryptToRestrictiveTemp(encrypted: LocalEncryptedPlan, key: Uint8Array, recipient: string): Promise<DecryptedPlanHandle>;
28
+ }
29
+ //# sourceMappingURL=local-plan-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-plan-transport.d.ts","sourceRoot":"","sources":["../src/local-plan-transport.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,cAAc,EAAE,iBAAiB,CAAC;IAC3C,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,CAAC;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AA2BD,qBAAa,2BAA2B;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAhC,YAA6B,GAAG,GAAE,MAAM,IAAuB,EAAI;IAEnE,OAAO,CACL,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAC9D,kBAAkB,CAuBpB;IAED,OAAO,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAkBjF;IAEK,wBAAwB,CAC5B,SAAS,EAAE,kBAAkB,EAC7B,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,CAAC,CAwB9B;CACF"}
@@ -0,0 +1,101 @@
1
+ import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
2
+ import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ function requireKey(key) {
6
+ if (key.byteLength !== 32) {
7
+ throw new TypeError("Local plan transport requires a caller-supplied 32-byte key");
8
+ }
9
+ return Buffer.from(key);
10
+ }
11
+ function digest(bytes) {
12
+ return createHash("sha256").update(bytes).digest("hex");
13
+ }
14
+ function authenticatedMetadata(metadata) {
15
+ return Buffer.from(JSON.stringify({
16
+ implementation: metadata.implementation,
17
+ algorithm: metadata.algorithm,
18
+ digest: metadata.digest,
19
+ recipient: metadata.recipient,
20
+ createdAt: metadata.createdAt,
21
+ expiresAt: metadata.expiresAt,
22
+ }), "utf8");
23
+ }
24
+ export class LocalEncryptedPlanTransport {
25
+ now;
26
+ constructor(now = () => new Date()) {
27
+ this.now = now;
28
+ }
29
+ encrypt(plaintext, key, options) {
30
+ if (options.recipient.trim().length === 0 || options.ttlMs <= 0) {
31
+ throw new TypeError("Plan recipient and positive expiry are required");
32
+ }
33
+ const createdAt = this.now();
34
+ const metadata = {
35
+ implementation: "local-reference",
36
+ algorithm: "aes-256-gcm",
37
+ digest: digest(plaintext),
38
+ recipient: options.recipient,
39
+ createdAt: createdAt.toISOString(),
40
+ expiresAt: new Date(createdAt.getTime() + options.ttlMs).toISOString(),
41
+ };
42
+ const iv = randomBytes(12);
43
+ const cipher = createCipheriv("aes-256-gcm", requireKey(key), iv);
44
+ cipher.setAAD(authenticatedMetadata(metadata));
45
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
46
+ return {
47
+ metadata,
48
+ iv: iv.toString("base64"),
49
+ authTag: cipher.getAuthTag().toString("base64"),
50
+ ciphertext: ciphertext.toString("base64"),
51
+ };
52
+ }
53
+ decrypt(encrypted, key, recipient) {
54
+ if (encrypted.metadata.implementation !== "local-reference" || encrypted.metadata.algorithm !== "aes-256-gcm") {
55
+ throw new Error("Unsupported encrypted plan transport");
56
+ }
57
+ if (encrypted.metadata.recipient !== recipient) {
58
+ throw new Error("Encrypted plan recipient does not match the current authority");
59
+ }
60
+ if (new Date(encrypted.metadata.expiresAt).getTime() <= this.now().getTime()) {
61
+ throw new Error("Encrypted plan has expired");
62
+ }
63
+ const decipher = createDecipheriv("aes-256-gcm", requireKey(key), Buffer.from(encrypted.iv, "base64"));
64
+ decipher.setAAD(authenticatedMetadata(encrypted.metadata));
65
+ decipher.setAuthTag(Buffer.from(encrypted.authTag, "base64"));
66
+ const plaintext = Buffer.concat([decipher.update(Buffer.from(encrypted.ciphertext, "base64")), decipher.final()]);
67
+ if (digest(plaintext) !== encrypted.metadata.digest) {
68
+ throw new Error("Encrypted plan digest mismatch");
69
+ }
70
+ return plaintext;
71
+ }
72
+ async decryptToRestrictiveTemp(encrypted, key, recipient) {
73
+ const directory = await mkdtemp(join(tmpdir(), "apex-local-plan-"));
74
+ const path = join(directory, "saved.tfplan");
75
+ try {
76
+ await writeFile(path, this.decrypt(encrypted, key, recipient), { mode: 0o600, flag: "wx" });
77
+ await chmod(path, 0o600);
78
+ let disposed = false;
79
+ return {
80
+ path,
81
+ async dispose() {
82
+ if (disposed)
83
+ return;
84
+ disposed = true;
85
+ try {
86
+ const bytes = await readFile(path);
87
+ await writeFile(path, randomBytes(bytes.length), { mode: 0o600 });
88
+ }
89
+ finally {
90
+ await rm(directory, { recursive: true, force: true });
91
+ }
92
+ },
93
+ };
94
+ }
95
+ catch (error) {
96
+ await rm(directory, { recursive: true, force: true });
97
+ throw error;
98
+ }
99
+ }
100
+ }
101
+ //# sourceMappingURL=local-plan-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-plan-transport.js","sourceRoot":"","sources":["../src/local-plan-transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import type { ApprovalEvidenceV1, DeploymentPreviewV1, ExecutionPlanAttestationV1, OperationRecordV1, ResourceInventoryV1 } from "@apexops/contracts";
2
+ import { type BicepStackTarget, type CommandPlan } from "./command-plans.js";
3
+ import { type CurrentDeploymentAuthority, type IacProvider, type ProviderExecutionEvidence, type PreviewRequest } from "./iac.js";
4
+ import { normalizeAzureWhatIf } from "./iac-normalizers.js";
5
+ import type { ProcessRunnerLike } from "./process-runner.js";
6
+ import { LocalEncryptedPlanTransport, type LocalEncryptedPlan } from "./local-plan-transport.js";
7
+ export interface NativeProviderRuntime {
8
+ readonly runner: ProcessRunnerLike;
9
+ readonly currentAuthority: () => Promise<CurrentDeploymentAuthority>;
10
+ readonly now?: () => Date;
11
+ readonly nextId?: () => string;
12
+ readonly timeoutMs?: number;
13
+ readonly maxOutputBytes?: number;
14
+ readonly bindingStore?: PreviewBindingStore;
15
+ }
16
+ export interface PreviewBindingStore {
17
+ save(previewHash: string, binding: PersistedPreviewBinding): Promise<void>;
18
+ load(previewHash: string): Promise<PersistedPreviewBinding | undefined>;
19
+ loadLatest?(projectId: string, runId: string, operation: "apply" | "destroy"): Promise<PersistedPreviewBinding | undefined>;
20
+ }
21
+ export interface EncryptedPlanArtifactStore {
22
+ put(reference: string, artifact: LocalEncryptedPlan): Promise<void>;
23
+ get(reference: string): Promise<LocalEncryptedPlan | undefined>;
24
+ }
25
+ export type PersistedPreviewBinding = BicepPreviewBinding | TerraformPreviewBinding;
26
+ export interface NativeBicepProviderOptions extends NativeProviderRuntime {
27
+ readonly target: BicepStackTarget;
28
+ }
29
+ export interface TerraformNativeTarget {
30
+ readonly cwd: string;
31
+ readonly target: string;
32
+ readonly planPath: (request: PreviewRequest, operation: "apply" | "destroy") => string;
33
+ readonly lockfileHash: string;
34
+ readonly configHash: () => Promise<string>;
35
+ }
36
+ export type TerraformPlanAttestation = ExecutionPlanAttestationV1;
37
+ export interface NativeTerraformProviderOptions extends NativeProviderRuntime {
38
+ readonly target: TerraformNativeTarget;
39
+ readonly keyProvider?: () => Promise<Uint8Array>;
40
+ readonly artifactStore?: EncryptedPlanArtifactStore;
41
+ readonly transport?: LocalEncryptedPlanTransport;
42
+ }
43
+ export interface BicepPreviewBinding {
44
+ readonly kind: "bicep";
45
+ readonly preview: DeploymentPreviewV1;
46
+ readonly providerBindingHash: string;
47
+ readonly templateHash: string;
48
+ readonly parametersHash: string;
49
+ readonly stackStateHash: string;
50
+ }
51
+ export interface TerraformPreviewBinding {
52
+ readonly kind: "terraform";
53
+ readonly preview: DeploymentPreviewV1;
54
+ readonly attestation: TerraformPlanAttestation;
55
+ }
56
+ declare abstract class NativeProviderBase {
57
+ #private;
58
+ protected readonly runner: ProcessRunnerLike;
59
+ protected readonly now: () => Date;
60
+ protected readonly nextId: () => string;
61
+ protected readonly currentAuthority: () => Promise<CurrentDeploymentAuthority>;
62
+ protected readonly bindingStore: PreviewBindingStore | undefined;
63
+ protected constructor(options: NativeProviderRuntime);
64
+ protected run(plan: CommandPlan): Promise<string>;
65
+ protected authorize(track: "bicep" | "terraform", operation: "apply" | "destroy", preview: DeploymentPreviewV1, approval: ApprovalEvidenceV1, suppliedAuthority: CurrentDeploymentAuthority, latestPreviewHash: string | undefined): Promise<CurrentDeploymentAuthority>;
66
+ protected record(operation: "apply" | "destroy", preview: DeploymentPreviewV1, approval: ApprovalEvidenceV1, authority: CurrentDeploymentAuthority, providerOperationId?: string, validatorIds?: readonly string[]): OperationRecordV1;
67
+ reconcile(operationId: string): Promise<OperationRecordV1 | undefined>;
68
+ executionEvidence(operationId: string): ProviderExecutionEvidence | undefined;
69
+ protected previewKey(request: PreviewRequest, operation: "apply" | "destroy"): string;
70
+ protected createPreview(track: "bicep" | "terraform", operation: "apply" | "destroy", request: PreviewRequest, normalized: ReturnType<typeof normalizeAzureWhatIf>, extra?: Partial<Pick<DeploymentPreviewV1, "artifactHash" | "stateLineage" | "stateSerial">>): DeploymentPreviewV1;
71
+ }
72
+ export declare class NativeBicepProvider extends NativeProviderBase implements IacProvider {
73
+ #private;
74
+ readonly track: "bicep";
75
+ constructor(options: NativeBicepProviderOptions);
76
+ validate(): Promise<readonly string[]>;
77
+ previewApply(request: PreviewRequest): Promise<DeploymentPreviewV1>;
78
+ previewDestroy(request: PreviewRequest): Promise<DeploymentPreviewV1>;
79
+ apply(preview: DeploymentPreviewV1, approval: ApprovalEvidenceV1, authority: CurrentDeploymentAuthority): Promise<OperationRecordV1>;
80
+ destroy(preview: DeploymentPreviewV1, approval: ApprovalEvidenceV1, authority: CurrentDeploymentAuthority): Promise<OperationRecordV1>;
81
+ inventory(projectId: string, runId: string): Promise<ResourceInventoryV1>;
82
+ }
83
+ export declare class NativeTerraformProvider extends NativeProviderBase implements IacProvider {
84
+ #private;
85
+ readonly track: "terraform";
86
+ constructor(options: NativeTerraformProviderOptions);
87
+ validate(): Promise<readonly string[]>;
88
+ previewApply(request: PreviewRequest): Promise<DeploymentPreviewV1>;
89
+ previewDestroy(request: PreviewRequest): Promise<DeploymentPreviewV1>;
90
+ apply(preview: DeploymentPreviewV1, approval: ApprovalEvidenceV1, authority: CurrentDeploymentAuthority): Promise<OperationRecordV1>;
91
+ destroy(preview: DeploymentPreviewV1, approval: ApprovalEvidenceV1, authority: CurrentDeploymentAuthority): Promise<OperationRecordV1>;
92
+ inventory(projectId: string, runId: string): Promise<ResourceInventoryV1>;
93
+ attestation(previewHash: string): TerraformPlanAttestation | undefined;
94
+ }
95
+ export {};
96
+ //# sourceMappingURL=native-iac-providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-iac-providers.d.ts","sourceRoot":"","sources":["../src/native-iac-providers.ts"],"names":[],"mappings":"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"}