@kungfu-tech/buildchain 2.3.2-alpha.0 → 2.4.0-alpha.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.
- package/bin/buildchain.mjs +35 -1
- package/dist/site/artifact-schemas.json +5 -0
- package/dist/site/buildchain-site.json +7 -0
- package/dist/site/cli-registry.json +11 -1
- package/dist/site/site-manifest.json +7 -0
- package/docs/MAP.md +3 -0
- package/docs/cli.md +24 -2
- package/docs/infra-contract.md +208 -0
- package/docs/lifecycle-protocol.md +12 -0
- package/docs/versioning.md +1 -0
- package/fixtures/infra-contract-aws-cdk-shaped/README.md +8 -0
- package/fixtures/infra-contract-aws-cli-shaped/README.md +7 -0
- package/fixtures/infra-contract-cloudformation-shaped/README.md +7 -0
- package/fixtures/infra-contract-opentofu-shaped/README.md +7 -0
- package/fixtures/infra-contract-pulumi-shaped/README.md +7 -0
- package/fixtures/infra-contract-shaped/README.md +8 -0
- package/fixtures/infra-contract-terraform-shaped/README.md +5 -0
- package/package.json +2 -1
- package/packages/core/buildchain-config.js +139 -2
- package/scripts/generate-site-bundle.mjs +9 -1
- package/scripts/infra-contract-core.mjs +1032 -0
- package/scripts/infra-contract.mjs +345 -0
- package/scripts/init-repo.mjs +85 -4
package/bin/buildchain.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { initBuildchainRepo } from "../scripts/init-repo.mjs";
|
|
8
8
|
import { npmPublishDryRun } from "../scripts/npm-publish-dry-run.mjs";
|
|
9
9
|
import { runLifecycle } from "../scripts/run-lifecycle-core.mjs";
|
|
10
|
+
import { verifyInfraContractEvidenceBundle } from "../scripts/infra-contract-core.mjs";
|
|
10
11
|
import { validateBuildchainConfig } from "../packages/core/buildchain-config.js";
|
|
11
12
|
import { detectPackageManager } from "../packages/core/package-manager.js";
|
|
12
13
|
import {
|
|
@@ -40,7 +41,7 @@ function usage() {
|
|
|
40
41
|
return `Usage:
|
|
41
42
|
buildchain --help
|
|
42
43
|
buildchain version
|
|
43
|
-
buildchain init [--cwd <dir>] [--type package|native|web-surface|anchored-package] [--force]
|
|
44
|
+
buildchain init [--cwd <dir>] [--type package|native|web-surface|infra-contract|anchored-package] [--force]
|
|
44
45
|
[--package-manager pnpm|npm|yarn] [--runner-preset <preset>]
|
|
45
46
|
[--artifact-name <template>]
|
|
46
47
|
buildchain validate [--cwd <dir>] [--require-version-state]
|
|
@@ -72,6 +73,7 @@ function usage() {
|
|
|
72
73
|
[--release-extra-json <json-or-path>]
|
|
73
74
|
[--publish-json <json-or-path>] [--output-dir <dir>] [--json]
|
|
74
75
|
buildchain verify release-passport <file-or-url> [--json]
|
|
76
|
+
buildchain verify infra-contract-evidence-bundle <file> [--json]
|
|
75
77
|
buildchain verify observability-log <jsonl> [--min-events <n>]
|
|
76
78
|
[--require-phase <csv>]
|
|
77
79
|
[--require-component <csv>]
|
|
@@ -94,6 +96,7 @@ function usage() {
|
|
|
94
96
|
buildchain span --event <name> [--phase <phase>] [--component <name>]
|
|
95
97
|
[--path <jsonl>] -- <command> [args...]
|
|
96
98
|
buildchain web-surface ...
|
|
99
|
+
buildchain infra-contract ...
|
|
97
100
|
buildchain publish-source <lock|manifest|verify-lock|validate-anchored-release> ...
|
|
98
101
|
buildchain build-contract ...
|
|
99
102
|
|
|
@@ -106,7 +109,15 @@ Examples:
|
|
|
106
109
|
buildchain span --event native.build -- cmake --build build
|
|
107
110
|
buildchain collect github-release --tag v2.2.0 --assets-dir dist --output-dir .buildchain/release-passport
|
|
108
111
|
buildchain verify release-passport .buildchain/release-passport/buildchain.release.json
|
|
112
|
+
buildchain verify infra-contract-evidence-bundle .buildchain/infra-contract-evidence-bundle.json
|
|
109
113
|
buildchain verify observability-log .buildchain/logs/events.jsonl --min-events 4 --require-phase build
|
|
114
|
+
buildchain infra-contract --mode plan --source-sha <sha>
|
|
115
|
+
buildchain infra-contract --mode ci --source-sha <sha>
|
|
116
|
+
buildchain infra-contract --mode plan --source-sha <sha> --execute-adapter-commands true
|
|
117
|
+
buildchain infra-contract --mode apply --plan <plan.json> --source-sha <sha> --approval-id <id>
|
|
118
|
+
buildchain infra-contract --mode apply --plan <plan.json> --source-sha <sha> --approval-id <id> --dry-run false --execute-adapter-commands true
|
|
119
|
+
buildchain infra-contract --mode propagation-apply --propagation-plan <plan.json> --dry-run true
|
|
120
|
+
buildchain infra-contract --mode evidence-bundle --artifact <artifact.json> --propagation-result <result.json>
|
|
110
121
|
`;
|
|
111
122
|
}
|
|
112
123
|
|
|
@@ -712,6 +723,24 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
712
723
|
process.exitCode = report.ok ? 0 : 1;
|
|
713
724
|
return;
|
|
714
725
|
}
|
|
726
|
+
if (subcommand === "infra-contract-evidence-bundle") {
|
|
727
|
+
if (!location) {
|
|
728
|
+
throw new Error("usage: buildchain verify infra-contract-evidence-bundle <file>");
|
|
729
|
+
}
|
|
730
|
+
const bundle = JSON.parse(fs.readFileSync(path.resolve(location), "utf8"));
|
|
731
|
+
const report = verifyInfraContractEvidenceBundle(bundle);
|
|
732
|
+
if (readBooleanFlag(verifyArgs, "json")) {
|
|
733
|
+
printJson(report);
|
|
734
|
+
} else {
|
|
735
|
+
process.stdout.write(`infra contract evidence bundle: ${report.ok ? "ok" : "failed"}\n`);
|
|
736
|
+
process.stdout.write(`artifact: ${report.artifactHash || "unknown"}\n`);
|
|
737
|
+
for (const entry of report.issues) {
|
|
738
|
+
process.stdout.write(`- ${entry.level}: ${entry.code}: ${entry.message}\n`);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
process.exitCode = report.ok ? 0 : 1;
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
715
744
|
if (subcommand !== "release-passport" || !location) {
|
|
716
745
|
throw new Error("usage: buildchain verify release-passport <file-or-url>");
|
|
717
746
|
}
|
|
@@ -774,6 +803,11 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
774
803
|
return;
|
|
775
804
|
}
|
|
776
805
|
|
|
806
|
+
if (command === "infra-contract") {
|
|
807
|
+
runScript("infra-contract.mjs", args);
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
|
|
777
811
|
if (command === "build-contract") {
|
|
778
812
|
runScript("resolve-build-contract.mjs", args);
|
|
779
813
|
return;
|
|
@@ -121,6 +121,13 @@
|
|
|
121
121
|
"path": "docs/web-surface-deployments.md",
|
|
122
122
|
"plane": "use",
|
|
123
123
|
"exists": true
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"id": "infra-contract",
|
|
127
|
+
"title": "Infra Contract",
|
|
128
|
+
"path": "docs/infra-contract.md",
|
|
129
|
+
"plane": "use",
|
|
130
|
+
"exists": true
|
|
124
131
|
}
|
|
125
132
|
],
|
|
126
133
|
"releaseModel": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"id": "init",
|
|
14
|
-
"usage": "buildchain init [--type package|native|web-surface|anchored-package]",
|
|
14
|
+
"usage": "buildchain init [--type package|native|web-surface|infra-contract|anchored-package]",
|
|
15
15
|
"purpose": "Bootstrap a repository with Buildchain configuration and caller workflow files."
|
|
16
16
|
},
|
|
17
17
|
{
|
|
@@ -44,6 +44,11 @@
|
|
|
44
44
|
"usage": "buildchain verify release-passport <file-or-url>",
|
|
45
45
|
"purpose": "Fail closed unless a release passport and its evidence are complete."
|
|
46
46
|
},
|
|
47
|
+
{
|
|
48
|
+
"id": "verify-infra-contract-evidence-bundle",
|
|
49
|
+
"usage": "buildchain verify infra-contract-evidence-bundle <file>",
|
|
50
|
+
"purpose": "Fail closed unless an infra-contract lifecycle evidence bundle is complete, hash-bound, and validation-consistent."
|
|
51
|
+
},
|
|
47
52
|
{
|
|
48
53
|
"id": "logging",
|
|
49
54
|
"usage": "buildchain log|mark|span|verify observability-log",
|
|
@@ -58,6 +63,11 @@
|
|
|
58
63
|
"id": "npm-dry-run",
|
|
59
64
|
"usage": "buildchain npm dry-run --json",
|
|
60
65
|
"purpose": "Verify npm publish shape before a release transaction."
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "infra-contract",
|
|
69
|
+
"usage": "buildchain infra-contract --mode validate|ci|plan|contract|propagation-plan|propagation-apply|apply|evidence-bundle",
|
|
70
|
+
"purpose": "Validate and publish provider-neutral infrastructure contract evidence with a mutation-free CI evidence chain, provider command plans, configured provider command execution, saved-plan apply gates, dry-run-first propagation, and lifecycle evidence bundles."
|
|
61
71
|
}
|
|
62
72
|
]
|
|
63
73
|
}
|
|
@@ -109,6 +109,13 @@
|
|
|
109
109
|
"path": "docs/web-surface-deployments.md",
|
|
110
110
|
"plane": "use",
|
|
111
111
|
"exists": true
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"id": "infra-contract",
|
|
115
|
+
"title": "Infra Contract",
|
|
116
|
+
"path": "docs/infra-contract.md",
|
|
117
|
+
"plane": "use",
|
|
118
|
+
"exists": true
|
|
112
119
|
}
|
|
113
120
|
],
|
|
114
121
|
"facts": [
|
package/docs/MAP.md
CHANGED
|
@@ -37,6 +37,7 @@ running artifact), *use* (consume / extend) - and a **status**:
|
|
|
37
37
|
| How do I call the reusable build workflow? | [`reusable-build-surface.md`](reusable-build-surface.md) | use | stable |
|
|
38
38
|
| How do I validate an unreleased Buildchain runtime train while keeping `@v2`? | [`runtime-train-validation.md`](runtime-train-validation.md) | use | stable |
|
|
39
39
|
| How do I deploy a site/app preview, staging, or production surface? | [`web-surface-deployments.md`](web-surface-deployments.md) | use | stable |
|
|
40
|
+
| How do I publish observed infrastructure contracts for downstream consumers? | [`infra-contract.md`](infra-contract.md) | use | preview |
|
|
40
41
|
| How do I use the active actions directly? | [`../actions/validate-config/README.md`](../actions/validate-config/README.md), [`../actions/run-lifecycle/README.md`](../actions/run-lifecycle/README.md), [`../actions/promote-buildchain-ref/README.md`](../actions/promote-buildchain-ref/README.md) | use | stable |
|
|
41
42
|
| What do the fixture repositories demonstrate? | [`../fixtures/libnode-shaped/README.md`](../fixtures/libnode-shaped/README.md), [`../fixtures/publish-transaction-shaped/README.md`](../fixtures/publish-transaction-shaped/README.md), [`../fixtures/web-surface-shaped/README.md`](../fixtures/web-surface-shaped/README.md) | verify | stable |
|
|
42
43
|
| What license and contribution terms apply? | [`../LICENSE`](../LICENSE) + [`../LICENSE-POLICY.md`](../LICENSE-POLICY.md) | use | stable |
|
|
@@ -63,6 +64,8 @@ running artifact), *use* (consume / extend) - and a **status**:
|
|
|
63
64
|
- **runtime train validation / temporary `buildchain-ref` override** ->
|
|
64
65
|
[`runtime-train-validation.md`](runtime-train-validation.md) and
|
|
65
66
|
[`reusable-build-surface.md`](reusable-build-surface.md).
|
|
67
|
+
- **infra contract / observed infrastructure outputs / downstream contract propagation** ->
|
|
68
|
+
[`infra-contract.md`](infra-contract.md).
|
|
66
69
|
- **standalone binary install / platform archives / GitHub Release bundle** ->
|
|
67
70
|
[`install.md`](install.md), [`binary-distribution.md`](binary-distribution.md),
|
|
68
71
|
and [`release-passport.md`](release-passport.md).
|
package/docs/cli.md
CHANGED
|
@@ -61,6 +61,10 @@ Supported presets:
|
|
|
61
61
|
- `--type package` for Node package repositories with pnpm, npm, or yarn.
|
|
62
62
|
- `--type native` for CMake-style native projects.
|
|
63
63
|
- `--type web-surface` for preview/staging/production site or app deployments.
|
|
64
|
+
- `--type infra-contract` for provider-agnostic infrastructure contract
|
|
65
|
+
validation, observation, contract publication, and downstream propagation
|
|
66
|
+
planning without default mutation. Provider adapters expose built-in command
|
|
67
|
+
plans by default, and only configured `[infra.commands]` hooks can execute.
|
|
64
68
|
- `--type anchored-package` for packages whose version is anchored to an
|
|
65
69
|
explicit upstream release manifest.
|
|
66
70
|
|
|
@@ -214,8 +218,8 @@ reusable build workflow outputs. It fails closed for direct `alpha/*` or
|
|
|
214
218
|
version against configured version files and the anchor manifest. The JSON
|
|
215
219
|
result is shaped for future `buildchain.libkungfu.dev` fact ingestion.
|
|
216
220
|
|
|
217
|
-
`buildchain release`, `buildchain web-surface`, `buildchain
|
|
218
|
-
and `buildchain build-contract` route to the same scripts used by Buildchain's
|
|
221
|
+
`buildchain release`, `buildchain web-surface`, `buildchain infra-contract`,
|
|
222
|
+
`buildchain publish-source`, and `buildchain build-contract` route to the same scripts used by Buildchain's
|
|
219
223
|
GitHub Actions workflows. This keeps local inspection and CI behavior on the
|
|
220
224
|
same implementation path.
|
|
221
225
|
|
|
@@ -288,6 +292,24 @@ The verifier fails closed when required protocol files are absent, artifacts are
|
|
|
288
292
|
not covered by evidence, or digests disagree. The explanation output is shaped
|
|
289
293
|
for agents: trust, completeness, impact, recovery route, and next action.
|
|
290
294
|
|
|
295
|
+
Verify infra-contract lifecycle evidence bundles:
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
buildchain infra-contract --mode ci --source-sha "$GITHUB_SHA"
|
|
299
|
+
buildchain verify infra-contract-evidence-bundle .buildchain/infra-contract-evidence-bundle.json
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
The infra-contract `ci` mode is mutation-free. It writes validate, plan,
|
|
303
|
+
contract, propagation dry-run, evidence bundle, and verification JSON artifacts
|
|
304
|
+
under `.buildchain/`, giving reusable workflows one standard responsibility
|
|
305
|
+
chain instead of hand-written command sequences.
|
|
306
|
+
|
|
307
|
+
The infra-contract verifier is read-only. It recomputes the bundle hash and
|
|
308
|
+
checks that desired, plan, approval, apply, observe, contract, and propagate
|
|
309
|
+
evidence remain bound to the same contract artifact. It also recomputes the
|
|
310
|
+
bundle validation summary, so stale or misleading summary booleans fail closed
|
|
311
|
+
even when the bundle hash has been refreshed.
|
|
312
|
+
|
|
291
313
|
`buildchain release --dry-run` explains the release-line state machine before a
|
|
292
314
|
maintainer opens or merges a channel PR:
|
|
293
315
|
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Infra Contract
|
|
2
|
+
|
|
3
|
+
`project.type = "infra-contract"` models infrastructure release responsibility
|
|
4
|
+
without binding Buildchain core to one infrastructure tool. The state machine is:
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
desired -> validate -> plan -> approval -> apply -> observe -> contract -> propagate
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
The first supported surface is mutation-free: Buildchain validates declarations,
|
|
11
|
+
creates a normalized plan, reads reviewed or adapter-shaped observed outputs,
|
|
12
|
+
publishes a deterministic contract artifact, and plans downstream consumer pull
|
|
13
|
+
requests. Propagation execution is also dry-run by default. Real infrastructure
|
|
14
|
+
mutation and real consumer pull request creation are not PR or ordinary push side
|
|
15
|
+
effects.
|
|
16
|
+
|
|
17
|
+
After apply and propagation produce their own result JSON, Buildchain can also
|
|
18
|
+
write a lifecycle evidence bundle. The bundle references the immutable contract
|
|
19
|
+
artifact by `artifactHash`, verifies that any apply result matches the artifact's
|
|
20
|
+
`sourceSha` and plan hash, verifies that propagation results target the same
|
|
21
|
+
artifact, and then hashes the combined desired, plan, approval, apply, observe,
|
|
22
|
+
contract, and propagation evidence.
|
|
23
|
+
|
|
24
|
+
## Configuration
|
|
25
|
+
|
|
26
|
+
```toml
|
|
27
|
+
schema = 1
|
|
28
|
+
|
|
29
|
+
[project]
|
|
30
|
+
type = "infra-contract"
|
|
31
|
+
name = "infra-kungfu-sites"
|
|
32
|
+
|
|
33
|
+
[infra]
|
|
34
|
+
adapter = "manual-observed"
|
|
35
|
+
adoption_mode = "manual-observed"
|
|
36
|
+
apply = "disabled"
|
|
37
|
+
environment = "staging"
|
|
38
|
+
desired = ["desired/site-kungfu-tech.json"]
|
|
39
|
+
contract = ["outputs/site-kungfu-tech.json"]
|
|
40
|
+
|
|
41
|
+
[[consumers]]
|
|
42
|
+
repo = "kungfu-systems/site-kungfu-tech"
|
|
43
|
+
path = "infra/outputs.json"
|
|
44
|
+
source = "outputs/site-kungfu-tech.json"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Supported adapters:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
manual-observed
|
|
51
|
+
aws-cloudformation
|
|
52
|
+
terraform
|
|
53
|
+
opentofu
|
|
54
|
+
pulumi
|
|
55
|
+
aws-cdk
|
|
56
|
+
aws-cli
|
|
57
|
+
custom-command
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Buildchain's safe fixture set covers the provider-neutral shape without live
|
|
61
|
+
provider calls:
|
|
62
|
+
|
|
63
|
+
- `manual-observed` for existing reviewed resources;
|
|
64
|
+
- `aws-cloudformation` for template plus stack output shapes;
|
|
65
|
+
- `terraform` for plan/output JSON shapes;
|
|
66
|
+
- `opentofu` for plan/output JSON shapes;
|
|
67
|
+
- `pulumi` for preview/output JSON shapes;
|
|
68
|
+
- `aws-cdk` for synthesized assembly plus stack output shapes;
|
|
69
|
+
- `aws-cli` for generic desired request plus observed response shapes;
|
|
70
|
+
- `custom-command` for user-defined validate, plan, observe, and approved apply
|
|
71
|
+
hooks.
|
|
72
|
+
|
|
73
|
+
For built-in provider adapters, Buildchain records planned adapter command
|
|
74
|
+
evidence for `validate`, `plan`, `apply`, and `observe` when a stage is
|
|
75
|
+
supported. These entries are command plans, not execution. They make the
|
|
76
|
+
adapter handoff auditable before a repository opts in to concrete commands,
|
|
77
|
+
and they stay `executed: false` even when `--execute-adapter-commands true` is
|
|
78
|
+
passed.
|
|
79
|
+
|
|
80
|
+
Any adapter can declare concrete command hooks under `[infra.commands]`.
|
|
81
|
+
Configured commands are the only executable provider surface. Buildchain records
|
|
82
|
+
them as planned adapter evidence by default. Passing
|
|
83
|
+
`--execute-adapter-commands true` to `plan` or `contract` executes the
|
|
84
|
+
non-mutating `validate`, `plan`, or `observe` hooks and stores their exit
|
|
85
|
+
status, stdout/stderr, and JSON stdout when present. The `apply` hook is only
|
|
86
|
+
available through the saved-plan apply path and is never executed by ordinary
|
|
87
|
+
PR validation.
|
|
88
|
+
|
|
89
|
+
Supported adoption modes:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
validate-only
|
|
93
|
+
plan-only
|
|
94
|
+
observe-only
|
|
95
|
+
manual-observed
|
|
96
|
+
import-planned
|
|
97
|
+
managed-apply
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`apply = "disabled"` is the default. Non-disabled apply requires
|
|
101
|
+
`adoption_mode = "managed-apply"`, a non-empty `environment`, a non-empty
|
|
102
|
+
`identity_ref`, and an explicit approval id before mutation. `identity_ref` is a
|
|
103
|
+
provider-neutral reference to the runtime role, service account, or environment
|
|
104
|
+
credential name; it is not a secret value. Apply also requires a saved plan
|
|
105
|
+
artifact whose `sourceSha`, `plannedAt`, and input hash still match the current
|
|
106
|
+
repository. Real apply execution requires a configured `[infra.commands].apply`
|
|
107
|
+
command, `--dry-run false`, and `--execute-adapter-commands true`. Without a
|
|
108
|
+
configured apply command, built-in provider adapters still fail closed before
|
|
109
|
+
mutation execution.
|
|
110
|
+
|
|
111
|
+
For managed apply, bind the target and runtime identity explicitly:
|
|
112
|
+
|
|
113
|
+
```toml
|
|
114
|
+
adoption_mode = "managed-apply"
|
|
115
|
+
apply = "manual-approval"
|
|
116
|
+
environment = "preview"
|
|
117
|
+
identity_ref = "AWS_ROLE_ARN"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## CLI
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
buildchain infra-contract --mode validate
|
|
124
|
+
buildchain infra-contract --mode ci --source-sha "$GITHUB_SHA"
|
|
125
|
+
buildchain infra-contract --mode plan --source-sha "$GITHUB_SHA" \
|
|
126
|
+
--output .buildchain/infra-contract-plan.json
|
|
127
|
+
buildchain infra-contract --mode plan --source-sha "$GITHUB_SHA" \
|
|
128
|
+
--execute-adapter-commands true \
|
|
129
|
+
--output .buildchain/infra-contract-plan.json
|
|
130
|
+
buildchain infra-contract --mode contract \
|
|
131
|
+
--plan .buildchain/infra-contract-plan.json \
|
|
132
|
+
--source-sha "$GITHUB_SHA" \
|
|
133
|
+
--output .buildchain/buildchain.infra-contract.json
|
|
134
|
+
buildchain infra-contract --mode propagation-plan \
|
|
135
|
+
--artifact .buildchain/buildchain.infra-contract.json \
|
|
136
|
+
--output .buildchain/infra-contract-propagation.json
|
|
137
|
+
buildchain infra-contract --mode propagation-apply \
|
|
138
|
+
--propagation-plan .buildchain/infra-contract-propagation.json \
|
|
139
|
+
--dry-run true \
|
|
140
|
+
--output .buildchain/infra-contract-propagation-apply.json
|
|
141
|
+
buildchain infra-contract --mode apply \
|
|
142
|
+
--plan .buildchain/infra-contract-plan.json \
|
|
143
|
+
--source-sha "$GITHUB_SHA" \
|
|
144
|
+
--approval-id "$APPROVAL_ID" \
|
|
145
|
+
--dry-run true \
|
|
146
|
+
--output .buildchain/infra-contract-apply.json
|
|
147
|
+
buildchain infra-contract --mode apply \
|
|
148
|
+
--plan .buildchain/infra-contract-plan.json \
|
|
149
|
+
--source-sha "$GITHUB_SHA" \
|
|
150
|
+
--approval-id "$APPROVAL_ID" \
|
|
151
|
+
--dry-run false \
|
|
152
|
+
--execute-adapter-commands true \
|
|
153
|
+
--output .buildchain/infra-contract-apply.json
|
|
154
|
+
buildchain infra-contract --mode evidence-bundle \
|
|
155
|
+
--artifact .buildchain/buildchain.infra-contract.json \
|
|
156
|
+
--apply-result .buildchain/infra-contract-apply.json \
|
|
157
|
+
--propagation-result .buildchain/infra-contract-propagation-apply.json \
|
|
158
|
+
--output .buildchain/infra-contract-evidence-bundle.json
|
|
159
|
+
buildchain verify infra-contract-evidence-bundle \
|
|
160
|
+
.buildchain/infra-contract-evidence-bundle.json
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`ci` is the default mutation-free lifecycle entrypoint for repositories created
|
|
164
|
+
with `buildchain init --type infra-contract`. It validates the project, writes a
|
|
165
|
+
plan, writes an observed contract artifact, writes a propagation plan, runs
|
|
166
|
+
propagation apply in dry-run mode, creates an evidence bundle, and verifies that
|
|
167
|
+
bundle. It does not execute provider apply commands or open consumer PRs.
|
|
168
|
+
|
|
169
|
+
For projects where apply is disabled, omit `--apply-result`. For projects with
|
|
170
|
+
no consumers, omit `--propagation-result`.
|
|
171
|
+
|
|
172
|
+
The evidence-bundle verifier is read-only. It recomputes the bundle hash,
|
|
173
|
+
checks the contract artifact hash, verifies that desired, plan, approval,
|
|
174
|
+
apply, observe, contract, and propagate evidence are all present, recomputes
|
|
175
|
+
the bundle validation summary, and fails closed when apply or propagation
|
|
176
|
+
results are not bound to the same artifact.
|
|
177
|
+
|
|
178
|
+
## Safety
|
|
179
|
+
|
|
180
|
+
- PR validation is mutation-free.
|
|
181
|
+
- `buildchain infra-contract --mode ci` is mutation-free by default and produces
|
|
182
|
+
auditable `.buildchain/infra-contract*.json` evidence for reusable workflow
|
|
183
|
+
artifacts.
|
|
184
|
+
- `manual-observed` and observe-only modes cannot apply.
|
|
185
|
+
- Apply fails before mutation unless approval, target environment, identity
|
|
186
|
+
reference, adapter capability, and ownership mode are explicit.
|
|
187
|
+
- Apply rejects missing, stale, source-mismatched, or input-drifted plan
|
|
188
|
+
artifacts before any adapter mutation can run.
|
|
189
|
+
- Built-in provider adapter command evidence is planned-only unless the
|
|
190
|
+
repository declares a concrete command for that stage under `[infra.commands]`.
|
|
191
|
+
- Provider apply requires saved plan freshness, an approval id, target
|
|
192
|
+
environment, identity reference, a configured apply command,
|
|
193
|
+
`--dry-run false`, and `--execute-adapter-commands true`; nonzero adapter
|
|
194
|
+
exits fail closed and are recorded as adapter evidence.
|
|
195
|
+
- Terraform/OpenTofu state files and Pulumi state or secret JSON files are not
|
|
196
|
+
accepted as contract inputs.
|
|
197
|
+
- Consumers are represented as pull request plans. `propagation-apply` defaults
|
|
198
|
+
to dry-run; real PR creation requires `--dry-run false`, `--approval-id`, and
|
|
199
|
+
explicit `--consumer-workspace owner/repo=/path/to/checkout` mappings.
|
|
200
|
+
- Buildchain never pushes mirrored contract files directly to consumer main
|
|
201
|
+
branches. Real propagation creates reviewable branches and calls
|
|
202
|
+
`gh pr create`.
|
|
203
|
+
- Evidence bundles do not execute adapters, mutate infrastructure, or open PRs.
|
|
204
|
+
They only verify and hash already saved contract, apply, and propagation
|
|
205
|
+
outputs.
|
|
206
|
+
- `buildchain verify infra-contract-evidence-bundle` is read-only and fails
|
|
207
|
+
closed when the lifecycle evidence chain is incomplete, tampered, or carries
|
|
208
|
+
a stale validation summary.
|
|
@@ -352,6 +352,18 @@ See [Web-surface deployments](web-surface-deployments.md) for named surface host
|
|
|
352
352
|
mappings, the manifest, preview alias, retention, cleanup, and dry-run deploy
|
|
353
353
|
contract.
|
|
354
354
|
|
|
355
|
+
## Infra-Contract Projects
|
|
356
|
+
|
|
357
|
+
`project.type = "infra-contract"` is for infrastructure contract repositories
|
|
358
|
+
that need provider-neutral desired, plan, approval, apply, observe, contract,
|
|
359
|
+
and propagation evidence. `buildchain init --type infra-contract` wires
|
|
360
|
+
`lifecycle.verify` to `buildchain infra-contract --mode ci`, which writes
|
|
361
|
+
mutation-free plan, contract, propagation dry-run, evidence bundle, and
|
|
362
|
+
verification artifacts under `.buildchain/`. The surface supports
|
|
363
|
+
manual-observed, observe-only, and mocked adapter fixtures without reading
|
|
364
|
+
cloud state files or executing live infrastructure mutation. See
|
|
365
|
+
[Infra Contract](infra-contract.md).
|
|
366
|
+
|
|
355
367
|
## Examples
|
|
356
368
|
|
|
357
369
|
### Node Workspace
|
package/docs/versioning.md
CHANGED
|
@@ -43,6 +43,7 @@ expected ref flow requires a major bump.
|
|
|
43
43
|
| 2026-07-02 | Buildchain toolkit observability is a minor surface. | `v2.1` | It adds the public logging SDK, CLI observability commands, and package subpaths that consumers can import. |
|
|
44
44
|
| 2026-07-02 | Release passport and binary distribution are a minor surface. | `v2.2` | They add agent-readable release passport files, artifact evidence, impact ledger, agent index, GitHub Release collection and verification commands, and standalone binary assets. |
|
|
45
45
|
| 2026-07-02 | Web surface host mapping is a minor surface. | `v2.3` | It adds first-class multi-host surface bindings, reusable workflow URL outputs, per-surface deployment overrides, and an agent-readable fixture contract. |
|
|
46
|
+
| 2026-07-03 | Infra contract lifecycle is a minor surface. | `v2.4` | It adds the provider-neutral `infra-contract` CLI command family, project type, adapter capability contract, lifecycle evidence bundle, propagation evidence, CI evidence mode, and consumer-facing contract artifacts. |
|
|
46
47
|
|
|
47
48
|
## Runner Policy
|
|
48
49
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# AWS CDK-shaped Infra Contract Fixture
|
|
2
|
+
|
|
3
|
+
This fixture proves the infra-contract model can represent AWS CDK synthesized
|
|
4
|
+
assembly metadata and observed CloudFormation output shapes without deploying a
|
|
5
|
+
stack.
|
|
6
|
+
|
|
7
|
+
It is static evidence only: no `cdk deploy` command is executed and no AWS
|
|
8
|
+
credentials are required.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# AWS CLI-shaped Infra Contract Fixture
|
|
2
|
+
|
|
3
|
+
This fixture proves the infra-contract model can represent a generic AWS CLI
|
|
4
|
+
desired request and observed response shape without calling a live AWS service.
|
|
5
|
+
|
|
6
|
+
It is static evidence only: no AWS CLI command is executed and no AWS
|
|
7
|
+
credentials are required.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# CloudFormation-shaped Infra Contract Fixture
|
|
2
|
+
|
|
3
|
+
This fixture proves the infra-contract model can represent CloudFormation
|
|
4
|
+
desired templates and observed stack outputs without making live AWS calls.
|
|
5
|
+
|
|
6
|
+
It is static evidence only: no change set is created, no stack is updated, and
|
|
7
|
+
no AWS credentials are required.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# OpenTofu-shaped Infra Contract Fixture
|
|
2
|
+
|
|
3
|
+
This fixture proves the infra-contract model can represent OpenTofu desired
|
|
4
|
+
configuration and observed output shapes without reading OpenTofu state files.
|
|
5
|
+
|
|
6
|
+
It is static evidence only: no `tofu apply` command is executed and no provider
|
|
7
|
+
credentials are required.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Pulumi-shaped Infra Contract Fixture
|
|
2
|
+
|
|
3
|
+
This fixture proves the infra-contract model can represent Pulumi preview and
|
|
4
|
+
stack output shapes without reading Pulumi state or secrets files.
|
|
5
|
+
|
|
6
|
+
It is static evidence only: no `pulumi up` command is executed and no Pulumi
|
|
7
|
+
secrets material is committed.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Infra Contract Shaped Fixture
|
|
2
|
+
|
|
3
|
+
This fixture models an infrastructure repository that already has live resources
|
|
4
|
+
and wants to publish observed output contracts before full IaC ownership exists.
|
|
5
|
+
|
|
6
|
+
It proves that `project.type = "infra-contract"` can validate desired files,
|
|
7
|
+
read reviewed observed outputs, publish a deterministic contract artifact, and
|
|
8
|
+
plan downstream consumer pull requests without mutating cloud infrastructure.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Terraform-shaped Infra Contract Fixture
|
|
2
|
+
|
|
3
|
+
This fixture proves the infra-contract model is not CloudFormation-specific.
|
|
4
|
+
It uses Terraform-shaped desired and output JSON fixtures as static evidence.
|
|
5
|
+
No Terraform state file is read and no provider command is executed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungfu-tech/buildchain",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0-alpha.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
|
|
6
6
|
"repository": "https://github.com/kungfu-systems/buildchain",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"docs/binary-distribution.md",
|
|
42
42
|
"docs/cli.md",
|
|
43
43
|
"docs/install.md",
|
|
44
|
+
"docs/infra-contract.md",
|
|
44
45
|
"docs/lifecycle-protocol.md",
|
|
45
46
|
"docs/migration-inventory.md",
|
|
46
47
|
"docs/ownership.md",
|