diff --git a/apps/control-station/test/sensorEnrollment.test.mjs b/apps/control-station/test/sensorEnrollment.test.mjs
index 94582ae..fbc5afa 100644
--- a/apps/control-station/test/sensorEnrollment.test.mjs
+++ b/apps/control-station/test/sensorEnrollment.test.mjs
@@ -88,6 +88,17 @@ test('Bluetooth failure before dispatch asks for discovery without blaming Wi-Fi
assert.equal(api.enrollmentBluetoothFailure(unknown),false);
assert.doesNotMatch(api.enrollmentNotice(unknown),/не были отправлены/);
});
+test('applied and restored network states admit read-only verification without credentials',async()=>{
+ const f=fixture();
+ const applied={...initial,allowed_actions:['observe-configured-device-network'],connection_attempt:{schema_version:'missioncore.xgrids-k1-connection-attempt/v1',attempt_id:'previous',status:'failed',stage:'control-bootstrap-failed',phase:'network_applied',side_effect_status:'applied',public_error_code:'TypeError'}};
+ assert.equal(api.enrollmentAllowed(applied,'verify'),true);
+ assert.match(api.enrollmentNotice(applied),/Проверить состояние K1/);
+ assert.equal(api.enrollmentAllowed({...applied,connection_attempt:null},'verify'),true);
+ await api.enroll(f.transport,applied,'verify',{device_id:'synthetic-ble'},f.observer);
+ assert.equal(f.request().action,'verify');
+ assert.deepEqual(f.request().parameters,{device_id:'synthetic-ble'});
+ assert.equal(f.counts().posts,1);
+});
test('new workflow content scrolls only the containing viewport without stealing focus',()=>{
const original={document:globalThis.document,window:globalThis.window,getComputedStyle:globalThis.getComputedStyle};
const calls=[];let reduced=false;
diff --git a/apps/node-agent/packaging/build.py b/apps/node-agent/packaging/build.py
index 0c53aaa..d9a1bd8 100644
--- a/apps/node-agent/packaging/build.py
+++ b/apps/node-agent/packaging/build.py
@@ -11,7 +11,7 @@ import sys
from build_deb import build, VERSION, BRAND_SHA256
ROOT = Path(__file__).resolve().parents[1]
-DG_COMMIT = "1bdfc6c24072d38cc1068086ea271c444f2524ad"
+DG_COMMIT = "5b882bc3d9b13a86e6c26111ef5ded687ea3a2fc"
def guideline_sources():
diff --git a/apps/node-agent/packaging/build_deb.py b/apps/node-agent/packaging/build_deb.py
index 2806c6d..f20be49 100644
--- a/apps/node-agent/packaging/build_deb.py
+++ b/apps/node-agent/packaging/build_deb.py
@@ -11,7 +11,7 @@ import sys
ROOT = Path(__file__).resolve().parents[1]
-VERSION = "0.8.4"
+VERSION = "0.8.5"
sys.path.insert(0, str(ROOT.parents[1] / "scripts/packaging"))
from debian import package
diff --git a/docs/audits/2026-09-07-k1-linux-route-contract-r7.md b/docs/audits/2026-09-07-k1-linux-route-contract-r7.md
new file mode 100644
index 0000000..9f88424
--- /dev/null
+++ b/docs/audits/2026-09-07-k1-linux-route-contract-r7.md
@@ -0,0 +1,61 @@
+# Applied Wi-Fi and Linux control-path contract R7
+
+The owner UI attempt on R6 confirmed K1 station Wi-Fi with an assigned private
+address. The network operation succeeded; its owned read-only control bootstrap
+then failed with TypeError. The terminal attempt is network_applied,
+side_effect_status=applied, stage=control-bootstrap-failed. This differs from
+the preceding pre-dispatch Bluetooth failure. A repeat provisioning write is
+not the appropriate next action.
+
+## Reproduced implementation defect
+
+HostWifiAssociationProbe defines observe(interface_name, *, timeout_seconds).
+The real service _sample_host_path calls that positional interface contract.
+LinuxWifiAssociationProbe instead declared interface_name keyword-only.
+Consequently every real Linux service path observation raised TypeError before
+examining Ethernet/Wi-Fi or probing the K1 control endpoint. The earlier adapter
+test called observe by keyword and therefore missed this consumer boundary.
+
+A new test invokes the actual service host-path and correlated TCP observation
+with the real Linux adapter and synthetic OS route/sysfs/TCP endpoints. Before
+the fix it reproduces TypeError at facade.py:_sample_host_path. The Linux adapter
+now accepts the existing protocol signature. Stable Ethernet reaches a single
+TCP probe without nmcli or host association; a route change across that probe
+still fails closed. The caller, route fingerprints, supervisor, Wi-Fi protocol,
+application authority and MQTT/Rerun profiles are unchanged.
+
+## Operator continuation and messages
+
+The modal previously displayed read-only verification only for
+network_outcome_unknown, leaving an applied network without its prescribed
+next action. It now exposes Check K1 state whenever the backend permits that
+read-only action for the explicitly selected device, including an applied or
+restored configured network. No credentials are required and the existing
+verification contract remains fenced by runtime/mode/discovery/target.
+The ordinary check still submits one explicit provisioning intent; final
+Connect still only completes a currently verified dialog.
+
+Messages in the modal use SettingsCard align=center. The canonical Design
+Guideline change is 5b882bc3d9b13a86e6c26111ef5ded687ea3a2fc, including registry,
+documentation and a catalog example. Centered cards omit an empty body and
+center their content on both axes; ordinary settings groups keep their existing
+start layout. No local CSS override, fixed height, new colors or decoration.
+Node packaging pins this exact DG source.
+
+## Validation and pending physical acceptance
+
+The failing reproduction is retained privately. After the fix: 18 NodeBridge /
+package lifecycle checks passed, four applied-network bootstrap lifecycle checks
+passed, 23 focused frontend/architecture checks passed and 794 full Core
+frontend tests passed. Changed Linux/backend files pass Ruff. DG ui-react build,
+catalog typecheck and registry validation passed. Production package and
+installation results follow separately.
+
+Node 0.8.5 and K1 0.1.4 are reserved for this source. The next owner UI test must
+clear browser cache, select K1 and use read-only Check K1 state to observe the
+already applied network. It must prove DeviceInfo/control readiness before
+claiming Bridge or live acceptance. Private screenshot, exact operation,
+UTC/monotonic manifest and hashed logs are retained under
+private/acceptance/k1-node085-20260907-core-ui. No agent CLI BLE/MQTT commands
+were sent. Publication of prior installation reports remains blocked by the
+earlier automatic review decision; no remote push workaround is used.
diff --git a/plugins/xgrids-k1/frontend/src/sensors/DeviceEnrollmentWindow.tsx b/plugins/xgrids-k1/frontend/src/sensors/DeviceEnrollmentWindow.tsx
index 2dda3d6..e5eb9ef 100644
--- a/plugins/xgrids-k1/frontend/src/sensors/DeviceEnrollmentWindow.tsx
+++ b/plugins/xgrids-k1/frontend/src/sensors/DeviceEnrollmentWindow.tsx
@@ -115,14 +115,14 @@ export function DeviceEnrollmentWindow({transport,onChange,onClose,renderWindow}