@msn-control/liftoff 0.9.8 → 0.10.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.
- package/DEVELOPER.md +142 -0
- package/README.md +26 -18
- package/assets/governance/single-maintainer-gitflow/policy.md +62 -13
- package/dist/args.js +21 -0
- package/dist/args.js.map +1 -1
- package/dist/artifact-lifecycle.d.ts +1 -1
- package/dist/artifact-lifecycle.js +5 -0
- package/dist/artifact-lifecycle.js.map +1 -1
- package/dist/commands.js +355 -13
- package/dist/commands.js.map +1 -1
- package/dist/file-system.js +100 -13
- package/dist/file-system.js.map +1 -1
- package/dist/governance-activation/activation-state.d.ts +32 -0
- package/dist/governance-activation/activation-state.js +165 -0
- package/dist/governance-activation/activation-state.js.map +1 -0
- package/dist/governance-activation/approvals.d.ts +188 -0
- package/dist/governance-activation/approvals.js +508 -0
- package/dist/governance-activation/approvals.js.map +1 -0
- package/dist/governance-activation/canonical-json.d.ts +3 -0
- package/dist/governance-activation/canonical-json.js +36 -0
- package/dist/governance-activation/canonical-json.js.map +1 -0
- package/dist/governance-activation/commands.d.ts +10 -0
- package/dist/governance-activation/commands.js +1023 -0
- package/dist/governance-activation/commands.js.map +1 -0
- package/dist/governance-activation/compatibility.d.ts +68 -0
- package/dist/governance-activation/compatibility.js +447 -0
- package/dist/governance-activation/compatibility.js.map +1 -0
- package/dist/governance-activation/credentials.d.ts +160 -0
- package/dist/governance-activation/credentials.js +403 -0
- package/dist/governance-activation/credentials.js.map +1 -0
- package/dist/governance-activation/doctor.d.ts +10 -0
- package/dist/governance-activation/doctor.js +379 -0
- package/dist/governance-activation/doctor.js.map +1 -0
- package/dist/governance-activation/evidence.d.ts +49 -0
- package/dist/governance-activation/evidence.js +246 -0
- package/dist/governance-activation/evidence.js.map +1 -0
- package/dist/governance-activation/graph.d.ts +397 -0
- package/dist/governance-activation/graph.js +441 -0
- package/dist/governance-activation/graph.js.map +1 -0
- package/dist/governance-activation/identity.d.ts +35 -0
- package/dist/governance-activation/identity.js +89 -0
- package/dist/governance-activation/identity.js.map +1 -0
- package/dist/governance-activation/index.d.ts +18 -0
- package/dist/governance-activation/index.js +19 -0
- package/dist/governance-activation/index.js.map +1 -0
- package/dist/governance-activation/migration.d.ts +44 -0
- package/dist/governance-activation/migration.js +268 -0
- package/dist/governance-activation/migration.js.map +1 -0
- package/dist/governance-activation/readiness.d.ts +23 -0
- package/dist/governance-activation/readiness.js +158 -0
- package/dist/governance-activation/readiness.js.map +1 -0
- package/dist/governance-activation/reconciliation.d.ts +11 -0
- package/dist/governance-activation/reconciliation.js +58 -0
- package/dist/governance-activation/reconciliation.js.map +1 -0
- package/dist/governance-activation/release-integrity.d.ts +11 -0
- package/dist/governance-activation/release-integrity.js +49 -0
- package/dist/governance-activation/release-integrity.js.map +1 -0
- package/dist/governance-activation/seed-lifecycle.d.ts +116 -0
- package/dist/governance-activation/seed-lifecycle.js +609 -0
- package/dist/governance-activation/seed-lifecycle.js.map +1 -0
- package/dist/governance-activation/source-of-truth.d.ts +164 -0
- package/dist/governance-activation/source-of-truth.js +986 -0
- package/dist/governance-activation/source-of-truth.js.map +1 -0
- package/dist/governance-activation/task-projection.d.ts +21 -0
- package/dist/governance-activation/task-projection.js +75 -0
- package/dist/governance-activation/task-projection.js.map +1 -0
- package/dist/governance-activation/transitions.d.ts +163 -0
- package/dist/governance-activation/transitions.js +2128 -0
- package/dist/governance-activation/transitions.js.map +1 -0
- package/dist/governance-activation/type-contract.d.ts +1 -0
- package/dist/governance-activation/type-contract.js +27 -0
- package/dist/governance-activation/type-contract.js.map +1 -0
- package/dist/governance-activation/types.d.ts +390 -0
- package/dist/governance-activation/types.js +108 -0
- package/dist/governance-activation/types.js.map +1 -0
- package/dist/governance-activation/validators.d.ts +17 -0
- package/dist/governance-activation/validators.js +1305 -0
- package/dist/governance-activation/validators.js.map +1 -0
- package/dist/init-filesystem.js +5 -1
- package/dist/init-filesystem.js.map +1 -1
- package/dist/planner.js +3 -3
- package/dist/planner.js.map +1 -1
- package/dist/power-apps-templates.js +14 -1
- package/dist/power-apps-templates.js.map +1 -1
- package/dist/process-runner.d.ts +3 -0
- package/dist/process-runner.js +68 -10
- package/dist/process-runner.js.map +1 -1
- package/dist/repository-governance.d.ts +13 -3
- package/dist/repository-governance.js +385 -52
- package/dist/repository-governance.js.map +1 -1
- package/dist/telemetry/contract.d.ts +1 -1
- package/dist/telemetry/contract.js +6 -0
- package/dist/telemetry/contract.js.map +1 -1
- package/dist/templates.js +320 -25
- package/dist/templates.js.map +1 -1
- package/dist/types.d.ts +14 -6
- package/docs/cli-reference.md +60 -12
- package/docs/configuration-and-manifests.md +40 -16
- package/docs/existing-repositories.md +22 -11
- package/docs/getting-started.md +46 -10
- package/docs/prerequisites.md +5 -0
- package/docs/project-structure.md +34 -5
- package/docs/repository-governance.md +200 -203
- package/docs/safety-and-consent.md +29 -2
- package/docs/troubleshooting.md +74 -4
- package/docs/workloads.md +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/governance-activation/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type HistoricalActivationStateMigration } from './compatibility.js';
|
|
2
|
+
import { type ActivationCompatibilityMap } from './identity.js';
|
|
3
|
+
import type { ActivationIdentity, PhaseId } from './types.js';
|
|
4
|
+
import { type ProjectFileMutation, type ProjectFileSnapshot } from '../file-system.js';
|
|
5
|
+
export declare const updateFailureInjectionEnv: 'LIFTOFF_UPDATE_INJECT_FAILURE';
|
|
6
|
+
export type ActivationStateMigrationPlan = {
|
|
7
|
+
status: 'not-present' | 'current';
|
|
8
|
+
mutations: readonly ProjectFileMutation[];
|
|
9
|
+
preconditions: readonly ProjectFileSnapshot[];
|
|
10
|
+
report: ActivationStateMigrationReport;
|
|
11
|
+
} | {
|
|
12
|
+
status: 'migrate';
|
|
13
|
+
mutations: readonly ProjectFileMutation[];
|
|
14
|
+
preconditions: readonly ProjectFileSnapshot[];
|
|
15
|
+
report: ActivationStateMigrationReport & {
|
|
16
|
+
fromIdentity: ActivationIdentity;
|
|
17
|
+
toIdentity: ActivationIdentity;
|
|
18
|
+
reconciliationPath: string;
|
|
19
|
+
preservedPhaseIds: readonly PhaseId[];
|
|
20
|
+
invalidPhaseIds: readonly PhaseId[];
|
|
21
|
+
};
|
|
22
|
+
} | {
|
|
23
|
+
status: 'blocked';
|
|
24
|
+
mutations: readonly ProjectFileMutation[];
|
|
25
|
+
preconditions: readonly ProjectFileSnapshot[];
|
|
26
|
+
report: ActivationStateMigrationReport & {
|
|
27
|
+
reasonCode: 'ad-hoc-state' | 'future-state-schema' | 'unsupported-activation-identity' | 'malformed-state' | 'reconciliation-conflict';
|
|
28
|
+
issues: readonly string[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export interface ActivationStateMigrationReport {
|
|
32
|
+
path: string;
|
|
33
|
+
status: 'not-present' | 'current' | 'migrate' | 'blocked';
|
|
34
|
+
checkModeWritesBytes: 0;
|
|
35
|
+
evidencePolicy: 'preserve-bytes';
|
|
36
|
+
unversionedImport: 'requires-explicit-import-mapping';
|
|
37
|
+
issues: readonly string[];
|
|
38
|
+
}
|
|
39
|
+
export interface ActivationStateMigrationMappingInput {
|
|
40
|
+
compatibility?: ActivationCompatibilityMap;
|
|
41
|
+
historicalStateMigrations?: readonly HistoricalActivationStateMigration[];
|
|
42
|
+
}
|
|
43
|
+
export declare function planHistoricalActivationStateMigration(projectRoot: string, nowIso?: string, mappingInput?: ActivationStateMigrationMappingInput): Promise<ActivationStateMigrationPlan>;
|
|
44
|
+
export declare function activationStateMigrationFingerprint(content: string | Buffer): string;
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { activationStateContentHash, activationStateFilePathParts, loadActivationState } from './activation-state.js';
|
|
2
|
+
import { canonicalJson } from './canonical-json.js';
|
|
3
|
+
import { graphReconciliationRecordFromMapping } from './compatibility.js';
|
|
4
|
+
import { activationCompatibility, currentActivationIdentity } from './graph.js';
|
|
5
|
+
import { activationStateSchemaVersion, resolveActivationCompatibility } from './identity.js';
|
|
6
|
+
import { phaseIds } from './types.js';
|
|
7
|
+
import { validateGraphReconciliationRecord, validateUserActivationState } from './validators.js';
|
|
8
|
+
import { captureProjectFileSnapshot, readProjectFile } from '../file-system.js';
|
|
9
|
+
export const updateFailureInjectionEnv = 'LIFTOFF_UPDATE_INJECT_FAILURE';
|
|
10
|
+
const identityFields = [
|
|
11
|
+
'liftoffVersion',
|
|
12
|
+
'manifestArtifactVersion',
|
|
13
|
+
'policyVersion',
|
|
14
|
+
'activationContractVersion',
|
|
15
|
+
'phaseGraphSchemaVersion',
|
|
16
|
+
'phaseGraphHash',
|
|
17
|
+
'activationStateSchemaVersion',
|
|
18
|
+
'evidenceHeaderSchemaVersion',
|
|
19
|
+
'approvalEnvelopeSchemaVersion',
|
|
20
|
+
'supersessionSchemaVersion',
|
|
21
|
+
'credentialPolicySchemaVersion'
|
|
22
|
+
];
|
|
23
|
+
function isRecord(value) {
|
|
24
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
function errorMessage(error) {
|
|
27
|
+
return error instanceof Error ? error.message : String(error);
|
|
28
|
+
}
|
|
29
|
+
function sameIdentity(left, right) {
|
|
30
|
+
return identityFields.every((field) => left[field] === right[field]);
|
|
31
|
+
}
|
|
32
|
+
function looseIdentity(value) {
|
|
33
|
+
if (!isRecord(value)) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
for (const field of identityFields) {
|
|
37
|
+
if (!Object.hasOwn(value, field)) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const identity = value;
|
|
42
|
+
if (typeof identity.liftoffVersion !== 'string' ||
|
|
43
|
+
typeof identity.manifestArtifactVersion !== 'number' ||
|
|
44
|
+
typeof identity.policyVersion !== 'string' ||
|
|
45
|
+
typeof identity.activationContractVersion !== 'number' ||
|
|
46
|
+
typeof identity.phaseGraphSchemaVersion !== 'number' ||
|
|
47
|
+
typeof identity.phaseGraphHash !== 'string' ||
|
|
48
|
+
typeof identity.activationStateSchemaVersion !== 'number' ||
|
|
49
|
+
typeof identity.evidenceHeaderSchemaVersion !== 'number' ||
|
|
50
|
+
typeof identity.approvalEnvelopeSchemaVersion !== 'number' ||
|
|
51
|
+
typeof identity.supersessionSchemaVersion !== 'number' ||
|
|
52
|
+
typeof identity.credentialPolicySchemaVersion !== 'number') {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
liftoffVersion: identity.liftoffVersion,
|
|
57
|
+
manifestArtifactVersion: identity.manifestArtifactVersion,
|
|
58
|
+
policyVersion: identity.policyVersion,
|
|
59
|
+
activationContractVersion: identity.activationContractVersion,
|
|
60
|
+
phaseGraphSchemaVersion: identity.phaseGraphSchemaVersion,
|
|
61
|
+
phaseGraphHash: identity.phaseGraphHash,
|
|
62
|
+
activationStateSchemaVersion: identity.activationStateSchemaVersion,
|
|
63
|
+
evidenceHeaderSchemaVersion: identity.evidenceHeaderSchemaVersion,
|
|
64
|
+
approvalEnvelopeSchemaVersion: identity.approvalEnvelopeSchemaVersion,
|
|
65
|
+
supersessionSchemaVersion: identity.supersessionSchemaVersion,
|
|
66
|
+
credentialPolicySchemaVersion: identity.credentialPolicySchemaVersion
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function blocked(reasonCode, issues) {
|
|
70
|
+
return {
|
|
71
|
+
status: 'blocked',
|
|
72
|
+
mutations: [],
|
|
73
|
+
preconditions: [],
|
|
74
|
+
report: {
|
|
75
|
+
path: activationStateFilePathParts.join('/'),
|
|
76
|
+
status: 'blocked',
|
|
77
|
+
checkModeWritesBytes: 0,
|
|
78
|
+
evidencePolicy: 'preserve-bytes',
|
|
79
|
+
unversionedImport: 'requires-explicit-import-mapping',
|
|
80
|
+
reasonCode,
|
|
81
|
+
issues
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function unchanged(status) {
|
|
86
|
+
return {
|
|
87
|
+
status,
|
|
88
|
+
mutations: [],
|
|
89
|
+
preconditions: [],
|
|
90
|
+
report: {
|
|
91
|
+
path: activationStateFilePathParts.join('/'),
|
|
92
|
+
status,
|
|
93
|
+
checkModeWritesBytes: 0,
|
|
94
|
+
evidencePolicy: 'preserve-bytes',
|
|
95
|
+
unversionedImport: 'requires-explicit-import-mapping',
|
|
96
|
+
issues: []
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function phaseImpact(record) {
|
|
101
|
+
const preserved = record.phaseMappings
|
|
102
|
+
.filter((mapping) => mapping.preserveEvidence && mapping.fromContractDigest === mapping.toContractDigest)
|
|
103
|
+
.map((mapping) => mapping.phaseId);
|
|
104
|
+
const invalid = phaseIds.filter((phaseId) => !preserved.includes(phaseId));
|
|
105
|
+
return { preservedPhaseIds: preserved, invalidPhaseIds: invalid };
|
|
106
|
+
}
|
|
107
|
+
function matchingHistoricalStateMigration(identity, migrations) {
|
|
108
|
+
return migrations.find((migration) => sameIdentity(migration.fromIdentity, identity) &&
|
|
109
|
+
sameIdentity(migration.toIdentity, currentActivationIdentity));
|
|
110
|
+
}
|
|
111
|
+
export async function planHistoricalActivationStateMigration(projectRoot, nowIso = new Date().toISOString(), mappingInput = {}) {
|
|
112
|
+
const bytes = await readProjectFile(projectRoot, [...activationStateFilePathParts]);
|
|
113
|
+
if (bytes === undefined) {
|
|
114
|
+
return unchanged('not-present');
|
|
115
|
+
}
|
|
116
|
+
const content = bytes.toString('utf8');
|
|
117
|
+
const snapshot = await captureProjectFileSnapshot(projectRoot, [...activationStateFilePathParts]);
|
|
118
|
+
try {
|
|
119
|
+
await loadActivationState(projectRoot);
|
|
120
|
+
return unchanged('current');
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// Re-parse below to distinguish supported historical state from ad hoc files.
|
|
124
|
+
}
|
|
125
|
+
let parsed;
|
|
126
|
+
try {
|
|
127
|
+
parsed = JSON.parse(content);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
return blocked('malformed-state', [
|
|
131
|
+
`Unable to parse governance/activation-state.json: ${errorMessage(error)}. Restore a valid versioned state or provide an explicit import mapping.`
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
if (!isRecord(parsed)) {
|
|
135
|
+
return blocked('ad-hoc-state', [
|
|
136
|
+
'governance/activation-state.json is not a JSON object; checkboxes, filenames, and prose are not evidence. Provide an explicit import mapping.'
|
|
137
|
+
]);
|
|
138
|
+
}
|
|
139
|
+
if (!Object.hasOwn(parsed, 'schemaVersion') || !Object.hasOwn(parsed, 'identity')) {
|
|
140
|
+
return blocked('ad-hoc-state', [
|
|
141
|
+
'governance/activation-state.json lacks explicit schemaVersion or identity. Unversioned/ad hoc state requires an explicit import mapping; checkboxes, filenames, and prose are not evidence.'
|
|
142
|
+
]);
|
|
143
|
+
}
|
|
144
|
+
if (parsed.schemaVersion !== activationStateSchemaVersion) {
|
|
145
|
+
if (typeof parsed.schemaVersion === 'number' &&
|
|
146
|
+
parsed.schemaVersion > activationStateSchemaVersion) {
|
|
147
|
+
return blocked('future-state-schema', [
|
|
148
|
+
`Unsupported activationState.schemaVersion: found ${JSON.stringify(parsed.schemaVersion)}; supported values are ${activationStateSchemaVersion}. Upgrade Liftoff before writing.`
|
|
149
|
+
]);
|
|
150
|
+
}
|
|
151
|
+
return blocked('unsupported-activation-identity', [
|
|
152
|
+
`Unsupported activationState.schemaVersion: found ${JSON.stringify(parsed.schemaVersion)}; supported values are ${activationStateSchemaVersion}. Explicit migration metadata is required.`
|
|
153
|
+
]);
|
|
154
|
+
}
|
|
155
|
+
const identity = looseIdentity(parsed.identity);
|
|
156
|
+
if (!identity) {
|
|
157
|
+
return blocked('ad-hoc-state', [
|
|
158
|
+
'activationState.identity is absent or malformed. Explicit import mapping is required; task checkboxes, filenames, and prose cannot be imported as evidence.'
|
|
159
|
+
]);
|
|
160
|
+
}
|
|
161
|
+
if (sameIdentity(identity, currentActivationIdentity)) {
|
|
162
|
+
return blocked('malformed-state', [
|
|
163
|
+
'Activation state uses the current identity but failed strict validation; preserve the bytes and repair the malformed state before writing.'
|
|
164
|
+
]);
|
|
165
|
+
}
|
|
166
|
+
const migration = matchingHistoricalStateMigration(identity, mappingInput.historicalStateMigrations ?? []);
|
|
167
|
+
if (!migration) {
|
|
168
|
+
const compatibility = resolveActivationCompatibility(identity, mappingInput.compatibility ?? activationCompatibility);
|
|
169
|
+
const issue = compatibility.compatible
|
|
170
|
+
? `Activation state identity is compatible but has no explicit historical migration mapping: found ${identity.phaseGraphHash}.`
|
|
171
|
+
: compatibility.reason;
|
|
172
|
+
return blocked('unsupported-activation-identity', [
|
|
173
|
+
`${issue} Production Liftoff 0.10.0 declares no historical activation-state mappings; provide an explicit compatibility/migration mapping or upgrade to a Liftoff release that declares one.`
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
176
|
+
if (migration.stateSchemaVersion !== activationStateSchemaVersion ||
|
|
177
|
+
migration.transaction !== 'managed-update-write-set' ||
|
|
178
|
+
migration.evidence !== 'preserve-bytes' ||
|
|
179
|
+
migration.unversionedImport !== 'requires-explicit-import-mapping' ||
|
|
180
|
+
migration.graphMapping.fromGraphHash !== migration.fromIdentity.phaseGraphHash ||
|
|
181
|
+
migration.graphMapping.toGraphHash !== migration.toIdentity.phaseGraphHash ||
|
|
182
|
+
!sameIdentity(migration.graphMapping.fromIdentity, migration.fromIdentity) ||
|
|
183
|
+
!sameIdentity(migration.graphMapping.toIdentity, migration.toIdentity)) {
|
|
184
|
+
return blocked('unsupported-activation-identity', [
|
|
185
|
+
'Explicit historical activation-state migration mapping is internally inconsistent. Provide schema-valid compatibility metadata before writing.'
|
|
186
|
+
]);
|
|
187
|
+
}
|
|
188
|
+
const migratedCandidate = {
|
|
189
|
+
...parsed,
|
|
190
|
+
identity: migration.toIdentity
|
|
191
|
+
};
|
|
192
|
+
let migrated;
|
|
193
|
+
try {
|
|
194
|
+
migrated = validateUserActivationState(migratedCandidate);
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
return blocked('malformed-state', [
|
|
198
|
+
`Supported historical activation state failed strict migration validation: ${errorMessage(error)}.`
|
|
199
|
+
]);
|
|
200
|
+
}
|
|
201
|
+
const mapping = migration.graphMapping;
|
|
202
|
+
const reconciliationCandidate = graphReconciliationRecordFromMapping(mapping, nowIso);
|
|
203
|
+
let reconciliation;
|
|
204
|
+
try {
|
|
205
|
+
reconciliation = validateGraphReconciliationRecord(reconciliationCandidate, new Set([mapping.fromGraphHash, mapping.toGraphHash]));
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
return blocked('unsupported-activation-identity', [
|
|
209
|
+
`Explicit historical activation-state migration mapping is invalid: ${errorMessage(error)}.`
|
|
210
|
+
]);
|
|
211
|
+
}
|
|
212
|
+
const reconciliationPathParts = [
|
|
213
|
+
'governance',
|
|
214
|
+
'reconciliation',
|
|
215
|
+
`${mapping.fromGraphHash.slice(0, 12)}-to-${mapping.toGraphHash.slice(0, 12)}.json`
|
|
216
|
+
];
|
|
217
|
+
const reconciliationContent = `${canonicalJson(reconciliation)}\n`;
|
|
218
|
+
const existingReconciliation = await readProjectFile(projectRoot, reconciliationPathParts);
|
|
219
|
+
if (existingReconciliation !== undefined &&
|
|
220
|
+
existingReconciliation.toString('utf8') !== reconciliationContent) {
|
|
221
|
+
return blocked('reconciliation-conflict', [
|
|
222
|
+
`${reconciliationPathParts.join('/')} already exists with different bytes; preserve it and reconcile manually.`
|
|
223
|
+
]);
|
|
224
|
+
}
|
|
225
|
+
const migratedContent = `${canonicalJson(migrated)}\n`;
|
|
226
|
+
const mutations = [
|
|
227
|
+
{
|
|
228
|
+
type: 'write',
|
|
229
|
+
pathParts: [...activationStateFilePathParts],
|
|
230
|
+
content: migratedContent
|
|
231
|
+
},
|
|
232
|
+
...(existingReconciliation === undefined
|
|
233
|
+
? [{
|
|
234
|
+
type: 'write',
|
|
235
|
+
pathParts: reconciliationPathParts,
|
|
236
|
+
content: reconciliationContent
|
|
237
|
+
}]
|
|
238
|
+
: [])
|
|
239
|
+
];
|
|
240
|
+
const impact = phaseImpact(reconciliation);
|
|
241
|
+
return {
|
|
242
|
+
status: 'migrate',
|
|
243
|
+
mutations,
|
|
244
|
+
preconditions: [
|
|
245
|
+
snapshot,
|
|
246
|
+
...(existingReconciliation === undefined
|
|
247
|
+
? [{ pathParts: reconciliationPathParts }]
|
|
248
|
+
: [{ pathParts: reconciliationPathParts, content: existingReconciliation }])
|
|
249
|
+
],
|
|
250
|
+
report: {
|
|
251
|
+
path: activationStateFilePathParts.join('/'),
|
|
252
|
+
status: 'migrate',
|
|
253
|
+
checkModeWritesBytes: 0,
|
|
254
|
+
evidencePolicy: 'preserve-bytes',
|
|
255
|
+
unversionedImport: 'requires-explicit-import-mapping',
|
|
256
|
+
issues: [],
|
|
257
|
+
fromIdentity: migration.fromIdentity,
|
|
258
|
+
toIdentity: migration.toIdentity,
|
|
259
|
+
reconciliationPath: reconciliationPathParts.join('/'),
|
|
260
|
+
preservedPhaseIds: impact.preservedPhaseIds,
|
|
261
|
+
invalidPhaseIds: impact.invalidPhaseIds
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
export function activationStateMigrationFingerprint(content) {
|
|
266
|
+
return activationStateContentHash(content);
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.js","sourceRoot":"","sources":["../../src/governance-activation/migration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type EvidenceFreshnessContext } from './evidence.js';
|
|
2
|
+
import type { ActivationIdentity, ApprovalEnvelope, EvidenceHeader, ManagedPhaseGraph, PhaseEvidenceRecord, PhaseId, PhaseState, UserActivationState } from './types.js';
|
|
3
|
+
export type PhaseReadiness = {
|
|
4
|
+
phaseId: PhaseId;
|
|
5
|
+
state: PhaseState | 'identity-incompatible';
|
|
6
|
+
blockers: readonly string[];
|
|
7
|
+
};
|
|
8
|
+
export interface ReadinessResult {
|
|
9
|
+
identityCompatible: boolean;
|
|
10
|
+
identityBlocker?: string;
|
|
11
|
+
phases: Record<PhaseId, PhaseReadiness>;
|
|
12
|
+
nextReadyPhase: PhaseId | null;
|
|
13
|
+
}
|
|
14
|
+
export interface ReadinessInput {
|
|
15
|
+
graph?: ManagedPhaseGraph;
|
|
16
|
+
state: UserActivationState;
|
|
17
|
+
approvals: readonly ApprovalEnvelope[];
|
|
18
|
+
evidence: readonly (EvidenceHeader | PhaseEvidenceRecord)[];
|
|
19
|
+
transitionContexts?: Partial<Record<PhaseId, EvidenceFreshnessContext>>;
|
|
20
|
+
identity?: ActivationIdentity;
|
|
21
|
+
now?: Date;
|
|
22
|
+
}
|
|
23
|
+
export declare function calculatePhaseReadiness(input: ReadinessInput): ReadinessResult;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { activationCompatibility, canonicalPhaseGraph } from './graph.js';
|
|
2
|
+
import { evidenceContextForPhase, requiredLiveReadbackProviders, selectLatestPhaseEvidence } from './evidence.js';
|
|
3
|
+
import { resolveActivationCompatibility } from './identity.js';
|
|
4
|
+
import { evaluateApprovalForTransitionPlan, transitionPlanForPhase } from './approvals.js';
|
|
5
|
+
import { validateApprovalEnvelope } from './validators.js';
|
|
6
|
+
function phaseMap(graph) {
|
|
7
|
+
return Object.fromEntries(graph.phases.map((phase) => [phase.id, phase]));
|
|
8
|
+
}
|
|
9
|
+
function applicabilityApplies(node, state) {
|
|
10
|
+
if (node.applicability.kind === 'always') {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
if (node.applicability.discriminator === 'state-path') {
|
|
14
|
+
if (node.applicability.when === 'statePath=existing-private') {
|
|
15
|
+
return state.applicability.statePath === 'existing-private';
|
|
16
|
+
}
|
|
17
|
+
if (node.applicability.when === 'statePath=bootstrap-local') {
|
|
18
|
+
return state.applicability.statePath === 'bootstrap-local';
|
|
19
|
+
}
|
|
20
|
+
return state.applicability.statePath !== 'none';
|
|
21
|
+
}
|
|
22
|
+
if (node.applicability.discriminator === 'private-staging-dast') {
|
|
23
|
+
return state.applicability.privateStagingDast;
|
|
24
|
+
}
|
|
25
|
+
return state.applicability.credentialRequired;
|
|
26
|
+
}
|
|
27
|
+
function isPhaseEvidenceRecord(value) {
|
|
28
|
+
return typeof value === 'object' && value !== null && 'header' in value && 'evidenceId' in value;
|
|
29
|
+
}
|
|
30
|
+
function evidenceRecord(entry, index) {
|
|
31
|
+
if (isPhaseEvidenceRecord(entry)) {
|
|
32
|
+
return entry;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
evidenceId: `inline-${index}`,
|
|
36
|
+
header: entry
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function rawRecordPhaseId(record) {
|
|
40
|
+
return typeof record.header.phaseId === 'string' ? record.header.phaseId : undefined;
|
|
41
|
+
}
|
|
42
|
+
function dependencySatisfied(dependency, calculated) {
|
|
43
|
+
return dependency.anyOf.some((phaseId) => {
|
|
44
|
+
const result = calculated[phaseId];
|
|
45
|
+
return result !== undefined &&
|
|
46
|
+
dependency.accepts.includes(result.state);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export function calculatePhaseReadiness(input) {
|
|
50
|
+
const graph = input.graph ?? canonicalPhaseGraph;
|
|
51
|
+
const identity = input.identity ?? input.state.identity;
|
|
52
|
+
const compatibility = resolveActivationCompatibility(identity, activationCompatibility);
|
|
53
|
+
const phases = {};
|
|
54
|
+
if (!compatibility.compatible) {
|
|
55
|
+
for (const phase of graph.phases) {
|
|
56
|
+
phases[phase.id] = {
|
|
57
|
+
phaseId: phase.id,
|
|
58
|
+
state: 'identity-incompatible',
|
|
59
|
+
blockers: [compatibility.reason]
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
identityCompatible: false,
|
|
64
|
+
identityBlocker: compatibility.reason,
|
|
65
|
+
phases,
|
|
66
|
+
nextReadyPhase: null
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const now = input.now ?? new Date();
|
|
70
|
+
const approvals = input.approvals.map((approval) => validateApprovalEnvelope(approval));
|
|
71
|
+
const evidence = input.evidence.map((entry, index) => evidenceRecord(entry, index));
|
|
72
|
+
const byId = phaseMap(graph);
|
|
73
|
+
for (const node of graph.phases) {
|
|
74
|
+
const stored = input.state.phases[node.id];
|
|
75
|
+
const blockers = [];
|
|
76
|
+
if (!applicabilityApplies(node, input.state)) {
|
|
77
|
+
phases[node.id] = { phaseId: node.id, state: 'inapplicable', blockers: [] };
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const recordsForPhase = evidence.filter((record) => rawRecordPhaseId(record) === node.id);
|
|
81
|
+
const context = input.transitionContexts?.[node.id] ?? evidenceContextForPhase(node.id, {
|
|
82
|
+
repositoryId: input.state.repository.id,
|
|
83
|
+
identity,
|
|
84
|
+
liveReadbackProviders: requiredLiveReadbackProviders(node),
|
|
85
|
+
now
|
|
86
|
+
});
|
|
87
|
+
const selectedEvidence = selectLatestPhaseEvidence(recordsForPhase, context);
|
|
88
|
+
if (selectedEvidence.selected?.header.result === 'failed' || stored.state === 'failed') {
|
|
89
|
+
phases[node.id] = {
|
|
90
|
+
phaseId: node.id,
|
|
91
|
+
state: 'failed',
|
|
92
|
+
blockers: selectedEvidence.selected?.header.result === 'failed' ? [] : stored.blockers
|
|
93
|
+
};
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (selectedEvidence.selected) {
|
|
97
|
+
const foundEvidence = selectedEvidence.selected.header;
|
|
98
|
+
phases[node.id] = {
|
|
99
|
+
phaseId: node.id,
|
|
100
|
+
state: foundEvidence.result === 'retained' ? 'retained' : foundEvidence.result,
|
|
101
|
+
blockers: []
|
|
102
|
+
};
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (recordsForPhase.length > 0 && selectedEvidence.issues.length > 0) {
|
|
106
|
+
phases[node.id] = {
|
|
107
|
+
phaseId: node.id,
|
|
108
|
+
state: 'blocked',
|
|
109
|
+
blockers: selectedEvidence.issues.map((entry) => entry.message)
|
|
110
|
+
};
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (stored.state === 'running') {
|
|
114
|
+
phases[node.id] = { phaseId: node.id, state: 'running', blockers: [] };
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (stored.state === 'blocked' && stored.blockers.length > 0) {
|
|
118
|
+
phases[node.id] = { phaseId: node.id, state: 'blocked', blockers: stored.blockers };
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (node.id === 'bootstrap-state-disposed' &&
|
|
122
|
+
input.state.bootstrapState?.status === 'retained' &&
|
|
123
|
+
Date.parse(input.state.bootstrapState.disposeAfter) > now.getTime()) {
|
|
124
|
+
phases[node.id] = {
|
|
125
|
+
phaseId: node.id,
|
|
126
|
+
state: 'blocked',
|
|
127
|
+
blockers: [`Retained bootstrap state is not disposable until ${input.state.bootstrapState.disposeAfter}.`]
|
|
128
|
+
};
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
for (const dependency of node.dependencies) {
|
|
132
|
+
if (!dependencySatisfied(dependency, phases)) {
|
|
133
|
+
blockers.push(dependency.description);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (node.approvalGate.required) {
|
|
137
|
+
const approval = evaluateApprovalForTransitionPlan(transitionPlanForPhase(byId[node.id], input.state, context.transition), approvals, { now });
|
|
138
|
+
if (approval.approvalRequired) {
|
|
139
|
+
blockers.push(`Approval gate ${node.approvalGate.kind} is not satisfied: ${approval.reasons.join('; ')}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (blockers.length > 0) {
|
|
143
|
+
phases[node.id] = { phaseId: node.id, state: 'blocked', blockers };
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (stored.state === 'approved' && node.terminalStates.includes('approved')) {
|
|
147
|
+
phases[node.id] = { phaseId: node.id, state: 'approved', blockers: [] };
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
phases[node.id] = { phaseId: node.id, state: 'ready', blockers: [] };
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
identityCompatible: true,
|
|
154
|
+
phases,
|
|
155
|
+
nextReadyPhase: graph.phases.find((phase) => phases[phase.id].state === 'ready')?.id ?? null
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=readiness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readiness.js","sourceRoot":"","sources":["../../src/governance-activation/readiness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GraphReconciliationRecord, ManagedPhaseGraph, PhaseId } from './types.js';
|
|
2
|
+
export interface GraphReconciliationResult {
|
|
3
|
+
record: GraphReconciliationRecord;
|
|
4
|
+
preservedPhaseIds: readonly PhaseId[];
|
|
5
|
+
invalidPhaseIds: readonly PhaseId[];
|
|
6
|
+
}
|
|
7
|
+
export declare function calculateGraphReconciliation(value: unknown, options?: {
|
|
8
|
+
fromGraph?: ManagedPhaseGraph;
|
|
9
|
+
toGraph?: ManagedPhaseGraph;
|
|
10
|
+
recognizedGraphHashes?: ReadonlySet<string>;
|
|
11
|
+
}): GraphReconciliationResult;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { canonicalPhaseGraph, canonicalPhaseGraphHash, phaseContractDigests } from './graph.js';
|
|
2
|
+
import { phaseIds } from './types.js';
|
|
3
|
+
import { validateGraphReconciliationRecord } from './validators.js';
|
|
4
|
+
function descendantsOf(graph, changed) {
|
|
5
|
+
const descendants = new Set(changed);
|
|
6
|
+
let changedDuringPass = true;
|
|
7
|
+
while (changedDuringPass) {
|
|
8
|
+
changedDuringPass = false;
|
|
9
|
+
for (const node of graph.phases) {
|
|
10
|
+
if (descendants.has(node.id)) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (node.dependencies.some((dependency) => dependency.anyOf.some((phaseId) => descendants.has(phaseId)))) {
|
|
14
|
+
descendants.add(node.id);
|
|
15
|
+
changedDuringPass = true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return descendants;
|
|
20
|
+
}
|
|
21
|
+
function assertMappingMatchesGraph(record, fromGraph, toGraph) {
|
|
22
|
+
const fromDigests = phaseContractDigests(fromGraph);
|
|
23
|
+
const toDigests = phaseContractDigests(toGraph);
|
|
24
|
+
for (const mapping of record.phaseMappings) {
|
|
25
|
+
if (fromDigests[mapping.phaseId] !== mapping.fromContractDigest) {
|
|
26
|
+
throw new Error(`graphReconciliation phase ${mapping.phaseId} fromContractDigest does not match the recognized source graph.`);
|
|
27
|
+
}
|
|
28
|
+
if (toDigests[mapping.phaseId] !== mapping.toContractDigest) {
|
|
29
|
+
throw new Error(`graphReconciliation phase ${mapping.phaseId} toContractDigest does not match the recognized target graph.`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function calculateGraphReconciliation(value, options = {}) {
|
|
34
|
+
const fromGraph = options.fromGraph ?? canonicalPhaseGraph;
|
|
35
|
+
const toGraph = options.toGraph ?? canonicalPhaseGraph;
|
|
36
|
+
const recognizedGraphHashes = options.recognizedGraphHashes ?? new Set([canonicalPhaseGraphHash]);
|
|
37
|
+
const record = validateGraphReconciliationRecord(value, recognizedGraphHashes);
|
|
38
|
+
assertMappingMatchesGraph(record, fromGraph, toGraph);
|
|
39
|
+
const directlyChanged = new Set(record.phaseMappings
|
|
40
|
+
.filter((mapping) => !mapping.preserveEvidence || mapping.fromContractDigest !== mapping.toContractDigest)
|
|
41
|
+
.map((mapping) => mapping.phaseId));
|
|
42
|
+
const invalid = descendantsOf(toGraph, directlyChanged);
|
|
43
|
+
const preserved = phaseIds.filter((phaseId) => {
|
|
44
|
+
if (invalid.has(phaseId)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
const mapping = record.phaseMappings.find((entry) => entry.phaseId === phaseId);
|
|
48
|
+
return mapping !== undefined &&
|
|
49
|
+
mapping.preserveEvidence &&
|
|
50
|
+
mapping.fromContractDigest === mapping.toContractDigest;
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
record,
|
|
54
|
+
preservedPhaseIds: preserved,
|
|
55
|
+
invalidPhaseIds: phaseIds.filter((phaseId) => invalid.has(phaseId))
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=reconciliation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconciliation.js","sourceRoot":"","sources":["../../src/governance-activation/reconciliation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAMhG,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,iCAAiC,EAAE,MAAM,iBAAiB,CAAC;AAQpE,SAAS,aAAa,CAAC,KAAwB,EAAE,OAA6B;IAC5E,MAAM,WAAW,GAAG,IAAI,GAAG,CAAU,OAAO,CAAC,CAAC;IAC9C,IAAI,iBAAiB,GAAG,IAAI,CAAC;IAC7B,OAAO,iBAAiB,EAAE,CAAC;QACzB,iBAAiB,GAAG,KAAK,CAAC;QAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAChC,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC7B,SAAS;YACX,CAAC;YACD,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACzB,iBAAiB,GAAG,IAAI,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,yBAAyB,CAChC,MAAiC,EACjC,SAA4B,EAC5B,OAA0B;IAE1B,MAAM,WAAW,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAChD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QAC3C,IAAI,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,kBAAkB,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,CAAC,OAAO,iEAAiE,CAAC,CAAC;QACjI,CAAC;QACD,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC5D,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,CAAC,OAAO,+DAA+D,CAAC,CAAC;QAC/H,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,KAAc,EACd,OAAO,GAIH,EAAE;IAEN,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,mBAAmB,CAAC;IAC3D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,mBAAmB,CAAC;IACvD,MAAM,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,IAAI,IAAI,GAAG,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAClG,MAAM,MAAM,GAAG,iCAAiC,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;IAC/E,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACtD,MAAM,eAAe,GAAG,IAAI,GAAG,CAC7B,MAAM,CAAC,aAAa;SACjB,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,kBAAkB,KAAK,OAAO,CAAC,gBAAgB,CAAC;SACzG,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CACrC,CAAC;IACF,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;QAC5C,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;QAChF,OAAO,OAAO,KAAK,SAAS;YAC1B,OAAO,CAAC,gBAAgB;YACxB,OAAO,CAAC,kBAAkB,KAAK,OAAO,CAAC,gBAAgB,CAAC;IAC5D,CAAC,CAAC,CAAC;IACH,OAAO;QACL,MAAM;QACN,iBAAiB,EAAE,SAAS;QAC5B,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;KACpE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ActivationIdentity, ManagedPhaseGraph } from './types.js';
|
|
2
|
+
export interface ReleaseIntegrityInput {
|
|
3
|
+
previousGraph: ManagedPhaseGraph;
|
|
4
|
+
currentGraph: ManagedPhaseGraph;
|
|
5
|
+
previousIdentity: ActivationIdentity;
|
|
6
|
+
currentIdentity: ActivationIdentity & {
|
|
7
|
+
setupSkillVersion?: string;
|
|
8
|
+
};
|
|
9
|
+
compatibleGraphHashes: ReadonlyMap<string, string>;
|
|
10
|
+
}
|
|
11
|
+
export declare function validateReleaseIntegrity(input: ReleaseIntegrityInput): void;
|