Files
story/scripts/probe-direct-no-startup.cjs
Codex Local bf1233d5df
ci / verify (push) Canceled after 0s
feat: expand companion platform, device controls, and memoir workflows
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
2026-10-08 10:06:44 +08:00

41 lines
2.5 KiB
JavaScript

// 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; });