Files
story/scripts/probe-direct-no-startup.cjs
T

41 lines
2.5 KiB
JavaScript
Raw Normal View History

// Read-only production checks on the independent handoff device. Never bind it,
// start a real conversation or print private keys/voice/MQTT credentials.
const fs = require('node:fs');
const crypto = require('node:crypto');
const net = require('node:net');
const assert = require('node:assert/strict');
const { sign } = require('../docs/embedded-signing-reference.cjs');
async function main() {
const init = JSON.parse(fs.readFileSync(process.argv[2], 'utf8').replace(/^\uFEFF/, ''));
assert.equal(init.factory_id, 'KP01-020000260914');
assert.equal(init.origin, 'https://82.157.201.114');
const health = await fetch(init.origin + '/health/ready', { signal: AbortSignal.timeout(15000) });
assert.equal(health.status, 200);
const offset = Date.parse(health.headers.get('date')) - Date.now();
assert.ok(Number.isFinite(offset));
const post = async (path, input) => {
const raw = JSON.stringify(input);
const headers = sign(Buffer.from(init.device_key_hex, 'hex'), { path, deviceId: init.factory_id,
keyVersion: init.key_version, timestamp: Date.now() + offset, nonce: crypto.randomBytes(16).toString('base64url'), requestId: crypto.randomUUID(), raw }).headers;
const response = await fetch(init.origin + path, { method: 'POST', headers, body: raw, signal: AbortSignal.timeout(15000) });
return { status: response.status, body: await response.json() };
};
const state = await post('/api/v1/device/ble-state', {});
assert.equal(state.status, 200);
assert.equal(state.body.data.bound, false, 'Test device is bound: skip any chat probe');
const start = await post('/api/v1/device/chat/start', { device_id: init.factory_id, session_id: crypto.randomUUID() });
assert.equal(start.status, 409);
assert.equal(start.body.code, 'DEVICE_UNBOUND');
const mqtt = await new Promise(resolve => {
const socket = net.connect({ host: '82.157.201.114', port: 1883 });
socket.setTimeout(8000);
socket.once('connect', () => { resolve('TCP_OK'); socket.destroy(); });
socket.once('timeout', () => { resolve('TIMEOUT'); socket.destroy(); });
socket.once('error', error => { resolve(error.code || 'TCP_FAILED'); socket.destroy(); });
});
console.log(JSON.stringify({ health: health.status, device_id: init.factory_id, bound: false,
chat_without_boot_id: start.status, chat_error: start.body.code, mqtt_public_tcp: mqtt,
startup_endpoints_called: 0, bindings_changed: 0, real_calls_started: 0 }));
}
main().catch(() => { console.error('Live probe failed; no private values printed.'); process.exitCode = 1; });