@kontourai/flow-agents 1.4.0 → 2.0.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/.github/CODEOWNERS +29 -0
- package/.github/actions/trust-verify/action.yml +145 -0
- package/.github/workflows/ci.yml +11 -4
- package/.github/workflows/kit-gates-demo.yml +2 -2
- package/.github/workflows/publish-npm.yml +10 -2
- package/.github/workflows/release-please.yml +1 -1
- package/.github/workflows/runtime-compat.yml +1 -1
- package/.github/workflows/trust-reconcile.yml +113 -0
- package/AGENTS.md +13 -0
- package/CHANGELOG.md +103 -0
- package/CONTRIBUTING.md +4 -4
- package/README.md +1 -0
- package/agents/tool-planner.json +1 -1
- package/build/src/cli/init.js +242 -20
- package/build/src/cli/validate-workflow-artifacts.js +19 -2
- package/build/src/cli/verify.d.ts +1 -0
- package/build/src/cli/verify.js +90 -0
- package/build/src/cli/workflow-sidecar.d.ts +316 -8
- package/build/src/cli/workflow-sidecar.js +1996 -91
- package/build/src/cli.js +2 -3
- package/build/src/lib/flow-resolver.d.ts +111 -0
- package/build/src/lib/flow-resolver.js +308 -0
- package/build/src/tools/build-universal-bundles.js +34 -22
- package/build/src/tools/generate-context-map.js +3 -16
- package/build/src/tools/validate-source-tree.d.ts +1 -1
- package/build/src/tools/validate-source-tree.js +42 -162
- package/context/contracts/artifact-contract.md +10 -0
- package/context/contracts/delivery-contract.md +1 -0
- package/context/contracts/review-contract.md +1 -0
- package/context/contracts/verification-contract.md +2 -0
- package/context/gate-awareness.md +39 -0
- package/context/scripts/hooks/stop-goal-fit.js +632 -70
- package/docs/adr/0001-flow-agents-consumes-flow.md +1 -1
- package/docs/adr/0002-flow-kits-as-extension-unit.md +1 -1
- package/docs/adr/0004-gates-expect-surface-claims.md +2 -0
- package/docs/adr/0005-kubernetes-inspired-resource-contracts.md +2 -0
- package/docs/adr/0007-skill-audit.md +1 -1
- package/docs/adr/0009-canonical-hook-core-kit-boundary.md +95 -0
- package/docs/adr/0010-workflow-trust-state-as-hachure-bundle.md +139 -0
- package/docs/adr/0011-mcp-posture.md +100 -0
- package/docs/adr/0012-agent-coordination-as-liveness-claims.md +119 -0
- package/docs/adr/0013-context-lifecycle.md +151 -0
- package/docs/adr/0014-core-vs-domain-kit-boundary.md +143 -0
- package/docs/adr/0015-flow-flow-agents-boundary-reconciliation.md +120 -0
- package/docs/adr/0016-three-hard-boundary-model.md +71 -0
- package/docs/adr/0017-anti-gaming-trust-security-model.md +155 -0
- package/docs/agent-system-guidebook.md +5 -12
- package/docs/context-map.md +4 -10
- package/docs/index.md +3 -2
- package/docs/integrations/framework-adapter.md +19 -6
- package/docs/integrations/index.md +2 -2
- package/docs/north-star.md +4 -4
- package/docs/operating-layers.md +3 -3
- package/docs/plans/adr-0010-phase2-gate-recompute.md +55 -0
- package/docs/repository-structure.md +2 -2
- package/docs/skills-map.md +1 -0
- package/docs/spec/runtime-hook-surface.md +62 -9
- package/docs/standards-register.md +3 -3
- package/docs/survey-utterance-check.md +1 -1
- package/docs/trust-anchor-adoption.md +197 -0
- package/docs/verifiable-trust.md +95 -0
- package/docs/veritas-integration.md +2 -2
- package/docs/workflow-usage-guide.md +69 -0
- package/evals/acceptance/DEMO-false-completion.md +144 -0
- package/evals/acceptance/demo-cast.sh +92 -0
- package/evals/acceptance/demo-false-completion.sh +72 -0
- package/evals/acceptance/demo-real-evidence.sh +104 -0
- package/evals/acceptance/demo.tape +29 -0
- package/evals/acceptance/prove-capture-teeth-declared.sh +335 -0
- package/evals/acceptance/prove-capture-teeth.sh +114 -0
- package/evals/acceptance/prove-teeth.sh +105 -0
- package/evals/ci/antigaming-suite.sh +55 -0
- package/evals/ci/run-baseline.sh +2 -0
- package/evals/fixtures/flow-kit-repository/invalid-missing-extension-asset/flows/review.flow.json +26 -0
- package/evals/fixtures/flow-kit-repository/invalid-missing-extension-asset/kit.json +20 -0
- package/evals/fixtures/flow-kit-repository/valid-unknown-extension/flows/review.flow.json +26 -0
- package/evals/fixtures/flow-kit-repository/valid-unknown-extension/kit.json +18 -0
- package/evals/integration/test_builder_step_producers.sh +379 -0
- package/evals/integration/test_bundle_install.sh +35 -71
- package/evals/integration/test_bundle_lifecycle.sh +39 -2
- package/evals/integration/test_captured_fail_reconciliation.sh +820 -0
- package/evals/integration/test_checkpoint_signing.sh +489 -0
- package/evals/integration/test_claim_lookup.sh +352 -0
- package/evals/integration/test_command_log_fork_classification.sh +134 -0
- package/evals/integration/test_command_log_integrity.sh +275 -0
- package/evals/integration/test_context_map.sh +0 -2
- package/evals/integration/test_dual_emit_flow_step.sh +278 -0
- package/evals/integration/test_enforcer_expects_driven.sh +281 -0
- package/evals/integration/test_evidence_capture_hook.sh +185 -0
- package/evals/integration/test_flow_kit_repository.sh +2 -0
- package/evals/integration/test_flowdef_session_activation.sh +273 -0
- package/evals/integration/test_flowdef_session_history_preservation.sh +250 -0
- package/evals/integration/test_gate_bypass_chain.sh +448 -0
- package/evals/integration/test_gate_lockdown.sh +1137 -0
- package/evals/integration/test_gate_review_inquiry_records.sh +399 -0
- package/evals/integration/test_goal_fit_escape_hatch.sh +73 -0
- package/evals/integration/test_goal_fit_hook.sh +69 -4
- package/evals/integration/test_goal_fit_rederive.sh +263 -0
- package/evals/integration/test_install_merge.sh +1176 -0
- package/evals/integration/test_kit_identity_trust.sh +393 -0
- package/evals/integration/test_mint_attestation.sh +373 -0
- package/evals/integration/test_phase_map_and_gate_claim.sh +365 -0
- package/evals/integration/test_publish_delivery.sh +269 -0
- package/evals/integration/test_reconcile_soundness.sh +528 -0
- package/evals/integration/test_resolvefirststep_security.sh +208 -0
- package/evals/integration/test_session_resume_roundtrip.sh +286 -0
- package/evals/integration/test_trust_checkpoint.sh +325 -0
- package/evals/integration/test_trust_reconcile.sh +293 -0
- package/evals/integration/test_verify_cli.sh +208 -0
- package/evals/integration/test_workflow_sidecar_writer.sh +549 -34
- package/evals/lib/node.sh +0 -6
- package/evals/run.sh +47 -0
- package/evals/static/test_workflow_skills.sh +6 -13
- package/install.sh +0 -7
- package/integrations/strands-ts/README.md +25 -15
- package/integrations/veritas/flow-agents.adapter.json +1 -2
- package/kits/builder/flows/build.flow.json +59 -12
- package/kits/builder/kit.json +85 -15
- package/kits/builder/skills/continue-work/SKILL.md +116 -0
- package/kits/builder/skills/deliver/SKILL.md +36 -6
- package/kits/builder/skills/design-probe/SKILL.md +28 -0
- package/kits/builder/skills/execute-plan/SKILL.md +9 -1
- package/kits/builder/skills/gate-review/SKILL.md +234 -0
- package/kits/builder/skills/learning-review/SKILL.md +30 -0
- package/kits/builder/skills/pickup-probe/SKILL.md +29 -0
- package/kits/builder/skills/plan-work/SKILL.md +13 -1
- package/kits/builder/skills/pull-work/SKILL.md +19 -0
- package/kits/knowledge/adapters/default-store/index.js +38 -0
- package/kits/knowledge/adapters/flow-runner/index.js +1620 -0
- package/kits/knowledge/adapters/obsidian-store/index.js +36 -6
- package/kits/knowledge/docs/store-contract.md +314 -0
- package/kits/knowledge/evals/audit-freshness/suite.test.js +368 -0
- package/kits/knowledge/evals/canonicalize-category/suite.test.js +383 -0
- package/kits/knowledge/evals/contract-suite/suite.test.js +111 -0
- package/kits/knowledge/evals/detect-contradictions/suite.test.js +324 -0
- package/kits/knowledge/evals/entities/suite.test.js +40 -0
- package/kits/knowledge/evals/glossary-sync/suite.test.js +416 -0
- package/kits/knowledge/evals/hygiene-review/suite.test.js +396 -0
- package/kits/knowledge/evals/retirement/suite.test.js +145 -0
- package/kits/knowledge/flows/audit-freshness.flow.json +44 -0
- package/kits/knowledge/flows/canonicalize-category.flow.json +44 -0
- package/kits/knowledge/flows/detect-contradictions.flow.json +44 -0
- package/kits/knowledge/flows/glossary-sync.flow.json +61 -0
- package/kits/knowledge/flows/hygiene-review.flow.json +43 -0
- package/kits/knowledge/kit.json +51 -1
- package/package.json +6 -6
- package/packaging/conformance/README.md +10 -2
- package/packaging/conformance/fixtures/evidence-capture--allow-records-command.json +29 -0
- package/packaging/conformance/fixtures/stop-goal-fit--block-bundle-disputed-claim.json +29 -0
- package/packaging/conformance/fixtures/stop-goal-fit--block-capture-contradicts-claimed-pass.json +30 -0
- package/packaging/conformance/fixtures/stop-goal-fit--block-mode.json +23 -0
- package/packaging/conformance/fixtures/stop-goal-fit--off-mode.json +24 -0
- package/packaging/conformance/fixtures/stop-goal-fit--warn-active-delivery.json +5 -2
- package/packaging/conformance/fixtures/stop-goal-fit--warn-no-bundle.json +23 -0
- package/packaging/conformance/fixtures/workflow-steering--reground-active-prompt.json +30 -0
- package/packaging/conformance/fixtures/workflow-steering--reground-session-start.json +30 -0
- package/packaging/conformance/run-conformance.js +1 -1
- package/scripts/README.md +2 -1
- package/scripts/build-universal-bundles.js +0 -1
- package/scripts/ci/mint-attestation.js +221 -0
- package/scripts/ci/trust-reconcile.js +545 -0
- package/scripts/hooks/config-protection.js +423 -1
- package/scripts/hooks/evidence-capture.js +348 -0
- package/scripts/hooks/lib/liveness-read.js +113 -0
- package/scripts/hooks/run-hook.js +6 -1
- package/scripts/hooks/stop-goal-fit.js +1524 -79
- package/scripts/hooks/workflow-steering.js +135 -5
- package/scripts/install-codex-home.sh +39 -0
- package/scripts/install-merge.js +330 -0
- package/scripts/repair-command-log.js +115 -0
- package/src/cli/init.ts +218 -20
- package/src/cli/validate-workflow-artifacts.ts +18 -2
- package/src/cli/verify.ts +100 -0
- package/src/cli/workflow-sidecar.ts +2127 -84
- package/src/cli.ts +2 -3
- package/src/lib/flow-resolver.ts +369 -0
- package/src/tools/build-universal-bundles.ts +34 -21
- package/src/tools/generate-context-map.ts +3 -17
- package/src/tools/validate-source-tree.ts +44 -104
- package/build/src/tools/filter-installed-packs.d.ts +0 -2
- package/build/src/tools/filter-installed-packs.js +0 -135
- package/packaging/packs.json +0 -49
- package/scripts/filter-installed-packs.js +0 -2
- package/src/tools/filter-installed-packs.ts +0 -132
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* mint-attestation.js — CI trust anchor Phase 2.
|
|
4
|
+
*
|
|
5
|
+
* Signs an in-toto v1 statement attesting CI's own fresh verification results
|
|
6
|
+
* via Sigstore keyless signing (Fulcio + Rekor). Consumes the results file
|
|
7
|
+
* that trust-reconcile.js writes, then calls signStatementWithSigstore from
|
|
8
|
+
* @kontourai/surface.
|
|
9
|
+
*
|
|
10
|
+
* Invocation (after trust-reconcile passes):
|
|
11
|
+
* node scripts/ci/mint-attestation.js
|
|
12
|
+
*
|
|
13
|
+
* Statement shape:
|
|
14
|
+
* subject: delivery/trust.bundle (sha256) if present; else ci-verify-results
|
|
15
|
+
* (sha256 of predicate JSON)
|
|
16
|
+
* predicateType: https://kontourai.dev/ci-verify/v1
|
|
17
|
+
* predicate: { commit_sha, canonical_commands, reconciled, built_at }
|
|
18
|
+
*
|
|
19
|
+
* Outputs (written to ATTESTATION_OUT_DIR, defaulting to cwd):
|
|
20
|
+
* Signed path (CI/OIDC):
|
|
21
|
+
* trust.attestation.sig.json — DSSE envelope
|
|
22
|
+
* trust.attestation.status.json — { status:"signed", output_path }
|
|
23
|
+
* Unsigned path (local/no OIDC):
|
|
24
|
+
* trust.attestation.intoto.json — unsigned in-toto statement
|
|
25
|
+
* trust.attestation.status.json — { status:"unsigned", reason, output_path }
|
|
26
|
+
*
|
|
27
|
+
* Fail-open: NEVER throws — returns exit 0 on signing failure so the job
|
|
28
|
+
* does not crash when no ambient OIDC identity is present.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
'use strict';
|
|
32
|
+
|
|
33
|
+
const fs = require('fs');
|
|
34
|
+
const os = require('os');
|
|
35
|
+
const path = require('path');
|
|
36
|
+
const crypto = require('crypto');
|
|
37
|
+
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Helpers
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* SHA-256 hex digest of a Buffer or string.
|
|
44
|
+
* @param {Buffer|string} data
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
function sha256hex(data) {
|
|
48
|
+
return crypto.createHash('sha256').update(data).digest('hex');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Load CI results written by trust-reconcile.js.
|
|
53
|
+
* Falls back to a synthesized record from env vars when the file is absent.
|
|
54
|
+
*
|
|
55
|
+
* @param {string} repoRoot
|
|
56
|
+
* @returns {{ commit_sha: string, canonical_commands: Array, reconciled: boolean, built_at: string }}
|
|
57
|
+
*/
|
|
58
|
+
function loadCiResults(repoRoot) {
|
|
59
|
+
const resultsDir = process.env.RUNNER_TEMP || os.tmpdir();
|
|
60
|
+
const resultsPath = path.join(resultsDir, 'ci-trust-reconcile-results.json');
|
|
61
|
+
|
|
62
|
+
if (fs.existsSync(resultsPath)) {
|
|
63
|
+
try {
|
|
64
|
+
const raw = fs.readFileSync(resultsPath, 'utf8');
|
|
65
|
+
const parsed = JSON.parse(raw);
|
|
66
|
+
process.stdout.write(`[mint-attestation] loaded CI results from: ${resultsPath}\n`);
|
|
67
|
+
return parsed;
|
|
68
|
+
} catch (err) {
|
|
69
|
+
process.stdout.write(`[mint-attestation] results file unreadable (${err.message}), synthesizing from env\n`);
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
process.stdout.write(`[mint-attestation] no CI results file found, synthesizing from env\n`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Synthesize from environment — trust-reconcile already passed so commands succeeded.
|
|
76
|
+
const cmdEnv = process.env.TRUST_RECONCILE_COMMANDS || '';
|
|
77
|
+
const commands = cmdEnv
|
|
78
|
+
? cmdEnv.split(/[,\n]/).map(c => c.trim()).filter(Boolean)
|
|
79
|
+
: ['npm run build'];
|
|
80
|
+
|
|
81
|
+
// Check for package.json trust-reconcile-verify script as trust-reconcile does.
|
|
82
|
+
let finalCmds = commands;
|
|
83
|
+
if (!cmdEnv) {
|
|
84
|
+
try {
|
|
85
|
+
const pkgPath = path.join(repoRoot, 'package.json');
|
|
86
|
+
if (fs.existsSync(pkgPath)) {
|
|
87
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
88
|
+
if (pkg && pkg.scripts && pkg.scripts['trust-reconcile-verify']) {
|
|
89
|
+
finalCmds = ['npm run trust-reconcile-verify'];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} catch { /* ignore */ }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
commit_sha: process.env.GITHUB_SHA || 'unknown',
|
|
97
|
+
canonical_commands: finalCmds.map(cmd => ({
|
|
98
|
+
command: cmd,
|
|
99
|
+
exitCode: 0,
|
|
100
|
+
passed: true, // reconcile passed, so all canonical commands passed
|
|
101
|
+
})),
|
|
102
|
+
reconciled: false, // synthesized: no bundle was confirmed
|
|
103
|
+
built_at: new Date().toISOString(),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Determine the subject artifact for the in-toto statement.
|
|
109
|
+
*
|
|
110
|
+
* If delivery/trust.bundle is present, use it as the subject (sha256 of its bytes).
|
|
111
|
+
* Otherwise synthesize a results artifact from the predicate and use that.
|
|
112
|
+
*
|
|
113
|
+
* @param {object} predicate — the predicate that will appear in the statement
|
|
114
|
+
* @param {string} repoRoot
|
|
115
|
+
* @returns {{ subjectName: string, subjectDigest: string, fromBundle: boolean }}
|
|
116
|
+
*/
|
|
117
|
+
function resolveSubject(predicate, repoRoot) {
|
|
118
|
+
const bundlePath = path.join(repoRoot, 'delivery', 'trust.bundle');
|
|
119
|
+
if (fs.existsSync(bundlePath)) {
|
|
120
|
+
const bundleBytes = fs.readFileSync(bundlePath);
|
|
121
|
+
const digest = sha256hex(bundleBytes);
|
|
122
|
+
process.stdout.write(`[mint-attestation] subject: delivery/trust.bundle sha256=${digest.slice(0, 16)}...\n`);
|
|
123
|
+
return { subjectName: 'delivery/trust.bundle', subjectDigest: digest, fromBundle: true };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// No bundle present: synthesize subject from predicate JSON (self-attesting the results).
|
|
127
|
+
const predicateJson = JSON.stringify(predicate);
|
|
128
|
+
const digest = sha256hex(Buffer.from(predicateJson, 'utf8'));
|
|
129
|
+
process.stdout.write(`[mint-attestation] subject: ci-verify-results (synthesized) sha256=${digest.slice(0, 16)}...\n`);
|
|
130
|
+
return { subjectName: 'ci-verify-results', subjectDigest: digest, fromBundle: false };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Main
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
async function main() {
|
|
138
|
+
const repoRoot = path.resolve(process.env.GITHUB_WORKSPACE || process.cwd());
|
|
139
|
+
const outDir = path.resolve(process.env.ATTESTATION_OUT_DIR || process.cwd());
|
|
140
|
+
|
|
141
|
+
process.stdout.write('[mint-attestation] CI trust anchor Phase 2 — minting attestation\n');
|
|
142
|
+
process.stdout.write(`[mint-attestation] repo-root: ${repoRoot}\n`);
|
|
143
|
+
process.stdout.write(`[mint-attestation] out-dir: ${outDir}\n`);
|
|
144
|
+
|
|
145
|
+
// 1. Load CI results.
|
|
146
|
+
const ciResults = loadCiResults(repoRoot);
|
|
147
|
+
|
|
148
|
+
// 2. Build predicate.
|
|
149
|
+
const predicate = {
|
|
150
|
+
commit_sha: ciResults.commit_sha,
|
|
151
|
+
canonical_commands: ciResults.canonical_commands,
|
|
152
|
+
reconciled: ciResults.reconciled,
|
|
153
|
+
built_at: ciResults.built_at,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// 3. Resolve subject artifact.
|
|
157
|
+
const { subjectName, subjectDigest } = resolveSubject(predicate, repoRoot);
|
|
158
|
+
|
|
159
|
+
// 4. Build in-toto statement.
|
|
160
|
+
const statement = {
|
|
161
|
+
_type: 'https://in-toto.io/Statement/v1',
|
|
162
|
+
subject: [{ name: subjectName, digest: { sha256: subjectDigest } }],
|
|
163
|
+
predicateType: 'https://kontourai.dev/ci-verify/v1',
|
|
164
|
+
predicate,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// 5. Attempt keyless Sigstore signing.
|
|
168
|
+
let signed = null;
|
|
169
|
+
try {
|
|
170
|
+
const { signStatementWithSigstore } = await import('@kontourai/surface');
|
|
171
|
+
signed = await signStatementWithSigstore(statement);
|
|
172
|
+
} catch (err) {
|
|
173
|
+
// Fail-open: if @sigstore/sign is missing or throws, signed stays null.
|
|
174
|
+
process.stdout.write(`[mint-attestation] signing threw (fail-open): ${err.message}\n`);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 6. Write output.
|
|
178
|
+
try {
|
|
179
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
180
|
+
} catch { /* ignore if already exists */ }
|
|
181
|
+
|
|
182
|
+
if (signed !== null) {
|
|
183
|
+
// Signed path: write DSSE envelope.
|
|
184
|
+
const sigPath = path.join(outDir, 'trust.attestation.sig.json');
|
|
185
|
+
fs.writeFileSync(sigPath, JSON.stringify(signed.envelope, null, 2));
|
|
186
|
+
|
|
187
|
+
const statusPath = path.join(outDir, 'trust.attestation.status.json');
|
|
188
|
+
fs.writeFileSync(statusPath, JSON.stringify({
|
|
189
|
+
status: 'signed',
|
|
190
|
+
assuranceLevel: signed.assuranceLevel,
|
|
191
|
+
output_path: sigPath,
|
|
192
|
+
}, null, 2));
|
|
193
|
+
|
|
194
|
+
process.stdout.write(`[mint-attestation] status: signed\n`);
|
|
195
|
+
process.stdout.write(`[mint-attestation] output: ${sigPath}\n`);
|
|
196
|
+
process.stdout.write(`[mint-attestation] status-file: ${statusPath}\n`);
|
|
197
|
+
} else {
|
|
198
|
+
// Unsigned path: write raw in-toto statement.
|
|
199
|
+
const intotoPath = path.join(outDir, 'trust.attestation.intoto.json');
|
|
200
|
+
fs.writeFileSync(intotoPath, JSON.stringify(statement, null, 2));
|
|
201
|
+
|
|
202
|
+
const reason = 'no ambient OIDC identity';
|
|
203
|
+
const statusPath = path.join(outDir, 'trust.attestation.status.json');
|
|
204
|
+
fs.writeFileSync(statusPath, JSON.stringify({
|
|
205
|
+
status: 'unsigned',
|
|
206
|
+
reason,
|
|
207
|
+
output_path: intotoPath,
|
|
208
|
+
}, null, 2));
|
|
209
|
+
|
|
210
|
+
process.stdout.write(`[mint-attestation] status: unsigned (${reason})\n`);
|
|
211
|
+
process.stdout.write(`[mint-attestation] output: ${intotoPath}\n`);
|
|
212
|
+
process.stdout.write(`[mint-attestation] status-file: ${statusPath}\n`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Entry point — never throw.
|
|
217
|
+
main().catch(err => {
|
|
218
|
+
// Fail-open: log the error but exit 0 so the CI job does not crash.
|
|
219
|
+
process.stdout.write(`[mint-attestation] unhandled error (fail-open): ${err && err.message}\n`);
|
|
220
|
+
process.exit(0);
|
|
221
|
+
});
|