import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { after, before, test } from "node:test"; import { createServer } from "vite"; let server; let parseDevicePluginManifest; let createDevicePluginRegistry; let xgridsK1Manifest; let xgridsK1Actions; let xgridsK1Api; let ApiError; let localizeRuntimeMessage; let lifecycle; let projectName; let automaticSourceStart; let presentation; let operatorIntentGeneration; let configuration; let compatibility; let networkProvisionFailureMessage; let discoveryScanFailureMessage; let connectionVerificationFailureMessage; let operationById; let physicalCommandConfirmation; let controlSessionCas; let ApiRequestTimeoutError; let requestTimeoutMsForAction; let isXgridsConnectionVerification; let isXgridsConnectionReconfiguration; let isXgridsConnectionPolicy; let isXgridsConnectionPolicyDecision; let isXgridsHostFailureDiagnostic; let XGRIDS_CONNECTION_VERIFICATION_STATUSES; let XGRIDS_CONNECTION_VERIFICATION_LEASE_STATES; let XGRIDS_CONNECTION_POLICY_ACTIONS; let XGRIDS_CONNECTION_POLICY_TARGET_SOURCES; let XGRIDS_CONNECTION_ATTEMPT_PHASES; let isXgridsConnectionAttemptPhase; before(async () => { server = await createServer({ appType: "custom", logLevel: "silent", server: { middlewareMode: true }, }); ({ parseDevicePluginManifest } = await server.ssrLoadModule( "/src/core/device-plugins/manifestParser.ts", )); ({ createDevicePluginRegistry } = await server.ssrLoadModule( "/src/core/device-plugins/registry.ts", )); ({ xgridsK1Manifest, xgridsK1Actions } = await server.ssrLoadModule( "@xgrids-k1/frontend/manifest.ts", )); lifecycle = await server.ssrLoadModule( "@xgrids-k1/frontend/lifecycle.ts", ); projectName = await server.ssrLoadModule( "@xgrids-k1/frontend/projectName.ts", ); automaticSourceStart = await server.ssrLoadModule( "@xgrids-k1/frontend/automaticSourceStart.ts", ); presentation = await server.ssrLoadModule( "@xgrids-k1/frontend/presentation.ts", ); operatorIntentGeneration = await server.ssrLoadModule( "@xgrids-k1/frontend/operatorIntentGeneration.ts", ); configuration = await server.ssrLoadModule( "@xgrids-k1/frontend/configuration.ts", ); compatibility = await server.ssrLoadModule( "@xgrids-k1/frontend/compatibility.ts", ); ({ xgridsK1Api, ApiError, ApiRequestTimeoutError, requestTimeoutMsForAction, isXgridsConnectionVerification, isXgridsConnectionReconfiguration, isXgridsConnectionPolicy, isXgridsConnectionPolicyDecision, isXgridsHostFailureDiagnostic, XGRIDS_CONNECTION_VERIFICATION_STATUSES, XGRIDS_CONNECTION_VERIFICATION_LEASE_STATES, XGRIDS_CONNECTION_POLICY_ACTIONS, XGRIDS_CONNECTION_POLICY_TARGET_SOURCES, XGRIDS_CONNECTION_ATTEMPT_PHASES, isXgridsConnectionAttemptPhase, } = await server.ssrLoadModule( "@xgrids-k1/frontend/api.ts", )); ({ localizeRuntimeMessage } = await server.ssrLoadModule( "@xgrids-k1/frontend/messages.ts", )); ({ networkProvisionFailureMessage, discoveryScanFailureMessage, connectionVerificationFailureMessage, operationById, } = await server.ssrLoadModule("@xgrids-k1/frontend/useXgridsK1Runtime.ts")); physicalCommandConfirmation = await server.ssrLoadModule( "@xgrids-k1/frontend/physicalCommandConfirmation.ts", ); controlSessionCas = await server.ssrLoadModule( "@xgrids-k1/frontend/controlSessionCas.ts", ); }); after(async () => { await server?.close(); }); function manifestDocument({ apiVersion = "missioncore.nodedc/v1alpha1", pluginId = "test.device.plugin", modelId = "test.device.model", } = {}) { const v1alpha2 = apiVersion === "missioncore.nodedc/v1alpha2"; return { apiVersion, kind: "DevicePlugin", metadata: { id: pluginId, version: "1.0.0", displayName: "Test device", }, spec: { hostApiRange: v1alpha2 ? "v1alpha2" : "v1alpha1", runtime: { backendEntrypoint: "test.plugin:build", isolation: "transitional-in-process", }, ...(v1alpha2 ? { compatibilityProfiles: [ { profileId: `${modelId}.fw-1.v1`, path: "profiles/fw-1/profile.v1.json", modelId, }, ], } : {}), permissions: ["device.read"], actions: [{ id: "state.read", mutating: false, secretFields: [] }], models: [ { id: modelId, vendor: "Test", displayName: "Test model", category: "Sensor", description: "Fixture model", verified: true, capabilities: [{ id: "device.read", label: "Read" }], ui: { slot: "device.connection", componentKey: "test.connection" }, }, ], }, }; } function uiPlugin(manifest) { return { manifest, RuntimeProvider: ({ children }) => children, connectionViews: { "test.connection": () => null }, }; } function supervisedConnectionState({ mode = "bridge", leaseState = "reachable", generation = 1, intentId = `intent-${mode}-1`, hostPathEpoch = 3, target = mode === "quick-connect" ? { ipv4: "192.168.56.1", port: 1883 } : { ipv4: "192.168.68.50", port: 1883 }, controlAllowed = leaseState === "reachable", dataAuthoritative = false, lastKnown = null, deviceNetworkState = "applied", hostAvailable = true, endpointState = "reachable", } = {}) { const observedAt = "2026-08-06T12:00:00Z"; const identityVerified = leaseState === "reachable"; const connectionReady = Boolean( controlAllowed && identityVerified && leaseState === "reachable" && deviceNetworkState === "applied" && hostAvailable && endpointState === "reachable", ); return { snapshot_runtime_id: "runtime-a", network_write_reconciliation: null, connection_lifecycle: { schema_version: "missioncore.xgrids-k1-connection-lifecycle/v1", revision: generation, desired_mode: mode, configured_mode: deviceNetworkState === "applied" ? mode : null, active_mode: connectionReady ? mode : null, mode_change: { state: connectionReady ? "ready" : "awaiting-control", from: deviceNetworkState === "applied" ? mode : null, to: mode, }, mode_selection: { allowed: true, reason_codes: [], automatic_retry: false, }, active_binding_key: connectionReady ? `binding-${intentId}-${hostPathEpoch}` : null, active_binding: connectionReady ? { binding_key: `binding-${intentId}-${hostPathEpoch}`, intent_id: intentId, transport_ref: "ble-k1-001", connection_mode: mode, target_ipv4: target.ipv4, target_port: target.port, host_path_epoch: hostPathEpoch, control_session_id: "control-session-001", logical_device_id: "device-k1-001", } : null, connection_ready: connectionReady, ready_to_start: connectionReady, operation: null, allowed_actions: connectionReady ? ["start-acquisition", "select-connection-mode"] : ["select-connection-mode"], automatic_retry: false, }, connection_supervisor: { schema_version: "missioncore.k1-connection-supervisor/v1", revision: generation, closed: false, intent: { intent_id: intentId, requested_mode: mode, expected_device_id: "device-k1-001", requested_at: observedAt, }, observed: { device_network: { state: deviceNetworkState, intent_id: deviceNetworkState === "applied" ? intentId : null, transport_ref: deviceNetworkState === "applied" ? "ble-k1-001" : null, connection_mode: deviceNetworkState === "applied" ? mode : null, target: deviceNetworkState === "applied" ? target : null, source: deviceNetworkState === "applied" ? "ble-read-only-status" : null, observed_at: deviceNetworkState === "applied" ? observedAt : null, }, host_path: { epoch: hostPathEpoch, available: hostAvailable, fingerprint: `en0:${hostPathEpoch}`, interface: "en0", source_ipv4: "192.168.68.10", route_class: hostAvailable ? "direct" : "unavailable", reason_code: null, observed_at: observedAt, }, endpoint: { target, tcp_state: endpointState, intent_id: intentId, host_path_epoch: hostPathEpoch, reason_code: null, observed_at: observedAt, }, device_identity: { state: identityVerified ? "verified" : "unverified", intent_id: identityVerified ? intentId : null, logical_device_id: identityVerified ? "device-k1-001" : null, compatibility_profile_id: identityVerified ? "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2" : null, connection_mode: identityVerified ? mode : null, source: identityVerified ? "mqtt-device-info" : null, host_path_epoch: identityVerified ? hostPathEpoch : null, observed_at: identityVerified ? observedAt : null, }, control_plane: { state: controlAllowed ? "healthy" : "idle", session_id: controlAllowed ? "control-session-001" : null, host_path_epoch: controlAllowed ? hostPathEpoch : null, reason_code: null, observed_at: controlAllowed ? observedAt : null, }, data_plane: { state: dataAuthoritative ? "healthy" : "idle", session_id: dataAuthoritative ? "data-session-001" : null, host_path_epoch: dataAuthoritative ? hostPathEpoch : null, reason_code: null, observed_at: dataAuthoritative ? observedAt : null, }, }, lease: { state: leaseState, generation, intent_id: intentId, host_path_epoch: hostPathEpoch, connection_mode: mode, target, logical_device_id: identityVerified ? "device-k1-001" : null, reason_code: null, observed_at: observedAt, }, authority: { network_mutation_allowed: false, control_allowed: controlAllowed, acquisition_start_allowed: controlAllowed, data_ingest_authoritative: dataAuthoritative, physical_motion_allowed: false, reason_codes: [], }, last_known: lastKnown, allowed_actions: [], }, }; } test("parser accepts reviewed v1alpha1 and v1alpha2 shapes", () => { const legacy = parseDevicePluginManifest(manifestDocument()); const current = parseDevicePluginManifest( manifestDocument({ apiVersion: "missioncore.nodedc/v1alpha2" }), ); assert.equal(legacy.apiVersion, "missioncore.nodedc/v1alpha1"); assert.equal(legacy.spec.hostApiRange, "v1alpha1"); assert.equal(current.apiVersion, "missioncore.nodedc/v1alpha2"); assert.equal(current.spec.hostApiRange, "v1alpha2"); assert.deepEqual(current.spec.compatibilityProfiles, [ { profileId: "test.device.model.fw-1.v1", path: "profiles/fw-1/profile.v1.json", modelId: "test.device.model", }, ]); }); test("v1alpha1 keeps the original nonblank identifier compatibility", () => { const legacyDocument = manifestDocument({ pluginId: "legacy plugin id", modelId: "legacy model id", }); legacyDocument.spec.permissions = ["legacy permission"]; legacyDocument.spec.actions[0].secretFields = ["legacy secret field"]; legacyDocument.spec.models[0].capabilities = [ { id: "legacy capability", label: "Legacy" }, ]; const legacy = parseDevicePluginManifest(legacyDocument); assert.equal(legacy.metadata.id, "legacy plugin id"); assert.equal(legacy.spec.models[0].id, "legacy model id"); assert.deepEqual(legacy.spec.permissions, ["legacy permission"]); }); test("v1alpha2 applies strict identifiers without redefining v1alpha1", () => { const current = manifestDocument({ apiVersion: "missioncore.nodedc/v1alpha2", pluginId: "current plugin id", }); assert.throws( () => parseDevicePluginManifest(current), /не является идентификатором/, ); }); test("v1alpha2 parser and registry accept multiple independently profiled models", () => { const document = manifestDocument({ apiVersion: "missioncore.nodedc/v1alpha2", pluginId: "test.family", modelId: "test.family.model-a", }); document.spec.models.push({ ...document.spec.models[0], id: "test.family.model-b", displayName: "Test model B", }); document.spec.compatibilityProfiles.push({ profileId: "test.family.model-b.fw-1.v1", path: "profiles/fw-1/model-b.v1.json", modelId: "test.family.model-b", }); const manifest = parseDevicePluginManifest(document); const plugin = { ...uiPlugin(manifest), connectionViews: { "test.connection": () => null }, }; const registry = createDevicePluginRegistry([plugin]); assert.deepEqual(registry.models.map(({ model }) => model.id), [ "test.family.model-a", "test.family.model-b", ]); }); test("installed XGRIDS frontend manifest exposes the semantic v1alpha2 actions", () => { assert.equal(xgridsK1Manifest.apiVersion, "missioncore.nodedc/v1alpha2"); assert.deepEqual(xgridsK1Manifest.spec.compatibilityProfiles, [ { profileId: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", path: "profiles/fw-3.0.2/local-network.v2.json", modelId: "xgrids.lixelkity-k1", }, ]); assert.equal(xgridsK1Actions.acquisitionPrepare, "acquisition.prepare"); assert.equal(xgridsK1Actions.acquisitionStart, "acquisition.start"); assert.equal(xgridsK1Actions.acquisitionStop, "acquisition.stop"); assert.equal(xgridsK1Actions.connectionVerify, "connection.verify"); assert.equal( xgridsK1Actions.configuredEndpointProbe, "connection.endpoint-probe", ); }); test("one operator action can open at most one K1 control session", () => { assert.equal(lifecycle.controlSessionEntryPlan("idle", false, true), "open"); assert.equal(lifecycle.controlSessionEntryPlan("failed", false, true), "open"); assert.equal(lifecycle.controlSessionEntryPlan("failed", false, false), "failed"); assert.equal(lifecycle.controlSessionEntryPlan("failed", true, true), "failed"); assert.equal( lifecycle.controlSessionEntryPlan("idle", true, true), "duplicate-open", ); assert.equal( lifecycle.controlSessionEntryPlan("connection-ready", true, false), "continue", ); }); test("K1 operator intent stays invalid after runtime deactivate and reactivate", () => { const generation = new operatorIntentGeneration.OperatorIntentGeneration(); generation.activateRuntime(); const oldIntent = generation.beginOperatorIntent(); assert.ok(oldIntent); assert.equal(generation.isOperatorIntentCurrent(oldIntent), true); generation.deactivateRuntime(); generation.activateRuntime(); const freshIntent = generation.beginOperatorIntent(); assert.ok(freshIntent); assert.notEqual(freshIntent.runtimeGeneration, oldIntent.runtimeGeneration); assert.equal(generation.isOperatorIntentCurrent(oldIntent), false); assert.equal(generation.isOperatorIntentCurrent(freshIntent), true); }); test("stale K1 intent cannot continue past an await after runtime reactivation", async () => { const generation = new operatorIntentGeneration.OperatorIntentGeneration(); generation.activateRuntime(); const oldIntent = generation.beginOperatorIntent(); assert.ok(oldIntent); let resolveOldRead; const oldRead = new Promise((resolve) => { resolveOldRead = resolve; }); const writes = []; const assertOldIntent = () => { if (!generation.isOperatorIntentCurrent(oldIntent)) { throw new Error("stale operator intent"); } }; const oldContinuation = operatorIntentGeneration.awaitWhileIntentCurrent( assertOldIntent, () => oldRead, ).then(() => writes.push("old-checkpoint")); generation.deactivateRuntime(); generation.activateRuntime(); const freshIntent = generation.beginOperatorIntent(); assert.ok(freshIntent); resolveOldRead({ phase: "connection-ready" }); await assert.rejects(oldContinuation, /stale operator intent/); assert.deepEqual(writes, []); const assertFreshIntent = () => { if (!generation.isOperatorIntentCurrent(freshIntent)) { throw new Error("stale fresh intent"); } }; await operatorIntentGeneration.awaitWhileIntentCurrent( assertFreshIntent, async () => ({ phase: "connection-ready" }), ); writes.push("fresh-checkpoint"); assert.deepEqual(writes, ["fresh-checkpoint"]); }); test("canonical K1 intent cannot cross from snapshot runtime A into B", async () => { const generation = new operatorIntentGeneration.OperatorIntentGeneration(); generation.activateRuntime(); const intent = generation.beginOperatorIntent(); assert.ok(intent); const actionRuntimeId = "snapshot-runtime-a"; let currentRuntimeId = actionRuntimeId; const writes = []; const assertActionCurrent = () => { if ( !generation.isOperatorIntentCurrent(intent) || !operatorIntentGeneration.isSnapshotRuntimeCurrent( actionRuntimeId, currentRuntimeId, ) ) { throw new Error("snapshot runtime changed"); } }; const continuation = operatorIntentGeneration.awaitWhileIntentCurrent( assertActionCurrent, async () => { currentRuntimeId = "snapshot-runtime-b"; return { phase: "connection-ready" }; }, ).then(() => writes.push("next-mutation")); await assert.rejects(continuation, /snapshot runtime changed/); assert.deepEqual(writes, []); }); test("a fresh explicit K1 intent supersedes the previous intent in one runtime", () => { const generation = new operatorIntentGeneration.OperatorIntentGeneration(); generation.activateRuntime(); const first = generation.beginOperatorIntent(); const second = generation.beginOperatorIntent(); assert.ok(first); assert.ok(second); assert.equal(first.runtimeGeneration, second.runtimeGeneration); assert.notEqual(first.intentGeneration, second.intentGeneration); assert.equal(generation.isOperatorIntentCurrent(first), false); assert.equal(generation.isOperatorIntentCurrent(second), true); }); test("canonical K1 preparation stops before START and guards every async stage", async () => { const hookSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/useXgridsK1Runtime.ts", import.meta.url, ), "utf8", ); const canonicalPreparation = hookSource.slice( hookSource.indexOf("const prepareCanonicalAcquisition"), hookSource.indexOf("const prepareAcquisition"), ); const finalStart = hookSource.slice( hookSource.indexOf("const startPreparedAcquisition"), hookSource.indexOf("const startReplay"), ); const controlPollingLoop = hookSource.slice( hookSource.indexOf("async function waitForControlPhase"), hookSource.indexOf("async function waitForPhysicalReconciliationProof"), ); const reconciliationPollingLoop = hookSource.slice( hookSource.indexOf("async function waitForPhysicalReconciliationProof"), hookSource.indexOf("function messageFor"), ); assert.doesNotMatch(hookSource, /mounted\.current/); assert.match(canonicalPreparation, /beginOperatorIntent\(\)/); assert.match(canonicalPreparation, /isOperatorIntentCurrent\(intentToken\)/); assert.match( canonicalPreparation, /const actionSnapshotRuntimeId = expectedSnapshotRuntimeId\(\)/, ); assert.match( canonicalPreparation, /isSnapshotRuntimeCurrent\(actionSnapshotRuntimeId\)/, ); assert.equal( canonicalPreparation.match( /expected_snapshot_runtime_id: actionSnapshotRuntimeId/g, )?.length, 3, ); assert.match(canonicalPreparation, /xgridsK1Api\.reconcilePhysicalCommand\(\{/); assert.doesNotMatch(canonicalPreparation, /await xgridsK1Api\./); assert.doesNotMatch(canonicalPreparation, /await waitForControlPhase\(/); assert.doesNotMatch(canonicalPreparation, /xgridsK1Api\.startAcquisition/); assert.match(finalStart, /xgridsK1Api\.startAcquisition/); assert.ok( canonicalPreparation.match(/awaitWhileIntentCurrent\(/g)?.length >= 7, "each preparation REST/checkpoint boundary must use the intent guard", ); assert.match(controlPollingLoop, /for \(;;\) \{\s*assertOperatorIntentCurrent\(\)/); assert.equal(controlPollingLoop.match(/awaitWhileIntentCurrent\(/g)?.length, 2); assert.match( reconciliationPollingLoop, /for \(;;\) \{\s*assertOperatorIntentCurrent\(\)/, ); assert.equal( reconciliationPollingLoop.match(/awaitWhileIntentCurrent\(/g)?.length, 2, ); }); test("K1 control-session CAS is exact, integer-only and mapped for each mutation family", () => { const state = { application_control_session: { mode: "interactive-canonical", state: "workspace-ready", session_generation: 17, state_revision: 43, }, }; assert.deepEqual( controlSessionCas.exactApplicationControlCas(state, "ENTER"), { expected_session_generation: 17, expected_state_revision: 43, }, ); assert.deepEqual( controlSessionCas.exactAcquisitionControlCas(state, "PREPARE"), { expected_control_session_generation: 17, expected_control_state_revision: 43, }, ); assert.equal(controlSessionCas.acquisitionMutationUsesControlSession(state), true); assert.equal( controlSessionCas.acquisitionMutationUsesControlSession({ application_control_session: { ...state.application_control_session, state: "closed" }, }), false, ); for (const [field, value] of [ ["session_generation", undefined], ["session_generation", 1.5], ["session_generation", -1], ["session_generation", Number.NaN], ["state_revision", undefined], ["state_revision", 2.25], ["state_revision", -1], ["state_revision", Number.POSITIVE_INFINITY], ]) { assert.throws( () => controlSessionCas.exactApplicationControlCas({ application_control_session: { ...state.application_control_session, [field]: value, }, }, "TEST"), (error) => error instanceof ApiError && /не отправлена/.test(error.message), `${field}=${String(value)}`, ); } }); test("K1 frontend reads CAS only from latest accepted state immediately before API mutations", async () => { const apiSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/api.ts", import.meta.url, ), "utf8", ); const hookSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/useXgridsK1Runtime.ts", import.meta.url, ), "utf8", ); assert.match(apiSource, /session_generation:\s*number/); assert.match(apiSource, /state_revision:\s*number/); assert.match(apiSource, /expected_session_generation:\s*number/); assert.match(apiSource, /expected_control_session_generation:\s*number/); assert.match(apiSource, /closeApplicationControlSession\(\s*body:/); assert.doesNotMatch(hookSource, /closeApplicationControlSession\(\)/); assert.ok( [...hookSource.matchAll(/exactApplicationControlCas\(\s*latestState\.current/g)].length >= 3, "standalone ENTER, CLOSE and canonical ENTER must use latest accepted state", ); assert.ok( [...hookSource.matchAll(/exactAcquisitionControlCas\(\s*latestState\.current/g)].length >= 4, "canonical PREPARE, generic PREPARE, START and STOP must use latest accepted state", ); assert.match( hookSource, /nextState = latestState\.current \?\? nextState;[\s\S]*?const phase = controlPhase\(nextState\)/, ); assert.match( hookSource, /mode:\s*"graceful",[\s\S]*?\.\.\.newMutationContext\("acquisition\.stop"\),[\s\S]*?\.\.\.controlCas/, ); assert.match(hookSource, /mode:\s*"capture-only"/); const stopMutation = hookSource.slice( hookSource.indexOf("const stop = useCallback"), hookSource.indexOf("const stopLocalReceiver = useCallback"), ); const localReceiverCleanup = hookSource.slice( hookSource.indexOf("const stopLocalReceiver = useCallback"), hookSource.indexOf("const abort = useCallback"), ); const mutationGate = stopMutation.indexOf( "physicalStopIntentCheckpoint(dispatchState)", ); const exactCas = stopMutation.indexOf("exactAcquisitionControlCas(", mutationGate); const spentFence = stopMutation.indexOf("spendPhysicalStopIntent(checkpoint)", exactCas); const physicalCall = stopMutation.indexOf("xgridsK1Api.stopAcquisition({", spentFence); assert.ok( mutationGate >= 0 && exactCas > mutationGate && spentFence > exactCas && physicalCall > spentFence, "physical STOP must re-read exact authority and spend it synchronously before its API call", ); assert.match(stopMutation, /physicalStopPresentationOwner\.current === stopPresentationOwner/); const captureOnlyMarker = stopMutation.indexOf('mode: "capture-only"'); const captureOnlyPolicyGate = stopMutation.lastIndexOf( 'connectionPolicyAllows(currentState, "stop-local-receiver")', captureOnlyMarker, ); const compatibilityCall = stopMutation.indexOf( "xgridsK1Api.stopSessionCompatibility({", captureOnlyMarker, ); const compatibilityPolicyGate = stopMutation.lastIndexOf( 'connectionPolicyAllows(currentState, "stop-local-receiver")', compatibilityCall, ); assert.ok( captureOnlyPolicyGate >= 0 && captureOnlyPolicyGate < captureOnlyMarker && compatibilityPolicyGate > captureOnlyMarker && compatibilityPolicyGate < compatibilityCall, "generic capture-only and compatibility STOP must fail closed on the current local-stop policy before API dispatch", ); const localReceiverPolicyGate = localReceiverCleanup.indexOf( 'connectionPolicyAllows(currentState, "stop-local-receiver")', ); const localReceiverFirstApiCall = localReceiverCleanup.indexOf("xgridsK1Api."); assert.ok( localReceiverPolicyGate >= 0 && localReceiverPolicyGate < localReceiverFirstApiCall, "a direct or stale local cleanup call must be denied before either API path", ); assert.match( localReceiverCleanup, /const stopPlan = localReceiverStopPlan\(currentState\)/, ); assert.match( localReceiverCleanup, /stopPlan\.kind === "acquisition"/, ); assert.match( localReceiverCleanup, /xgridsK1Api\.stopAcquisition\(\{[\s\S]*?acquisition_id: stopPlan\.acquisitionId,[\s\S]*?mode: "capture-only"[\s\S]*?expected_snapshot_runtime_id: snapshotRuntimeId/, ); assert.match( localReceiverCleanup, /xgridsK1Api\.stopSessionCompatibility\(\{[\s\S]*?expected_snapshot_runtime_id: snapshotRuntimeId/, ); assert.doesNotMatch( localReceiverCleanup, /exactAcquisitionControlCas|physical_acceptance|spendPhysicalStopIntent/, ); }); test("K1 API forwards runtime fences and exact CAS fields without dropping them", async () => { const originalFetch = globalThis.fetch; const calls = []; globalThis.fetch = async (path, init) => { calls.push({ path, init }); return new Response(JSON.stringify({ state: { source_mode: "idle" } }), { status: 200, headers: { "Content-Type": "application/json" }, }); }; try { await xgridsK1Api.openApplicationControlSession({ expected_snapshot_runtime_id: "snapshot-runtime-cas", operator_present: true, owner_controlled_device: true, lixelgo_closed: true, battery_storage_confirmed: true, expected_physical_state_confirmed: true, timezone_name: "Europe/Moscow", }); await xgridsK1Api.enterApplicationWorkspace({ expected_snapshot_runtime_id: "snapshot-runtime-cas", operator_confirmed: true, expected_session_generation: 7, expected_state_revision: 8, }); await xgridsK1Api.closeApplicationControlSession({ expected_snapshot_runtime_id: "snapshot-runtime-cas", expected_session_generation: 9, expected_state_revision: 10, }); await xgridsK1Api.reconcilePhysicalCommand({ expected_snapshot_runtime_id: "snapshot-runtime-cas", reconciliation_id: "reconciliation-cas", expected_session_generation: 9, expected_state_revision: 10, }); await xgridsK1Api.prepareAcquisition({ expected_snapshot_runtime_id: "snapshot-runtime-cas", operation_id: "op-00000000-0000-4000-8000-000000000101", idempotency_key: "acquisition.prepare:op-00000000-0000-4000-8000-000000000101", project_name: "CAS01", mount_type: "handheld", gnss_mode: "none", compatibility_attestation: { firmware_version: "3.0.2", topology: "direct-lan", verification: "live-device-info", }, expected_control_session_generation: 11, expected_control_state_revision: 12, }); await xgridsK1Api.startAcquisition({ expected_snapshot_runtime_id: "snapshot-runtime-cas", operation_id: "op-00000000-0000-4000-8000-000000000102", idempotency_key: "acquisition.start:op-00000000-0000-4000-8000-000000000102", acquisition_id: "acquisition-cas", expected_control_session_generation: 13, expected_control_state_revision: 14, }); await xgridsK1Api.stopAcquisition({ expected_snapshot_runtime_id: "snapshot-runtime-cas", operation_id: "op-00000000-0000-4000-8000-000000000103", idempotency_key: "acquisition.stop:op-00000000-0000-4000-8000-000000000103", acquisition_id: "acquisition-cas", mode: "graceful", expected_control_session_generation: 15, expected_control_state_revision: 16, }); await xgridsK1Api.abortAcquisition({ expected_snapshot_runtime_id: "snapshot-runtime-cas", operation_id: "op-00000000-0000-4000-8000-000000000104", idempotency_key: "acquisition.abort:op-00000000-0000-4000-8000-000000000104", acquisition_id: "acquisition-cas", expected_control_session_generation: 17, expected_control_state_revision: 18, }); await xgridsK1Api.stopSessionCompatibility({ expected_snapshot_runtime_id: "snapshot-runtime-cas", }); } finally { globalThis.fetch = originalFetch; } assert.deepEqual( calls.map(({ init }) => JSON.parse(init.body).input), [ { expected_snapshot_runtime_id: "snapshot-runtime-cas", operator_present: true, owner_controlled_device: true, lixelgo_closed: true, battery_storage_confirmed: true, expected_physical_state_confirmed: true, timezone_name: "Europe/Moscow", }, { expected_snapshot_runtime_id: "snapshot-runtime-cas", operator_confirmed: true, expected_session_generation: 7, expected_state_revision: 8, }, { expected_snapshot_runtime_id: "snapshot-runtime-cas", expected_session_generation: 9, expected_state_revision: 10, }, { expected_snapshot_runtime_id: "snapshot-runtime-cas", reconciliation_id: "reconciliation-cas", expected_session_generation: 9, expected_state_revision: 10, }, { expected_snapshot_runtime_id: "snapshot-runtime-cas", operation_id: "op-00000000-0000-4000-8000-000000000101", idempotency_key: "acquisition.prepare:op-00000000-0000-4000-8000-000000000101", project_name: "CAS01", mount_type: "handheld", gnss_mode: "none", compatibility_attestation: { firmware_version: "3.0.2", topology: "direct-lan", verification: "live-device-info", }, expected_control_session_generation: 11, expected_control_state_revision: 12, }, { expected_snapshot_runtime_id: "snapshot-runtime-cas", operation_id: "op-00000000-0000-4000-8000-000000000102", idempotency_key: "acquisition.start:op-00000000-0000-4000-8000-000000000102", acquisition_id: "acquisition-cas", expected_control_session_generation: 13, expected_control_state_revision: 14, }, { expected_snapshot_runtime_id: "snapshot-runtime-cas", operation_id: "op-00000000-0000-4000-8000-000000000103", idempotency_key: "acquisition.stop:op-00000000-0000-4000-8000-000000000103", acquisition_id: "acquisition-cas", mode: "graceful", expected_control_session_generation: 15, expected_control_state_revision: 16, }, { expected_snapshot_runtime_id: "snapshot-runtime-cas", operation_id: "op-00000000-0000-4000-8000-000000000104", idempotency_key: "acquisition.abort:op-00000000-0000-4000-8000-000000000104", acquisition_id: "acquisition-cas", expected_control_session_generation: 17, expected_control_state_revision: 18, }, { expected_snapshot_runtime_id: "snapshot-runtime-cas", }, ], ); }); test("K1 lifecycle mutation context is unique and binds one key to one operation", () => { const first = lifecycle.newMutationContext("acquisition.start"); const second = lifecycle.newMutationContext("acquisition.start"); assert.match(first.operation_id, /^op-[0-9a-f-]{36}$/); assert.equal(first.idempotency_key, `acquisition.start:${first.operation_id}`); assert.notEqual(second.operation_id, first.operation_id); assert.equal(second.idempotency_key, `acquisition.start:${second.operation_id}`); assert.throws( () => lifecycle.newMutationContext(" "), /безопасный ключ не создан/, ); }); test("K1 API uses bounded no-retry timeout classes per operation family", async () => { const apiSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/api.ts", import.meta.url, ), "utf8", ); assert.equal(requestTimeoutMsForAction(xgridsK1Actions.stateRead), 8_000); assert.equal(requestTimeoutMsForAction(xgridsK1Actions.discoveryScan), 70_000); assert.equal(requestTimeoutMsForAction(xgridsK1Actions.networkProvision), 300_000); assert.equal(requestTimeoutMsForAction(xgridsK1Actions.connectionVerify), 150_000); assert.equal(requestTimeoutMsForAction(xgridsK1Actions.configuredEndpointProbe), 15_000); for (const action of [ xgridsK1Actions.applicationControlSessionOpen, xgridsK1Actions.applicationControlWorkspaceEnter, xgridsK1Actions.applicationControlSessionClose, xgridsK1Actions.acquisitionPrepare, xgridsK1Actions.acquisitionStart, xgridsK1Actions.acquisitionStop, ]) { assert.equal(requestTimeoutMsForAction(action), 120_000, action); } const timeout = new ApiRequestTimeoutError("acquisition.start", 120_000); assert.equal(timeout.outcomeUnknown, true); assert.equal(timeout.automaticRetry, false); assert.equal(timeout.transportUnavailable, false); assert.match(timeout.message, /автоматический повтор запрещён/); assert.match(apiSource, /const controller = new AbortController\(\)/); assert.match(apiSource, /setTimeout\(\(\) => \{\s*timedOut = true;\s*controller\.abort\(\)/); assert.match(apiSource, /finally \{\s*clearTimeout\(timeout\)/); assert.doesNotMatch(apiSource, /automaticRetry\s*=\s*true/); }); test("one explicit K1 operator action supplies the backend physical acceptance", () => { assert.deepEqual(physicalCommandConfirmation.operatorActionPhysicalAcceptance(), { operator_present: true, owner_controlled_device: true, lixelgo_closed: true, battery_storage_confirmed: true, expected_physical_state_confirmed: true, }); }); test("final K1 START target requires exact prepared project and fresh READY authority", () => { const state = { ...supervisedConnectionState(), phase: "ready", source_mode: "idle", selected_device_id: "ble-k1-001", device_ref: { device_id: "device-k1-001", }, device_session: { device_session_id: "device-session-001", device_id: "device-k1-001", connectivity: "connected", }, compatibility: { permitted_mode: "active-control", vendor_writes_enabled: true, }, acquisition: { acquisition_id: "acquisition-001", device_id: "device-k1-001", device_session_id: "device-session-001", compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", control_mode: "plugin-commanded", project_name: "RAVNOVES01", requested_streams: [], target_host: "127.0.0.1", duration_seconds: null, evidence_policy: "required", state: "prepared", state_revision: 4, }, application_control_session: { session_generation: 5, state_revision: 8, state: "project-ready", control_socket_open: true, can_start: true, verified_control: { logical_device_id: "device-k1-001", compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", control_session_id: "control-session-001", source: "mqtt-device-info", intent_id: "intent-bridge-1", transport_ref: "ble-k1-001", host_path_epoch: 3, target_ipv4: "192.168.68.50", target_port: 1883, connection_mode: "bridge", control_proof_revision: 9, control_proof_source: "device-status", control_proof_fresh: true, }, transport: { latest_device_session_state: "ready", latest_device_project_bound: true, latest_device_init_ready: false, }, }, }; const target = physicalCommandConfirmation.preparedStartTarget(state); assert.ok(target); const { fence, ...displayTarget } = target; assert.deepEqual(displayTarget, { deviceId: "device-k1-001", connection: "bridge · 192.168.68.50:1883", projectName: "RAVNOVES01", acquisitionId: "acquisition-001", deviceState: "READY · проект привязан · инициализация не запущена", }); assert.equal(fence.kind, "start"); assert.equal(fence.controlSessionGeneration, 5); assert.equal(fence.controlStateRevision, 8); assert.equal(fence.connectionIntentId, "intent-bridge-1"); assert.equal(fence.transportRef, "ble-k1-001"); assert.equal(fence.acquisitionStateRevision, 4); for (const mutate of [ (candidate) => { candidate.application_control_session.can_start = false; }, (candidate) => { candidate.application_control_session.transport.latest_device_session_state = "scanning"; }, (candidate) => { candidate.application_control_session.transport.latest_device_project_bound = false; }, (candidate) => { candidate.application_control_session.transport.latest_device_init_ready = true; }, (candidate) => { candidate.application_control_session.verified_control.control_proof_fresh = false; }, (candidate) => { candidate.connection_supervisor.authority.acquisition_start_allowed = false; }, (candidate) => { candidate.acquisition.device_id = "another-device"; }, (candidate) => { candidate.application_control_session.verified_control.intent_id = "stale-intent"; }, (candidate) => { candidate.application_control_session.verified_control.host_path_epoch = 2; }, (candidate) => { candidate.application_control_session.verified_control.transport_ref = "stale-transport"; }, (candidate) => { candidate.application_control_session.verified_control.target_port = 1884; }, (candidate) => { candidate.connection_lifecycle.ready_to_start = false; }, ]) { const stale = structuredClone(state); mutate(stale); assert.equal(physicalCommandConfirmation.preparedStartTarget(stale), null); } }); test("physical K1 modal checkpoint stays stable on refresh and invalidates on topology, CAS or state changes", () => { const state = { ...supervisedConnectionState(), phase: "ready", source_mode: "idle", selected_device_id: "ble-k1-001", device_ref: { device_id: "device-k1-001" }, device_session: { device_session_id: "device-session-001", device_id: "device-k1-001", connectivity: "connected", }, acquisition: { acquisition_id: "acquisition-fence-1", device_id: "device-k1-001", device_session_id: "device-session-001", compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", control_mode: "plugin-commanded", project_name: "FENCE01", requested_streams: [], target_host: "127.0.0.1", duration_seconds: null, evidence_policy: "required", state: "prepared", state_revision: 21, }, application_control_session: { session_generation: 13, state_revision: 34, state: "project-ready", control_socket_open: true, can_start: true, verified_control: { logical_device_id: "device-k1-001", compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", control_session_id: "control-session-001", source: "mqtt-device-info", intent_id: "intent-bridge-1", transport_ref: "ble-k1-001", host_path_epoch: 3, target_ipv4: "192.168.68.50", target_port: 1883, connection_mode: "bridge", control_proof_revision: 55, control_proof_source: "device-status", control_proof_fresh: true, }, transport: { latest_device_session_state: "ready", latest_device_project_bound: true, latest_device_init_ready: false, }, }, }; const openingTarget = physicalCommandConfirmation.preparedStartTarget(state); assert.ok(openingTarget); const checkpoint = physicalCommandConfirmation.createPhysicalCommandCheckpoint( "start", openingTarget, ); const readOnlyRefresh = structuredClone(state); readOnlyRefresh.snapshot_revision = 999; // The supervisor revision is an observation counter, not a topology // generation: a semantically identical host/MQTT poll increments it. // Such a refresh must not destroy an operator confirmation in progress. readOnlyRefresh.connection_supervisor.revision += 1; readOnlyRefresh.snapshot_runtime_started_at_utc = "2026-08-06T12:01:00Z"; readOnlyRefresh.connection_supervisor.observed.host_path.observed_at = "2026-08-06T12:01:00Z"; readOnlyRefresh.connection_supervisor.observed.endpoint.observed_at = "2026-08-06T12:01:00Z"; const unchangedTarget = physicalCommandConfirmation.preparedStartTarget(readOnlyRefresh); assert.ok(unchangedTarget); assert.equal( physicalCommandConfirmation.physicalCommandCheckpointMatches( checkpoint, "start", unchangedTarget, ), true, ); assert.equal( physicalCommandConfirmation.physicalCommandCheckpointMatches( checkpoint, "stop", unchangedTarget, ), false, ); assert.equal(Object.isFrozen(checkpoint), true); assert.equal(Object.isFrozen(checkpoint.fence), true); assert.equal(Object.isFrozen(checkpoint.target), true); const topologyChanged = structuredClone(state); topologyChanged.connection_supervisor.revision += 1; topologyChanged.connection_supervisor.intent.intent_id = "intent-bridge-2"; topologyChanged.connection_supervisor.observed.device_network.intent_id = "intent-bridge-2"; topologyChanged.connection_supervisor.observed.endpoint.intent_id = "intent-bridge-2"; topologyChanged.connection_supervisor.observed.device_identity.intent_id = "intent-bridge-2"; topologyChanged.connection_supervisor.lease.intent_id = "intent-bridge-2"; topologyChanged.connection_lifecycle.active_binding.intent_id = "intent-bridge-2"; topologyChanged.connection_lifecycle.active_binding.binding_key = "binding-intent-bridge-2-3"; topologyChanged.connection_lifecycle.active_binding_key = "binding-intent-bridge-2-3"; topologyChanged.application_control_session.verified_control.intent_id = "intent-bridge-2"; const topologyTarget = physicalCommandConfirmation.preparedStartTarget(topologyChanged); assert.ok(topologyTarget); assert.equal( physicalCommandConfirmation.physicalCommandCheckpointMatches( checkpoint, "start", topologyTarget, ), false, ); const casChanged = structuredClone(state); casChanged.application_control_session.session_generation += 1; casChanged.application_control_session.state_revision += 1; const casTarget = physicalCommandConfirmation.preparedStartTarget(casChanged); assert.ok(casTarget); assert.equal( physicalCommandConfirmation.physicalCommandCheckpointMatches( checkpoint, "start", casTarget, ), false, ); const runtimeStateChanged = structuredClone(state); runtimeStateChanged.phase = "degraded"; const runtimeTarget = physicalCommandConfirmation.preparedStartTarget(runtimeStateChanged); assert.ok(runtimeTarget); assert.equal( physicalCommandConfirmation.physicalCommandCheckpointMatches( checkpoint, "start", runtimeTarget, ), false, ); assert.equal(checkpoint.target.projectName, "FENCE01"); const changedDisplay = structuredClone(openingTarget); changedDisplay.projectName = "FENCE02"; assert.equal( physicalCommandConfirmation.physicalCommandCheckpointMatches( checkpoint, "start", changedDisplay, ), false, ); assert.equal(checkpoint.target.projectName, "FENCE01"); }); test("K1 STOP target is bound to the active acquisition instead of START constants", () => { const state = { compatibility: { permitted_mode: "active-control", vendor_writes_enabled: true, }, acquisition: { acquisition_id: "acquisition-active-77", device_id: "device-k1-active", device_session_id: "device-session-active", compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", control_mode: "plugin-commanded", project_name: "ROUTE77", requested_streams: [], target_host: "127.0.0.1", duration_seconds: null, evidence_policy: "required", state: "acquiring", state_revision: 12, }, application_control_session: { state: "scanning", verified_control: { logical_device_id: "device-k1-active", compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", connection_mode: "quick-connect", target_ipv4: "192.168.56.1", target_port: 1883, }, transport: { latest_device_session_state: "scanning", latest_device_project_bound: true, latest_device_init_ready: true, }, }, }; const target = physicalCommandConfirmation.activeStopTarget(state); assert.ok(target); const { fence, ...displayTarget } = target; assert.deepEqual(displayTarget, { deviceId: "device-k1-active", connection: "quick-connect · 192.168.56.1:1883", projectName: "ROUTE77", acquisitionId: "acquisition-active-77", deviceState: "SCANNING · проект привязан · инициализация завершена", }); assert.equal(fence.kind, "stop"); assert.equal(fence.acquisitionStateRevision, 12); assert.equal( physicalCommandConfirmation.activeStopTarget({ ...state, acquisition: { ...state.acquisition, control_mode: "operator-manual" }, }), null, ); }); test("K1 control errors stay informative and only fetch failures mark transport unavailable", async () => { assert.equal( localizeRuntimeMessage( "control MQTT connect call failed: [Errno 61] Connection refused", ), "Управляющее соединение со сканером не открылось: устройство не приняло MQTT-соединение. Команды сканирования не отправлялись.", ); const domainError = new ApiError("Диалог остановлен до команды START."); assert.equal(domainError.transportUnavailable, false); const originalFetch = globalThis.fetch; globalThis.fetch = async () => { throw new TypeError("synthetic network failure"); }; try { await assert.rejects( () => xgridsK1Api.getState(), (error) => error instanceof ApiError && error.transportUnavailable === true, ); } finally { globalThis.fetch = originalFetch; } }); test("v1alpha2 compatibility profile is exact-key and rejects duplicated profile status", () => { const document = manifestDocument({ apiVersion: "missioncore.nodedc/v1alpha2" }); document.spec.compatibilityProfiles[0].status = "verified"; assert.throws( () => parseDevicePluginManifest(document), /неизвестные поля status/, ); }); test("v1alpha2 compatibility profile fails closed on unsafe paths", () => { const document = manifestDocument({ apiVersion: "missioncore.nodedc/v1alpha2" }); document.spec.compatibilityProfiles[0].path = "../private/profile.json"; assert.throws( () => parseDevicePluginManifest(document), /безопасным относительным JSON-путём/, ); }); test("v1alpha2 compatibility profile cannot reference an unknown model", () => { const document = manifestDocument({ apiVersion: "missioncore.nodedc/v1alpha2" }); document.spec.compatibilityProfiles[0].modelId = "missing.model"; assert.throws( () => parseDevicePluginManifest(document), /ссылается на неизвестную модель missing\.model/, ); }); test("registry accepts v1alpha1 and v1alpha2 plugins together", () => { const legacy = parseDevicePluginManifest( manifestDocument({ pluginId: "test.legacy", modelId: "test.legacy.model" }), ); const current = parseDevicePluginManifest( manifestDocument({ apiVersion: "missioncore.nodedc/v1alpha2", pluginId: "test.current", modelId: "test.current.model", }), ); const registry = createDevicePluginRegistry([uiPlugin(legacy), uiPlugin(current)]); assert.equal(registry.plugins.length, 2); assert.equal(registry.models.length, 2); assert.equal(registry.resolveModel("test.current.model")?.plugin.manifest.metadata.id, "test.current"); }); test("registry independently rejects an uncovered v1alpha2 model", () => { const current = parseDevicePluginManifest( manifestDocument({ apiVersion: "missioncore.nodedc/v1alpha2" }), ); current.spec.compatibilityProfiles[0].modelId = "missing.model"; assert.throws( () => createDevicePluginRegistry([uiPlugin(current)]), /ссылается на неизвестную модель missing\.model/, ); }); test("live source is confirmed only by an acquiring acquisition", () => { const waiting = { source_mode: "live", phase: "live", acquisition: { state: "awaiting_external_start" }, }; const acquiring = { ...supervisedConnectionState({ dataAuthoritative: true }), ...waiting, acquisition: { state: "acquiring" }, }; assert.equal(lifecycle.isConfirmedLiveState(waiting), false); assert.equal(lifecycle.confirmedRuntimeSourceMode(waiting), "idle"); assert.equal(lifecycle.sourceStatusLabel(waiting), "Ожидание реальных данных"); assert.equal(lifecycle.isConfirmedLiveState(acquiring), true); assert.equal(lifecycle.confirmedRuntimeSourceMode(acquiring), "live"); assert.equal(lifecycle.liveStartPlan(acquiring), "already-running"); const staleDataEpoch = structuredClone(acquiring); staleDataEpoch.connection_supervisor.observed.data_plane.host_path_epoch = 2; assert.equal(lifecycle.isConfirmedLiveState(staleDataEpoch), false); assert.equal( lifecycle.controlSessionEntryPlan("scanning", false, false), "continue", ); }); test("prepared acquisition resumes without another prepare and remains recoverable", () => { const prepared = { source_mode: "idle", acquisition: { acquisition_id: "acq-1", state: "prepared", }, }; assert.equal(lifecycle.liveStartPlan(prepared), "resume-prepared"); assert.equal(lifecycle.recoverableAcquisition(prepared)?.acquisition_id, "acq-1"); }); test("project name is canonicalized and rejected outside the bounded safe contract", () => { assert.deepEqual(projectName.validateProjectName(" Mission 01 "), { value: "Mission 01", error: null, }); assert.match(projectName.validateProjectName("line\nbreak").error, /управляющие/); assert.match(projectName.validateProjectName("\ud800").error, /управляющие/); assert.match(projectName.validateProjectName("x".repeat(97)).error, /не длиннее 96/); assert.match(projectName.validateProjectName(" \t ").error, /Введите название/); }); test("automatic spatial source replaces the old scene only after a successful start", async () => { const failedEvents = []; assert.equal(await automaticSourceStart.runAutomaticSpatialSourceStart( async () => { failedEvents.push("start"); return false; }, () => failedEvents.push("activate"), () => failedEvents.push("open"), ), false); assert.deepEqual(failedEvents, ["start"]); const successfulEvents = []; assert.equal(await automaticSourceStart.runAutomaticSpatialSourceStart( async () => { successfulEvents.push("start"); return true; }, () => successfulEvents.push("activate"), () => successfulEvents.push("open"), ), true); assert.deepEqual(successfulEvents, ["start", "activate", "open"]); }); test("vendor commands fail closed unless the profile and acquisition both enable them", () => { const capability = { compatibility: { vendor_writes_enabled: true, permitted_mode: "active-control", }, }; assert.equal(lifecycle.isVendorWriteCapable(capability), true); assert.equal(lifecycle.isVendorWriteCapable({ compatibility: { vendor_writes_enabled: true, permitted_mode: "read-only" }, }), false); assert.equal(lifecycle.isSoftwareCommandedAcquisition({ ...capability, acquisition: { control_mode: "operator-manual" }, }), false); assert.equal(lifecycle.isSoftwareCommandedAcquisition({ ...capability, acquisition: { control_mode: "plugin-commanded" }, }), true); }); test("device modeling telemetry maps only finite non-negative values", () => { assert.deepEqual(presentation.deviceTelemetry({ device_elapsed_seconds: 12.5, device_route_distance_meters: 8.25, device_speed_meters_per_second: 0.75, }), { elapsedSeconds: 12.5, routeDistanceMeters: 8.25, speedMetersPerSecond: 0.75, }); assert.deepEqual(presentation.deviceTelemetry({ device_elapsed_seconds: -1, device_route_distance_meters: Number.NaN, device_speed_meters_per_second: Number.POSITIVE_INFINITY, }), { elapsedSeconds: null, routeDistanceMeters: null, speedMetersPerSecond: null, }); }); test("spatial K1 action failures have an explicit retry-safe presentation", () => { assert.equal(presentation.spatialActionFailure(null), null); assert.equal(presentation.spatialActionFailure(" "), null); assert.deepEqual(presentation.spatialActionFailure(" stop failed "), { title: "Действие K1 не выполнено", detail: "stop failed", }); assert.equal(lifecycle.shouldRenderSpatialControls({ source_mode: "live", acquisition: { state: "failed", cleanup_pending: true }, }), true); assert.equal(lifecycle.shouldRenderSpatialControls({ source_mode: "idle", acquisition: { state: "failed", cleanup_pending: false }, }), false); }); test("physical-command guidance projects backend policy without exposing reason codes", () => { const denied = { connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", allowed_actions: ["stop-local-receiver"], recommended_action: "stop-local-receiver", actions: { "stop-acquisition": { allowed: false, reason_codes: ["physical-command-reconciliation-required"], target_source: "connection-supervisor", required_transport_ref: null, requires_live_gatt_validation: false, automatic_retry: false, }, }, facts: { retained_context_is_presence: false }, }, }; const guidance = presentation.connectionPolicyOperatorGuidance( denied, "stop-acquisition", ); assert.deepEqual(guidance, { reason: "Результат предыдущей физической команды K1 не подтверждён.", nextAction: "Завершите локальный приём; физическое состояние K1 проверьте вручную.", }); assert.doesNotMatch(`${guidance.reason} ${guidance.nextAction}`, /physical-command|stop-local/); const allowed = structuredClone(denied); allowed.connection_policy.allowed_actions.push("stop-acquisition"); allowed.connection_policy.actions["stop-acquisition"].allowed = true; allowed.connection_policy.actions["stop-acquisition"].reason_codes = []; assert.equal( presentation.connectionPolicyOperatorGuidance(allowed, "stop-acquisition"), null, ); }); test("restart-recovery guidance describes automatic recovery without protocol ceremony", () => { const deniedFresh = { connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", allowed_actions: ["observe-configured-device-network"], recommended_action: "observe-configured-device-network", actions: { "observe-fresh-device-network": { allowed: false, reason_codes: ["reconciliation-target-not-observed"], target_source: "fresh-scan", required_transport_ref: "exact-durable-k1", required_connection_mode: "bridge", requires_live_gatt_validation: true, automatic_retry: false, }, "observe-configured-device-network": { allowed: true, reason_codes: [], target_source: "durable-configured-state", required_transport_ref: "exact-durable-k1", required_connection_mode: "bridge", requires_live_gatt_validation: true, automatic_retry: false, }, }, facts: { retained_context_is_presence: false }, }, }; const durableGuidance = presentation.connectionPolicyOperatorGuidance( deniedFresh, "observe-fresh-device-network", ); assert.deepEqual(durableGuidance, { reason: "В свежем Bluetooth-поиске не найден K1, связанный с незавершённой записью.", nextAction: "Дождитесь автоматического восстановления сохранённого подключения K1.", }); assert.doesNotMatch( `${durableGuidance.reason} ${durableGuidance.nextAction}`, /observe-configured|durable-configured/, ); deniedFresh.connection_policy.recommended_action = "observe-current-device-network"; assert.equal( presentation.connectionPolicyOperatorGuidance( deniedFresh, "observe-fresh-device-network", ).nextAction, "Дождитесь автоматического восстановления связи с тем же K1.", ); }); test("replay ignores a stale failed live acquisition", () => { const replay = { source_mode: "replay", phase: "replay", rerun_grpc_url: "rerun+http://127.0.0.1:9876/proxy", acquisition: { acquisition_id: "old-live-acquisition", state: "failed", }, }; assert.equal(lifecycle.normalizeRuntimePhase(replay), "replaying"); assert.equal(lifecycle.effectiveAcquisition(replay), null); assert.equal( lifecycle.spatialSourceId(replay, replay.rerun_grpc_url), `replay:${replay.rerun_grpc_url}`, ); }); test("K1 configuration exposes all reviewed local connection directions", () => { assert.equal(configuration.DEFAULT_CONNECTION_MODE, "bridge"); assert.equal(configuration.SUPPORTED_MOUNT_TYPE, "handheld"); assert.equal(configuration.SUPPORTED_GNSS_MODE, "none"); assert.deepEqual( configuration.connectionModeOptions.map(({ value, disabled = false }) => ({ value, disabled })), [ { value: "bridge", disabled: false }, { value: "quick-connect", disabled: false }, { value: "direct-connect", disabled: false }, ], ); assert.deepEqual( configuration.mountTypeOptions.map(({ value, disabled = false }) => ({ value, disabled })), [ { value: "handheld", disabled: false }, { value: "vehicle-mounted", disabled: true }, { value: "uav", disabled: true }, { value: "backpack", disabled: true }, ], ); assert.deepEqual( configuration.gnssModeOptions.map(({ value, disabled = false }) => ({ value, disabled })), [ { value: "none", disabled: false }, { value: "rtk", disabled: true }, { value: "ppk", disabled: true }, ], ); }); test("connection directions select distinct fail-closed topologies", () => { assert.deepEqual(compatibility.profileSelectionForConnectionMode("bridge"), { firmware_version: "3.0.2", topology: "direct-lan", verification: "live-device-info", }); assert.equal( compatibility.profileSelectionForConnectionMode("quick-connect").topology, "device-ap", ); assert.equal( compatibility.profileSelectionForConnectionMode("direct-connect").topology, "controller-hotspot", ); }); test("a provisioned address is not presented as a verified device connection", () => { assert.equal(lifecycle.normalizeRuntimePhase({ phase: "connected", application_control_session: { state: "idle" }, }), "configuring"); assert.equal(lifecycle.normalizeRuntimePhase({ phase: "connected", application_control_session: { state: "connection-ready" }, }), "configuring"); assert.equal(lifecycle.normalizeRuntimePhase({ ...supervisedConnectionState({ leaseState: "configured-unverified", controlAllowed: false, }), phase: "connected", }), "connected"); }); test("a released acquisition failure stays exact in the acquisition panel without poisoning global runtime", () => { const releasedFailure = { phase: "error", source_mode: "idle", acquisition: { state: "failed", cleanup_pending: false, }, application_control_session: { state: "idle", failure: { network_change_admissible: true, message: "control connection was lost after acknowledged stop", }, }, }; assert.equal(lifecycle.isReleasedTerminalAcquisitionFailure(releasedFailure), true); assert.equal(lifecycle.normalizeRuntimePhase(releasedFailure), "idle"); assert.equal(lifecycle.shouldSurfaceRuntimeActionError("live", releasedFailure), false); assert.equal(lifecycle.shouldSurfaceRuntimeActionError("control", releasedFailure), false); assert.equal(lifecycle.shouldSurfaceRuntimeActionError("scan", releasedFailure), true); assert.equal( lifecycle.authoritativeStateSupersedesRuntimeError( { action: "stop", runtimeId: "runtime-a", leaseGeneration: 4 }, releasedFailure, ), true, ); assert.equal( lifecycle.authoritativeStateSupersedesRuntimeError( { action: "scan", runtimeId: "runtime-a", leaseGeneration: 4 }, releasedFailure, ), false, ); assert.equal( lifecycle.isReleasedTerminalAcquisitionFailure({ ...releasedFailure, acquisition: { state: "failed", cleanup_pending: true }, }), false, ); assert.equal( lifecycle.isReleasedTerminalAcquisitionFailure({ ...releasedFailure, application_control_session: { state: "failed", failure: { network_change_admissible: false }, }, }), false, ); }); test("poll and WebSocket state acceptance clear stale runtime banners after local release", async () => { const runtimeSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/useXgridsK1Runtime.ts", import.meta.url, ), "utf8", ); assert.match(runtimeSource, /authoritativeStateSupersedesRuntimeError\(\s*errorCorrelation\.current,\s*acceptedState/); assert.match(runtimeSource, /openEventSocket\(acceptState/); }); test("observed SCANNING recovery is a successful STOP-only connection outcome", async () => { const recoveredScanning = { ...supervisedConnectionState({ mode: "bridge" }), connection_mode: "bridge", active_connection_mode: "bridge", application_control_session: { state: "scanning", can_stop: true, physical_command: { requires_reconciliation: false, resolved_active_recovery_required: true, observed_session_state: "scanning", }, }, }; assert.equal(lifecycle.isRecoveredPhysicalScanning(recoveredScanning, "bridge"), true); assert.equal( lifecycle.isRecoveredPhysicalScanning(recoveredScanning, "quick-connect"), false, ); const replayDuringPhysicalRecovery = { ...recoveredScanning, source_mode: "replay", compatibility: { vendor_writes_enabled: true, permitted_mode: "active-control", }, acquisition: { acquisition_id: "terminal-live-acquisition", device_id: "original-k1", device_session_id: "fresh-verified-session", project_name: null, compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", control_mode: "plugin-commanded", requested_streams: [], target_host: "192.168.68.52", evidence_policy: "disabled", state: "failed", state_revision: 9, cleanup_pending: false, result: { recovery_only: true, device_state: "scanning", automatic_replay_allowed: false, }, }, }; assert.equal( lifecycle.requiresCanonicalStopAfterTerminalLocalFailure(replayDuringPhysicalRecovery), true, ); const recoveredStopTarget = physicalCommandConfirmation.activeStopTarget( replayDuringPhysicalRecovery, ); assert.ok(recoveredStopTarget); assert.equal(recoveredStopTarget.acquisitionId, "terminal-live-acquisition"); assert.equal(recoveredStopTarget.deviceId, "original-k1"); assert.equal(recoveredStopTarget.fence.kind, "stop"); const runtimeSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/useXgridsK1Runtime.ts", import.meta.url, ), "utf8", ); const provisioningSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/components/K1ProvisioningPipeline.tsx", import.meta.url, ), "utf8", ); const acquisitionSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/components/K1AcquisitionPipeline.tsx", import.meta.url, ), "utf8", ); assert.match(runtimeSource, /requireExactReadOnlyVerificationOutcome/); assert.match(runtimeSource, /isRecoveredPhysicalScanning\(failedState, requestedConnectionMode\)/); assert.match(provisioningSource, /isPhysicalStopRecoverySettling\(state\)/); assert.match( provisioningSource, /const canScan = backendScanAllowed && !physicalStopRecoverySettling/, ); assert.doesNotMatch( provisioningSource, /K1 продолжает сканирование|Завершаем остановку K1/, ); assert.match(acquisitionSource, /recoveredPhysicalStop\s*\? "Требуется остановка"/); assert.match(acquisitionSource, /terminalPhysicalStopObserved\s*\? "warning"/); assert.match(acquisitionSource, /recoveredPhysicalStop \? "Сканирование продолжается"/); assert.match(acquisitionSource, /Нажмите «Остановить сканирование» ниже или в пространственной сцене/); assert.match( acquisitionSource, /canIssueCanonicalStop\(state, physicalStopIntentSpent\)/, ); assert.match( acquisitionSource, /physicalStopInFlight\s*\? "Останавливаем устройство…"/, ); assert.match( acquisitionSource, /: physicalStopPresented \? recoveredPhysicalStop \? "Остановить сканирование" : "Остановить устройство и запись"/, ); assert.ok( acquisitionSource.indexOf("terminalPhysicalStopObserved ? (") < acquisitionSource.indexOf("
"), "recovered SCANNING must render the STOP-only branch before project/START controls", ); }); test("K1 provisioning mutations require the operator's fresh BLE candidate", () => { const backendLease = { selected_device_id: "stale-backend-lease-device", connection_mode: "bridge", devices: [ { device_id: "fresh-scan-candidate", name: "K1 candidate", connectable: true, }, ], }; assert.equal( lifecycle.provisioningCandidateById(backendLease.devices, ""), null, ); assert.equal( lifecycle.provisioningCandidateById( backendLease.devices, backendLease.selected_device_id, ), null, ); assert.equal(lifecycle.canSubmitProvisioningMutation({ devices: backendLease.devices, selectedDeviceId: "expired-scan-candidate", credentialsReady: true, isBusy: false, }), false); assert.equal(lifecycle.canSubmitProvisioningMutation({ devices: backendLease.devices, selectedDeviceId: "fresh-scan-candidate", credentialsReady: true, isBusy: false, }), true); }); test("K1 connection status is green only for a reachable matching lease", () => { const legacyReachableLease = { k1_ip: "192.168.68.50", connection_mode: "bridge", connection_verification: { lease_state: "reachable", network_reachability: "reachable", }, }; const reachableLease = supervisedConnectionState(); assert.equal(lifecycle.isReachableConnectionLease(legacyReachableLease, "bridge"), false); assert.equal(lifecycle.isReachableConnectionLease(reachableLease, "bridge"), true); assert.equal(lifecycle.isReachableConnectionLease(reachableLease, "quick-connect"), false); assert.equal(lifecycle.isReachableConnectionLease({ k1_ip: "192.168.68.50", connection_mode: "bridge", }, "bridge"), false); assert.equal(lifecycle.isReachableConnectionLease({ k1_ip: "192.168.56.1", connection_mode: "quick-connect", connection_verification: { status: "control-transport-lost", lease_state: "disconnected", network_reachability: "unreachable", }, }, "quick-connect"), false); for (const mutate of [ (state) => { state.connection_supervisor.observed.device_network.state = "unconfigured"; }, (state) => { state.connection_supervisor.observed.device_network.intent_id = "stale-intent"; }, (state) => { state.connection_supervisor.observed.device_network.transport_ref = null; }, (state) => { state.connection_supervisor.observed.device_network.target = { ...state.connection_supervisor.observed.device_network.target, ipv4: "192.168.68.99", }; }, (state) => { state.connection_supervisor.observed.endpoint.intent_id = "stale-intent"; }, (state) => { state.connection_supervisor.observed.endpoint.host_path_epoch = 2; }, (state) => { state.connection_supervisor.observed.host_path.route_class = "default"; }, (state) => { state.connection_supervisor.observed.device_identity.intent_id = "stale-intent"; }, (state) => { state.connection_supervisor.observed.device_identity.host_path_epoch = 2; }, (state) => { state.connection_supervisor.observed.control_plane.host_path_epoch = 2; }, (state) => { state.connection_supervisor.observed.control_plane.session_id = null; }, (state) => { state.connection_supervisor.observed.endpoint.target = { ...state.connection_supervisor.observed.endpoint.target, ipv4: "192.168.68.99", }; }, ]) { const stale = structuredClone(reachableLease); mutate(stale); assert.equal(lifecycle.isReachableConnectionLease(stale, "bridge"), false); } }); test("frontend connection authority fails closed without the backend lifecycle projection", () => { const reachable = supervisedConnectionState(); assert.equal(lifecycle.isReachableConnectionLease(reachable, "bridge"), true); const omitted = structuredClone(reachable); delete omitted.connection_lifecycle; assert.equal(lifecycle.isReachableConnectionLease(omitted, "bridge"), false); assert.equal( lifecycle.currentAppliedConnectionTopology(omitted, "bridge")?.status, "configured-unverified", ); const drifted = structuredClone(reachable); drifted.connection_lifecycle.active_mode = "quick-connect"; assert.equal(lifecycle.isReachableConnectionLease(drifted, "bridge"), false); }); test("backend topology distinguishes reachable authority from last-known address", () => { const target = { ipv4: "192.168.56.1", port: 1883 }; const lastKnown = supervisedConnectionState({ mode: "quick-connect", target, leaseState: "lost", controlAllowed: false, deviceNetworkState: "unconfigured", lastKnown: { connection_mode: "quick-connect", target, logical_device_id: "device-k1-001", compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", verified_at: "2026-08-06T11:59:00Z", }, }); const configured = supervisedConnectionState({ mode: "quick-connect", target, leaseState: "configured-unverified", controlAllowed: false, }); const active = supervisedConnectionState({ mode: "quick-connect", target }); assert.deepEqual(lifecycle.backendConnectionTopology(lastKnown), { connectionMode: "quick-connect", status: "configured-offline", source: "last-known", endpoint: "192.168.56.1", }); assert.deepEqual(lifecycle.backendConnectionTopology(configured), { connectionMode: "quick-connect", status: "configured-unverified", source: "applied", endpoint: "192.168.56.1", }); assert.deepEqual(lifecycle.backendConnectionTopology(active), { connectionMode: "quick-connect", status: "active", source: "applied", endpoint: "192.168.56.1", }); assert.equal(lifecycle.activeConnectionEndpointLabel(lastKnown), null); assert.equal( lifecycle.activeConnectionEndpointLabel(active), "192.168.56.1", ); assert.equal(lifecycle.backendConnectionTopology({}), null); }); test("current BLE topology remains visible offline and supersedes durable history", () => { const currentOffline = supervisedConnectionState({ mode: "bridge", leaseState: "lost", controlAllowed: false, hostAvailable: false, endpointState: "unreachable", }); currentOffline.semantic_topology_store = { status: "available", configured_offline_evidence: true, live_connection_authority: false, reason_code: null, record: { schema_version: "missioncore.xgrids-k1-semantic-topology/v1", revision: 2, transport_ref: "ble-k1-old", connection_mode: "quick-connect", ipv4: "192.168.56.1", compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", firmware_version: "3.0.2", source: "ble-read-only-status", observed_at_utc: "2026-08-06T11:00:00Z", }, }; assert.deepEqual(lifecycle.backendConnectionTopology(currentOffline), { connectionMode: "bridge", status: "configured-offline", source: "applied", endpoint: "192.168.68.50", }); assert.equal(lifecycle.backendConnectionTopology(currentOffline, "quick-connect"), null); assert.equal(lifecycle.isReachableConnectionLease(currentOffline, "bridge"), false); assert.equal(lifecycle.isConfiguredConnectionLease(currentOffline, "bridge"), true); assert.equal(lifecycle.hasControlAuthority(currentOffline), false); assert.equal( lifecycle.normalizeRuntimePhase({ ...currentOffline, phase: "connected" }), "configuring", ); assert.equal(lifecycle.canonicalDeviceConnectivity(currentOffline), "offline"); }); test("durable semantic topology is configured-offline evidence, never authority", () => { const durable = { semantic_topology_store: { status: "available", configured_offline_evidence: true, live_connection_authority: false, reason_code: null, record: { schema_version: "missioncore.xgrids-k1-semantic-topology/v1", revision: 4, transport_ref: "ble-k1-001", connection_mode: "quick-connect", ipv4: "192.168.56.1", compatibility_profile_id: "xgrids.lixelkity-k1.fw-3.0.2.local-network.v2", firmware_version: "3.0.2", source: "ble-post-write-status", observed_at_utc: "2026-08-06T12:00:00Z", }, }, }; assert.deepEqual(lifecycle.backendConnectionTopology(durable), { connectionMode: "quick-connect", status: "configured-offline", source: "durable", endpoint: "192.168.56.1", }); assert.equal(lifecycle.isConfiguredConnectionLease(durable, "quick-connect"), true); assert.equal(lifecycle.isReachableConnectionLease(durable, "quick-connect"), false); assert.equal(lifecycle.hasControlAuthority(durable), false); assert.equal(lifecycle.normalizeRuntimePhase({ ...durable, phase: "connected" }), "configuring"); assert.equal(lifecycle.canonicalDeviceConnectivity(durable), "offline"); const hostProbed = structuredClone(durable); hostProbed.configured_endpoint_probe = { schema_version: "missioncore.xgrids-k1-configured-endpoint-probe/v1", status: "reachable", target_source: "durable-semantic-topology", connection_mode: "quick-connect", endpoint: "192.168.56.1", transport_ref: "ble-k1-001", intent_id: null, semantic_revision: 4, host_route_available: true, host_route_class: "direct", tcp_reachable: true, identity_validation: "not-performed", control_authority_granted: false, ble_operation_performed: false, network_mutation_performed: false, automatic_retry: false, observed_at: "2026-08-08T12:30:19Z", reason_code: null, }; assert.deepEqual(lifecycle.backendConnectionTopology(hostProbed), { connectionMode: "quick-connect", status: "configured-unverified", source: "durable", endpoint: "192.168.56.1", }); assert.equal(lifecycle.isReachableConnectionLease(hostProbed, "quick-connect"), false); assert.equal(lifecycle.hasControlAuthority(hostProbed), false); for (const status of ["empty", "corrupt"]) { const unavailable = structuredClone(durable); unavailable.semantic_topology_store.status = status; unavailable.semantic_topology_store.record = null; unavailable.semantic_topology_store.configured_offline_evidence = false; assert.equal(lifecycle.backendConnectionTopology(unavailable), null); } }); test("unresolved or corrupt durable mutation state remains a provisioning barrier", () => { assert.equal(lifecycle.hasUnresolvedNetworkMutation({}), false); assert.equal(lifecycle.hasUnresolvedNetworkMutation({ network_write_reconciliation: {} }), true); assert.equal(lifecycle.hasUnresolvedNetworkMutation({ network_mutation_ledger: { status: "unresolved", mutation_allowed: false }, }), true); assert.equal(lifecycle.hasUnresolvedNetworkMutation({ network_mutation_ledger: { status: "corrupt", mutation_allowed: false }, }), true); assert.equal(lifecycle.hasUnresolvedNetworkMutation({ network_mutation_ledger: { status: "resolved", mutation_allowed: true }, }), false); }); test("retained BLE context is never presence but can carry one backend-authorized recovery", () => { const activeQuick = { current_device_recovery: { transport_ref: "exact-session-handle", connection_mode: "quick-connect", handle_available: true, handle_retained: true, advertised_now: false, gatt_validated_recently: true, }, connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", allowed_actions: ["recover-current-device-network"], actions: { "recover-current-device-network": { allowed: true, reason_codes: [], target_source: "retained-current-process", required_transport_ref: "exact-session-handle", requires_live_gatt_validation: true, automatic_retry: false, }, }, facts: { retained_context_is_presence: false, }, }, }; assert.equal( lifecycle.currentDeviceTransportRef(activeQuick), "exact-session-handle", ); assert.deepEqual(lifecycle.retainedBleRecoveryTarget(activeQuick), { transportRef: "exact-session-handle", connectionMode: "quick-connect", gattValidatedRecently: true, }); assert.equal( lifecycle.provisioningCandidateById([], "exact-session-handle"), null, ); assert.equal( lifecycle.canSubmitProvisioningMutation({ devices: [], selectedDeviceId: "exact-session-handle", credentialsReady: true, isBusy: false, }), false, ); assert.equal( lifecycle.connectionPolicyAllows( activeQuick, "recover-current-device-network", ), true, ); assert.equal( lifecycle.connectionPolicyDecision( activeQuick, "recover-current-device-network", ).requires_live_gatt_validation, true, ); const freshlyObserved = { device_id: "exact-session-handle", name: "Lixel K1", connectable: true, }; assert.equal( lifecycle.provisioningCandidateById( [freshlyObserved], "exact-session-handle", ), freshlyObserved, ); assert.equal( lifecycle.canSubmitProvisioningMutation({ devices: [freshlyObserved], selectedDeviceId: "exact-session-handle", credentialsReady: true, isBusy: false, }), true, ); assert.equal(lifecycle.retainedBleRecoveryTarget({ current_device_recovery: { ...activeQuick.current_device_recovery, advertised_now: true, }, }), null); }); test("browser refresh never adopts an existing backend K1 session as selection", () => { const backendSession = { selected_device_id: "ble-k1-001", connection_mode: "bridge", device_session: { device_session_id: "device-session-001", device_id: "logical-k1-001", }, current_device_recovery: { transport_ref: "ble-k1-001", connection_mode: "bridge", handle_retained: true, }, }; assert.equal( lifecycle.locallyInitiatedBleSessionTarget(backendSession, null, "bridge"), null, ); assert.equal( lifecycle.locallyInitiatedBleSessionTarget( backendSession, "another-device", "bridge", ), null, ); assert.equal( lifecycle.locallyInitiatedBleSessionTarget( backendSession, "ble-k1-001", "quick-connect", ), null, ); }); test("a pending local connect cannot bind the old matching backend session", () => { const oldBackendSession = { selected_device_id: "ble-k1-001", connection_mode: "bridge", device_session: { device_session_id: "device-session-A", device_id: "logical-k1-001", }, current_device_recovery: { transport_ref: "ble-k1-001", connection_mode: "bridge", handle_retained: true, }, }; const oldTarget = lifecycle.bleSessionTargetForTransport( oldBackendSession, "ble-k1-001", "bridge", ); assert.equal(oldTarget?.key, "device-session-A:bridge:ble-k1-001"); assert.equal( lifecycle.locallyInitiatedBleSessionTarget( oldBackendSession, null, "bridge", ), null, "pending is not a successful local intent and grants no bind authority", ); assert.equal( lifecycle.acceptedBleSessionKeyAfterConnect( oldBackendSession, "ble-k1-001", "bridge", oldTarget.key, ), null, "the session that predated the click is not an accepted result", ); }); test("a successful local connect binds only the new matching backend session", () => { const backendSession = { selected_device_id: "ble-k1-001", connection_mode: "bridge", device_session: { device_session_id: "device-session-B", device_id: "logical-k1-001", }, current_device_recovery: { transport_ref: "ble-k1-001", connection_mode: "bridge", handle_retained: true, }, }; const acceptedSessionKey = lifecycle.acceptedBleSessionKeyAfterConnect( backendSession, "ble-k1-001", "bridge", "device-session-A:bridge:ble-k1-001", ); assert.equal(acceptedSessionKey, "device-session-B:bridge:ble-k1-001"); assert.deepEqual( lifecycle.locallyInitiatedBleSessionTarget( backendSession, "ble-k1-001", "bridge", { requiredSessionKey: acceptedSessionKey }, ), { transportRef: "ble-k1-001", connectionMode: "bridge", deviceSessionId: "device-session-B", key: "device-session-B:bridge:ble-k1-001", }, ); assert.equal( lifecycle.locallyInitiatedBleSessionTarget( { ...backendSession, device_session: { ...backendSession.device_session, device_session_id: "device-session-C", }, }, "ble-k1-001", "bridge", { requiredSessionKey: acceptedSessionKey }, ), null, "a later session cannot silently replace the accepted session B", ); assert.equal( lifecycle.locallyInitiatedBleSessionTarget( { ...backendSession, device_session: null }, "ble-k1-001", "bridge", { requiredSessionKey: acceptedSessionKey }, ), null, ); assert.equal( lifecycle.acceptedBleSessionKeyAfterConnect( { ...backendSession, device_session: null }, "ble-k1-001", "bridge", "device-session-A:bridge:ble-k1-001", ), null, "success without an exact returned session key is a clean reset", ); assert.equal( lifecycle.canAdmitProvisioningConnection({ policyAllowed: true, targetSource: "fresh-scan", hasSuccessfulLocalConnect: false, localPrerequisitesReady: true, }), true, "after the reset a fresh explicit scan selection can connect", ); }); test("an arbitrary BLE result set never selects or connects a device", () => { const devices = Array.from({ length: 20 }, (_, index) => ({ device_id: `ble-device-${String(index + 1).padStart(2, "0")}`, name: `BLE device ${index + 1}`, connectable: true, })); assert.equal(lifecycle.provisioningCandidateById(devices, ""), null); assert.equal( lifecycle.canSubmitProvisioningMutation({ devices, selectedDeviceId: "", credentialsReady: true, isBusy: false, }), false, ); }); test("connection policy remains authoritative when historical operations are present", () => { const state = { operations: [{ action: "network.provision", status: "running", operation_id: "historical-operation", }], connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", facts: { retained_context_is_presence: false }, allowed_actions: ["provision-fresh-device"], actions: { "provision-fresh-device": { allowed: true, reason_codes: [], target_source: "fresh-scan", required_transport_ref: null, requires_live_gatt_validation: true, automatic_retry: false, }, }, }, }; assert.equal( lifecycle.connectionPolicyAllows(state, "provision-fresh-device"), true, ); assert.equal( lifecycle.canAdmitProvisioningConnection({ policyAllowed: true, targetSource: "fresh-scan", hasSuccessfulLocalConnect: false, localPrerequisitesReady: true, }), true, ); }); test("legacy backend recovery evidence keeps exact UUID and mode outside UI admission", () => { const decision = (allowed, target_source, required_transport_ref, required_connection_mode) => ({ allowed, reason_codes: allowed ? [] : ["not-selected"], target_source, required_transport_ref, required_connection_mode, requires_live_gatt_validation: true, automatic_retry: false, }); const state = { ble_discovery_generation: 7, devices: [{ device_id: "fresh-policy-k1", name: "Lixel K1", connectable: true, }], network_mutation_ledger: { status: "unresolved", mutation_allowed: false, }, connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", allowed_actions: [ "observe-fresh-device-network", "observe-current-device-network", "observe-configured-device-network", ], actions: { "observe-fresh-device-network": decision( true, "fresh-scan", "fresh-policy-k1", "direct-connect", ), "observe-current-device-network": decision( true, "retained-current-process", "retained-policy-k1", "quick-connect", ), "observe-configured-device-network": decision( true, "durable-configured-state", "durable-policy-k1", "bridge", ), }, facts: { retained_context_is_presence: false }, }, }; assert.deepEqual( lifecycle.readOnlyConnectionObservationTarget( state, "different-browser-selection", "bridge", ), { action: "observe-fresh-device-network", deviceId: "fresh-policy-k1", connectionMode: "direct-connect", source: "fresh-scan", serverBound: true, expectedDiscoveryGeneration: 7, }, ); state.devices = []; state.connection_policy.allowed_actions = [ "observe-current-device-network", "observe-configured-device-network", ]; state.connection_policy.actions["observe-fresh-device-network"] = decision( false, "fresh-scan", "fresh-policy-k1", "direct-connect", ); assert.deepEqual( lifecycle.readOnlyConnectionObservationTarget( state, "stale-browser-selection", "direct-connect", ), { action: "observe-current-device-network", deviceId: "retained-policy-k1", connectionMode: "quick-connect", source: "retained-current-process", serverBound: true, expectedDiscoveryGeneration: null, }, ); assert.deepEqual( lifecycle.serverBoundAppliedNetworkObservationTarget(state, "quick-connect"), { action: "observe-current-device-network", deviceId: "retained-policy-k1", connectionMode: "quick-connect", source: "retained-current-process", serverBound: true, expectedDiscoveryGeneration: null, }, ); state.network_mutation_ledger = { status: "resolved", mutation_allowed: true, }; state.devices = [{ device_id: "durable-policy-k1", name: "Lixel K1", connectable: true, }]; state.connection_policy.allowed_actions = [ "observe-fresh-device-network", "observe-configured-device-network", ]; state.connection_policy.actions["observe-fresh-device-network"] = decision( true, "fresh-scan", null, null, ); state.connection_policy.actions["observe-current-device-network"] = decision( false, "retained-current-process", "retained-policy-k1", "quick-connect", ); assert.deepEqual( lifecycle.readOnlyConnectionObservationTarget( state, "stale-browser-selection", "direct-connect", ), { action: "observe-configured-device-network", deviceId: "durable-policy-k1", connectionMode: "bridge", source: "durable-configured-state", serverBound: true, expectedDiscoveryGeneration: null, }, ); assert.deepEqual( lifecycle.serverBoundAppliedNetworkObservationTarget(state, "bridge"), { action: "observe-configured-device-network", deviceId: "durable-policy-k1", connectionMode: "bridge", source: "durable-configured-state", serverBound: true, expectedDiscoveryGeneration: null, }, ); }); test("legacy unresolved backend evidence never falls back to stale browser state", () => { const state = { devices: [], network_mutation_ledger: { status: "unresolved", mutation_allowed: false, }, connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", allowed_actions: ["observe-configured-device-network"], actions: { "observe-configured-device-network": { allowed: true, reason_codes: [], target_source: "durable-configured-state", required_transport_ref: "durable-policy-k1", required_connection_mode: null, requires_live_gatt_validation: true, automatic_retry: false, }, }, facts: { retained_context_is_presence: false }, }, }; assert.equal( lifecycle.readOnlyConnectionObservationTarget( state, "stale-browser-k1", "quick-connect", ), null, ); }); test("local receiver cleanup never targets a replay session's retained acquisition", () => { assert.deepEqual(lifecycle.localReceiverStopPlan({ source_mode: "replay", acquisition: { acquisition_id: "terminal-live-acquisition", state: "completed", cleanup_pending: false, }, }), { kind: "compatibility" }); assert.deepEqual(lifecycle.localReceiverStopPlan({ source_mode: "idle", acquisition: { acquisition_id: " exact-cleanup-target ", state: "failed", cleanup_pending: true, }, }), { kind: "acquisition", acquisitionId: "exact-cleanup-target", }); assert.deepEqual(lifecycle.localReceiverStopPlan({ source_mode: "idle", acquisition: { acquisition_id: "released-terminal-acquisition", state: "failed", cleanup_pending: false, }, }), { kind: "compatibility" }); }); test("local receiver policy denial distinguishes proven idle from active cleanup", () => { assert.equal(lifecycle.isProvenLocalReceiverInactive({ source_mode: "idle", acquisition: null, }), true); assert.equal(lifecycle.isProvenLocalReceiverInactive({ source_mode: "idle", acquisition: { state: "failed", cleanup_pending: false, }, }), true); assert.equal(lifecycle.isProvenLocalReceiverInactive({ source_mode: "idle", acquisition: { state: "failed", cleanup_pending: true, }, }), false); assert.equal(lifecycle.isProvenLocalReceiverInactive({ source_mode: "live", acquisition: { state: "acquiring", cleanup_pending: false, }, }), false); assert.equal(lifecycle.isProvenLocalReceiverInactive({ source_mode: "replay", acquisition: { state: "completed", cleanup_pending: false, }, }), false); }); test("trusted K1 recovery uses only one exact backend-owned device and mode", () => { const state = { physical_command: { status: "unresolved", requires_reconciliation: true, resolved_active_recovery_required: false, }, connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", allowed_actions: ["observe-configured-device-network"], actions: { "provision-fresh-device": { allowed: false, reason_codes: ["physical-command-reconciliation-required"], target_source: "fresh-scan", required_transport_ref: "physical-k1", required_connection_mode: "bridge", requires_live_gatt_validation: true, automatic_retry: false, }, "observe-configured-device-network": { allowed: true, reason_codes: [], target_source: "durable-configured-state", required_transport_ref: "physical-k1", required_connection_mode: "bridge", requires_live_gatt_validation: true, automatic_retry: false, }, }, facts: { retained_context_is_presence: false }, }, semantic_topology_store: { record: { transport_ref: "semantic-k1", connection_mode: "quick-connect", }, }, current_device_recovery: { transport_ref: "process-k1", connection_mode: "direct-connect", }, }; assert.deepEqual(lifecycle.trustedConnectionBinding(state), { deviceId: "physical-k1", connectionMode: "bridge", }); delete state.connection_policy.actions["provision-fresh-device"]; state.physical_command.requires_reconciliation = false; assert.deepEqual(lifecycle.trustedConnectionBinding(state), { deviceId: "semantic-k1", connectionMode: "quick-connect", }); state.semantic_topology_store.record.connection_mode = null; assert.deepEqual(lifecycle.trustedConnectionBinding(state), { deviceId: "process-k1", connectionMode: "direct-connect", }); state.current_device_recovery.connection_mode = null; assert.equal(lifecycle.trustedConnectionBinding(state), null); }); test("only an unresolved durable STOP blocks connection controls during backend cleanup", () => { const unresolvedStop = { source_mode: "live", acquisition: { state: "stopping", cleanup_pending: true, }, application_control_session: { state: "awaiting-standby-confirmation", physical_command: { status: "unresolved", requires_reconciliation: true, record: { action: "stop", stage: "requested", resolution: null, }, }, }, }; assert.equal(lifecycle.isPhysicalStopRecoverySettling(unresolvedStop), true); const boundedTimeout = structuredClone(unresolvedStop); boundedTimeout.source_mode = "idle"; boundedTimeout.acquisition.state = "failed"; boundedTimeout.acquisition.cleanup_pending = false; boundedTimeout.operations = [{ action: "acquisition.stop", status: "timed_out", }]; // The durable physical ledger remains intentionally unresolved, but all // local work is released. The connection screen must leave the STOP loader // and may start the separate bounded connection recovery path. assert.equal(lifecycle.isPhysicalStopRecoverySettling(boundedTimeout), false); const backendObservedStandby = structuredClone(unresolvedStop); backendObservedStandby.application_control_session.state = "idle"; backendObservedStandby.application_control_session.physical_command.status = "resolved"; backendObservedStandby.application_control_session.physical_command.requires_reconciliation = false; backendObservedStandby.application_control_session.physical_command.record.stage = "resolved"; backendObservedStandby.application_control_session.physical_command.record.resolution = "stop-standby-observed"; assert.equal( lifecycle.isPhysicalStopRecoverySettling(backendObservedStandby), false, ); const unresolvedStart = structuredClone(unresolvedStop); unresolvedStart.application_control_session.physical_command.record.action = "start"; assert.equal(lifecycle.isPhysicalStopRecoverySettling(unresolvedStart), false); }); test("physical recovery stays pinned to the original K1 across a multi-device BLE scan", () => { const state = { physical_command: { status: "unresolved", requires_reconciliation: true, resolved_active_recovery_required: false, }, ble_discovery_generation: 9, devices: [ { device_id: "nearby-other-k1", name: "Nearby K1", connectable: true }, { device_id: "original-k1", name: "Original K1", connectable: true }, ], connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", allowed_actions: ["scan-ble", "observe-fresh-device-network"], actions: { "provision-fresh-device": { allowed: false, reason_codes: ["physical-device-already-active"], target_source: "fresh-scan", required_transport_ref: "original-k1", required_connection_mode: "bridge", requires_live_gatt_validation: true, automatic_retry: false, }, "observe-fresh-device-network": { allowed: true, reason_codes: [], target_source: "fresh-scan", required_transport_ref: "original-k1", required_connection_mode: "bridge", requires_live_gatt_validation: true, automatic_retry: false, }, }, facts: { retained_context_is_presence: false }, }, }; assert.equal(lifecycle.requiresReadOnlyPhysicalRecovery(state), true); assert.deepEqual(lifecycle.readOnlyPhysicalRecoveryBinding(state), { deviceId: "original-k1", connectionMode: "bridge", }); assert.deepEqual( lifecycle.readOnlyConnectionObservationTarget( state, "nearby-other-k1", "quick-connect", ), { action: "observe-fresh-device-network", deviceId: "original-k1", connectionMode: "bridge", source: "fresh-scan", serverBound: true, expectedDiscoveryGeneration: 9, }, ); state.devices = [{ device_id: "nearby-other-k1", name: "Nearby K1", connectable: true }]; assert.equal( lifecycle.readOnlyConnectionObservationTarget( state, "nearby-other-k1", "quick-connect", ), null, "another nearby K1 must not become a fallback recovery target", ); }); test("READY-classified STOP exits recovery UI while START follows backend authority", () => { const readyPhysical = { status: "resolved", reason_code: null, requires_reconciliation: false, resolved_active_recovery_required: false, observed_session_state: "ready", record: { action: "stop", stage: "resolved", resolution: "not-dispatched", reconciled_physical_state: "standby", }, }; const readySuccessor = { physical_command: readyPhysical, application_control_session: { physical_command: readyPhysical, }, connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", allowed_actions: ["start-acquisition"], actions: { "start-acquisition": { allowed: true, reason_codes: [], target_source: "durable-physical-command", required_transport_ref: "original-k1", required_connection_mode: "bridge", requires_live_gatt_validation: true, automatic_retry: false, }, "provision-fresh-device": { allowed: false, reason_codes: ["physical-command-reconciliation-required"], target_source: "fresh-scan", required_transport_ref: "original-k1", required_connection_mode: "bridge", requires_live_gatt_validation: true, automatic_retry: false, }, }, facts: { retained_context_is_presence: false }, }, connection_lifecycle: { schema_version: "missioncore.xgrids-k1-connection-lifecycle/v1", mode_selection: { allowed: false, reason_codes: ["connection-mode-selection-physical-state-unsafe"], automatic_retry: false, }, allowed_actions: ["start-acquisition"], }, }; assert.equal(lifecycle.requiresReadOnlyPhysicalRecovery(readySuccessor), false); assert.equal(lifecycle.connectionPolicyAllows(readySuccessor, "start-acquisition"), true); assert.equal( lifecycle.connectionPolicyAllows(readySuccessor, "provision-fresh-device"), false, "the exact successor binding remains pinned against network mutation", ); assert.equal( lifecycle.canSelectConnectionMode(readySuccessor), false, "the exact successor binding remains pinned against mode changes", ); const unresolved = structuredClone(readySuccessor); unresolved.application_control_session.physical_command.requires_reconciliation = true; assert.equal(lifecycle.requiresReadOnlyPhysicalRecovery(unresolved), true); const scanOver = structuredClone(readySuccessor); scanOver.application_control_session.physical_command.requires_reconciliation = true; scanOver.application_control_session.physical_command.resolved_scan_over_recovery_required = true; assert.equal(lifecycle.requiresReadOnlyPhysicalRecovery(scanOver), true); const reconciledActive = structuredClone(readySuccessor); reconciledActive.application_control_session.physical_command.resolved_active_recovery_required = true; reconciledActive.application_control_session.physical_command.observed_session_state = "scanning"; assert.equal(lifecycle.requiresReadOnlyPhysicalRecovery(reconciledActive), true); const reopened = structuredClone(readySuccessor); reopened.application_control_session.physical_command.resolved_active_recovery_required = true; reopened.application_control_session.physical_command.reopened_physical_state_recovery_required = true; assert.equal(lifecycle.requiresReadOnlyPhysicalRecovery(reopened), true); }); test("only a newer authoritative reachable lease resolves connection errors", () => { const error = { action: "connect", runtimeId: "runtime-a", leaseGeneration: 4, }; const reachableBridge = supervisedConnectionState({ generation: 5 }); assert.equal( lifecycle.authoritativeReachableLeaseSupersedesError(error, reachableBridge), true, ); assert.equal( lifecycle.authoritativeReachableLeaseSupersedesError( { ...error, action: "scan" }, reachableBridge, ), false, ); assert.equal( lifecycle.authoritativeReachableLeaseSupersedesError( error, supervisedConnectionState({ generation: 4 }), ), false, ); assert.equal( lifecycle.authoritativeReachableLeaseSupersedesError( error, { ...reachableBridge, network_write_reconciliation: {} }, ), false, ); assert.equal( lifecycle.authoritativeReachableLeaseSupersedesError( error, { ...reachableBridge, snapshot_runtime_id: "runtime-b" }, ), false, ); }); test("connection-mode reset is explicit and CAS-fenced before the next flow", async () => { const pipelineSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/components/K1ProvisioningPipeline.tsx", import.meta.url, ), "utf8", ); const connectionSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/XgridsK1Connection.tsx", import.meta.url, ), "utf8", ); assert.doesNotMatch(pipelineSource, /nextReachableConnectionModeSynchronization/); assert.doesNotMatch(pipelineSource, /synchronizedLeaseKeyRef/); assert.doesNotMatch(pipelineSource, /setConnectionMode\(/); assert.match(connectionSource, /state\.desired_connection_mode/); assert.doesNotMatch(connectionSource, /selectConnectionMode\(\{/); assert.match(connectionSource, /desiredModeLocallyDirty\.current = mode !== state\?\.desired_connection_mode/); assert.match(connectionSource, /setDesiredConnectionMode\(mode\)/); const localModeChange = pipelineSource.slice( pipelineSource.indexOf("const changeDesiredConnectionMode"), pipelineSource.indexOf("const selectFreshDevice"), ); const explicitModeCommit = pipelineSource.slice( pipelineSource.indexOf("const commitDesiredModeForExplicitAction"), pipelineSource.indexOf("const currentPreparingReconfigurationRequest"), ); assert.match(localModeChange, /await selectConnectionMode\(\{/); assert.match(localModeChange, /expected_revision: expectedRevision as number/); assert.match(localModeChange, /reset_scenario: true/); assert.match(localModeChange, /reset_id: resetId/); assert.doesNotMatch( localModeChange, /scanWithResult\(|connect\(|verifyConnection\(|prepareConnection/, ); assert.match(explicitModeCommit, /selectConnectionMode\(\{/); assert.match(explicitModeCommit, /expected_revision: expectedRevision as number/); assert.match( pipelineSource, /const repeatDeviceScan[\s\S]*?await commitDesiredModeForExplicitAction\(\)/, ); assert.match( pipelineSource, /const submitConnect[\s\S]*?await commitDesiredModeForExplicitAction\(\)/, ); }); test("connection-mode selector follows the authoritative backend admission", () => { const ready = supervisedConnectionState({ connectionReady: true }); assert.equal(lifecycle.canSelectConnectionMode(ready), true); const prepared = structuredClone(ready); prepared.acquisition = { acquisition_id: "acq-prepared", state: "prepared", project_name: "TEST001", }; assert.equal(lifecycle.canSelectConnectionMode(prepared), true); for (const reasonCode of [ "connection-mode-selection-control-state-unsafe", "connection-mode-selection-acquisition-active", "connection-mode-selection-physical-state-unsafe", ]) { const blocked = structuredClone(ready); blocked.connection_lifecycle.mode_selection = { allowed: false, reason_codes: [reasonCode], automatic_retry: false, }; blocked.connection_lifecycle.allowed_actions = ["start-acquisition"]; assert.equal(lifecycle.canSelectConnectionMode(blocked), false); } const drifted = structuredClone(ready); drifted.connection_lifecycle.allowed_actions = ["start-acquisition"]; assert.equal(lifecycle.canSelectConnectionMode(drifted), false); assert.equal(lifecycle.canSelectConnectionMode({}), false); }); test("prepared project survives a mode draft and its cancellation", () => { assert.equal(projectName.shouldHydratePreparedProject({ acquisitionId: "acq-prepared", hydratedAcquisitionId: null, modeSwitchRequired: false, }), true); let displayedProject = projectName.projectNameAfterConnectionModeSelection("TEST001"); assert.equal(displayedProject, "TEST001"); assert.equal(projectName.validateProjectName(displayedProject).error, null); assert.equal(projectName.shouldHydratePreparedProject({ acquisitionId: "acq-prepared", hydratedAcquisitionId: "acq-prepared", modeSwitchRequired: true, }), false); displayedProject = projectName.projectNameAfterConnectionModeSelection("TEST001"); assert.equal(displayedProject, "TEST001"); assert.equal(projectName.validateProjectName(displayedProject).error, null); assert.equal(projectName.shouldHydratePreparedProject({ acquisitionId: "acq-prepared", hydratedAcquisitionId: "acq-prepared", modeSwitchRequired: false, }), true); assert.equal(projectName.projectNameAfterConnectionModeSelection(null), ""); }); test("one in-flight provisioning call keeps its idempotency key internally", () => { let created = 0; const createUuid = () => { created += 1; return "11111111-1111-4111-8111-111111111111"; }; const first = lifecycle.provisioningIntentKey(null, createUuid); const repeated = lifecycle.provisioningIntentKey(first, createUuid); const failedOperation = { status: "failed", error: { safe_to_retry: false, side_effect_status: "unknown" }, }; const safePreWriteFailure = { status: "failed", error: { safe_to_retry: true, side_effect_status: "none" }, }; assert.equal(first, "network-provision:11111111-1111-4111-8111-111111111111"); assert.equal(repeated, first); assert.equal(created, 1); assert.equal(lifecycle.operationNeedsReconciliation(failedOperation), true); assert.equal( lifecycle.operationAllowsFreshProvisioningIntent(safePreWriteFailure), true, ); assert.equal( lifecycle.operationAllowsFreshProvisioningIntent(failedOperation), false, ); }); test("read-only verification releases only a durably resolved matching write fence", () => { const fence = { operation_id: "op-ambiguous", transport_ref: "k1-a", }; const before = { snapshot_runtime_id: "runtime-a", network_write_reconciliation: fence, }; const resolvedLedger = { status: "resolved", mutation_allowed: true, operation_id: "op-ambiguous", stage: "resolved", resolution: "target-observed", }; assert.equal( lifecycle.readOnlyVerificationClearedReconciliation( before, { snapshot_runtime_id: "runtime-restarted", network_write_reconciliation: null, network_mutation_ledger: resolvedLedger, }, "k1-a", ), true, ); assert.equal( lifecycle.readOnlyVerificationClearedReconciliation( before, { network_write_reconciliation: null, network_mutation_ledger: { status: "empty", mutation_allowed: true, operation_id: null, stage: null, resolution: null, }, }, "k1-a", ), true, ); assert.equal( lifecycle.readOnlyVerificationClearedReconciliation(before, {}, "k1-a"), false, ); assert.equal( lifecycle.readOnlyVerificationClearedReconciliation( before, { network_write_reconciliation: fence, network_mutation_ledger: { ...resolvedLedger, status: "unresolved", mutation_allowed: false, stage: "observing", resolution: null, }, }, "k1-a", ), false, ); assert.equal( lifecycle.readOnlyVerificationClearedReconciliation( before, { network_write_reconciliation: null, network_mutation_ledger: resolvedLedger, }, "k1-b", ), false, ); assert.equal( lifecycle.readOnlyVerificationClearedReconciliation( before, { network_write_reconciliation: null, network_mutation_ledger: { ...resolvedLedger, operation_id: "op-different", }, }, "k1-a", ), false, ); assert.equal( lifecycle.readOnlyVerificationClearedReconciliation( before, { network_write_reconciliation: null, network_mutation_ledger: { ...resolvedLedger, resolution: null, }, }, "k1-a", ), false, ); }); test("each terminal explicit provisioning click starts a fresh operation identity", async () => { const hookSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/useXgridsK1Runtime.ts", import.meta.url, ), "utf8", ); const pipelineSource = await readFile( new URL( "../../../plugins/xgrids-k1/frontend/src/components/K1ProvisioningPipeline.tsx", import.meta.url, ), "utf8", ); const connectRecovery = hookSource.slice( hookSource.indexOf("const connect = useCallback"), hookSource.indexOf("const verifyConnection = useCallback"), ); const submitConnect = pipelineSource.slice( pipelineSource.indexOf("const submitConnect = async"), pipelineSource.indexOf("return (", pipelineSource.indexOf("const submitConnect = async")), ); assert.match( connectRecovery, /failedOperation\?\.status === "succeeded"[\s\S]*?!exactAppliedNetworkIntentCompleted\([\s\S]*?&& !hasExactConnectionReady/, ); assert.match( connectRecovery, /const exactNetworkIntentCompleted = exactAppliedNetworkIntentCompleted\([\s\S]*?nextState = acceptSuccessfulConnectState\(nextState\)/, ); assert.match(connectRecovery, /acceptedBleSessionKeyAfterConnect\(/); assert.match( connectRecovery, /acceptedSessionKey:\s*networkIntentCompleted \? acceptedSessionKey : null/, ); assert.match(submitConnect, /provisioningIntentKey\(null\)/); assert.doesNotMatch(submitConnect, /provisioningIntentRef/); assert.match( submitConnect, /const freshStartAllowed = result\.intentDisposition === "release"/, ); assert.match( submitConnect, /setExplicitProvisioningDraft\(null\);[\s\S]*?setPassword\(""\);[\s\S]*?await connect\(/, ); assert.match(submitConnect, /setSelectedDeviceSnapshot\(null\)/); assert.doesNotMatch(pipelineSource, /Проверить K1 без записи/); }); test("device mutations send explicit nested compatibility attestation", async () => { const originalFetch = globalThis.fetch; const calls = []; const syntheticCredential = "x".repeat(32); globalThis.fetch = async (path, init) => { calls.push({ path, init }); return new Response(JSON.stringify({ state: { source_mode: "idle" } }), { status: 200, headers: { "Content-Type": "application/json" }, }); }; const attestation = { firmware_version: "3.0.2", topology: "direct-lan", verification: "live-device-info", }; try { await xgridsK1Api.connect({ expected_snapshot_runtime_id: "snapshot-runtime-test", device_id: "ble-device", ssid: "lab-network", password: syntheticCredential, connection_mode: "bridge", compatibility_attestation: attestation, idempotency_key: "network-provision:test", expected_mode_revision: 4, expected_discovery_generation: 9, }); await xgridsK1Api.prepareAcquisition({ project_name: "Mission 01", mount_type: "handheld", gnss_mode: "none", compatibility_attestation: attestation, }); } finally { globalThis.fetch = originalFetch; } assert.equal(calls.length, 2); const provisioning = JSON.parse(calls[0].init.body); const prepare = JSON.parse(calls[1].init.body); assert.deepEqual(provisioning.input.compatibility_attestation, attestation); assert.equal(provisioning.input.idempotency_key, "network-provision:test"); assert.equal(provisioning.input.expected_mode_revision, 4); assert.equal(provisioning.input.expected_discovery_generation, 9); assert.equal( provisioning.input.expected_snapshot_runtime_id, "snapshot-runtime-test", ); assert.deepEqual(prepare.input.compatibility_attestation, attestation); assert.equal(prepare.input.project_name, "Mission 01"); }); test("endpoint probing is separate from BLE refresh and read-only adoption", async () => { const originalFetch = globalThis.fetch; const calls = []; globalThis.fetch = async (path, init) => { calls.push({ path, init }); return new Response(JSON.stringify({ state: { source_mode: "idle" } }), { status: 200, headers: { "Content-Type": "application/json" }, }); }; const attestation = { firmware_version: "3.0.2", topology: "direct-lan", verification: "live-device-info", }; try { await xgridsK1Api.verifyConnection({ expected_snapshot_runtime_id: "snapshot-runtime-test", device_id: "fresh-ble-device", source: "fresh-scan", compatibility_attestation: attestation, expected_discovery_generation: 11, }); await xgridsK1Api.verifyConnection({ expected_snapshot_runtime_id: "snapshot-runtime-test", device_id: "durable-ble-device", source: "durable-configured-state", compatibility_attestation: attestation, }); await xgridsK1Api.probeConfiguredEndpoint({ expected_snapshot_runtime_id: "snapshot-runtime-test", }); } finally { globalThis.fetch = originalFetch; } assert.equal(calls.length, 3); assert.match(String(calls[0].path), /actions\/connection\.verify$/); const adoption = JSON.parse(calls[0].init.body).input; assert.deepEqual(adoption, { expected_snapshot_runtime_id: "snapshot-runtime-test", device_id: "fresh-ble-device", source: "fresh-scan", compatibility_attestation: attestation, expected_discovery_generation: 11, }); assert.equal("ssid" in adoption, false); assert.equal("password" in adoption, false); assert.equal("connection_mode" in adoption, false); const durableAdoption = JSON.parse(calls[1].init.body).input; assert.deepEqual(durableAdoption, { expected_snapshot_runtime_id: "snapshot-runtime-test", device_id: "durable-ble-device", source: "durable-configured-state", compatibility_attestation: attestation, }); assert.equal("expected_discovery_generation" in durableAdoption, false); assert.match(String(calls[2].path), /actions\/connection\.endpoint-probe$/); assert.deepEqual(JSON.parse(calls[2].init.body), { input: { expected_snapshot_runtime_id: "snapshot-runtime-test" }, }); }); test("connection verification accepts only the backend literal status and lease contract", () => { const statuses = [ "not-probed", "device-network-applied", "device-network-applied-host-failed", "adopted", "host-route-mismatch", "endpoint-unreachable", "tcp-reachable-device-info-unverified", "reachable", "recovered", "control-transport-lost", "unreachable", ]; const leaseStates = ["disconnected", "configured-unverified", "reachable"]; assert.deepEqual([...XGRIDS_CONNECTION_VERIFICATION_STATUSES], statuses); assert.deepEqual([...XGRIDS_CONNECTION_VERIFICATION_LEASE_STATES], leaseStates); const exact = { status: "not-probed", lease_state: "disconnected", lease_generation: 0, supervisor_revision: 1, endpoint_validation: "not-performed", network_reachability: "unknown", observed_at: null, }; for (const status of statuses) { assert.equal(isXgridsConnectionVerification({ ...exact, status }), true, status); } for (const lease_state of leaseStates) { assert.equal( isXgridsConnectionVerification({ ...exact, lease_state }), true, lease_state, ); } for (const malformed of [ { ...exact, status: "configured" }, { ...exact, lease_state: "lost" }, { ...exact, lease_generation: -1 }, { ...exact, supervisor_revision: 1.25 }, { ...exact, network_reachability: "degraded" }, { ...exact, observed_at: 123 }, Object.fromEntries(Object.entries(exact).filter(([key]) => key !== "status")), Object.fromEntries(Object.entries(exact).filter(([key]) => key !== "lease_state")), ]) { assert.equal(isXgridsConnectionVerification(malformed), false); } }); test("connection policy accepts the exact restart-recovery actions, sources and modes", () => { assert.deepEqual([...XGRIDS_CONNECTION_POLICY_ACTIONS], [ "scan-ble", "provision-fresh-device", "prepare-select-device", "prepare-change-network", "cancel-reconfiguration", "recover-current-device-network", "observe-fresh-device-network", "observe-current-device-network", "observe-configured-device-network", "inspect-configured-endpoint", "inspect-host-network", "probe-endpoint", "verify-control-device-info", "start-acquisition", "stop-acquisition", "stop-local-receiver", "retire-unavailable-physical-target", "acknowledge-data-loss", ]); assert.deepEqual([...XGRIDS_CONNECTION_POLICY_TARGET_SOURCES], [ "none", "fresh-scan", "retained-current-process", "durable-configured-state", "configured-topology", "connection-supervisor", "local-runtime", "local-prestart-handoff", "local-reconfiguration-intent", "durable-physical-command", ]); const retainedDecision = { allowed: true, reason_codes: [], target_source: "retained-current-process", required_transport_ref: "9AE978F2-37A8-4B4B-9BCD-BD7010BB20D1", required_connection_mode: "quick-connect", requires_live_gatt_validation: true, automatic_retry: false, }; const durableDecision = { ...retainedDecision, target_source: "durable-configured-state", required_transport_ref: "0CA8AB68-E37B-46A2-B09F-C34B5C49428C", required_connection_mode: "bridge", }; const policy = { schema_version: "missioncore.xgrids-k1-connection-policy/v1", supervisor_revision: 17, network_ledger_revision: 4, recommended_action: "observe-current-device-network", allowed_actions: [ "observe-current-device-network", "observe-configured-device-network", ], actions: { "observe-current-device-network": retainedDecision, "observe-configured-device-network": durableDecision, }, facts: { retained_context_is_presence: false }, }; assert.equal(isXgridsConnectionPolicyDecision(retainedDecision), true); assert.equal(isXgridsConnectionPolicy(policy), true); const retirementDecision = { allowed: true, reason_codes: [], target_source: "durable-physical-command", required_transport_ref: "0CA8AB68-E37B-46A2-B09F-C34B5C49428C", required_connection_mode: "bridge", requires_live_gatt_validation: false, physical_command_allowed: false, physical_outcome: "unknown", device_write_performed: false, automatic_retry: false, }; assert.equal(isXgridsConnectionPolicyDecision(retirementDecision), true); assert.equal(isXgridsConnectionPolicy({ ...policy, recommended_action: "retire-unavailable-physical-target", allowed_actions: ["retire-unavailable-physical-target"], actions: { "retire-unavailable-physical-target": retirementDecision, }, }), true); for (const malformedRetirement of [ { ...retirementDecision, target_source: "durable-configured-state" }, { ...retirementDecision, physical_command_allowed: undefined }, { ...retirementDecision, physical_outcome: undefined }, { ...retirementDecision, device_write_performed: undefined }, { ...retirementDecision, requires_live_gatt_validation: true }, ]) { assert.equal(isXgridsConnectionPolicy({ ...policy, recommended_action: "retire-unavailable-physical-target", allowed_actions: ["retire-unavailable-physical-target"], actions: { "retire-unavailable-physical-target": malformedRetirement, }, }), false); } assert.equal( isXgridsConnectionPolicyDecision({ ...retainedDecision, required_connection_mode: undefined, }), true, "older decisions may omit the optional mode field", ); for (const malformed of [ { ...retainedDecision, target_source: "server-cache" }, { ...retainedDecision, required_connection_mode: "automatic" }, { ...retainedDecision, automatic_retry: true }, ]) { assert.equal(isXgridsConnectionPolicyDecision(malformed), false); } assert.equal(isXgridsConnectionPolicy({ ...policy, actions: { ...policy.actions, "observe-current-device-network": { ...retainedDecision, required_connection_mode: undefined, }, }, }), false, "an allowed retained recovery must pin its mode"); assert.equal(isXgridsConnectionPolicy({ ...policy, actions: { ...policy.actions, "observe-configured-device-network": { ...durableDecision, target_source: "configured-topology", }, }, }), false, "durable recovery cannot drift to an endpoint-only source"); }); test("connection reconfiguration accepts only the exact resumable v1 projection", () => { const exact = { schema_version: "missioncore.xgrids-k1-connection-reconfiguration/v1", revision: 4, intent_id: "connection-reconfigure-001", intent: "change-network", status: "fresh-scan-completed", required_transport_ref: "BLE-DEVICE-001", required_connection_mode: "bridge", minimum_discovery_generation: 10, fresh_discovery_generation: 10, required_transport_observed: true, prepared_at: "2026-08-10T12:00:00Z", automatic_retry: false, }; assert.equal(isXgridsConnectionReconfiguration(exact), true); assert.equal(isXgridsConnectionReconfiguration({ ...exact, status: "idle", intent: null, intent_id: null, required_transport_ref: null, required_connection_mode: null, minimum_discovery_generation: null, fresh_discovery_generation: null, required_transport_observed: null, prepared_at: null, }), true); for (const malformed of [ { ...exact, revision: -1 }, { ...exact, intent: "cancel" }, { ...exact, status: "scanning" }, { ...exact, required_connection_mode: "bluetooth" }, { ...exact, automatic_retry: true }, { ...exact, intent_id: null }, ]) { assert.equal(isXgridsConnectionReconfiguration(malformed), false); } }); test("connection attempt phase distinguishes no write from an unknown write outcome", async () => { assert.deepEqual([...XGRIDS_CONNECTION_ATTEMPT_PHASES], [ "network_applied", "network_not_applied", "network_outcome_unknown", ]); for (const phase of XGRIDS_CONNECTION_ATTEMPT_PHASES) { assert.equal(isXgridsConnectionAttemptPhase(phase), true, phase); } for (const phase of [ "network_write_failed", "network_not_confirmed", "outcome_unknown", null, ]) { assert.equal(isXgridsConnectionAttemptPhase(phase), false, String(phase)); } const originalFetch = globalThis.fetch; globalThis.fetch = async () => new Response(JSON.stringify({ state: { source_mode: "idle", connection_attempt: { schema_version: "missioncore.xgrids-k1-connection-attempt/v1", phase: "network_outcome_unknown", automatic_retry: false, }, }, }), { status: 200, headers: { "Content-Type": "application/json" }, }); try { const state = await xgridsK1Api.getState(); assert.equal(state.connection_attempt.phase, "network_outcome_unknown"); } finally { globalThis.fetch = originalFetch; } }); test("state API rejects an unreviewed connection attempt phase", async () => { const originalFetch = globalThis.fetch; globalThis.fetch = async () => new Response(JSON.stringify({ state: { source_mode: "idle", connection_attempt: { schema_version: "missioncore.xgrids-k1-connection-attempt/v1", phase: "network_write_failed", automatic_retry: false, }, }, }), { status: 200, headers: { "Content-Type": "application/json" }, }); try { await assert.rejects( xgridsK1Api.getState(), (error) => error instanceof ApiError && error.message === "Локальный сервер вернул некорректное состояние.", ); } finally { globalThis.fetch = originalFetch; } }); test("state API rejects a drifted connection verification object at runtime", async () => { const originalFetch = globalThis.fetch; globalThis.fetch = async () => new Response(JSON.stringify({ state: { source_mode: "idle", connection_verification: { status: "configured", lease_state: "lost", lease_generation: 1, supervisor_revision: 2, endpoint_validation: "not-performed", network_reachability: "degraded", observed_at: null, }, }, }), { status: 200, headers: { "Content-Type": "application/json" }, }); try { await assert.rejects( xgridsK1Api.getState(), (error) => error instanceof ApiError && error.message === "Локальный сервер вернул некорректное состояние.", ); } finally { globalThis.fetch = originalFetch; } }); test("state API rejects a drifted restart-recovery policy at runtime", async () => { const originalFetch = globalThis.fetch; globalThis.fetch = async () => new Response(JSON.stringify({ state: { source_mode: "idle", connection_policy: { schema_version: "missioncore.xgrids-k1-connection-policy/v1", supervisor_revision: 5, network_ledger_revision: 3, recommended_action: "observe-configured-device-network", allowed_actions: ["observe-configured-device-network"], actions: { "observe-configured-device-network": { allowed: true, reason_codes: [], target_source: "durable-configured-state", required_transport_ref: "exact-k1", required_connection_mode: "automatic", requires_live_gatt_validation: true, automatic_retry: false, }, }, facts: { retained_context_is_presence: false }, }, }, }), { status: 200, headers: { "Content-Type": "application/json" }, }); try { await assert.rejects( xgridsK1Api.getState(), (error) => error instanceof ApiError && error.message === "Локальный сервер вернул некорректное состояние.", ); } finally { globalThis.fetch = originalFetch; } }); test("host diagnostic guard rejects every unreviewed literal dimension", () => { const exact = { schema_version: "missioncore.host-failure-diagnostic/v1", code: "host.keychain.interaction-required", domain: "keychain", impact: "control", operator_action: "unlock-or-authorize-keychain", automatic_retry: false, redacted: true, }; assert.equal(isXgridsHostFailureDiagnostic(exact), true); for (const malformed of [ { ...exact, code: "PermissionError: private" }, { ...exact, domain: "python-runtime" }, { ...exact, impact: "unknown-impact" }, { ...exact, operator_action: "run-private-shell-command" }, { ...exact, automatic_retry: true }, { ...exact, redacted: false }, ]) { assert.equal(isXgridsHostFailureDiagnostic(malformed), false); } }); test("failed network-profile writes close the UI session with a fresh explicit next step", () => { const message = networkProvisionFailureMessage({ status: "failed", error: { code: "BleakGATTProtocolError" }, }); assert.equal( message, "Bluetooth-периферия завершила сетевую операцию ошибкой. Команда могла быть принята K1; итог текущей попытки не подтверждён. Автоматический повтор команды K1 не отправлялся. Сессия подключения в интерфейсе сброшена. Выполните новый поиск Bluetooth, выберите K1 и запустите подключение ещё раз.", ); assert.doesNotMatch(message, /Bleak|GATT|ATT/i); const attMessage = networkProvisionFailureMessage({ action: "network.provision", status: "failed", error: { code: "BleakGATTProtocolError", ble_att_error_code: 4, ble_att_error_name: "INVALID_PDU", }, }); assert.match(attMessage, /ATT 4 INVALID_PDU/); assert.match(attMessage, /Автоматический повтор команды K1 не отправлялся/); assert.match(attMessage, /Сессия подключения в интерфейсе сброшена/); assert.match(attMessage, /новый поиск Bluetooth, выберите K1/); const preWriteAttMessage = networkProvisionFailureMessage({ action: "network.provision", status: "failed", error: { code: "BleakGATTProtocolError", operation_stage: "baseline-read", device_write_attempted: false, side_effect_status: "none", safe_to_retry: true, ble_att_error_code: 4, ble_att_error_name: "INVALID_PDU", }, }); assert.match(preWriteAttMessage, /до команды изменения сети/); assert.match(preWriteAttMessage, /Запись сетевого профиля не выполнялась/); assert.doesNotMatch(preWriteAttMessage, /результат изменения сети неизвестен/i); }); test("post-dispatch ambiguity resets the UI session without an automatic retry", () => { const message = networkProvisionFailureMessage({ action: "network.provision", status: "failed", error: { code: "network-provision-target-not-distinguishable-from-baseline", device_write_attempted: true, side_effect_status: "unknown", safe_to_retry: false, }, }); assert.equal( message, "После BLE-команды K1 вернул сетевой статус, неотличимый от исходного; итог текущей попытки подключения не подтверждён. Автоматический повтор команды K1 не отправлялся. Сессия подключения в интерфейсе сброшена. Выполните новый поиск Bluetooth, выберите K1 и запустите подключение ещё раз.", ); assert.doesNotMatch(message, /ручн|read-only|защитный барьер/i); }); test("Bluetooth scan failures explain whether a device command was sent", () => { const busy = discoveryScanFailureMessage({ action: "discovery.scan", status: "failed", error: { code: "ble-runtime-busy" }, }); const cleanupPending = discoveryScanFailureMessage({ action: "discovery.scan", status: "failed", error: { code: "ble-runtime-cleanup-pending" }, }); const timedOut = discoveryScanFailureMessage({ action: "discovery.scan", status: "failed", error: { code: "ble-discovery-timeout" }, }); assert.match(busy, /занят другой локальной операцией/); assert.match(cleanupPending, /подтверждает отключение/); assert.match(timedOut, /принудительно остановлен/); assert.match(timedOut, /Команды K1 не отправлялись/); }); test("connection recovery exposes safe operator-facing failure classes", () => { const addressUnavailable = connectionVerificationFailureMessage({ action: "connection.verify", status: "failed", error: { code: "connection-verify-address-unavailable", side_effect_status: "none", safe_to_retry: true, }, }); const missingAdvertisement = connectionVerificationFailureMessage({ action: "connection.verify", status: "failed", error: { code: "connection-verify-device-not-rediscovered" }, }); const statusReadFailed = connectionVerificationFailureMessage({ action: "connection.verify", status: "failed", error: { code: "connection-verify-status-read-failed", operation_stage: "exact-uuid-scan", side_effect_status: "none", }, }); const exactUuidScanTimedOut = connectionVerificationFailureMessage({ action: "connection.verify", status: "failed", error: { code: "connection-verify-exact-uuid-scan-timeout", operation_stage: "exact-uuid-scan", side_effect_status: "none", }, }); const indistinguishableFromBaseline = connectionVerificationFailureMessage({ action: "connection.verify", status: "failed", error: { code: "connection-verify-target-not-distinguishable-from-baseline", side_effect_status: "none", safe_to_retry: false, }, }); const staleEndpoint = connectionVerificationFailureMessage({ action: "connection.verify", status: "failed", error: { code: "connection-verify-mqtt-unreachable", side_effect_status: "none", safe_to_retry: true, }, }); const bindingChanged = connectionVerificationFailureMessage({ action: "connection.verify", status: "failed", error: { code: "application-connection-binding-lost", side_effect_status: "none", safe_to_retry: true, }, }); const physicalProofTimedOut = connectionVerificationFailureMessage({ action: "connection.verify", status: "failed", error: { code: "physical-command-reconciliation-proof-timeout", side_effect_status: "none", safe_to_retry: true, }, }); assert.match(addressUnavailable, /K1 ответил/); assert.match(addressUnavailable, /настройки устройства не менялись/); assert.match(missingAdvertisement, /Mission Core не получил объявление/); assert.match(missingAdvertisement, /Команды K1 не отправлялись/); assert.doesNotMatch(missingAdvertisement, /питани|перезапуст|не работает|пропал/i); assert.match(statusReadFailed, /Mission Core не завершил/); assert.match(statusReadFailed, /команды не отправлялись/); assert.doesNotMatch(statusReadFailed, /питани|перезапуст|не работает|K1 не ответил/i); assert.match(exactUuidScanTimedOut, /точного сохранённого CoreBluetooth UUID/); assert.match(exactUuidScanTimedOut, /не является выводом о состоянии устройства/); assert.doesNotMatch(exactUuidScanTimedOut, /питани|перезапуст|не работает|K1 не ответил/i); assert.match(staleEndpoint, /можно заново применить настройки общей сети/); assert.match(staleEndpoint, /Команда Wi-Fi не отправлялась/); assert.doesNotMatch(staleEndpoint, /новый поиск|read-only/i); assert.match(bindingChanged, /нажмите «Подключиться заново»/); assert.doesNotMatch(bindingChanged, /поиск Bluetooth/i); assert.match(physicalProofTimedOut, /START и STOP не отправлялись/); assert.match(physicalProofTimedOut, /нажмите «Подключиться заново»/); assert.doesNotMatch(physicalProofTimedOut, /поиск Bluetooth/i); assert.equal( indistinguishableFromBaseline, "K1 ответил, но приложение не смогло подтвердить, что прежние настройки сети были применены. Автоматического повтора и новой записи не было.", ); assert.doesNotMatch(indistinguishableFromBaseline, /поиск Bluetooth|повторите запись/i); }); test("scan and verify errors correlate only with the requested operation id", () => { const state = { operations: [ { operation_id: "op-requested", action: "discovery.scan", status: "failed", error: { code: "ble-discovery-timeout" }, }, { operation_id: "op-other-tab", action: "discovery.scan", status: "failed", error: { code: "ble-discovery-already-running" }, }, ], last_operation: { operation_id: "op-other-tab", action: "discovery.scan", status: "failed", }, }; assert.equal( operationById(state, "discovery.scan", "op-requested")?.error?.code, "ble-discovery-timeout", ); assert.equal(operationById(state, "discovery.scan", "op-missing"), null); }); test("host Wi-Fi failures close the attempt and require a fresh explicit connection", () => { const operationTimeout = networkProvisionFailureMessage({ status: "failed", error: { code: "host-wifi-operation-timeout" }, }); const missingNetwork = networkProvisionFailureMessage({ status: "failed", error: { code: "network-not-found", side_effect_status: "confirmed", safe_to_retry: false, scan_attempt_count: 13, scan_elapsed_ms: 17524, }, }); const preWriteKeychain = networkProvisionFailureMessage({ status: "failed", error: { code: "keychain-authorization-required", side_effect_status: "none", safe_to_retry: true, }, }); const postWriteKeychain = networkProvisionFailureMessage({ status: "failed", error: { code: "keychain-authorization-denied", side_effect_status: "confirmed", safe_to_retry: false, }, }); assert.equal( operationTimeout, "Локальная операция подготовки Wi‑Fi не завершилась вовремя; итог текущей попытки подключения не подтверждён. Автоматический повтор команды K1 не отправлялся. Сессия подключения в интерфейсе сброшена. Выполните новый поиск Bluetooth, выберите K1 и запустите подключение ещё раз.", ); assert.doesNotMatch(operationTimeout, /получите пароль|пароль отсутствует/i); assert.match(missingNetwork, /K1 принял команду Quick Connect/); assert.match(missingNetwork, /13 проверок за 17\.5 с/); assert.match(missingNetwork, /автоматического повтора не было/); assert.match(preWriteKeychain, /Команда устройству не отправлялась/); assert.match(postWriteKeychain, /Дополнительный пароль не запрашивался/); });