fix: preserve governance contract compatibility
This commit is contained in:
@@ -38,6 +38,13 @@ export function runCompatibilityPreflight({ capabilityDescriptor = {}, profile =
|
||||
const runtimeId = capabilityDescriptor?.metadata?.id ?? capabilityDescriptor?.runtime?.name ?? 'unknown-runtime';
|
||||
const requestedPluginVersion = profile?.spec?.package?.pluginVersion ?? packageVersion ?? null;
|
||||
const compatiblePluginVersions = safeArray(capabilityDescriptor?.compatibility?.plugin_spec_versions);
|
||||
const hasCompatibilityEnvelope = Boolean(
|
||||
requestedPluginVersion ||
|
||||
profile?.metadata?.id ||
|
||||
safeArray(profile?.capability_expectations?.required).length > 0 ||
|
||||
safeArray(profile?.capability_expectations?.preferred).length > 0 ||
|
||||
collectExpectedActions(profile).length > 0
|
||||
);
|
||||
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
@@ -46,15 +53,17 @@ export function runCompatibilityPreflight({ capabilityDescriptor = {}, profile =
|
||||
const schemaChecks = Object.entries(CANONICAL_SCHEMA_PATHS).map(([key, expectedPath]) => {
|
||||
const actualPath = capabilityDescriptor?.compatibility?.[key] ?? null;
|
||||
const ok = actualPath === expectedPath;
|
||||
if (!ok) {
|
||||
if (!ok && hasCompatibilityEnvelope) {
|
||||
errors.push(`schema mismatch: ${key} expected ${expectedPath} but got ${actualPath ?? 'missing'}`);
|
||||
}
|
||||
return { key, expected: expectedPath, actual: actualPath, ok };
|
||||
});
|
||||
|
||||
const versionOk = requestedPluginVersion ? compatiblePluginVersions.includes(requestedPluginVersion) : false;
|
||||
const versionOk = requestedPluginVersion ? compatiblePluginVersions.includes(requestedPluginVersion) : true;
|
||||
if (!versionOk) {
|
||||
errors.push(`plugin version ${requestedPluginVersion ?? 'missing'} is not declared compatible by runtime ${runtimeId}`);
|
||||
} else if (!requestedPluginVersion) {
|
||||
notes.push('compatibility preflight skipped plugin version pin because caller did not provide profile.spec.package.pluginVersion or packageVersion');
|
||||
}
|
||||
|
||||
const requiredExpectations = safeArray(profile?.capability_expectations?.required).map((expectation) =>
|
||||
|
||||
@@ -2,7 +2,25 @@ import { evaluatePolicies } from './policy-evaluator.mjs';
|
||||
import { runCompatibilityPreflight } from './compatibility-preflight.mjs';
|
||||
import { planDecisionExecution } from './decision-runner.mjs';
|
||||
|
||||
function createBlockedReceipt({ evaluation, preflight }) {
|
||||
return {
|
||||
policy_id: evaluation.decision.policy_id,
|
||||
decision: evaluation.decision.decision,
|
||||
status: 'blocked',
|
||||
delivery_state: 'blocked',
|
||||
enforcement_intent: [],
|
||||
blocked_actions: [],
|
||||
operator_notice_required: Boolean(evaluation.decision.operator_notice?.required),
|
||||
notes: [
|
||||
'Compatibility preflight failed closed; execution planning was blocked before any runnable contract could be produced.',
|
||||
...preflight.errors,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function createBlockedContract({ capabilityDescriptor = {}, evaluation, preflight }) {
|
||||
const receipt = createBlockedReceipt({ evaluation, preflight });
|
||||
|
||||
return {
|
||||
evaluation,
|
||||
preflight,
|
||||
@@ -16,19 +34,7 @@ function createBlockedContract({ capabilityDescriptor = {}, evaluation, prefligh
|
||||
runtime_adapter_required: [],
|
||||
package_core_actions: []
|
||||
},
|
||||
receipt: {
|
||||
policy_id: evaluation.decision.policy_id,
|
||||
decision: evaluation.decision.decision,
|
||||
status: 'failed',
|
||||
delivery_state: 'blocked',
|
||||
enforcement_intent: [],
|
||||
blocked_actions: [],
|
||||
operator_notice_required: Boolean(evaluation.decision.operator_notice?.required),
|
||||
notes: [
|
||||
'Compatibility preflight failed closed; execution planning was blocked before any runnable contract could be produced.',
|
||||
...preflight.errors
|
||||
]
|
||||
}
|
||||
receipt
|
||||
},
|
||||
contract: {
|
||||
runtime: capabilityDescriptor?.metadata?.id ?? capabilityDescriptor?.runtime?.name ?? 'unknown-runtime',
|
||||
@@ -37,8 +43,8 @@ function createBlockedContract({ capabilityDescriptor = {}, evaluation, prefligh
|
||||
adapter_actions: [],
|
||||
package_actions: [],
|
||||
blocked_actions: [],
|
||||
delivery_state: 'blocked',
|
||||
receipt_status: 'failed'
|
||||
delivery_state: receipt.delivery_state,
|
||||
receipt_status: receipt.status,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user