use std::fs;
use std::path::PathBuf;
use std::process::{Command, Output};
use std::sync::atomic::{AtomicU64, Ordering};
static NEXT_FIXTURE: AtomicU64 = AtomicU64::new(0);
struct Fixture {
root: PathBuf,
}
impl Fixture {
fn new(label: &str, tracing: &str, server_options: &str) -> Self {
let ordinal = NEXT_FIXTURE.fetch_add(1, Ordering::Relaxed);
let root = std::env::temp_dir().join(format!(
"noxid-wo25-qa1-nested-{label}-{}-{ordinal}",
std::process::id()
));
fs::create_dir_all(&root).expect("create WO-25 nested QA fixture");
fs::write(root.join("package.json"), "{\"type\":\"module\"}\n").expect("write ESM marker");
fs::write(
root.join("Noxid.toml"),
format!(
"[app]\ntitle = \"WO-25 nested QA\"\nhost = \"src/host.js\"\n\n[server]\ntracing = \"{tracing}\"\n{server_options}"
),
)
.expect("write fixture manifest");
let fixture = Self { root };
fixture.write(
"src/host.js",
"export default Object.freeze({ authorizeComponent() { return true; } });\n",
);
fixture
}
fn write(&self, relative: &str, contents: &str) {
let path = self.root.join(relative);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).expect("create fixture parent");
}
fs::write(path, contents).expect("write fixture file");
}
fn build(&self) -> Output {
Command::new(env!("CARGO_BIN_EXE_noxid"))
.args(["build", ".", "--out-dir", "dist"])
.current_dir(&self.root)
.output()
.expect("build WO-25 nested QA fixture")
}
fn run(&self, name: &str, source: &str) -> Output {
self.write(&format!("dist/{name}.mjs"), source);
Command::new("node")
.arg(format!("{name}.mjs"))
.current_dir(self.root.join("dist"))
.output()
.expect("execute generated tracing runtime")
}
fn run_with_database(&self, name: &str, source: &str) -> Output {
self.write(&format!("dist/{name}.mjs"), source);
Command::new("node")
.arg(format!("{name}.mjs"))
.env("DATABASE_URL", "postgres://qa.invalid/noxid")
.current_dir(self.root.join("dist"))
.output()
.expect("execute generated tracing runtime with fake database")
}
fn install_fake_postgres(&self) {
self.write(
"dist/node_modules/postgres/package.json",
"{\"type\":\"module\",\"exports\":\"./index.js\"}\n",
);
self.write(
"dist/node_modules/postgres/index.js",
r#"export default function postgres() {
const sql = async (strings) => {
const query = strings.join("?");
if (query.includes("SELECT id, queue, payload")) return globalThis.__qaSelect();
return [];
};
sql.unsafe = async () => [];
sql.begin = async (callback) => callback(sql);
sql.end = async () => {};
sql.json = (value) => value;
return sql;
}
"#,
);
}
}
impl Drop for Fixture {
fn drop(&mut self) {
let _ = fs::remove_dir_all(&self.root);
}
}
fn assert_success(output: &Output, context: &str) {
assert!(
output.status.success(),
"{context}:\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
}
fn trace_records(output: &Output) -> Vec<&str> {
std::str::from_utf8(&output.stdout)
.expect("trace output must be UTF-8")
.lines()
.collect()
}
fn write_nested_surfaces(fixture: &Fixture) {
fixture.write(
"src/routes/+page.nox",
r#"component Home {
route { title: "Nested tracing" render: ssr }
render { mode: universal hydrate: never }
requires [ probe.read ]
props { value: Static<String> }
actions { server loadValue(): String { } }
loaders { value = loadValue() }
view { <main>{value}</main> }
}
"#,
);
fixture.write(
"server/api/probe.get.nox",
r#"endpoint Probe {
result: String
capabilities [probe.read]
}
"#,
);
fixture.write(
"server/tasks/Nightly.nox",
"task Nightly { schedule: \"0 3 * * *\" }\n",
);
fixture.write(
"server/host.js",
r#"export const actions = Object.freeze({
"action:Home.loadValue": async (_arguments, context) => {
globalThis.__qaContexts?.push({ kind: "action", traceId: context.traceId, semanticId: context.semanticId });
return "loaded";
},
});
export const endpoints = Object.freeze({
"endpoint:Probe@1": async (_arguments, context) => {
globalThis.__qaContexts?.push({ kind: "endpoint", traceId: context.traceId, semanticId: context.semanticId });
return "ready";
},
});
export const tasks = Object.freeze({
"task:Nightly": async (_arguments, context) => {
globalThis.__qaContexts?.push({ kind: "task", traceId: context.traceId, semanticId: context.semanticId });
return "done";
},
});
export async function authorize({ request }) {
return request.headers.get("x-grant") === "yes";
}
"#,
);
}
#[test]
fn nested_ssr_loader_and_mcp_endpoint_inherit_one_trace_without_duplicate_request_spans() {
let fixture = Fixture::new("nested-success", "full", "mcp = true\n");
write_nested_surfaces(&fixture);
assert_success(&fixture.build(), "build nested SSR/MCP tracing fixture");
let output = fixture.run(
"nested-success",
r#"import { fetch as handle } from "./server/handler.js";
const ssr = await handle(new Request("http://noxid.test/_noxid/ssr", {
method: "POST",
headers: { "content-type": "application/json", "x-grant": "yes", "x-noxid-trace": "QA_NESTED_SSR_0001" },
body: JSON.stringify({ url: "http://noxid.test/" }),
}));
if (ssr.status !== 200 || (await ssr.json()).ok !== true) throw new Error("SSR loader failed");
const mcp = await handle(new Request("http://noxid.test/_noxid/mcp", {
method: "POST",
headers: {
"content-type": "application/json",
accept: "application/json, text/event-stream",
"x-grant": "yes",
"x-noxid-trace": "QA_NESTED_MCP_0001",
},
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "Probe", arguments: {} } }),
}));
const rpc = await mcp.json();
if (mcp.status !== 200 || rpc.result?.isError !== false) throw new Error(JSON.stringify(rpc));
"#,
);
assert_success(&output, "execute nested SSR/MCP tracing fixture");
let records = trace_records(&output);
assert_eq!(records.len(), 8, "unexpected nested spans: {records:?}");
for (offset, (trace_id, semantic_event, semantic_id, nested_span)) in [
(
"QA_NESTED_SSR_0001",
"action",
"action:Home.loadValue",
"loader",
),
(
"QA_NESTED_MCP_0001",
"endpoint",
"endpoint:Probe@1",
"subrequest",
),
]
.into_iter()
.enumerate()
{
let slice = &records[offset * 4..offset * 4 + 4];
assert!(slice[0].contains(&format!("\"traceId\":\"{trace_id}\"")));
assert!(
slice[0].contains("\"sequence\":1") && slice[0].contains("\"event\":\"request.start\"")
);
assert!(slice[1].contains("\"sequence\":2"));
assert!(slice[1].contains(&format!("\"event\":\"{semantic_event}\"")));
assert!(slice[1].contains(&format!("\"semanticId\":\"{semantic_id}\"")));
assert!(
slice[2].contains("\"sequence\":3")
&& slice[2].contains(&format!("\"event\":\"{nested_span}\""))
&& slice[2].contains(&format!("\"spanName\":\"{nested_span}\"")),
"the nested span must keep its own name and the trace's counter: {}",
slice[2]
);
assert!(
slice[3].contains("\"sequence\":4") && slice[3].contains("\"event\":\"request.end\"")
);
if trace_id == "QA_NESTED_MCP_0001" {
for record in slice {
assert!(
record.contains("\"agentSemanticId\":\"endpoint:Probe@1\"")
&& record.contains("\"actingPrincipal\":\"system\""),
"agent span lacks its stable identity: {record}"
);
}
}
}
}
#[test]
fn nested_mcp_validation_refusal_keeps_outer_trace_and_emits_once() {
let fixture = Fixture::new("mcp-refusal", "full", "mcp = true\n");
fixture.write(
"server/api/probe.post.nox",
"endpoint Probe { body { value: String } result: String }\n",
);
fixture.write(
"server/host.js",
r#"export const endpoints = Object.freeze({
"endpoint:Probe@1": async ({ value }) => value,
});
"#,
);
assert_success(&fixture.build(), "build MCP refusal fixture");
let output = fixture.run(
"mcp-refusal",
r#"import { fetch as handle } from "./server/handler.js";
const response = await handle(new Request("http://noxid.test/_noxid/mcp", {
method: "POST",
headers: {
"content-type": "application/json",
accept: "application/json, text/event-stream",
"x-noxid-trace": "QA_MCP_REFUSAL_0001",
},
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "Probe", arguments: { value: 7 } } }),
}));
const rpc = await response.json();
if (rpc.result?.structuredContent?.body?.error?.code !== "ENDPOINT_INPUT_TYPE") throw new Error(JSON.stringify(rpc));
"#,
);
assert_success(&output, "execute nested MCP refusal fixture");
let records = trace_records(&output);
assert_eq!(
records.len(),
4,
"MCP refusal emitted duplicate/missing spans: {records:?}"
);
assert!(
records[0].contains("\"event\":\"request.start\"") && records[0].contains("\"sequence\":1")
);
assert!(records[1].contains("\"event\":\"validation.refused\""));
assert!(
records[1].contains("\"code\":\"ENDPOINT_INPUT_TYPE\"")
&& records[1].contains("\"sequence\":2")
);
assert!(
records[2].contains("\"event\":\"subrequest\"")
&& records[2].contains("\"spanName\":\"subrequest\"")
&& records[2].contains("\"sequence\":3"),
"the refused subrequest must close as a nested span on the trace's own \
counter: {}",
records[2]
);
assert!(
records[3].contains("\"event\":\"request.end\"") && records[3].contains("\"sequence\":4")
);
assert_eq!(
records
.iter()
.filter(|line| line.contains("\"event\":\"validation.refused\""))
.count(),
1,
"the nested refusal must be owned once: {records:?}"
);
assert!(
records
.iter()
.all(|line| line.contains("\"traceId\":\"QA_MCP_REFUSAL_0001\""))
);
}
#[test]
fn nested_ssr_loader_capability_refusal_is_not_lost_when_renderer_wraps_response() {
let fixture = Fixture::new("ssr-refusal", "full", "");
write_nested_surfaces(&fixture);
assert_success(&fixture.build(), "build SSR loader refusal fixture");
let output = fixture.run(
"ssr-refusal",
r#"import { fetch as handle } from "./server/handler.js";
const response = await handle(new Request("http://noxid.test/_noxid/ssr", {
method: "POST",
headers: { "content-type": "application/json", "x-noxid-trace": "QA_SSR_REFUSAL_0001" },
body: JSON.stringify({ url: "http://noxid.test/" }),
}));
if (response.status !== 403) throw new Error(`unexpected SSR status ${response.status}: ${await response.text()}`);
"#,
);
assert_success(&output, "execute SSR loader refusal fixture");
let records = trace_records(&output);
let denials = records
.iter()
.filter(|line| line.contains("\"event\":\"capability.denied\""))
.collect::<Vec<_>>();
assert_eq!(
denials.len(),
1,
"nested loader denial was lost or duplicated: {records:?}"
);
assert!(denials[0].contains("\"code\":\"BOUNDARY_CAPABILITY_DENIED\""));
assert!(denials[0].contains("\"semanticId\":\"action:Home.loadValue\""));
assert_eq!(
records
.iter()
.filter(|line| line.contains("\"event\":\"request.start\""))
.count(),
1
);
assert_eq!(
records
.iter()
.filter(|line| line.contains("\"event\":\"request.end\""))
.count(),
1
);
for (index, line) in records.iter().enumerate() {
assert!(
line.contains(&format!("\"sequence\":{}", index + 1)),
"{line}"
);
assert!(
line.contains("\"traceId\":\"QA_SSR_REFUSAL_0001\""),
"{line}"
);
}
}
#[test]
fn idempotency_snapshot_wrapper_preserves_result_validation_refusal_metadata() {
let fixture = Fixture::new("idempotent-refusal", "full", "");
fixture.write(
"server/api/save.post.nox",
r#"endpoint Save {
body { value: String }
result: String
idempotent
}
"#,
);
fixture.write(
"server/host.js",
r#"export const endpoints = Object.freeze({
"endpoint:Save@1": async () => 7,
});
"#,
);
assert_success(&fixture.build(), "build idempotent refusal fixture");
let output = fixture.run(
"idempotent-refusal",
r#"import { fetch as handle } from "./server/handler.js";
const response = await handle(new Request("http://noxid.test/api/save", {
method: "POST",
headers: {
"content-type": "application/json",
"idempotency-key": "qa-result-refusal",
"x-noxid-trace": "QA_IDEMPOTENT_0001",
},
body: JSON.stringify({ value: "accepted-input" }),
}), { ip: "192.0.2.25" });
const body = await response.json();
if (response.status !== 500 || body.error?.code !== "ENDPOINT_RESULT_TYPE") throw new Error(JSON.stringify(body));
"#,
);
assert_success(&output, "execute idempotent refusal fixture");
let records = trace_records(&output);
let refusals = records
.iter()
.filter(|line| line.contains("\"event\":\"validation.refused\""))
.collect::<Vec<_>>();
assert_eq!(
refusals.len(),
1,
"idempotency response wrapper lost refusal metadata: {records:?}"
);
assert!(refusals[0].contains("\"code\":\"ENDPOINT_RESULT_TYPE\""));
assert!(refusals[0].contains("\"semanticId\":\"endpoint-result:Save\""));
}
#[test]
fn request_and_off_modes_filter_ssr_mcp_task_and_queue_worker_semantic_spans() {
for mode in ["requests", "off"] {
let fixture = Fixture::new(&format!("filter-{mode}"), mode, "mcp = true\n");
write_nested_surfaces(&fixture);
fixture.write(
"server/queues/SendReceipt.nox",
"queue SendReceipt { payload { value: String } retry: 1 backoff: 1s }\n",
);
fixture.write(
"server/host.js",
r#"export const actions = Object.freeze({ "action:Home.loadValue": async () => "loaded" });
export const endpoints = Object.freeze({ "endpoint:Probe@1": async () => "ready" });
export const tasks = Object.freeze({ "task:Nightly": async () => "done" });
export const queues = Object.freeze({ "queue:SendReceipt": async () => true });
export async function authorize() { return true; }
"#,
);
assert_success(&fixture.build(), &format!("build {mode} filtering fixture"));
let output = fixture.run(
&format!("filter-{mode}"),
r#"import { fetch as handle, startQueueWorker } from "./server/handler.js";
let response = await handle(new Request("http://noxid.test/_noxid/ssr", {
method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ url: "http://noxid.test/" }),
}));
await response.text();
response = await handle(new Request("http://noxid.test/_noxid/mcp", {
method: "POST",
headers: { "content-type": "application/json", accept: "application/json, text/event-stream" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "Probe", arguments: {} } }),
}));
await response.text();
response = await handle(new Request("http://noxid.test/_noxid/tasks/Nightly", { method: "POST" }));
await response.text();
const worker = startQueueWorker({ queue: "SendReceipt", setTimeout: () => 1, clearTimeout: () => {}, onError: () => {} });
await new Promise((resolve) => setImmediate(resolve));
await worker.stop();
"#,
);
assert_success(&output, &format!("execute {mode} filtering fixture"));
let records = trace_records(&output);
if mode == "off" {
assert!(
records.is_empty(),
"off emitted nested/task/queue spans: {records:?}"
);
} else {
assert_eq!(
records.len(),
6,
"requests mode leaked full spans: {records:?}"
);
assert_eq!(
records
.iter()
.filter(|line| line.contains("\"event\":\"request.start\""))
.count(),
3
);
assert_eq!(
records
.iter()
.filter(|line| line.contains("\"event\":\"request.end\""))
.count(),
3
);
for forbidden in [
"\"event\":\"action\"",
"\"event\":\"endpoint\"",
"\"event\":\"task\"",
"\"event\":\"queue.state\"",
] {
assert!(
!records.iter().any(|line| line.contains(forbidden)),
"requests mode emitted {forbidden}: {records:?}"
);
}
}
}
}
#[test]
fn task_and_queue_context_trace_ids_match_allowlisted_semantic_spans() {
let fixture = Fixture::new("task-queue-identity", "full", "");
fixture.write(
"server/tasks/Nightly.nox",
"task Nightly { schedule: \"0 3 * * *\" }\n",
);
fixture.write(
"server/queues/SendReceipt.nox",
"queue SendReceipt { payload { secretPayload: String } retry: 1 backoff: 1s }\n",
);
fixture.write(
"server/host.js",
r#"export const tasks = Object.freeze({
"task:Nightly": async (_arguments, context) => { globalThis.__qaTaskContext = context; return "done"; },
});
export const queues = Object.freeze({
"queue:SendReceipt": async (payload, context) => { globalThis.__qaQueue = { payload, context }; return true; },
});
export async function authorize() { return true; }
"#,
);
assert_success(&fixture.build(), "build task/queue identity fixture");
fixture.install_fake_postgres();
let output = fixture.run_with_database(
"task-queue-identity",
r#"globalThis.__qaSelect = (() => {
let claimed = false;
return async () => {
if (claimed) return [];
claimed = true;
return [{ id: "qa-job-25", queue: "SendReceipt", payload: { secretPayload: "QUEUE_SECRET_MUST_NOT_LEAK" }, principal: null, attempts: 4, run_at: new Date("2028-02-29T12:00:00Z") }];
};
})();
const emitted = [];
const originalLog = console.log;
console.log = (line) => { emitted.push(JSON.parse(line)); originalLog(line); };
const { fetch: handle, workQueueOnce, closeQueueDatabase } = await import("./server/handler.js");
let response = await handle(new Request("http://noxid.test/_noxid/tasks/Nightly", {
method: "POST", headers: { "x-noxid-trace": "QA_TASK_IDENTITY_01" },
}));
if (response.status !== 200) throw new Error(`task status ${response.status}`);
await response.text();
const queued = await workQueueOnce({ queue: "SendReceipt", worker: "qa", now: "2028-02-29T12:00:00Z" });
if (queued?.state !== "completed") throw new Error(JSON.stringify(queued));
await closeQueueDatabase();
if (globalThis.__qaTaskContext.semanticId !== "task:Nightly" || globalThis.__qaTaskContext.traceId !== "QA_TASK_IDENTITY_01") throw new Error("task context identity drifted");
if (globalThis.__qaQueue.context.semanticId !== "queue:SendReceipt") throw new Error("queue semantic identity drifted");
const queueSpan = emitted.find((record) => record.event === "queue");
if (typeof queueSpan?.traceId !== "string" || globalThis.__qaQueue.context.traceId !== queueSpan.traceId) throw new Error("queue trace context disagreed with its semantic span");
"#,
);
assert_success(&output, "execute task/queue identity fixture");
let records = trace_records(&output);
assert_eq!(records.len(), 4, "unexpected task/queue spans: {records:?}");
assert!(
records[1].contains("\"event\":\"task\"")
&& records[1].contains("\"semanticId\":\"task:Nightly\"")
);
assert!(
records[3].contains("\"event\":\"queue\"")
&& records[3].contains("\"semanticId\":\"queue:SendReceipt\"")
);
assert!(
records[3].contains("\"jobId\":\"qa-job-25\"") && records[3].contains("\"attempts\":5")
);
let queue_trace = records[3]
.split("\"traceId\":\"")
.nth(1)
.and_then(|tail| tail.split('"').next())
.expect("queue span trace ID");
assert!(!queue_trace.is_empty());
let stdout = String::from_utf8_lossy(&output.stdout);
for forbidden in ["secretPayload", "QUEUE_SECRET_MUST_NOT_LEAK"] {
assert!(
!stdout.contains(forbidden),
"queue span leaked {forbidden}: {stdout}"
);
}
}
#[test]
fn throwing_request_accessors_cannot_echo_secret_values_or_split_json_lines() {
let fixture = Fixture::new("hostile-accessors", "requests", "");
fixture.write("server/host.js", "export default Object.freeze({});\n");
fixture.write(
"server/tasks/Probe.nox",
"task Probe { schedule: \"0 0 * * *\" handler { return true } }\n",
);
assert_success(&fixture.build(), "build hostile accessor fixture");
let output = fixture.run(
"hostile-accessors",
r#"import { withNoxidRequestTrace } from "./server/handler.js";
const secret = "ACCESSOR_SECRET_\r\n{\"event\":\"forged\"}";
const request = {};
Object.defineProperty(request, "headers", { get() { throw new Error(secret); } });
Object.defineProperty(request, "method", { get() { throw new Error(secret); } });
const response = await withNoxidRequestTrace(request, async () => new Response(null, { status: 204 }));
if (response.status !== 204) throw new Error("operation changed");
"#,
);
assert_success(&output, "execute hostile accessor fixture");
let records = trace_records(&output);
assert_eq!(
records.len(),
2,
"hostile accessor split trace records: {records:?}"
);
for line in records {
assert!(
!line.contains("ACCESSOR_SECRET") && !line.contains("forged"),
"accessor value leaked: {line}"
);
assert!(line.parse::<String>().is_ok());
}
}