import type { RuntimePhase, SourceMode as RuntimeSourceMode } from "@mission-core/plugin-sdk"; import type { AcquisitionState, BleDevice, XgridsApplicationControlPhase, XgridsAcquisition, XgridsConnectionAttempt, XgridsK1State, XgridsOperation, ReopenRetiredPhysicalReconciliationRequest, XgridsConnectionMode, XgridsConnectionReconfiguration, XgridsConnectionPolicyAction, XgridsConnectionPolicyDecision, } from "./api"; const TERMINAL_ACQUISITION_STATES = new Set([ "completed", "failed", "aborted", "interrupted", ]); const FAILED_OPERATION_STATUSES = new Set([ "failed", "cancelled", "timed_out", "interrupted", ]); export type LiveStartPlan = "prepare" | "resume-prepared" | "already-running" | "blocked"; export type LocalReceiverStopPlan = | { kind: "acquisition"; acquisitionId: string } | { kind: "compatibility" }; export type ControlSessionEntryPlan = | "open" | "continue" | "failed" | "duplicate-open"; export function controlSessionEntryPlan( phase: XgridsApplicationControlPhase, openedByCurrentOperatorAction: boolean, canOpen: boolean, ): ControlSessionEntryPlan { if (phase === "failed") { return !openedByCurrentOperatorAction && canOpen ? "open" : "failed"; } if (["idle", "closed", "completed"].includes(phase)) { return openedByCurrentOperatorAction ? "duplicate-open" : "open"; } return "continue"; } export function isTerminalAcquisitionState( state: AcquisitionState | null | undefined, ): boolean { return state ? TERMINAL_ACQUISITION_STATES.has(state) : false; } /** * Select the exact local runtime cleanup target without inheriting a retained * terminal acquisition into a replay session. Terminal acquisition state is * actionable only while its backend-owned local cleanup remains pending. */ export function localReceiverStopPlan( state: XgridsK1State | null | undefined, ): LocalReceiverStopPlan { const acquisition = state?.acquisition; const acquisitionId = acquisition?.acquisition_id?.trim(); const liveOrIdleRuntime = state?.source_mode === "live" || state?.source_mode === "idle"; if ( acquisition && acquisitionId && liveOrIdleRuntime && ( !isTerminalAcquisitionState(acquisition.state) || acquisition.cleanup_pending === true ) ) { return { kind: "acquisition", acquisitionId }; } return { kind: "compatibility" }; } export function isProvenLocalReceiverInactive( state: XgridsK1State | null | undefined, ): state is XgridsK1State { const acquisition = state?.acquisition; const acquisitionReleased = Boolean( acquisition && isTerminalAcquisitionState(acquisition.state) && acquisition.cleanup_pending === false, ); return Boolean( state?.source_mode === "idle" && (!acquisition || acquisitionReleased), ); } export function isReleasedTerminalAcquisitionFailure( state: XgridsK1State | null | undefined, ): boolean { const controlState = state?.application_control_session?.state; const acquisition = state?.acquisition; return Boolean( state?.source_mode === "idle" && acquisition && ["failed", "interrupted"].includes(acquisition.state) && acquisition.cleanup_pending === false && [ "idle", "connection-ready", "active-recovery-requested", "scanning", "completed", "closed", ].includes(controlState ?? ""), ); } export function shouldSurfaceRuntimeActionError( action: string, state: XgridsK1State | null | undefined, ): boolean { return !( ["control", "live", "stop", "abort"].includes(action) && isReleasedTerminalAcquisitionFailure(state) ); } export function shouldRenderSpatialControls( state: XgridsK1State | null | undefined, ): boolean { const acquisition = state?.acquisition; if (!acquisition || state?.source_mode === "replay") return false; return ( !isTerminalAcquisitionState(acquisition.state) || acquisition.cleanup_pending === true || requiresCanonicalStopAfterTerminalLocalFailure(state) ); } export function requiresCanonicalStopAfterTerminalLocalFailure( state: XgridsK1State | null | undefined, ): boolean { const acquisition = state?.acquisition; const control = state?.application_control_session; return Boolean( acquisition && isTerminalAcquisitionState(acquisition.state) && isSoftwareCommandedAcquisition(state) && control?.state === "scanning" && control.can_stop === true ); } export interface PhysicalStopIntentCheckpoint { snapshotRuntimeId: string; acquisitionId: string; deviceId: string; deviceSessionId: string; controlSessionGeneration: number; controlStateRevision: number; } function positiveInteger(value: unknown): value is number { return Number.isSafeInteger(value) && (value as number) >= 1; } /** * Capture the exact backend authority consumed by one physical STOP intent. * Snapshot identity is retained when available, while the control-session CAS * is mandatory: a presentation-only error dismissal must never manufacture a * fresh command intent against the same control checkpoint. */ export function physicalStopIntentCheckpoint( state: XgridsK1State | null | undefined, ): PhysicalStopIntentCheckpoint | null { const control = state?.application_control_session; const acquisition = state?.acquisition; const acquisitionId = acquisition?.acquisition_id?.trim(); const deviceId = acquisition?.device_id?.trim(); const deviceSessionId = acquisition?.device_session_id?.trim(); const runtimeId = state?.snapshot_runtime_id?.trim(); if ( !control || !acquisitionId || !deviceId || !deviceSessionId || !runtimeId || !positiveInteger(control.session_generation) || !positiveInteger(control.state_revision) || control.state !== "scanning" || control.can_stop !== true || !connectionPolicyAllows(state, "stop-acquisition") ) return null; return { snapshotRuntimeId: runtimeId, acquisitionId, deviceId, deviceSessionId, controlSessionGeneration: control.session_generation, controlStateRevision: control.state_revision, }; } /** * A spent physical STOP may be released only by an already-accepted exact * STOP-authoritative runtime replacement, a distinct acquisition target, or * an exact control-session CAS transition. A same-runtime polling snapshot * whose target and control CAS stayed fixed is not new physical-command * authority. */ export function authoritativeStateSupersedesPhysicalStopIntent( spent: PhysicalStopIntentCheckpoint | null | undefined, state: XgridsK1State | null | undefined, ): boolean { if (!spent) return false; const current = physicalStopIntentCheckpoint(state); if (!current) return false; const sameRuntime = current.snapshotRuntimeId === spent.snapshotRuntimeId; if (!sameRuntime) { // Snapshot ordering is resolved before this helper is called. A different // accepted runtime with a complete exact STOP gate is fresh authority even // when its process-local CAS counters restarted. return true; } const sameTarget = current.acquisitionId === spent.acquisitionId && current.deviceId === spent.deviceId && current.deviceSessionId === spent.deviceSessionId; if (!sameTarget) { // A newly accepted acquisition/device/session tuple is a distinct command // target. The caller has already admitted this state monotonically. return true; } const controlCasAdvanced = current.controlSessionGeneration > spent.controlSessionGeneration || ( current.controlSessionGeneration === spent.controlSessionGeneration && current.controlStateRevision > spent.controlStateRevision ); if (!controlCasAdvanced) return false; // Within one runtime the exact control CAS must advance; observation-only // polls remain locked regardless of their snapshot observation revision. return true; } /** * Admit one physical STOP button only from the exact current control proof. * A failed action spends that browser intent independently of its dismissible * presentation error: the operator may still finish the host receiver * locally, but the UI must not create a fresh physical STOP mutation from the * same accepted snapshot/control CAS. */ export function canIssueCanonicalStop( state: XgridsK1State | null | undefined, physicalStopIntentSpent: boolean | null | undefined, ): boolean { const control = state?.application_control_session; return Boolean( !physicalStopIntentSpent && physicalStopIntentCheckpoint(state) && control?.state === "scanning" && control.can_stop === true && connectionPolicyAllows(state, "stop-acquisition"), ); } /** * A successful read-only Verify may truthfully end in SCANNING rather than * connection-ready. That state grants exactly one explicit STOP, never START * or provisioning authority. */ export function isRecoveredPhysicalScanning( state: XgridsK1State | null | undefined, expectedMode?: XgridsConnectionMode, ): boolean { const control = state?.application_control_session; const physical = control?.physical_command ?? state?.physical_command; const mode = state?.active_connection_mode ?? state?.connection_mode; return Boolean( control?.state === "scanning" && control.can_stop === true && physical?.requires_reconciliation !== true && physical?.resolved_active_recovery_required === true && physical.observed_session_state === "scanning" && (!expectedMode || mode === expectedMode) && (!expectedMode || currentAppliedConnectionTopology(state, expectedMode)?.status === "active") ); } /** * A STOP that was accepted before the host path disappeared is completed by * the backend from its durable command ledger. The connection screen must * wait for that cleanup instead of turning the condition into another device * action (Scan, START, STOP, or Wi-Fi provisioning). */ export function isPhysicalStopRecoverySettling( state: XgridsK1State | null | undefined, ): boolean { const control = state?.application_control_session; const physical = control?.physical_command ?? state?.physical_command; const record = physical?.record; const action = record?.action; const resolution = record?.resolution; const acquisition = state?.acquisition; const acquisitionStillSettling = Boolean( acquisition && ( !isTerminalAcquisitionState(acquisition.state) || acquisition.cleanup_pending === true ), ); const stopOperationStillSettling = Boolean( state?.operations?.some((operation) => operation.action === "acquisition.stop" && ["accepted", "running", "operator_action_required"].includes(operation.status) ), ); return Boolean( action === "stop" && resolution !== "stop-standby-observed" && (physical?.requires_reconciliation === true || physical?.status === "unresolved") && (acquisitionStillSettling || stopOperationStillSettling), ); } export function recoverableAcquisition( state: XgridsK1State | null | undefined, ): XgridsAcquisition | null { const acquisition = state?.acquisition; return acquisition && !isTerminalAcquisitionState(acquisition.state) ? acquisition : null; } export function isConfirmedLiveState(state: XgridsK1State | null | undefined): boolean { return Boolean( state?.source_mode === "live" && state.acquisition?.state === "acquiring" && hasAuthoritativeData(state), ); } export function isSourceRuntimeBusy(state: XgridsK1State | null | undefined): boolean { return state?.source_mode === "live" || state?.source_mode === "replay"; } export function isVendorWriteCapable( state: XgridsK1State | null | undefined, ): boolean { return ( state?.compatibility?.vendor_writes_enabled === true && state.compatibility.permitted_mode === "active-control" ); } export function isSoftwareCommandedAcquisition( state: XgridsK1State | null | undefined, ): boolean { return isVendorWriteCapable(state) && state?.acquisition?.control_mode === "plugin-commanded"; } export function confirmedRuntimeSourceMode( state: XgridsK1State | null | undefined, ): RuntimeSourceMode { if (state?.source_mode === "replay") return "replay"; if (isConfirmedLiveState(state)) return "live"; return "idle"; } export function effectiveAcquisition( state: XgridsK1State | null | undefined, ): XgridsAcquisition | null { if (state?.source_mode === "replay") return null; return state?.acquisition ?? null; } export function liveStartPlan(state: XgridsK1State | null | undefined): LiveStartPlan { if (state?.source_mode === "replay") return "blocked"; const acquisition = recoverableAcquisition(state); if (!acquisition) return state?.source_mode === "live" ? "blocked" : "prepare"; if (acquisition.state === "prepared") return "resume-prepared"; if ( acquisition.state === "starting" || acquisition.state === "awaiting_external_start" || acquisition.state === "acquiring" ) { return "already-running"; } return "blocked"; } export function normalizeRuntimePhase( state: XgridsK1State | null | undefined, ): RuntimePhase { const phase = state?.phase; const acquisitionState = effectiveAcquisition(state)?.state; const releasedFailure = isReleasedTerminalAcquisitionFailure(state); if ( !releasedFailure && (acquisitionState === "failed" || acquisitionState === "interrupted") ) return "error"; if (acquisitionState === "awaiting_external_start" || acquisitionState === "starting") { return "starting"; } if (acquisitionState === "acquiring") { return isConfirmedLiveState(state) ? "streaming" : "starting"; } if ( acquisitionState === "awaiting_external_stop" || acquisitionState === "stopping" || acquisitionState === "finalizing" ) { return "stopping"; } if (acquisitionState === "prepared") { const topology = currentAppliedConnectionTopology(state); return topology && topology.status !== "configured-offline" ? "connected" : "configuring"; } if (phase === "error") return releasedFailure ? "idle" : "error"; if (phase === "connected") { const topology = currentAppliedConnectionTopology(state); return topology && topology.status !== "configured-offline" ? "connected" : "configuring"; } if (phase === "starting_live") return "starting"; if (phase === "live") return isConfirmedLiveState(state) ? "streaming" : "starting"; if (phase === "replay") return "replaying"; if (phase === "stopping") return "stopping"; if (["scanning", "device_selected", "provisioning", "connecting"].includes(phase ?? "")) { return "configuring"; } return "idle"; } export function spatialSourceId( state: XgridsK1State | null | undefined, sourceUrl: string, ): string | null { if (!sourceUrl) return null; if (state?.source_mode === "replay") return `replay:${sourceUrl}`; return state?.acquisition?.acquisition_id ?? sourceUrl; } export function sourceStatusLabel(state: XgridsK1State | null | undefined): string { if (state?.source_mode === "replay") return "Повтор записи"; if (isConfirmedLiveState(state)) return "Реальное время · данные подтверждены"; if (state?.source_mode === "live") { if (state.acquisition?.state === "failed" || state.phase === "error") { return "Ошибка локального приёмника"; } if (state.connection_supervisor?.observed.data_plane.state === "lost") { return "Поток данных потерян"; } if (state.connection_supervisor?.observed.data_plane.state === "stalled") { return "Поток данных нестабилен"; } return "Ожидание реальных данных"; } if (state?.acquisition?.state === "prepared") return "Приём подготовлен"; return "Ожидание"; } export function operationByIdempotencyKey( state: XgridsK1State | null | undefined, action: string, idempotencyKey: string | null | undefined, ): XgridsOperation | null { if (!idempotencyKey) return null; return ( [...(state?.operations ?? [])] .reverse() .find( (operation) => operation.action === action && operation.idempotency_key === idempotencyKey, ) ?? null ); } export function operationNeedsReconciliation( operation: XgridsOperation | null | undefined, ): boolean { if (!operation || !FAILED_OPERATION_STATUSES.has(operation.status)) return false; return operation.error?.safe_to_retry !== true; } export function operationAllowsFreshProvisioningIntent( operation: XgridsOperation | null | undefined, ): boolean { return Boolean( operation && FAILED_OPERATION_STATUSES.has(operation.status) && operation.error?.safe_to_retry === true && operation.error.side_effect_status === "none", ); } const FRESH_CANDIDATE_RETRY_REASON_CODES = new Set([ "BleakDeviceNotFoundError", "network-provision-candidate-not-fresh", "network-provision-candidate-changed", "network-provision-discovery-generation-conflict", ]); /** * These failures are proven pre-write rejections caused only by an expired * Bluetooth capture. One explicit network-submit click may refresh discovery * once and then continue with the exact returned generation. A second failure * is terminal for that click; this predicate never authorizes an unbounded * retry or a repeat after an ambiguous/device-write outcome. */ export function provisioningFailureRequiresFreshCandidate( reasonCode: string | null | undefined, ): boolean { return typeof reasonCode === "string" && FRESH_CANDIDATE_RETRY_REASON_CODES.has(reasonCode); } export function readOnlyVerificationClearedReconciliation( previousState: XgridsK1State | null | undefined, nextState: XgridsK1State | null | undefined, verifiedDeviceId: string | null | undefined, ): boolean { const previousFence = previousState?.network_write_reconciliation; const previousOperationId = previousFence?.operation_id?.trim(); const nextLedger = nextState?.network_mutation_ledger; if ( !verifiedDeviceId || !previousOperationId || transportRefEquivalenceKey(previousFence?.transport_ref) !== transportRefEquivalenceKey(verifiedDeviceId) // An omitted field or a replacement unresolved fence is never proof that // this durable operation was reconciled. || nextState?.network_write_reconciliation !== null || !nextLedger || nextLedger.mutation_allowed !== true ) { return false; } const sameOperationResolved = Boolean( nextLedger.status === "resolved" && nextLedger.operation_id === previousOperationId && nextLedger.stage === "resolved" && nextLedger.resolution !== null, ); const operationExplicitlyAbsent = Boolean( nextLedger.status === "empty" && nextLedger.operation_id === null && nextLedger.stage === null, ); return sameOperationResolved || operationExplicitlyAbsent; } export function provisioningCandidateById( devices: readonly BleDevice[], selectedDeviceId: string, ): BleDevice | null { const selectedKey = transportRefEquivalenceKey(selectedDeviceId); if (!selectedKey) return null; return devices.find( (device) => transportRefEquivalenceKey(device.device_id) === selectedKey, ) ?? null; } export function currentDeviceTransportRef( state: XgridsK1State | null | undefined, ): string | null { const recoveryRef = state?.current_device_recovery?.transport_ref?.trim(); if (recoveryRef) return recoveryRef; const selectedRef = state?.selected_device_id?.trim(); return selectedRef || null; } export interface LocallyInitiatedBleSessionTarget { transportRef: string; connectionMode: XgridsConnectionMode; deviceSessionId: string; key: string; } export interface LocalBleSessionBindingConstraints { /** Bind only the exact session accepted by the explicit connect response. */ requiredSessionKey?: string | null; } export function bleSessionTargetForTransport( state: XgridsK1State | null | undefined, transportRef: string | null | undefined, selectedConnectionMode: XgridsConnectionMode, ): LocallyInitiatedBleSessionTarget | null { const expectedTransportRef = transportRef?.trim(); const backendTransportRef = state?.current_device_recovery?.transport_ref?.trim() || state?.selected_device_id?.trim(); const connectionMode = state?.current_device_recovery?.connection_mode ?? state?.connection_mode; const deviceSessionId = state?.device_session?.device_session_id?.trim(); if ( !expectedTransportRef || !backendTransportRef || expectedTransportRef !== backendTransportRef || !deviceSessionId || connectionMode !== selectedConnectionMode ) { return null; } return { transportRef: backendTransportRef, connectionMode, deviceSessionId, key: `${deviceSessionId}:${connectionMode}:${backendTransportRef}`, }; } export function acceptedBleSessionKeyAfterConnect( state: XgridsK1State | null | undefined, transportRef: string | null | undefined, selectedConnectionMode: XgridsConnectionMode, sessionKeyBeforeConnect: string | null | undefined, ): string | null { const target = bleSessionTargetForTransport( state, transportRef, selectedConnectionMode, ); if (!target || target.key === sessionKeyBeforeConnect) return null; return target.key; } /** * Bind backend session state only to a connection initiated by this UI * instance. A browser refresh has no local device id and therefore never * turns an existing backend session into an implicit operator selection. */ export function locallyInitiatedBleSessionTarget( state: XgridsK1State | null | undefined, locallyInitiatedDeviceId: string | null | undefined, selectedConnectionMode: XgridsConnectionMode, constraints: LocalBleSessionBindingConstraints = {}, ): LocallyInitiatedBleSessionTarget | null { const localRef = locallyInitiatedDeviceId?.trim(); if (!localRef) return null; const target = bleSessionTargetForTransport( state, localRef, selectedConnectionMode, ); if (!target) return null; if ( constraints.requiredSessionKey && constraints.requiredSessionKey !== target.key ) return null; return target; } export interface RetainedBleRecoveryTarget { transportRef: string; connectionMode: NonNullable | null; gattValidatedRecently: boolean; } export function retainedBleRecoveryTarget( state: XgridsK1State | null | undefined, ): RetainedBleRecoveryTarget | null { const recovery = state?.current_device_recovery; const transportRef = recovery?.transport_ref?.trim(); if ( !transportRef || recovery?.handle_retained !== true || recovery.advertised_now === true ) { return null; } return { transportRef, connectionMode: recovery.connection_mode ?? null, gattValidatedRecently: recovery.gatt_validated_recently === true, }; } export function connectionPolicyDecision( state: XgridsK1State | null | undefined, action: XgridsConnectionPolicyAction, ): XgridsConnectionPolicyDecision | null { const policy = state?.connection_policy; if ( policy?.schema_version !== "missioncore.xgrids-k1-connection-policy/v1" || policy.facts.retained_context_is_presence !== false ) { return null; } return policy.actions[action] ?? null; } export function connectionPolicyAllows( state: XgridsK1State | null | undefined, action: XgridsConnectionPolicyAction, ): boolean { const decision = connectionPolicyDecision(state, action); return Boolean( decision?.allowed === true && decision.automatic_retry === false && state?.connection_policy?.allowed_actions.includes(action), ); } export interface ProvisioningNetworkStepDisclosure { /** A concrete K1 has been admitted or selected by this operator flow. */ deviceExplicitlySelectedOrAdmitted: boolean; /** A network/connection intent, rather than discovery alone, has started. */ networkIntentStarted: boolean; } /** * Keep Bluetooth discovery entirely inside step 02. * * Raw controller settlement is deliberately not an input: an old scan, * reconfiguration, retirement, or physical-cleanup promise may still be * unwinding after its authority has gone stale, but that does not mean the * operator has reached the network step for the current device choice. */ export function shouldRevealProvisioningNetworkStep({ deviceExplicitlySelectedOrAdmitted, networkIntentStarted, }: ProvisioningNetworkStepDisclosure): boolean { return deviceExplicitlySelectedOrAdmitted || networkIntentStarted; } export function activeConnectionReconfiguration( state: XgridsK1State | null | undefined, ): XgridsConnectionReconfiguration | null { const reconfiguration = state?.connection_reconfiguration; if ( !reconfiguration || reconfiguration.schema_version !== "missioncore.xgrids-k1-connection-reconfiguration/v1" || reconfiguration.intent === null || reconfiguration.status === "idle" ) { return null; } return reconfiguration; } /** * A network-change intent is pinned to the exact device and mode which were * current when the operator opened it. Selecting another advertisement must * not turn that intent into a different-device network write. */ export function reconfigurationAllowsFreshDevice( reconfiguration: XgridsConnectionReconfiguration | null, deviceId: string, connectionMode: XgridsConnectionMode, ): boolean { if (!reconfiguration || !deviceId.trim()) return false; if ( connectionMode !== "bridge" || reconfiguration.required_connection_mode !== "bridge" ) return false; if (reconfiguration.intent === "select-device") return true; return Boolean( reconfiguration.intent === "change-network" && transportRefEquivalenceKey(reconfiguration.required_transport_ref) === transportRefEquivalenceKey(deviceId) && reconfiguration.required_connection_mode === connectionMode, ); } export function readOnlyObservationShowsNetworkUnavailable( state: XgridsK1State | null | undefined, ): boolean { const verification = state?.connection_verification; if (!verification) return false; return [ "device-network-applied-host-failed", "host-route-mismatch", "endpoint-unreachable", "unreachable", ].includes(verification.status) || Boolean( verification.lease_state === "configured-unverified" && verification.network_reachability === "unreachable", ) || Boolean( verification.status === "device-network-applied" && verification.lease_state === "configured-unverified" && verification.reason_code === "endpoint-target-unconfigured", ); } const READ_ONLY_NETWORK_UNAVAILABLE_REASON_CODES = new Set([ "connection-verify-address-unavailable", "connection-verify-connection-missing", "connection-verify-route-mismatch", "connection-verify-mqtt-unreachable", "configured-endpoint-unavailable", "endpoint-target-unconfigured", ]); /** * Only failures which prove that the selected device cannot use the current * Bridge topology may lead from read-only adoption to explicit credentials. * BLE, identity, lifecycle and CAS failures deliberately stay outside this * allowlist. */ export function readOnlyFailureShowsNetworkUnavailable( reasonCode: string | null | undefined, ): boolean { return typeof reasonCode === "string" && READ_ONLY_NETWORK_UNAVAILABLE_REASON_CODES.has(reasonCode); } /** * Preserve the stronger BLE observation across refreshes and later scan * failures: this saved Bridge needs network setup, not another old-address * reconnect attempt. */ export function savedBridgeRequiresNetworkSetup( state: XgridsK1State | null | undefined, ): boolean { if ( state?.connection_verification?.reason_code === "connection-verify-address-unavailable" ) return true; const operation = state?.last_operation; return Boolean( operation?.action === "connection.verify" && operation.status === "failed" && operation.error?.code === "connection-verify-address-unavailable", ); } export function requiresReadOnlyPhysicalRecovery( state: XgridsK1State | null | undefined, ): boolean { const control = state?.application_control_session; const physical = control?.physical_command ?? state?.physical_command; return Boolean( // The coordinator folds unresolved commands and resolved SCAN_OVER into // requires_reconciliation, while resolved active and explicitly reopened // rows remain read-only recovery through the separate active flag. physical?.requires_reconciliation === true || physical?.resolved_active_recovery_required === true, ); } export interface ReadOnlyPhysicalRecoveryBinding { deviceId: string; connectionMode: XgridsConnectionMode; } export interface TrustedConnectionBinding { deviceId: string; connectionMode: XgridsConnectionMode; } /** * CoreBluetooth UUID text is case-insensitive. Keep the original spelling for * display and exact CAS payloads, but use this key whenever refs are compared. */ export function transportRefEquivalenceKey( transportRef: string | null | undefined, ): string { return transportRef?.trim().toLowerCase() ?? ""; } /** * Resolve the exact K1 remembered by durable/backend-owned state. This is * selection context only: it can authorize bounded observation, but never a * device write without the separate connection policy and an explicit click. */ export function trustedConnectionBinding( state: XgridsK1State | null | undefined, ): TrustedConnectionBinding | null { const physical = readOnlyPhysicalRecoveryBinding(state); if (physical) return physical; const retiredTransportRefs = retiredPhysicalTransportRefs(state); const semanticRecord = state?.semantic_topology_store?.record; const semanticDeviceId = semanticRecord?.transport_ref?.trim(); const semanticMode = semanticRecord?.connection_mode; if ( semanticDeviceId && !retiredTransportRefs.has(transportRefEquivalenceKey(semanticDeviceId)) && isConnectionMode(semanticMode) ) { return { deviceId: semanticDeviceId, connectionMode: semanticMode }; } const recovery = state?.current_device_recovery; const recoveryDeviceId = recovery?.transport_ref?.trim(); const recoveryMode = recovery?.connection_mode; if ( recoveryDeviceId && !retiredTransportRefs.has(transportRefEquivalenceKey(recoveryDeviceId)) && isConnectionMode(recoveryMode) ) { return { deviceId: recoveryDeviceId, connectionMode: recoveryMode }; } return null; } /** Transport refs explicitly retired by the operator must never rehydrate. */ export function retiredPhysicalTransportRefs( state: XgridsK1State | null | undefined, ): ReadonlySet { const policyRetiredRefs = state?.connection_policy?.facts.retired_transport_refs; if (Array.isArray(policyRetiredRefs)) { // This backend projection is the authoritative *active* deny-list. The // durable ledger keeps historical retirement audits even after an explicit // reconciliation reopen, so unioning every old audit would make a safely // reopened UUID impossible to use forever. return new Set( policyRetiredRefs.map(transportRefEquivalenceKey).filter(Boolean), ); } const record = state?.physical_command?.record; const retired = new Set(); if (!record) return retired; const retirements = Array.isArray(record.operator_retirements) ? record.operator_retirements : []; for (const candidate of retirements) { if (!candidate || typeof candidate !== "object") continue; const transportRef = "retired_transport_ref" in candidate && typeof candidate.retired_transport_ref === "string" ? candidate.retired_transport_ref.trim() : ""; if (transportRef) retired.add(transportRefEquivalenceKey(transportRef)); } if (record.resolution === "operator-retired-outcome-unknown") { const connection = record.connection; if (connection && typeof connection === "object") { const transportRef = "transport_ref" in connection && typeof connection.transport_ref === "string" ? connection.transport_ref.trim() : ""; if (transportRef) retired.add(transportRefEquivalenceKey(transportRef)); } } return retired; } export interface RetiredPhysicalReopenAuthority { expectedRevision: number; expectedRetirementId: string; expectedTransportRef: string; expectedDiscoveryGeneration: number; expectedDesiredMode: XgridsConnectionMode; expectedDesiredModeRevision: number; } /** * Admit the local-only reopen affordance only for the exact fresh retired row * and exact backend-projected ledger/discovery CAS. This helper grants no GATT * or write authority; the separately explicit Verify remains server-fenced. */ export function retiredPhysicalReopenAuthority( state: XgridsK1State | null | undefined, candidateTransportRef: string, connectionMode: NonNullable, ): RetiredPhysicalReopenAuthority | null { const projection = state?.physical_command?.operator_reconciliation_reopen; const expectedRevision = projection?.expected_revision; const expectedRetirementId = projection?.expected_retirement_id?.trim() ?? ""; const expectedTransportRef = projection?.expected_transport_ref?.trim() ?? ""; const expectedDiscoveryGeneration = projection?.expected_discovery_generation; const expectedDesiredMode = projection?.expected_desired_mode; const expectedDesiredModeRevision = projection?.expected_desired_mode_revision; const candidateKey = transportRefEquivalenceKey(candidateTransportRef); const expectedKey = transportRefEquivalenceKey(expectedTransportRef); const currentGeneration = state?.ble_discovery_generation; const record = state?.physical_command?.record; const recordRevision = record && typeof record.revision === "number" ? record.revision : null; const retirements = record && Array.isArray(record.operator_retirements) ? record.operator_retirements : []; const exactRetirementRecorded = retirements.some((candidate) => Boolean( candidate && typeof candidate === "object" && "retirement_id" in candidate && candidate.retirement_id === expectedRetirementId && "retired_transport_ref" in candidate && typeof candidate.retired_transport_ref === "string" && transportRefEquivalenceKey(candidate.retired_transport_ref) === expectedKey )); const freshCandidates = (state?.devices ?? []).filter( (device) => transportRefEquivalenceKey(device.device_id) === candidateKey, ); const freshCandidate = freshCandidates.length === 1 ? freshCandidates[0] : null; const recordConnection = record && typeof record.connection === "object" && record.connection !== null ? record.connection : null; const recoveryConnectionMode = recordConnection && "connection_mode" in recordConnection && typeof recordConnection.connection_mode === "string" ? recordConnection.connection_mode : null; const recoveryMatchesMode = Boolean( recordConnection && "transport_ref" in recordConnection && typeof recordConnection.transport_ref === "string" && transportRefEquivalenceKey(recordConnection.transport_ref) === expectedKey && recoveryConnectionMode === connectionMode, ); // CoreBluetooth may advertise the exact returned transport while marking // the passive scan row non-connectable. The backend's exact reopen CAS is // the only exception: the explicit click is still server-fenced, and every // unrelated non-connectable row remains blocked by the presentation layer. if ( projection?.allowed !== true || projection.automatic_retry !== false || projection.device_io_performed !== false || projection.reason_codes.length !== 0 || !Number.isInteger(expectedRevision) || (expectedRevision ?? 0) < 1 || recordRevision !== expectedRevision || !expectedRetirementId || !candidateKey || candidateKey !== expectedKey || !Number.isInteger(expectedDiscoveryGeneration) || expectedDiscoveryGeneration !== currentGeneration || expectedDesiredMode !== connectionMode || state?.desired_connection_mode !== expectedDesiredMode || !Number.isInteger(expectedDesiredModeRevision) || expectedDesiredModeRevision !== state?.desired_connection_mode_revision || !retiredPhysicalTransportRefs(state).has(candidateKey) || !exactRetirementRecorded || !freshCandidate || !recoveryMatchesMode ) return null; return { expectedRevision: expectedRevision as number, expectedRetirementId, expectedTransportRef, expectedDiscoveryGeneration: expectedDiscoveryGeneration as number, expectedDesiredMode, expectedDesiredModeRevision: expectedDesiredModeRevision as number, }; } /** * Prove that a lost reopen response actually committed the exact local-only * ledger transition. Nothing here grants Verify by itself; the caller must * also retain the original full connection-action authority. */ export function reopenedPhysicalReconciliationMatches( state: XgridsK1State | null | undefined, request: ReopenRetiredPhysicalReconciliationRequest, ): boolean { const record = state?.physical_command?.record; const recordRevision = record && typeof record.revision === "number" ? record.revision : null; const reopens = record && Array.isArray(record.operator_reconciliation_reopens) ? record.operator_reconciliation_reopens : []; const requestKey = transportRefEquivalenceKey(request.expected_transport_ref); const exactAudit = reopens.some((candidate) => Boolean( candidate && typeof candidate === "object" && "reopening_id" in candidate && candidate.reopening_id === request.reopening_id && "retirement_id" in candidate && candidate.retirement_id === request.expected_retirement_id && "retired_record_revision" in candidate && candidate.retired_record_revision === request.expected_revision && "reopened_transport_ref" in candidate && typeof candidate.reopened_transport_ref === "string" && transportRefEquivalenceKey(candidate.reopened_transport_ref) === requestKey && "discovery_generation" in candidate && candidate.discovery_generation === request.expected_discovery_generation && "reason" in candidate && candidate.reason === request.reason )); const activeRetiredRefs = state?.connection_policy?.facts.retired_transport_refs; const activeDenyRemoved = Array.isArray(activeRetiredRefs) && !activeRetiredRefs.some( (value) => transportRefEquivalenceKey(value) === requestKey, ); const freshCandidates = (state?.devices ?? []).filter( (device) => transportRefEquivalenceKey(device.device_id) === requestKey, ); const freshCandidate = freshCandidates.length === 1 ? freshCandidates[0] : null; return Boolean( request.expected_desired_mode === state?.desired_connection_mode && request.expected_desired_mode_revision === state?.desired_connection_mode_revision && requestKey && recordRevision === request.expected_revision + 1 && (record?.stage === "dispatching" || record?.stage === "observing") && record.resolution === null && state?.physical_command?.requires_reconciliation === true && state.ble_discovery_generation === request.expected_discovery_generation && exactAudit && activeDenyRemoved && freshCandidate && freshCandidate.connectable !== false ); } /** The exact durable K1 binding that recovery is allowed to observe. */ export function readOnlyPhysicalRecoveryBinding( state: XgridsK1State | null | undefined, ): ReadOnlyPhysicalRecoveryBinding | null { if (!requiresReadOnlyPhysicalRecovery(state)) return null; const actions: ReadOnlyNetworkObservationAction[] = [ "observe-fresh-device-network", "observe-current-device-network", "observe-configured-device-network", ]; for (const action of actions) { const decision = connectionPolicyDecision(state, action); const deviceId = decision?.required_transport_ref?.trim(); const connectionMode = decision?.required_connection_mode ?? null; if (deviceId && isConnectionMode(connectionMode)) { return { deviceId, connectionMode }; } } return null; } export function canSelectConnectionMode( state: XgridsK1State | null | undefined, ): boolean { const lifecycle = state?.connection_lifecycle; return Boolean( lifecycle?.schema_version === "missioncore.xgrids-k1-connection-lifecycle/v1" && lifecycle.mode_selection.allowed === true && lifecycle.mode_selection.automatic_retry === false && lifecycle.allowed_actions.includes("select-connection-mode"), ); } type ReadOnlyNetworkObservationAction = Extract< XgridsConnectionPolicyAction, | "observe-fresh-device-network" | "observe-current-device-network" | "observe-configured-device-network" >; export type ReadOnlyConnectionObservationAction = | ReadOnlyNetworkObservationAction | Extract; export type ReadOnlyConnectionObservationSource = | "fresh-scan" | "retained-current-process" | "durable-configured-state"; export interface ReadOnlyConnectionObservationTarget { action: ReadOnlyConnectionObservationAction; deviceId: string; connectionMode: XgridsConnectionMode; source: ReadOnlyConnectionObservationSource; serverBound: boolean; expectedDiscoveryGeneration: number | null; } function isConnectionMode(value: unknown): value is XgridsConnectionMode { return value === "bridge" || value === "quick-connect" || value === "direct-connect"; } function exactPolicyObservationTarget( state: XgridsK1State | null | undefined, action: ReadOnlyNetworkObservationAction, source: ReadOnlyConnectionObservationSource, ): ReadOnlyConnectionObservationTarget | null { if (!connectionPolicyAllows(state, action)) return null; const decision = connectionPolicyDecision(state, action); const deviceId = decision?.required_transport_ref?.trim(); const connectionMode = decision?.required_connection_mode ?? null; if ( decision?.target_source !== source || !deviceId || !isConnectionMode(connectionMode) ) { return null; } if (source === "fresh-scan") { const freshDevice = provisioningCandidateById(state?.devices ?? [], deviceId); if ( !freshDevice || freshDevice.connectable === false || !Number.isInteger(state?.ble_discovery_generation) || (state?.ble_discovery_generation ?? -1) < 0 ) return null; } return { action, deviceId, connectionMode, source, serverBound: true, expectedDiscoveryGeneration: source === "fresh-scan" ? state?.ble_discovery_generation as number : null, }; } const SERVER_BOUND_RECOVERY_OBSERVATION_PRIORITY: ReadonlyArray = [ "observe-current-device-network", "observe-configured-device-network", "observe-fresh-device-network", ]; /** * Resolve a recovery Verify target from the public policy, never from a * browser selection. A reconnect must prefer already bound or durable state * over a projected fresh scan: a browser projection cannot prove that the * native BLEDevice is still retained by the backend process. The backend * policy still decides which exact actions are allowed; this helper only * chooses the safest allowed source in current -> configured -> fresh order. */ export function recommendedConnectionRecoveryObservationTarget( state: XgridsK1State | null | undefined, ): ReadOnlyConnectionObservationTarget | null { const sources: Record< ReadOnlyNetworkObservationAction, ReadOnlyConnectionObservationSource > = { "observe-current-device-network": "retained-current-process", "observe-configured-device-network": "durable-configured-state", "observe-fresh-device-network": "fresh-scan", }; for (const action of SERVER_BOUND_RECOVERY_OBSERVATION_PRIORITY) { const target = exactPolicyObservationTarget(state, action, sources[action]); if (target?.serverBound) return target; } return null; } /** * A terminal control session may block the network-observation actions while * the supervisor still explicitly allows its narrower DeviceInfo Verify. * Reuse that permission only when the physical ledger and durable topology * independently pin the same K1 and mode; browser selection is never used. */ function exactControlVerificationTarget( state: XgridsK1State | null | undefined, ): ReadOnlyConnectionObservationTarget | null { if ( !requiresReadOnlyPhysicalRecovery(state) || !connectionPolicyAllows(state, "verify-control-device-info") ) return null; const binding = readOnlyPhysicalRecoveryBinding(state); const semanticStore = state?.semantic_topology_store; const durable = semanticStore?.record; if ( !binding || semanticStore?.status !== "available" || semanticStore.configured_offline_evidence !== true || semanticStore.live_connection_authority !== false || durable?.schema_version !== "missioncore.xgrids-k1-semantic-topology/v1" || transportRefEquivalenceKey(durable.transport_ref) !== transportRefEquivalenceKey(binding.deviceId) || durable.connection_mode !== binding.connectionMode ) return null; return { action: "verify-control-device-info", deviceId: binding.deviceId, connectionMode: binding.connectionMode, source: "durable-configured-state", serverBound: true, expectedDiscoveryGeneration: null, }; } /** * Resolve the one read-only BLE target authorized by the server policy. * Unresolved writes never fall back to a browser selection or dropdown mode: * their UUID, mode and recovery source must be pinned by the same decision. */ export function readOnlyConnectionObservationTarget( state: XgridsK1State | null | undefined, selectedDeviceId = "", selectedConnectionMode: XgridsConnectionMode | null = null, ): ReadOnlyConnectionObservationTarget | null { // An unresolved physical command must first use the exact durable // DeviceInfo path when the supervisor authorizes it. A projected fresh BLE // row can outlive the backend's native BLEDevice and therefore cannot // outrank this read-only reconciliation route. const exactControl = exactControlVerificationTarget(state); if (exactControl) return exactControl; const exactFresh = exactPolicyObservationTarget( state, "observe-fresh-device-network", "fresh-scan", ); if (exactFresh) return exactFresh; // Outside reconciliation, the backend deliberately leaves the fresh target // unpinned because the operator may choose among several current adverts. // Preserve that reviewed path, but never use it for an unresolved write. if ( !hasUnresolvedNetworkMutation(state) && !requiresReadOnlyPhysicalRecovery(state) && selectedConnectionMode && connectionPolicyAllows(state, "observe-fresh-device-network") ) { const freshDevice = provisioningCandidateById( state?.devices ?? [], selectedDeviceId, ); if ( freshDevice && freshDevice.connectable !== false && Number.isInteger(state?.ble_discovery_generation) && (state?.ble_discovery_generation ?? -1) >= 0 ) { return { action: "observe-fresh-device-network", deviceId: freshDevice.device_id, connectionMode: selectedConnectionMode, source: "fresh-scan", serverBound: false, expectedDiscoveryGeneration: state?.ble_discovery_generation as number, }; } } return exactPolicyObservationTarget( state, "observe-current-device-network", "retained-current-process", ) ?? exactPolicyObservationTarget( state, "observe-configured-device-network", "durable-configured-state", ); } /** * Resolve recovery for an already-applied network only from a backend-pinned * current/configured target. A browser-selected advertisement is never an * authority for this read-only continuation, even when it happens to carry * the same UUID. */ export function serverBoundAppliedNetworkObservationTarget( state: XgridsK1State | null | undefined, connectionMode: XgridsConnectionMode, ): ReadOnlyConnectionObservationTarget | null { const target = exactPolicyObservationTarget( state, "observe-current-device-network", "retained-current-process", ) ?? exactPolicyObservationTarget( state, "observe-configured-device-network", "durable-configured-state", ); return target?.serverBound === true && target.connectionMode === connectionMode ? target : null; } export interface BackendConnectionTopology { connectionMode: NonNullable; status: "active" | "configured-unverified" | "configured-offline"; source: "applied" | "durable" | "last-known"; endpoint: string | null; } function sameTarget( left: { ipv4: string; port: number } | null | undefined, right: { ipv4: string; port: number } | null | undefined, ): boolean { return Boolean( left && right && left.ipv4 === right.ipv4 && left.port === right.port, ); } export function currentAppliedConnectionTopology( state: XgridsK1State | null | undefined, connectionMode?: NonNullable, ): BackendConnectionTopology | null { const supervisor = state?.connection_supervisor; if (!supervisor || supervisor.closed) return null; const { intent, lease, observed } = supervisor; const deviceNetwork = observed.device_network; const mode = deviceNetwork?.connection_mode; const target = deviceNetwork?.target; const currentDeviceNetwork = Boolean( intent && mode && target && (!connectionMode || mode === connectionMode) && deviceNetwork.state === "applied" && deviceNetwork.intent_id === intent.intent_id && Boolean(deviceNetwork.transport_ref) && mode === intent.requested_mode ); if (!currentDeviceNetwork || !mode || !target) return null; const currentEndpoint = Boolean( ["configured-unverified", "reachable"].includes(lease.state) && lease.intent_id === intent?.intent_id && lease.connection_mode === mode && sameTarget(lease.target, target) && observed.host_path.available === true && observed.host_path.route_class === "direct" && lease.host_path_epoch === observed.host_path.epoch && observed.endpoint.intent_id === intent?.intent_id && observed.endpoint.host_path_epoch === observed.host_path.epoch && observed.endpoint.tcp_state === "reachable" && sameTarget(target, observed.endpoint.target) ); const identity = observed.device_identity; const controlPlane = observed.control_plane; const lifecycle = state?.connection_lifecycle; const activeBinding = lifecycle?.active_binding; const identityExact = Boolean( identity.state === "verified" && identity.intent_id === intent?.intent_id && identity.connection_mode === mode && identity.host_path_epoch === observed.host_path.epoch && identity.logical_device_id && lease.logical_device_id === identity.logical_device_id && (!intent?.expected_device_id || identity.logical_device_id === intent.expected_device_id), ); const active = Boolean( currentEndpoint && lease.state === "reachable" && supervisor.authority.control_allowed === true && identityExact && controlPlane.state === "healthy" && Boolean(controlPlane.session_id) && controlPlane.host_path_epoch === observed.host_path.epoch && lifecycle?.schema_version === "missioncore.xgrids-k1-connection-lifecycle/v1" && lifecycle.connection_ready === true && lifecycle.configured_mode === mode && lifecycle.active_mode === mode && activeBinding?.connection_mode === mode && activeBinding.intent_id === intent?.intent_id && transportRefEquivalenceKey(activeBinding.transport_ref) === transportRefEquivalenceKey(deviceNetwork.transport_ref) && activeBinding.target_ipv4 === target.ipv4 && activeBinding.target_port === target.port && activeBinding.host_path_epoch === observed.host_path.epoch && activeBinding.control_session_id === controlPlane.session_id ); return { connectionMode: mode, status: active ? "active" : currentEndpoint ? "configured-unverified" : "configured-offline", source: "applied", endpoint: target.ipv4, }; } export function backendConnectionTopology( state: XgridsK1State | null | undefined, connectionMode?: NonNullable, ): BackendConnectionTopology | null { const supervisor = state?.connection_supervisor; const applied = currentAppliedConnectionTopology(state); // A current BLE-proved device topology supersedes every persisted or // historical address, including when the selected UI mode is different. if (applied) { return !connectionMode || applied.connectionMode === connectionMode ? applied : null; } const semanticStore = state?.semantic_topology_store; const durable = semanticStore?.record; if ( semanticStore?.status === "available" && semanticStore.configured_offline_evidence === true && semanticStore.live_connection_authority === false && durable && durable.schema_version === "missioncore.xgrids-k1-semantic-topology/v1" && (!connectionMode || durable.connection_mode === connectionMode) && Boolean(durable.ipv4.trim()) ) { const endpointProbe = state?.configured_endpoint_probe; const durableEndpointReachable = Boolean( endpointProbe?.status === "reachable" && endpointProbe.target_source === "durable-semantic-topology" && endpointProbe.connection_mode === durable.connection_mode && endpointProbe.endpoint === durable.ipv4 && transportRefEquivalenceKey(endpointProbe.transport_ref) === transportRefEquivalenceKey(durable.transport_ref) && endpointProbe.semantic_revision === durable.revision && endpointProbe.host_route_available === true && endpointProbe.host_route_class === "direct" && endpointProbe.tcp_reachable === true && endpointProbe.identity_validation === "not-performed" && endpointProbe.control_authority_granted === false && endpointProbe.ble_operation_performed === false && endpointProbe.network_mutation_performed === false && endpointProbe.automatic_retry === false ); return { connectionMode: durable.connection_mode, status: durableEndpointReachable ? "configured-unverified" : "configured-offline", source: "durable", endpoint: durable.ipv4, }; } const lastKnown = supervisor?.last_known; if ( !lastKnown || (connectionMode && lastKnown.connection_mode !== connectionMode) ) return null; return { connectionMode: lastKnown.connection_mode, status: "configured-offline", source: "last-known", endpoint: lastKnown.target.ipv4, }; } export function hasUnresolvedNetworkMutation( state: XgridsK1State | null | undefined, ): boolean { if (state?.network_write_reconciliation) return true; const ledger = state?.network_mutation_ledger; return Boolean( ledger && ( ledger.status === "unresolved" || ledger.status === "corrupt" || ledger.mutation_allowed !== true ), ); } export function canSubmitProvisioningMutation({ devices, selectedDeviceId, credentialsReady, isBusy, }: { devices: readonly BleDevice[]; selectedDeviceId: string; credentialsReady: boolean; isBusy: boolean; }): boolean { const candidate = provisioningCandidateById(devices, selectedDeviceId); return Boolean( credentialsReady && !isBusy && candidate && candidate.connectable !== false, ); } export function canAdmitProvisioningConnection({ policyAllowed, targetSource, hasSuccessfulLocalConnect, localPrerequisitesReady, }: { policyAllowed: boolean; targetSource: "fresh-scan" | null; hasSuccessfulLocalConnect: boolean; localPrerequisitesReady: boolean; }): boolean { return Boolean( policyAllowed && targetSource === "fresh-scan" && !hasSuccessfulLocalConnect && localPrerequisitesReady, ); } export function isReachableConnectionLease( state: XgridsK1State | null | undefined, connectionMode: NonNullable, ): boolean { const supervisor = state?.connection_supervisor; if (!supervisor || supervisor.closed) return false; return currentAppliedConnectionTopology(state, connectionMode)?.status === "active"; } export function isConfiguredConnectionLease( state: XgridsK1State | null | undefined, connectionMode: NonNullable, ): boolean { const topology = backendConnectionTopology(state, connectionMode); return Boolean(topology && topology.source !== "last-known"); } export function hasControlAuthority( state: XgridsK1State | null | undefined, ): boolean { const topology = currentAppliedConnectionTopology(state); return Boolean(topology?.status === "active"); } export function hasAuthoritativeData( state: XgridsK1State | null | undefined, ): boolean { const supervisor = state?.connection_supervisor; const dataPlane = supervisor?.observed.data_plane; return Boolean( hasControlAuthority(state) && supervisor?.authority.data_ingest_authoritative === true && dataPlane?.state === "healthy" && Boolean(dataPlane.session_id) && dataPlane.host_path_epoch === supervisor.observed.host_path.epoch, ); } export function canonicalDeviceConnectivity( state: XgridsK1State | null | undefined, ): "unknown" | "offline" | "connecting" | "connected" | "degraded" { const topology = currentAppliedConnectionTopology(state); if (topology?.status === "active") { const supervisor = state?.connection_supervisor; return supervisor && ["stalled", "lost"].includes(supervisor.observed.data_plane.state) ? "degraded" : "connected"; } if (topology?.status === "configured-unverified") return "connecting"; if (topology?.status === "configured-offline") return "offline"; const fallback = backendConnectionTopology(state); if (fallback?.source === "last-known") return "degraded"; if (fallback?.status === "configured-offline") return "offline"; const supervisor = state?.connection_supervisor; if (!supervisor || supervisor.closed) return supervisor?.closed ? "offline" : "unknown"; if (supervisor.lease.state === "lost" || supervisor.last_known) return "degraded"; return "offline"; } export function activeConnectionEndpointLabel( state: XgridsK1State | null | undefined, ): string | null { const topology = currentAppliedConnectionTopology(state); return topology?.status === "active" ? topology.endpoint : null; } export interface ReachableConnectionLeaseIdentity { key: string; runtimeId: string; leaseGeneration: number; intentId: string; hostPathEpoch: number; connectionMode: NonNullable; } export interface RuntimeErrorCorrelation { action: string; runtimeId: string | null; leaseGeneration: number | null; connectionAttemptId: string | null; } /** * Attach connection-attempt diagnostics only to the exact failed Connect * action which produced them. A global Scan/Verify/Refresh failure must never * borrow an older durable attempt merely because it remains in the snapshot. */ export function connectionAttemptForRuntimeError( error: RuntimeErrorCorrelation | null | undefined, state: XgridsK1State | null | undefined, ): XgridsConnectionAttempt | null { const runtimeId = state?.snapshot_runtime_id?.trim() || null; const attempt = state?.connection_attempt; return error?.action === "connect" && typeof error.runtimeId === "string" && error.runtimeId === runtimeId && typeof error.connectionAttemptId === "string" && attempt && error.connectionAttemptId === attempt?.attempt_id && !["accepted", "running"].includes(attempt.status) ? attempt : null; } export function reachableConnectionLeaseIdentity( state: XgridsK1State | null | undefined, ): ReachableConnectionLeaseIdentity | null { const runtimeId = state?.snapshot_runtime_id; const supervisor = state?.connection_supervisor; const connectionMode = supervisor?.lease.connection_mode; const leaseGeneration = supervisor?.lease.generation; const intentId = supervisor?.intent?.intent_id; const hostPathEpoch = supervisor?.lease.host_path_epoch; if ( typeof runtimeId !== "string" || !runtimeId.trim() || !connectionMode || !intentId || !Number.isInteger(leaseGeneration) || (leaseGeneration ?? -1) < 0 || !Number.isInteger(hostPathEpoch) || (hostPathEpoch ?? 0) < 1 || !isReachableConnectionLease(state, connectionMode) ) { return null; } return { key: `${runtimeId}:${intentId}:${hostPathEpoch}:${leaseGeneration}`, runtimeId, leaseGeneration: leaseGeneration as number, intentId, hostPathEpoch: hostPathEpoch as number, connectionMode, }; } export function authoritativeReachableLeaseSupersedesError( error: RuntimeErrorCorrelation | null | undefined, state: XgridsK1State | null | undefined, ): boolean { if ( !error || (error.action !== "connect" && error.action !== "verify") || typeof error.runtimeId !== "string" || !Number.isInteger(error.leaseGeneration) // An omitted legacy field is not proof that the process-owned write fence // was cleared. Only the canonical explicit null may dismiss the banner. || hasUnresolvedNetworkMutation(state) ) { return false; } const identity = reachableConnectionLeaseIdentity(state); return Boolean( identity && identity.runtimeId === error.runtimeId && identity.leaseGeneration > (error.leaseGeneration as number), ); } /** * Clear a transient action banner when a later authoritative state proves * that the failed local acquisition has already been sealed and released. * Every poll/WebSocket state enters through the same reducer, so recovery * needs no refresh button or browser-cache reset. */ export function authoritativeStateSupersedesRuntimeError( error: RuntimeErrorCorrelation | null | undefined, state: XgridsK1State | null | undefined, ): boolean { return Boolean( authoritativeReachableLeaseSupersedesError(error, state) || (error && !shouldSurfaceRuntimeActionError(error.action, state)), ); } function defaultUuid(): string { const cryptoApi = globalThis.crypto; if (!cryptoApi) { throw new Error("Web Crypto недоступен; безопасный идентификатор операции не создан."); } if (typeof cryptoApi.randomUUID === "function") return cryptoApi.randomUUID(); const bytes = new Uint8Array(16); cryptoApi.getRandomValues(bytes); bytes[6] = (bytes[6] & 0x0f) | 0x40; bytes[8] = (bytes[8] & 0x3f) | 0x80; const hex = [...bytes].map((value) => value.toString(16).padStart(2, "0")); return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex .slice(6, 8) .join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`; } export function newOperationId(): string { return `op-${defaultUuid()}`; } export function newPhysicalRetirementId(): string { return `retirement-${defaultUuid()}`; } export function newPhysicalReopeningId(): string { return `reopening-${defaultUuid()}`; } export function newMutationContext(action: string): { operation_id: string; idempotency_key: string; } { const normalizedAction = action.trim(); if (!normalizedAction) { throw new Error("Действие операции не задано; безопасный ключ не создан."); } const operationId = newOperationId(); return { operation_id: operationId, idempotency_key: `${normalizedAction}:${operationId}`, }; } export function provisioningIntentKey( current: string | null, createUuid: () => string = defaultUuid, ): string { return current ?? `network-provision:${createUuid()}`; }