fix: align device pod status contract

This commit is contained in:
Codex
2026-05-29 19:13:06 +08:00
parent 49b435796b
commit 8f0bda969b
4 changed files with 58 additions and 6 deletions
+7
View File
@@ -28,6 +28,13 @@ test("device pod executor exposes cloud-api authority boundary and method guards
assert.equal(status.devicePodId, "device-pod-test");
assert.equal(status.status, "blocked");
assert.equal(status.summary.blocker.code, "gateway_dispatch_unavailable");
assert.equal(status.targetId, null);
assert.equal(status.profileHash, "");
assert.match(status.traceId, /^trc_devicepod_/u);
assert.match(status.operationId, /^op_devicepod_/u);
assert.equal(status.freshness.stale, true);
assert.equal(status.truncation.truncated, false);
assert.match(status.output.summary, /device-host-cli dispatch is owned/u);
const events = await fetchJson(`http://127.0.0.1:${service.port}/v1/device-pods/device-pod-test/events?limit=1`);
assert.equal(events.events.length, 1);
+19 -2
View File
@@ -103,17 +103,34 @@ function listPayload() {
}
function statusPayload(id) {
const blocker = gatewayAdapterBlocker("device-host-cli dispatch is owned by hwlab-cloud-api gateway routing");
const observedAt = new Date().toISOString();
const output = boundedOutput({ text: blocker.summary, summary: blocker.summary });
const freshnessPayload = freshness(observedAt, blocker);
return {
serviceId: SERVICE_ID,
contractVersion: CONTRACT_VERSION,
status: "blocked",
devicePodId: id,
observedAt: new Date().toISOString(),
targetId: null,
profileHash: "",
traceId: `trc_devicepod_${randomUUID()}`,
operationId: `op_devicepod_${randomUUID()}`,
observedAt,
source: sourcePayload(),
blocker,
freshness: freshnessPayload,
output,
text: output.text,
bytes: output.bytes,
truncation: output.truncation,
summary: {
devicePodId: id,
targetId: null,
profileHash: "",
status: "blocked",
blocker: gatewayAdapterBlocker("device-host-cli dispatch is owned by hwlab-cloud-api gateway routing")
freshness: freshnessPayload,
blocker
}
};
}
+13
View File
@@ -110,6 +110,19 @@ test("cloud api access control grants visible device pods and requires device-po
assert.equal(visible.body.devicePods[0].devicePodId, "device-pod-71-freq");
assert.match(visible.body.devicePods[0].profileHash, /^sha256:/u);
const status = await getJson(port, "/v1/device-pods/device-pod-71-freq/status", aliceCookie);
assert.equal(status.status, 200);
assert.equal(status.body.devicePodId, "device-pod-71-freq");
assert.equal(status.body.targetId, "target-71-freq");
assert.equal(status.body.profileHash, visible.body.devicePods[0].profileHash);
assert.match(status.body.traceId, /^trc_devicepod_/u);
assert.match(status.body.operationId, /^op_devicepod_/u);
assert.equal(status.body.status, "ok");
assert.equal(status.body.freshness.stale, false);
assert.equal(status.body.blocker, null);
assert.equal(status.body.truncation.truncated, false);
assert.equal(status.body.output.summary, "device-pod status ok");
const job = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", {
intent: "workspace.ls",
args: { path: "." }
+19 -4
View File
@@ -609,19 +609,34 @@ class AccessController {
const gatewaySessionId = textOr(route.gatewaySessionId, "");
const gatewayOnline = gatewaySessionId && this.gatewayRegistry?.isOnline?.(gatewaySessionId) === true;
const blocker = gatewayOnline ? null : gatewayDispatchBlocker(gatewaySessionId ? "gateway session is not connected" : "profile route.gatewaySessionId is missing");
const observedAt = this.now();
const status = blocker ? "blocked" : "ok";
const output = boundedOutput({ text: blocker?.summary ?? "device-pod status ok", summary: blocker?.summary ?? "device-pod status ok" });
const freshnessPayload = freshness(observedAt, blocker);
return {
serviceId: CLOUD_API_SERVICE_ID,
contractVersion: "device-pod-authority-v1",
status: blocker ? "blocked" : "ok",
observedAt: this.now(),
status,
devicePodId: pod.id,
targetId: targetIdFromProfile(pod.profile),
profileHash: pod.profileHash,
traceId: `trc_devicepod_${randomUUID()}`,
operationId: `op_devicepod_${randomUUID()}`,
observedAt,
source: authoritySource(),
actor: publicActor(actor),
devicePod: publicDevicePod(pod),
blocker,
freshness: freshnessPayload,
output: output.output,
text: output.text,
bytes: output.bytes,
truncation: output.truncation,
summary: {
devicePodId: pod.id,
targetId: targetIdFromProfile(pod.profile),
status: blocker ? "blocked" : "ok",
freshness: freshness(this.now(), blocker),
status,
freshness: freshnessPayload,
profileHash: pod.profileHash,
blocker
}