From e93d3f30d2b392275cf54bdbe8bc8490bb60e830 Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Mon, 27 Apr 2026 17:40:39 +0200 Subject: [PATCH] Add support for Shelly device generation detection and update related tests - Implement generation detection logic for Shelly devices using model codes, metadata, and type inference. - Extend relay switch and inventory handling to include generation capabilities. - Ensure compatibility with Gen1, Gen2, and Gen3 devices for relay control and diagnostics. - Update unit tests to validate generation inference, fallback behavior, and API compatibility. --- services/edge-agent/dist/agent.mjs | 193 ++++++++-- services/edge-agent/test/agent.test.mjs | 80 +++- services/edge-broker/server.mjs | 153 +++++++- .../nginx/app/.phpunit.cache/test-results | 2 +- .../app/classes/shelly_relay_inventory.php | 151 +++++++- .../classes/edge_gateway_manager.php | 364 +++++++++++++++++- .../edge_gateway_operation_exception.php | 3 +- .../edgegateway/routes/edgeGatewaysRoute.php | 25 +- .../tests/Api/EdgeGatewayBrokerApiTest.php | 48 ++- .../EdgeGatewayManagerCommandQueueTest.php | 7 + .../Selfserve/ShellyRelayInventoryTest.php | 70 ++++ 11 files changed, 1022 insertions(+), 74 deletions(-) diff --git a/services/edge-agent/dist/agent.mjs b/services/edge-agent/dist/agent.mjs index 6a7e7d4a..2a4c8073 100644 --- a/services/edge-agent/dist/agent.mjs +++ b/services/edge-agent/dist/agent.mjs @@ -145,6 +145,8 @@ function buildTransportHeartbeatState(brokerState = {}) { broker_last_connected_at: brokerState.lastConnectedAt || null, broker_last_disconnected_at: brokerState.lastDisconnectedAt || null, broker_disconnect_reason: brokerState.disconnectReason || null, + broker_last_close_code: brokerState.lastCloseCode ?? null, + broker_last_close_clean: brokerState.lastCloseClean ?? null, }, }; } @@ -179,6 +181,30 @@ function buildBrokerSocketUrl(brokerUrl, gatewayId, token) { return `${baseUrl}/ws/agent?${search.toString()}`; } +function redactBrokerSocketUrl(value) { + try { + const parsed = new URL(String(value || "")); + for (const key of ["token", "agentToken", "agent_token"]) { + if (parsed.searchParams.has(key)) { + parsed.searchParams.set(key, "***"); + } + } + return parsed.toString(); + } catch { + return String(value || "").replace(/([?&](?:token|agentToken|agent_token)=)[^&]+/gi, "$1***"); + } +} + +function normalizeBrokerSocketError(error, socketUrl) { + const message = error instanceof Error && error.message + ? error.message + : error?.message + ? String(error.message) + : "Broker connection failed"; + const redactedUrl = redactBrokerSocketUrl(socketUrl); + return redactedUrl ? `${message} (${redactedUrl})` : message; +} + async function readSocketMessageText(data) { if (typeof data === "string") { return data; @@ -509,6 +535,90 @@ function expandCandidateIps(options = {}) { return []; } +function normalizeShellyDeviceGeneration(value) { + if (Number.isInteger(value) && value > 0) { + return value; + } + + if (typeof value === "number" && Number.isFinite(value) && value > 0) { + return Math.trunc(value); + } + + return inferShellyDeviceGenerationFromString(value); +} + +function inferShellyDeviceGenerationFromString(value) { + const normalized = String(value || "").trim(); + if (!normalized) { + return null; + } + + const explicit = normalized.match(/\bgen(?:eration)?\s*([1-9]\d*)\b/i); + if (explicit) { + return Number(explicit[1]); + } + + const upper = normalized.toUpperCase(); + const sSeries = upper.match(/\bS([3-9])(?:[A-Z0-9]+)?-[A-Z0-9-]+\b/); + if (sSeries) { + return Number(sSeries[1]); + } + + if (/\b(?:SHELLY\s+)?(?:PLUS|PRO)\b/i.test(normalized) || /\bSP[A-Z0-9]+-[A-Z0-9-]+\b/.test(upper)) { + return 2; + } + + if (/\bSH[A-Z0-9]+-?[A-Z0-9-]*\b/.test(upper)) { + return 1; + } + + return null; +} + +function resolveShellyDeviceGeneration(identity = {}) { + for (const candidate of [ + identity.gen, + identity.generation, + identity.device_generation, + identity.capabilities?.generation, + ]) { + const generation = normalizeShellyDeviceGeneration(candidate); + if (generation !== null) { + return generation; + } + } + + for (const candidate of [ + identity.model, + identity.type, + identity.app, + identity.name, + identity.id, + identity.mac, + ]) { + const generation = inferShellyDeviceGenerationFromString(candidate); + if (generation !== null) { + return generation; + } + } + + return null; +} + +function resolveShellyCommandGeneration(payload = {}) { + return resolveShellyDeviceGeneration({ + gen: payload.gen ?? payload.generation ?? payload.deviceGeneration ?? payload.device_generation, + device_generation: payload.device_generation, + capabilities: payload.capabilities, + model: payload.model ?? payload.deviceModel ?? payload.device_model ?? payload.deviceType ?? payload.device_type, + type: payload.type ?? payload.deviceType ?? payload.device_type, + app: payload.app, + name: payload.name ?? payload.deviceName ?? payload.device_name, + id: payload.deviceId ?? payload.device_id ?? payload.relayId ?? payload.relay_id, + mac: payload.mac, + }); +} + export async function discoverShellyDevices(options = {}, fetchImpl = fetch) { const candidateIps = expandCandidateIps(options); const discovered = []; @@ -526,7 +636,7 @@ export async function discoverShellyDevices(options = {}, fetchImpl = fetch) { channel_count: Number(identity.num_outputs || identity.num_switches || 1), online: true, capabilities: { - generation: identity.gen || null, + generation: resolveShellyDeviceGeneration(identity), }, metadata: identity, }); @@ -587,48 +697,55 @@ export async function setRelayState(payload, fetchImpl = fetch) { const toggleAfter = resolveRelayToggleAfterSeconds(payload); const timerQuery = toggleAfter === null ? "" : `&toggle_after=${encodeURIComponent(String(toggleAfter))}`; const legacyTimerQuery = toggleAfter === null ? "" : `&timer=${encodeURIComponent(String(toggleAfter))}`; + const deviceGeneration = resolveShellyCommandGeneration(payload); if (!ip) { throw new Error("Missing relay local IP"); } - if (toggleAfter !== null) { - try { - const legacy = await fetchJson(`http://${ip}/relay/${channel}?turn=${on ? "on" : "off"}${legacyTimerQuery}`, fetchImpl, { timeoutMs }); - return { - online: true, - on: Boolean(legacy.ison ?? legacy.output ?? on), - raw: legacy, - }; - } catch (error) { - if (isHttpTimeoutError(error)) { - throw error; - } - const rpc = await fetchJson(`http://${ip}/rpc/Switch.Set?id=${channel}&on=${on ? "true" : "false"}${timerQuery}`, fetchImpl, { timeoutMs }); - return { - online: true, - on: Boolean(rpc.output ?? on), - raw: rpc, - }; - } - } - - try { + const runRpcSwitch = async () => { const rpc = await fetchJson(`http://${ip}/rpc/Switch.Set?id=${channel}&on=${on ? "true" : "false"}${timerQuery}`, fetchImpl, { timeoutMs }); return { online: true, on: Boolean(rpc.output ?? on), raw: rpc, }; - } catch (error) { - if (isHttpTimeoutError(error)) { - throw error; - } + }; + const runLegacySwitch = async () => { const legacy = await fetchJson(`http://${ip}/relay/${channel}?turn=${on ? "on" : "off"}${legacyTimerQuery}`, fetchImpl, { timeoutMs }); return { online: true, on: Boolean(legacy.ison ?? legacy.output ?? on), raw: legacy, }; + }; + + if (toggleAfter !== null) { + const attempts = deviceGeneration === 1 + ? [runLegacySwitch, runRpcSwitch] + : [runRpcSwitch, runLegacySwitch]; + + let lastError = null; + for (const attempt of attempts) { + try { + return await attempt(); + } catch (error) { + if (isHttpTimeoutError(error)) { + throw error; + } + lastError = error; + } + } + + throw lastError || new Error("Unable to switch relay"); + } + + try { + return await runRpcSwitch(); + } catch (error) { + if (isHttpTimeoutError(error)) { + throw error; + } + return await runLegacySwitch(); } } @@ -1227,12 +1344,13 @@ export function createShellBridge(sendMessage, { createPtyProcess = createDefaul sessions.set(sessionId, sessionRecord); sendMessage({ type: "SHELL_OPENED", sessionId }); } catch (error) { + const message = error instanceof Error ? error.message : String(error); sendMessage({ type: "SHELL_OUTPUT", sessionId, - data: `Failed to start root shell: ${error instanceof Error ? error.message : String(error)}\r\n`, + data: `Failed to start root shell: ${message}\r\n`, }); - sendMessage({ type: "SHELL_EXIT", sessionId, code: 1 }); + sendMessage({ type: "SHELL_EXIT", sessionId, code: 1, reason: "shell_spawn_failed", message }); } }; @@ -1567,13 +1685,15 @@ function normalizeShellEvent(message) { } if (message.type === "SHELL_EXIT") { + const reason = String(message.reason || "agent_exit"); return { sessionId: String(sessionId), event: { type: "CLOSED", payload: { code: Number.isFinite(message.code) ? message.code : 0, - reason: "agent_exit", + reason, + message: message.message ? String(message.message) : null, }, }, }; @@ -1704,6 +1824,8 @@ function createBrokerBridge({ disconnectReason: null, lastConnectedAt: null, lastDisconnectedAt: null, + lastCloseCode: null, + lastCloseClean: null, }; let stopped = false; @@ -1761,6 +1883,8 @@ function createBrokerBridge({ state.connected = true; state.lastError = null; state.disconnectReason = null; + state.lastCloseCode = null; + state.lastCloseClean = null; state.lastConnectedAt = formatUpdateTimestamp(); }; @@ -1814,14 +1938,19 @@ function createBrokerBridge({ } }; - socket.onerror = () => { - state.lastError = "Broker connection failed"; + socket.onerror = (error) => { + state.lastError = normalizeBrokerSocketError(error, socketUrl); }; socket.onclose = (event) => { socket = null; state.connected = false; state.disconnectReason = event.reason || "broker_disconnected"; + state.lastCloseCode = Number.isFinite(Number(event.code)) ? Number(event.code) : null; + state.lastCloseClean = typeof event.wasClean === "boolean" ? event.wasClean : null; + if (state.lastCloseCode && state.lastCloseCode !== 1000 && !state.lastError) { + state.lastError = `Broker websocket closed with code ${state.lastCloseCode}`; + } state.lastDisconnectedAt = formatUpdateTimestamp(); if (!stopped) { scheduleReconnect(); diff --git a/services/edge-agent/test/agent.test.mjs b/services/edge-agent/test/agent.test.mjs index d4195c90..8e0c68b7 100644 --- a/services/edge-agent/test/agent.test.mjs +++ b/services/edge-agent/test/agent.test.mjs @@ -11,6 +11,7 @@ import { buildStatusReport, claimIfNeeded, createShellBridge, + discoverShellyDevices, finalizePendingUpdateOnStartup, getAgentStatus, getRelayStatus, @@ -120,6 +121,29 @@ test("relay status and switch commands support both Shelly RPC and legacy endpoi assert.equal(switched.on, false); }); +test("Shelly discovery infers Gen3 from S3 relay model codes when generation is omitted", async () => { + const inventory = await discoverShellyDevices({ candidateIps: ["192.168.1.2"] }, async (url) => { + assert.equal(String(url), "http://192.168.1.2/shelly"); + return { + ok: true, + async json() { + return { + id: "shelly1minig3-e4b3231f6410", + mac: "E4B3231F6410", + model: "S3SW-001X8EU", + type: "Shelly 1 Mini Gen3", + num_switches: 1, + }; + }, + }; + }); + + assert.equal(inventory.length, 1); + assert.equal(inventory[0].device_id, "E4B3231F6410"); + assert.equal(inventory[0].model, "S3SW-001X8EU"); + assert.equal(inventory[0].capabilities.generation, 3); +}); + test("relay status reads use the legacy endpoint when the RPC status endpoint stalls", async () => { const urls = []; const fakeFetch = async (url) => { @@ -181,19 +205,22 @@ test("relay switch commands pass timer values to local Shelly APIs", async () => }; }; - await setRelayState({ localIp: "10.1.0.31", channel: 0, on: true, toggleAfter: 3 }, legacyFetch); + await setRelayState({ + localIp: "10.1.0.31", + channel: 0, + on: true, + toggleAfter: 3, + deviceGeneration: 1, + }, legacyFetch); assert.equal( legacyUrls[0], "http://10.1.0.31/relay/0?turn=on&timer=3" ); - const fallbackUrls = []; - const rpcFallbackFetch = async (url) => { - fallbackUrls.push(String(url)); - if (String(url).includes("/relay/")) { - throw new Error("Legacy relay endpoint unsupported"); - } + const gen3Urls = []; + const gen3Fetch = async (url) => { + gen3Urls.push(String(url)); return { ok: true, @@ -203,12 +230,46 @@ test("relay switch commands pass timer values to local Shelly APIs", async () => }; }; - await setRelayState({ localIp: "10.1.0.31", channel: 0, on: true, toggle_after: 3 }, rpcFallbackFetch); + await setRelayState({ + localIp: "10.1.0.31", + channel: 0, + on: true, + toggle_after: 3, + device_generation: 3, + }, gen3Fetch); assert.equal( - fallbackUrls[1], + gen3Urls[0], "http://10.1.0.31/rpc/Switch.Set?id=0&on=true&toggle_after=3" ); + + const fallbackUrls = []; + const legacyFallbackFetch = async (url) => { + fallbackUrls.push(String(url)); + if (String(url).includes("/rpc/")) { + throw new Error("RPC switch endpoint unsupported"); + } + + return { + ok: true, + async json() { + return { ison: true, has_timer: true, timer_duration: 3 }; + }, + }; + }; + + await setRelayState({ + localIp: "10.1.0.31", + channel: 0, + on: true, + toggle_after: 3, + device_model: "S3SW-001X8EU", + }, legacyFallbackFetch); + + assert.deepEqual(fallbackUrls, [ + "http://10.1.0.31/rpc/Switch.Set?id=0&on=true&toggle_after=3", + "http://10.1.0.31/relay/0?turn=on&timer=3", + ]); }); test("runUpdate stages a pending verification restart after installing new artifacts", async () => { @@ -800,6 +861,7 @@ test("startAgent reports API polling metadata, executes polled commands, and upl assert.equal(commandResultPosts[0].body.ok, true); assert.equal(Array.isArray(commandResultPosts[0].body.payload.inventory), true); assert.equal(commandResultPosts[0].body.payload.inventory[0].device_id, "AA:BB:CC:DD:EE:FF"); + assert.equal(commandResultPosts[0].body.payload.inventory[0].capabilities.generation, 2); assert.ok(shellCalls.some((call) => call.type === "open")); assert.ok(shellCalls.some((call) => call.type === "close")); diff --git a/services/edge-broker/server.mjs b/services/edge-broker/server.mjs index b9a02b7f..616ed108 100644 --- a/services/edge-broker/server.mjs +++ b/services/edge-broker/server.mjs @@ -3,6 +3,8 @@ import { randomUUID } from "node:crypto"; import { fileURLToPath } from "node:url"; import { WebSocketServer } from "ws"; +const DEFAULT_SHELL_OPEN_TIMEOUT_MS = 15000; + function parseJsonBody(req) { return new Promise((resolve, reject) => { let raw = ""; @@ -119,11 +121,40 @@ function normalizeErrorMessage(error, fallback = "Connection step failed") { return message || fallback; } +function rejectUpgrade(socket, statusCode, errorCode, message, details = {}) { + const statusText = { + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 500: "Internal Server Error", + 503: "Service Unavailable", + }[statusCode] || "WebSocket Upgrade Rejected"; + const body = JSON.stringify({ + ok: false, + error_code: errorCode, + message, + details, + }); + + socket.end( + [ + `HTTP/1.1 ${statusCode} ${statusText}`, + "content-type: application/json; charset=utf-8", + `content-length: ${Buffer.byteLength(body)}`, + "connection: close", + "", + body, + ].join("\r\n") + ); +} + export function createBrokerServer(options = {}) { const sharedSecret = options.sharedSecret ?? process.env.EDGE_BROKER_SHARED_SECRET ?? ""; const managerUrl = resolveManagerUrl(options); const authMode = resolveAuthMode(options, managerUrl); const commandTimeoutMs = options.commandTimeoutMs ?? 10000; + const shellOpenTimeoutMs = options.shellOpenTimeoutMs ?? DEFAULT_SHELL_OPEN_TIMEOUT_MS; const agents = new Map(); const pendingCommands = new Map(); @@ -147,7 +178,11 @@ export function createBrokerServer(options = {}) { }); const json = await parseJsonResponse(response); if (!response.ok) { - throw new Error(json?.data?.message || json?.message || json?.error || `HTTP ${response.status}`); + const error = new Error(json?.data?.message || json?.message || json?.error || `HTTP ${response.status}`); + error.status = response.status; + error.code = json?.data?.error_code || json?.error_code || null; + error.details = json?.data?.diagnostics || json?.diagnostics || null; + throw error; } return json?.data ?? json; @@ -177,11 +212,12 @@ export function createBrokerServer(options = {}) { options.closeShellSession || (authMode === "stub" ? async () => ({}) - : async (_id, token, transcript, reason) => + : async (_id, token, transcript, reason, details = {}) => managerRequest("/edge-agent/internal/shell-sessions/close", { token, transcript, reason, + ...details, })); const validateBrowserStream = options.validateBrowserStream || @@ -254,21 +290,41 @@ export function createBrokerServer(options = {}) { } }; - const closeBrowserShellSession = async (sessionRecord, reason) => { + const closeBrowserShellSession = async (sessionRecord, reason, details = {}) => { try { await closeShellSession( sessionRecord.session.id, sessionRecord.ws.sessionToken, sessionRecord.transcript, - reason + reason, + { + message: sessionRecord.closedMessage || null, + code: sessionRecord.closedCode ?? null, + stage: sessionRecord.closedStage || null, + broker_connection_id: sessionRecord.agentConnectionId || null, + details: sessionRecord.closedDetails || {}, + ...details, + } ); } catch { // Preserve socket teardown even when the manager callback is unavailable. } }; - const closeBrowserShellSocket = (sessionRecord, reason, message = null, code = 1000) => { + const clearShellOpenTimer = (sessionRecord) => { + if (sessionRecord?.openTimer) { + clearTimeout(sessionRecord.openTimer); + sessionRecord.openTimer = null; + } + }; + + const closeBrowserShellSocket = (sessionRecord, reason, message = null, code = 1000, details = {}) => { sessionRecord.closedReason = reason; + sessionRecord.closedMessage = message || null; + sessionRecord.closedCode = code; + sessionRecord.closedDetails = details && typeof details === "object" ? details : {}; + sessionRecord.closedStage = String(sessionRecord.closedDetails.stage || (sessionRecord.opened ? "shell_active" : "shell_open")); + clearShellOpenTimer(sessionRecord); if (sessionRecord.ws.readyState >= 2) { return; } @@ -276,7 +332,9 @@ export function createBrokerServer(options = {}) { sendJson(sessionRecord.ws, { type: "closed", reason, + code, ...(message ? { message } : {}), + ...(Object.keys(sessionRecord.closedDetails).length ? { details: sessionRecord.closedDetails } : {}), }); sessionRecord.ws.close(code, reason); }; @@ -287,7 +345,11 @@ export function createBrokerServer(options = {}) { continue; } - closeBrowserShellSocket(sessionRecord, reason, "Gateway agent disconnected from the broker.", 1011); + closeBrowserShellSocket(sessionRecord, reason, "Gateway agent disconnected from the broker.", 1011, { + stage: "agent_disconnect", + gateway_id: gatewayId, + shell_session_id: sessionRecord.session.id, + }); } }; @@ -513,11 +575,20 @@ export function createBrokerServer(options = {}) { if (url.pathname === "/ws/browser-shell") { const token = String(url.searchParams.get("token") || ""); if (token === "") { - socket.destroy(); + rejectUpgrade(socket, 400, "shell_session_token_missing", "Missing shell session token."); + return; + } + + let session; + try { + session = await validateShellSession({ token, headers: req.headers }); + } catch (error) { + rejectUpgrade(socket, Number(error?.status) === 403 ? 403 : 401, error?.code || "shell_session_invalid", normalizeErrorMessage(error, "Shell session could not be validated."), { + stage: "shell_session_validate", + }); return; } - const session = await validateShellSession({ token, headers: req.headers }); wss.handleUpgrade(req, socket, head, (ws) => { ws.sessionToken = token; ws.sessionInfo = session; @@ -526,12 +597,20 @@ export function createBrokerServer(options = {}) { session, transcript: "", closedReason: null, + closedMessage: null, + closedCode: null, + closedDetails: {}, + closedStage: null, + opened: false, + openTimer: null, + agentConnectionId: null, }; browserShellSessions.set(String(session.id), sessionRecord); wss.emit("connection", ws, req); const agent = agents.get(String(session.gateway_id)); if (agent && agent.readyState === 1) { + sessionRecord.agentConnectionId = agent.connectionId || null; sendJson(agent, { type: "OPEN_ROOT_SHELL", payload: { @@ -544,12 +623,32 @@ export function createBrokerServer(options = {}) { shellArgs: session.shell_args ?? session.metadata?.shell_args ?? [], }, }); + sessionRecord.openTimer = setTimeout(() => { + closeBrowserShellSocket( + sessionRecord, + "shell_open_timeout", + "Gateway agent did not confirm that the shell opened before the broker timeout.", + 1011, + { + stage: "shell_open", + timeout_ms: shellOpenTimeoutMs, + gateway_id: session.gateway_id, + shell_session_id: session.id, + } + ); + }, Math.max(250, shellOpenTimeoutMs)); + sessionRecord.openTimer.unref?.(); } else { closeBrowserShellSocket( sessionRecord, "agent_offline", "Gateway agent is not connected to the broker.", - 1011 + 1011, + { + stage: "agent_lookup", + gateway_id: session.gateway_id, + shell_session_id: session.id, + } ); } }); @@ -583,8 +682,8 @@ export function createBrokerServer(options = {}) { }); return; } - } catch { - socket.destroy(); + } catch (error) { + rejectUpgrade(socket, 500, "websocket_upgrade_failed", normalizeErrorMessage(error, "WebSocket upgrade failed.")); return; } @@ -706,17 +805,35 @@ export function createBrokerServer(options = {}) { } if (message.type === "SHELL_OPENED") { + sessionRecord.opened = true; + sessionRecord.agentConnectionId = ws.connectionId || sessionRecord.agentConnectionId || null; + clearShellOpenTimer(sessionRecord); await markShellSessionOpened(sessionRecord.ws.sessionToken, ws.connectionId || null).catch(() => {}); sendJson(sessionRecord.ws, { type: "opened" }); return; } if (message.type === "SHELL_EXIT") { - sendJson(sessionRecord.ws, { type: "closed", reason: "agent_exit", code: message.code ?? 0 }); - await closeBrowserShellSession(sessionRecord, "agent_exit"); + const reason = String(message.reason || "agent_exit"); + const parsedExitCode = Number(message.code); + const exitCode = Number.isFinite(parsedExitCode) ? parsedExitCode : 0; + const closeMessage = message.message ? String(message.message) : null; + clearShellOpenTimer(sessionRecord); + sendJson(sessionRecord.ws, { + type: "closed", + reason, + code: exitCode, + ...(closeMessage ? { message: closeMessage } : {}), + }); + await closeBrowserShellSession(sessionRecord, reason, { + message: closeMessage, + code: exitCode, + stage: sessionRecord.opened ? "shell_active" : "shell_start", + broker_connection_id: ws.connectionId || null, + }); browserShellSessions.delete(String(message.sessionId)); if (sessionRecord.ws.readyState < 2) { - sessionRecord.ws.close(1000, "agent_exit"); + sessionRecord.ws.close(1000, reason); } } } @@ -796,7 +913,7 @@ export function createBrokerServer(options = {}) { } }); - ws.on("close", async (_code, buffer) => { + ws.on("close", async (code, buffer) => { const closeReason = buffer?.toString?.("utf8") || null; if (ws.gatewayId) { @@ -832,7 +949,11 @@ export function createBrokerServer(options = {}) { } const sessionRecord = browserShellSessions.get(sessionId); if (sessionRecord) { - await closeBrowserShellSession(sessionRecord, sessionRecord.closedReason || "browser_closed"); + await closeBrowserShellSession(sessionRecord, sessionRecord.closedReason || "browser_closed", { + code, + stage: sessionRecord.closedStage || "browser_socket_close", + message: sessionRecord.closedMessage || null, + }); browserShellSessions.delete(sessionId); } return; diff --git a/services/nginx/app/.phpunit.cache/test-results b/services/nginx/app/.phpunit.cache/test-results index 5873c4f3..3db7f32f 100644 --- a/services/nginx/app/.phpunit.cache/test-results +++ b/services/nginx/app/.phpunit.cache/test-results @@ -1 +1 @@ -{"version":"pest_3.8.6","defects":{"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_self_serve_machine_type__eligibility__summary__and_webhook_endpoints":1,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_defines_reusable_self_serve_wash_and_machine_type_schemas":1,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_redistributes_booked_department_75_net_amounts_using_fixed_pricing_and_wash_subscription_weights":7,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_keeps_classified_booked_department_75_amounts_undistributed_when_no_monthly_basis_exists":8,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_keeps_unclassified_booked_department_75_lines_undistributed_with_warnings":8,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_documents_v2_historical_distribution_and_pricing_history_paths_in_openapi":1,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_defines_new_reusable_v2_schemas_for_normalization_comparison_versioning_and_distribution":1,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_supports_bulk_booked_invoice_line_payloads_with_top_level_department_numbers":7,"P\\Tests\\Unit\\Redis\\RedisAtomicReservationTest::__pest_evaluable_it_claims_a_slot_atomically_with_nx_and_expiration":8,"P\\Tests\\Unit\\Redis\\RedisAtomicReservationTest::__pest_evaluable_it_returns_false_when_the_slot_is_already_claimed_and_clamps_ttl_to_one_second":8,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_documents_economic_v2_invoice_paths_in_openapi":1,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_aligns_legacy_compare_schema_with_runtime_payload_by_removing_stale_required_order__ids":1,"P\\Tests\\Unit\\Search\\SystemSearchEntityTypeCoverageTest::__pest_evaluable_it_documents_every_supported_search_entity_type_in_openapi_enum":1,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_system_wide_search_endpoints_in_openapi":1,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_debug__intent_and_parser_metadata_schema_in_openapi":1,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_e_conomic_indexed_customer_matching_and_synonym_behavior":1,"P\\Tests\\Integration\\Database\\DbConnectionTest::__pest_evaluable_it_can_connect_to_a_configured_MySQL_instance_in_integration_mode":1,"P\\Tests\\Integration\\Invoicing\\EconomicV2BackfillAndDistributionIntegrationTest::__pest_evaluable_it_runs_best_effort_backfill_repeatedly_without_introducing_duplicate_same_start_rows":1,"P\\Tests\\Integration\\Invoicing\\EconomicV2BackfillAndDistributionIntegrationTest::__pest_evaluable_it_resolves_version_aware_distribution_payload_shapes_over_a_real_date_range":1,"P\\Tests\\Integration\\Invoicing\\EconomicV2VersioningServiceIntegrationTest::__pest_evaluable_it_creates_closes_and_rotates_fixed_pricing_versions_without_overlap":1,"P\\Tests\\Integration\\Invoicing\\EconomicV2VersioningServiceIntegrationTest::__pest_evaluable_it_tracks_vehicle_and_discount_version_lifecycles_with_closure_semantics":1,"P\\Tests\\Integration\\Permissions\\LegacyPermissionRedisCacheScriptTest::__pest_evaluable_it_keeps_legacy_route_permission_redis_cache_script_green":1,"P\\Tests\\Unit\\Goals\\GoalsOpenApiSpecTest::__pest_evaluable_it_documents_advanced_goals_target_duration_fields_in_openapi":1,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineSchemaConformanceTest::__pest_evaluable_it_documents_the_date_key_in_the_openapi_department_weather_timeline_schema":1,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_builds_timeline_entries_with_mostly__clear_weather_when_forecast_payload_is_empty":8,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_wires_departments_weather_route_through_the_forecast_fallback_path":7,"P\\Tests\\Unit\\Orders\\AttachmentsListManyTest::__pest_evaluable_it_groups_attachments_by_object_id_and_preserves_empty_object_groups":8,"P\\Tests\\Unit\\Orders\\AttachmentsListManyTest::__pest_evaluable_it_keeps_listMany_payload_parity_with_list_for_one_object_id":8,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsOpenApiSpecTest::__pest_evaluable_it_documents_department_weather_target_endpoints_and_reusable_schemas_in_openapi":1,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsOpenApiSpecTest::__pest_evaluable_it_documents_unknown_weather_status_behavior_when_targets_are_missing":1,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_respects_the_1_request_per_second_Shelly_gate_for_back_to_back_requests":8,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_in_progress_self_serve_wash_start_and_machine_relay_fields":1,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_stores_config_json_with_apostrophes_without_violating_json_constraints":8,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_adds_vehicle_type_product_on_STOP_when_program_selector_is_on__then_turns_off_cleaner_machine_and_selector_relays":7,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_skips_vehicle_type_product_add_when_program_selector_is_off_and_only_disables_configured_relays":7,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_self_serve_machine_wash_included_minutes_in_config_schemas":1,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_workspace_id_is_missing_for_gate_calls":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_channel_id_is_missing_for_gate_calls":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_with_terminal_status_details_when_call_never_reaches_accepted_state":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_hangs_up_when_call_reaches_accepted_state":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_hangs_up_immediately_when_status_transitions_to_accepted":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_maps_legacy_timeout_option_to_documented_ringTimeout_payload_field":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_clamps_derived_ringTimeout_to_Bird_documented_max_when_gate_timeout_is_high":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_passes_documented_hangup_cause_when_provided":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_drops_unsupported_hangup_cause_values_from_request_payload":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_workspace_id_is_missing_for_gate_flash_calls":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_creates_gate_flash_call_with_documented_ringTimeout_payload":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_polls_flash_call_and_succeeds_once_accepted":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_flash_gate_flow_when_terminal_failure_status_is_returned":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_does_not_fallback_to_regular_gate_call_when_flash_succeeds":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_falls_back_to_regular_gate_call_when_flash_fails":8,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_property_gate_lane_commands_and_sanitized_gate_failure_responses":1,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_returns_raw_payload_for_malformed_JSON_responses_and_null_for_empty_responses":8,"P\\Tests\\Unit\\Bird\\BirdRouteWiringTest::__pest_evaluable_it_keeps_Bird_number_and_webhook_routes_intact":7,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_handles_malformed_and_empty_response_bodies_without_throwing_transport_errors":8,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherStatusTargetsTest::__pest_evaluable_it_aggregates_multi_department_slot_statuses_using_worst_severity_and_unknown_fallback_rules":7,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_adds_vehicle_type_product_on_STOP_when_program_selector_relay_is_online__then_turns_off_cleaner_and_machine_relays":7,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_bills_primary_product_when_selector_relay_is_online_even_if_relay_output_is_off":7,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_documents_all_Bird_voice_call_parity_endpoints_including_gather_recordings_insights_and_log":1,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_documents_flash_hangup_endpoint_and_marks_end_alias_as_deprecated":1,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_defines_request_and_response_schemas_for_Bird_call_command_recording_insight_log_and_flash_payloads":1,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueRouteRegistrationTest::__pest_evaluable_it_registers_collected_invoice_queue_endpoints_in_orderInvoicesRoute":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_uses_a_consistent_unavailable_service_contract_for_missing_queue_dependencies":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_wires_zero_cost_and_zero_quantity_skip_guard_into_transfer_line_builder":7,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_processes_queued_transfer_jobs_to_completion":1,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_deduplicates_active_jobs_per_transfer_target":1,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_rejects_invalid_payloads_without_inserting_queue_rows":1,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_supports_fail_retry_and_reprocess_lifecycle_transitions":1,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_supports_synchronous_fallback_branches_before_queue_enqueue_on_economic_invoice_export_routes":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_keeps_queue_status_endpoints_guarded_while_collected_invoice_export_routes_support_synchronous_fallback":7,"P\\Tests\\Unit\\Invoicing\\UserCollectedInvoiceUpdateRouteValidationTest::__pest_evaluable_it_supports_independent_po__number_and_closed__at_updates_for_PUT__collected_invoices_in_user_route":7,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueRouteHardeningTest::__pest_evaluable_it_returns_pagination_metadata_and_strict_status_handling_for_collected_invoice_queue_list":7,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueRouteHardeningTest::__pest_evaluable_it_enforces_retry_constraints_for_collected_invoice_queue_jobs_before_retry_execution":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_collected_queue_list_metadata_and_strict_status_filter_enum_in_openapi":7,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_builds_a_completed_collected_invoice_queue_summary_from_payload_and_result":8,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_prefers_queue_error_messages_for_failed_jobs_and_keeps_null_safe_outcome_fields":8,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_uses_deterministic_status_message_fallback_when_no_explicit_message_exists":8,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_handles_object_payload_result_values_and_malformed_fields_without_throwing":8,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueWorkerTickRouteTest::__pest_evaluable_it_ticks_collected_invoice_transfer_queue_from_queue_list_and_status_routes":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueWorkerTickRouteTest::__pest_evaluable_it_ticks_order_transfer_queue_from_draft_and_invoice_status_routes":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_builds_the_installer_around_the_PHP_agent_artifacts_and_management_polling_config":8,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_exposes_update_payload__credential_rotation__and_operation_endpoints_without_shell_transport_wiring":8,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_relay_fallback_and_transport_health_details_without_shell_or_update_runtime_state":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_resolves_edge_agent_artifacts_from_the_source_tree_layout":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_prioritizes_mounted_and_baked_in_artifact_directories_before_repo_fallbacks":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_prioritizes_router_resources_before_mounted_and_baked_in_artifact_directories":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_lists_orders_for_an_admin_scoped_user_and_limits_the_results_to_the_permitted_departments":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_lists_only_the_targeted_customer_orders_for_subuser_sessions":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_returns_the_current_auth_and_permission_failures_when_order_listing_is_not_allowed":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_creates_orders_through_the_real_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_order_creation_requests":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_updates_orders_through_the_primary_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_reassigns_invoice_collections_when_changing_an_order_across_the_draft_customer_boundary":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_supports_legacy_field_value_metadata_updates_through_the_primary_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_updates_through_the_primary_order_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_updates_orders_through_the_legacy_alias_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_supports_legacy_field_value_metadata_updates_through_the_alias_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_updates_through_the_legacy_alias_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_unsupported_legacy_field_value_updates_on_both_update_endpoints":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_deletes_orders_through_the_real_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_order_delete_requests":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_regenerates_attached_wash_certificates_when_certificate_metadata_changes_through_the_primary_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_regenerates_attached_wash_certificates_for_legacy_field_value_updates_through_the_alias_endpoint":7,"P\\Tests\\Api\\ApiCoverageManifestTest::__pest_evaluable_it_keeps_every_selected_API_operation_covered_by_happy_path_and_failure_tests":1,"P\\Tests\\Api\\ApiCoverageManifestTest::__pest_evaluable_it_keeps_the_OpenAPI_manifest_entries_aligned_with_the_API_spec":1,"P\\Tests\\Api\\ApiFixturesCleanupTest::__pest_evaluable_it_removes_generated_customer_traces_during_fixture_cleanup":1,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_in_with_valid_customer_credentials":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_login_payloads_and_credentials":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_returns_the_cached_auth_session_payload_for_a_valid_token":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_includes_economic_runtime_config_for_uncached_auth_sessions":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_auth_session_tokens":1,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_out_and_invalidates_the_token_for_future_session_calls":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_out_and_invalidates_cached_subuser_sessions":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_logout_tokens":1,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_the_raw_202_gather_webhook_contract_over_HTTP":1,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_still_prompts_for_department_selection_when_only_one_department_is_eligible":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_accepts_the_legacy_initial_webhook_body_with_top_level_call_identifiers":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_native_flow_gather_data_after_a_top_level_department_selection_when_distinct_gate_choices_exist":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_opens_the_gate_immediately_after_a_top_level_department_selection_when_entrance_and_exit_share_the_same_gate":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_uses_a_multi_digit_gather_contract_when_10_departments_are_eligible":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_a_raw_400_transport_error_for_malformed_webhook_payloads":1,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_lists_only_visible_departments_and_can_return_a_single_department_with_the_slack_webhook":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_department_listing_when_the_permission_is_missing":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_creates_departments_through_the_real_endpoint":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_create_requests":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_updates_departments_through_the_real_endpoint":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_update_requests":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_lists_department_categories_for_a_department":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_category_requests":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_lists_the_draft_customer_config_entry_in_economic_config_responses":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_round_trips_the_draft_customer_config_value_through_economic_config_updates":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_order_draft_exports_for_the_configured_draft_customer":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_booked_invoice_exports_for_the_configured_draft_customer":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_collected_invoice_exports_for_the_configured_draft_customer":7,"P\\Tests\\Api\\PingApiTest::__pest_evaluable_it_returns_the_ping_contract":1,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_setup_required_error_when_department_terminal_readers_are_requested_without_terminal_setup":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_sends_a_Stripe_invoice_by_email_and_persists_the_hosted_invoice_association":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_conflict_when_a_Stripe_hosted_invoice_is_already_active_for_the_order":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_allows_sending_a_new_Stripe_hosted_invoice_when_the_existing_association_is_already_terminal":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_voids_an_unpaid_Stripe_hosted_invoice_and_clears_the_local_order_association":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_refuses_to_cancel_a_paid_Stripe_hosted_invoice":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_setup_required_error_when_creating_a_payment_intent_for_a_department_without_terminal_setup":8,"P\\Tests\\Api\\VehiclesApiTest::__pest_evaluable_it_returns_the_newest_vehicle_last__order__id_that_still_has_order_items":7,"P\\Tests\\Api\\VehiclesApiTest::__pest_evaluable_it_returns_a_null_vehicle_last__order__id_when_no_order_with_items_exists":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_syncs_gateway_snapshots_into_cached_list_payloads_and_refreshes_fleet_usage":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_keeps_only_the_module_facade_in_the_global_classes_directory_and_conditionally_loads_module_routes":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_install_script_urls_with_the_compose_edge_gateway_artifacts_and_forwarded_https_scheme":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_builds_the_installer_around_the_compose_stack_artifacts_and_management_polling_config":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_exposes_update_payload__credential_rotation__cancel_endpoints__and_operation_endpoints_without_shell_transport_wiring":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_the_v2_operator_facing_edge_gateway_routes":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewaySchemaBootstrapTest::__pest_evaluable_it_defines_the_v2_edge_gateway_schema_bootstrap_tables":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewaySchemaBootstrapTest::__pest_evaluable_it_stores_operation_metadata_and_event_timelines_for_management_workflows":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_prefers_EDGE__PUBLIC__API__URL_when_explicitly_configured":7,"P\\Tests\\Api\\PlateScannersApiTest::__pest_evaluable_it_returns_the_updated_lane_id_after_editing_a_scanner_whose_null_lane_was_already_cached":7,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_serves_installer_artifacts_and_recovers_gateway_runtime_status_after_fresh_heartbeats":1,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_polls_operations_and_commands__submits_results__and_records_broker_presence_for_task_pages":7,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_builds_broker_backlog_and_completes_gateway_operations_through_broker_endpoints":7,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_creates_install_tokens__tracks_installer_status__and_exposes_claimed_gateway_detail_to_authorized_operators":8,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_manages_edge_gateway_metadata__bindings__operations__sessions__rotation__cutover__and_deletion":8,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_assembles_tasks__logs__statistics__operations__commands__and_shell_lifecycle_state_from_persisted_records":7,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_rejects_invalid_edge_broker_shared_secrets":8,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_rejects_operator_edge_routes_when_module_permission_or_department_access_is_missing":8,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_rejects_missing_and_invalid_edge_agent_tokens":1,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_persists_gateway_cutover_relay_bindings_used_by_self_serve_Shelly_dispatch":7},"times":{"P\\Tests\\Unit\\Auth\\CreateTokenTest::__pest_evaluable_it_creates_a_64_char_auth_token_for_an_existing_user":0.11,"P\\Tests\\Unit\\Auth\\CreateTokenTest::__pest_evaluable_it_throws_a_clear_exception_when_customer_user_is_missing":0.017,"P\\Tests\\Unit\\Auth\\LegacyAuthScriptParityTest::__pest_evaluable_it_keeps_passkey_challenge_legacy_script_green_during_migration":0.028,"P\\Tests\\Unit\\Auth\\LegacyAuthScriptParityTest::__pest_evaluable_it_keeps_register_CVR_legacy_script_green_during_migration":0.029,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_builds_deterministic_department_digit_map_and_caps_to_9_options":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_resolves_department_ids_by_selected_digit":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_resolves_gate_type_digit_to_entrance_or_exit":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_stores__loads_and_clears_ivr_state_with_ttl":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_validates_state_caller_fingerprint_matching":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_builds_department_and_gate_prompts":0,"P\\Tests\\Unit\\Permissions\\PermissionNodeDefinitionTest::__pest_evaluable_it_creates_permission_nodes_linked_to_subuser_permission_keys":0,"P\\Tests\\Unit\\Permissions\\PermissionNodeDefinitionTest::__pest_evaluable_it_rejects_empty_permission_definitions":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_normalizes_button_arrays__json_and_csv_inputs":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_rejects_invalid_button_inputs":0.012,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_normalizes_vehicle_type_values_and_null_semantics":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_rejects_invalid_vehicle_type_values":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_rejects_non_numeric_vehicle_type_strings":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_keeps_lane_service_enum_contract_for_MACHINE":0,"P\\Tests\\Unit\\Subusers\\SubuserGrantInitializationTest::__pest_evaluable_it_initializes_booking_node_grants_without_DB_dependency":0,"P\\Tests\\Unit\\Subusers\\SubuserGrantInitializationTest::__pest_evaluable_it_initializes_selfserve_node_grants_without_DB_dependency":0,"P\\Tests\\Unit\\Subusers\\SubusersRoutePermissionLinkTest::__pest_evaluable_it_keeps_subusers_route_list_permission_linked_to_SUBUSERS__LIST_node":0.005,"P\\Tests\\Unit\\Search\\SystemSearchEntityTypeCoverageTest::__pest_evaluable_it_keeps_route_and_service_entity_type_registries_in_sync_with_expanded_coverage":0,"P\\Tests\\Unit\\Search\\SystemSearchEntityTypeCoverageTest::__pest_evaluable_it_documents_every_supported_search_entity_type_in_openapi_enum":0.009,"P\\Tests\\Unit\\Search\\SystemSearchEconomicCustomerIndexWiringTest::__pest_evaluable_it_wires_local_e_conomic_customer_index_into_customer_related_search_entities":0.003,"P\\Tests\\Unit\\Search\\SystemSearchEconomicCustomerIndexWiringTest::__pest_evaluable_it_registers_cron_tasks_that_keep_the_e_conomic_search_index_refreshed":0.003,"P\\Tests\\Unit\\Search\\SystemSearchInvalidationHooksTest::__pest_evaluable_it_marks_system_search_cache_dirty_from_generic_db_object_mutation_flows":0.004,"P\\Tests\\Unit\\Search\\SystemSearchInvalidationHooksTest::__pest_evaluable_it_marks_system_search_cache_dirty_from_object_property_mutations":0.003,"P\\Tests\\Unit\\Search\\SystemSearchInvalidationHooksTest::__pest_evaluable_it_marks_system_search_cache_dirty_when_module_config_values_change":0.002,"P\\Tests\\Unit\\Search\\SystemSearchInvalidationHooksTest::__pest_evaluable_it_registers_cron_maintenance_task_for_system_search_cache":0.002,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_redacts_obvious_sensitive_fragments_before_sending_query_to_intent_parser":0.001,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_builds_payload_with_redacted_query_and_parses_strict_JSON_output":0,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_falls_back_safely_when_OpenAI_is_disabled":0,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_handles_malformed_OpenAI_response_payloads_without_throwing":0,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_uses_parser_cache_for_identical_query_and_allowed_type_combinations":0,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_caps_alias_and_hint_payloads_from_OpenAI_and_filters_hints_to_allowed_types":0.006,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_system_wide_search_endpoints_in_openapi":0.007,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_debug__intent_and_parser_metadata_schema_in_openapi":0.007,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_e_conomic_indexed_customer_matching_and_synonym_behavior":0.005,"P\\Tests\\Unit\\Search\\SystemSearchRouteBehaviorTest::__pest_evaluable_it_normalizes_type_lists_from_csv_json_and_arrays":0,"P\\Tests\\Unit\\Search\\SystemSearchRouteBehaviorTest::__pest_evaluable_it_parses_booleans_and_clamps_integers_using_route_defaults":0,"P\\Tests\\Unit\\Search\\SystemSearchRouteBehaviorTest::__pest_evaluable_it_exposes_expected_searchable_entity_types":0,"P\\Tests\\Unit\\Search\\SystemSearchRouteWiringTest::__pest_evaluable_it_registers_system_wide_search_GET_and_POST_endpoints_with_intent_debug_support":0.003,"P\\Tests\\Unit\\Search\\SystemSearchRouteWiringTest::__pest_evaluable_it_registers_superuser_cache_clear_and_rebuild_endpoints_for_system_search":0.003,"P\\Tests\\Unit\\Search\\SystemSearchRouteWiringTest::__pest_evaluable_it_passes_permission_and_own_scope_context_into_system_search_service":0.003,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_does_not_invoke_intent_parser_when_lexical_confidence_is_already_high":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_invokes_parser_on_low_confidence_lexical_results_and_applies_hints_only_boosts":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_never_lets_parser_entity_hints_override_explicit_include_filters":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_returns_fallback_parser_metadata_when_parser_fails_gracefully":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_scopes_query_cache_by_permission_context_to_avoid_cross_user_cache_leakage":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_caps_AI_driven_expanded_terms_to_prevent_query_amplification":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_expands_danish_discount_wording_into_lexical_discount_synonyms":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_invokes_parser_for_intent_driven_natural_language_queries_even_when_lexical_score_is_high":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_uses_association_hints_to_pull_related_customer_records_from_non_customer_matches":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_prefers_newer_records_when_relevance_scores_are_comparable":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_keeps_explicit_identifier_matches_ahead_of_newer_but_weaker_records":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_promotes_invoices_orders_order_bookings_and_customers_in_ranking":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_never_prioritizes_cancelled_bookings_over_active_bookings":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_heavily_demotes_configured_low_priority_entity_types_in_ranking":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_tokenizes_unicode_names_without_stripping_non_ascii_letters":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_does_not_treat_explicit_identifier_queries_as_intent_driven":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_requires_broader_term_coverage_for_multi_word_scoring":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_enriches_object_attachment_results_with_associated_customer_context":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_includes_the_economic_customer_index_in_cache_dependencies_for_customer_scoped_results":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_falls_back_to_invoice_date_ranges_when_invoice_names_are_missing":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_derives_xlvask_customer_numbers_only_from_digits_only_extern_ids":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_replaces_unnamed_user_titles_with_the_customer_context_name":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_uses_the_goal_criteria_label_for_department_goal_titles":0,"P\\Tests\\Integration\\Search\\SystemSearchCacheIntegrationTest::__pest_evaluable_it_reuses_parser_cache_entries_for_repeated_natural_language_intent_requests":0.106,"P\\Tests\\Integration\\Search\\SystemSearchCacheIntegrationTest::__pest_evaluable_it_clears_parser_cache_namespace_via_clearAll_to_force_a_fresh_parse":0,"P\\Tests\\Integration\\Search\\SystemSearchCacheIntegrationTest::__pest_evaluable_it_bumps_per_table_cache_versions_when_a_dirty_table_marker_is_registered":0.081,"P\\Tests\\Unit\\Invoicing\\EconomicV2DistributionServiceFallbackTest::__pest_evaluable_it_falls_back_to_system_orders_for_fixed_pricing_when_regular_orders_yield_no_customers":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2DistributionServiceFallbackTest::__pest_evaluable_it_falls_back_to_system_orders_for_wash_subscriptions_when_regular_orders_yield_no_customers":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2CliBackfillCommandTest::__pest_evaluable_it_registers_economic_v2_backfill_command_in_cli_dispatcher":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2CliBackfillCommandTest::__pest_evaluable_it_provides_a_backfill_cron_script_entrypoint":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_returns_exact__match_when_totals_lines_and_departments_are_identical":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_returns_total__mismatch_when_only_totals_differ":0.015,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_detects_line_level_mismatches_for_quantity_and_price":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_detects_departmental_distribution_mismatches":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_returns_missing__target_when_draft_or_booked_target_is_unavailable":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2LineNormalizerTest::__pest_evaluable_it_normalizes_draft_invoice_lines_including_departmental_distributions":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2LineNormalizerTest::__pest_evaluable_it_marks_text_only_zero_value_lines_as_non_billable_and_keeps_deterministic_key":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicV2LineNormalizerTest::__pest_evaluable_it_normalizes_booked_invoices_and_computes_net_total_delta_from_lines":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2LineNormalizerTest::__pest_evaluable_it_contains_internal_normalization_path_with_departmental_metadata_support":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_documents_economic_v2_invoice_paths_in_openapi":0.009,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_documents_v2_historical_distribution_and_pricing_history_paths_in_openapi":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_aligns_legacy_compare_schema_with_runtime_payload_by_removing_stale_required_order__ids":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_defines_new_reusable_v2_schemas_for_normalization_comparison_versioning_and_distribution":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2RevenueAndBarredSupportTest::__pest_evaluable_it_supports_barred_filtering_when_listing_e_conomic_customers":0.006,"P\\Tests\\Unit\\Invoicing\\EconomicV2RevenueAndBarredSupportTest::__pest_evaluable_it_implements_a_dedicated_v2_e_conomic_revenue_statistics_service_and_route":0.006,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_registers_all_collected_invoice_economic_v2_routes_with_explicit_permissions":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_registers_version_aware_distribution_and_pricing_history_v2_routes":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_caches_v2_distribution_responses_with_a_configurable_redis_ttl":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_writes_fixed_pricing_versions_from_create_and_delete_flows":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_writes_vehicle_subscription_versions_for_create_update_delete_flows":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_writes_discount_override_versions_from_superuser_discounts_route":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_keeps_legacy_compare_endpoint_path_for_backward_compatibility":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicV2VersioningServiceStructureTest::__pest_evaluable_it_implements_effective_range_lifecycle_methods_for_all_versioned_entities":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicV2VersioningServiceStructureTest::__pest_evaluable_it_closes_previous_active_interval_before_inserting_a_new_version":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2VersioningServiceStructureTest::__pest_evaluable_it_includes_best_effort_backfill_with_provenance_and_confidence_metadata":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2VersioningServiceStructureTest::__pest_evaluable_it_anchors_historical_resolution_on_order_created__at_timestamps_in_distribution_service":0.004,"P\\Tests\\Unit\\Invoicing\\InvoicingOrdersCalculationsHardeningTest::__pest_evaluable_it_guards_against_empty_order_ids_in_net_amount_calculation":0.007,"P\\Tests\\Unit\\Invoicing\\InvoicingOrdersCalculationsHardeningTest::__pest_evaluable_it_guards_against_empty_customer_arrays_in_date_range_transaction_fetches":0.003,"P\\Tests\\Unit\\Invoicing\\InvoicingOrdersCalculationsHardeningTest::__pest_evaluable_it_uses_centralized_duplicate_filtering_for_possible_duplicate_detection":0.003,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteCacheHelpersTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_clamps_negative_ttl_to_zero":0,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteCacheHelpersTest::__pest_evaluable_it_builds_deterministic_cache_keys_per_scope_and_date_range":0.007,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteCacheHelpersTest::__pest_evaluable_it_falls_back_to_resolver_directly_when_cache_ttl_is_disabled":0,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteGuardsTest::__pest_evaluable_it_requires_superuser_permission_for_invoicing_period_distribution_all_endpoint":0.017,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteGuardsTest::__pest_evaluable_it_uses_shared_date_range_normalization_across_invoicing_period_endpoints":0.032,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodUtilsTest::__pest_evaluable_it_normalizes_a_valid_invoicing_date_range_to_full_day_timestamps":0,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodUtilsTest::__pest_evaluable_it_rejects_invalid_date_formats":0.012,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodUtilsTest::__pest_evaluable_it_rejects_descending_date_ranges":0,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodUtilsTest::__pest_evaluable_it_finds_duplicate_orders_regardless_of_original_input_order":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2DistributionServiceFallbackTest::__pest_evaluable_it_runs_best_effort_backfill_when_fixed_pricing_version_history_is_empty":0,"P\\Tests\\Unit\\Selfserve\\SelfserveConditionEvaluatorTest::__pest_evaluable_it_evaluates_self_serve_conditions_with_combined_AND_and_OR_semantics":0,"P\\Tests\\Unit\\Selfserve\\SelfserveConditionEvaluatorTest::__pest_evaluable_it_prefers_condition_results_over_question_answers_when_evaluating_task_gates":0,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_self_serve_machine_type__eligibility__summary__and_webhook_endpoints":0.008,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_defines_reusable_self_serve_wash_and_machine_type_schemas":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_self_serve_machine_types__eligibility__summaries__and_machine_start_webhook_routes":0.084,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_keeps_machine_type_support_wired_into_lanes__tasks__and_conditions_routes":0.024,"P\\Tests\\Unit\\N8n\\N8nRouteHelpersTest::__pest_evaluable_it_normalizes_webhook_methods_and_falls_back_to_POST_for_unsupported_verbs":0,"P\\Tests\\Unit\\N8n\\N8nRouteHelpersTest::__pest_evaluable_it_filters_request_parameters_down_to_the_allowed_n8n_query_keys":0,"P\\Tests\\Unit\\N8n\\N8nRouteWiringTest::__pest_evaluable_it_registers_workflow_lifecycle_endpoints_for_the_n8n_module":0.002,"P\\Tests\\Unit\\N8n\\N8nRouteWiringTest::__pest_evaluable_it_registers_execution_and_webhook_trigger_endpoints_for_the_n8n_module":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_redistributes_booked_department_75_net_amounts_using_fixed_pricing_and_wash_subscription_weights":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_keeps_classified_booked_department_75_amounts_undistributed_when_no_monthly_basis_exists":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_keeps_unclassified_booked_department_75_lines_undistributed_with_warnings":0,"P\\Tests\\Unit\\Invoicing\\EconomicEndpointUrlEncodingTest::__pest_evaluable_it_encodes_raw_filter_query_values_that_include_timestamps":0,"P\\Tests\\Unit\\Invoicing\\EconomicEndpointUrlEncodingTest::__pest_evaluable_it_avoids_double_encoding_query_values_that_are_already_escaped":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_supports_bulk_booked_invoice_line_payloads_with_top_level_department_numbers":0,"P\\Tests\\Unit\\Redis\\RedisAtomicReservationTest::__pest_evaluable_it_claims_a_slot_atomically_with_nx_and_expiration":0,"P\\Tests\\Unit\\Redis\\RedisAtomicReservationTest::__pest_evaluable_it_returns_false_when_the_slot_is_already_claimed_and_clamps_ttl_to_one_second":0,"P\\Tests\\Unit\\Bookings\\OrderBookingRouteIdempotencyGuardTest::__pest_evaluable_it_guards_order_booking_creation_with_redis_backed_idempotency":0.24,"P\\Tests\\Unit\\DynamicImages\\DynamicImagePreRenderCronWiringTest::__pest_evaluable_it_registers_dynamic_image_pre_render_cron_task_and_related_helpers":0.005,"P\\Tests\\Integration\\Database\\DbConnectionTest::__pest_evaluable_it_can_connect_to_a_configured_MySQL_instance_in_integration_mode":0.226,"P\\Tests\\Integration\\Invoicing\\EconomicV2BackfillAndDistributionIntegrationTest::__pest_evaluable_it_runs_best_effort_backfill_repeatedly_without_introducing_duplicate_same_start_rows":0.017,"P\\Tests\\Integration\\Invoicing\\EconomicV2BackfillAndDistributionIntegrationTest::__pest_evaluable_it_resolves_version_aware_distribution_payload_shapes_over_a_real_date_range":0.014,"P\\Tests\\Integration\\Invoicing\\EconomicV2VersioningServiceIntegrationTest::__pest_evaluable_it_creates_closes_and_rotates_fixed_pricing_versions_without_overlap":0.011,"P\\Tests\\Integration\\Invoicing\\EconomicV2VersioningServiceIntegrationTest::__pest_evaluable_it_tracks_vehicle_and_discount_version_lifecycles_with_closure_semantics":0.016,"P\\Tests\\Integration\\Permissions\\LegacyPermissionRedisCacheScriptTest::__pest_evaluable_it_keeps_legacy_route_permission_redis_cache_script_green":0.013,"P\\Tests\\Unit\\Permissions\\AllowOwnOrDepartmentAccessForbiddenTest::__pest_evaluable_it_returns_both_own_and_elevated_permissions_when_both_are_missing":0,"P\\Tests\\Unit\\Permissions\\AllowOwnOrDepartmentAccessForbiddenTest::__pest_evaluable_it_returns_only_elevated_permission_when_own_permission_exists_but_own_context_fails":0,"P\\Tests\\Unit\\Permissions\\AllowOwnOrDepartmentAccessForbiddenTest::__pest_evaluable_it_allows_elevated_permission_path_without_forbidden_and_validates_department_access":0,"P\\Tests\\Unit\\Permissions\\ForbiddenResponseWiringTest::__pest_evaluable_it_routes_and_trait_use_forbidden_responses_for_permission_and_ownership_denials":0.018,"P\\Tests\\Unit\\Permissions\\GroupPermissionSessionInvalidationWiringTest::__pest_evaluable_it_invalidates_related_user_permission_and_auth_session_caches_when_group_permissions_change":0.004,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_parses_advanced_target_duration_from_snake__case_fields":0.066,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_parses_advanced_target_duration_from_camelCase_aliases":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_normalizes_ENTIRE__DURATION_to_ignore_target__duration__every":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_defaults_recurring_target__duration__every_to_1_when_omitted":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_keeps_strict_legacy_mode_when_target__duration_is_invalid":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_computes_weekly_target_using_touched_ISO_weeks_for_March_2026":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_applies_target__duration__every_for_weekly_cadence":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_prorates_ENTIRE__DURATION_target_by_overlap_days":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_splits_advanced_target_by_override_weights_per_department":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_preserves_legacy_target_behavior_when_target__duration_is_missing":0,"P\\Tests\\Unit\\Goals\\GoalsLegacyRendererScriptsTest::__pest_evaluable_it_keeps_legacy_monthly_renderer_script_green":0.147,"P\\Tests\\Unit\\Goals\\GoalsLegacyRendererScriptsTest::__pest_evaluable_it_keeps_legacy_department_daily_renderer_script_green":0.147,"P\\Tests\\Unit\\Goals\\GoalsOpenApiSpecTest::__pest_evaluable_it_documents_advanced_goals_target_duration_fields_in_openapi":0.007,"P\\Tests\\Unit\\Workfeed\\WorkfeedClientConformanceTest::__pest_evaluable_it_uses_company_scoped_workfeed_endpoints_and_raw_Authorization_header":0.003,"P\\Tests\\Unit\\Workfeed\\WorkfeedClientConformanceTest::__pest_evaluable_it_normalizes_documented_shift_query_parameters":0.001,"P\\Tests\\Unit\\Workfeed\\WorkfeedConfigRouteWiringTest::__pest_evaluable_it_registers_module_config_endpoints_for_workfeed":0.004,"P\\Tests\\Unit\\Workfeed\\WorkfeedRouteHelpersTest::__pest_evaluable_it_filters_request_parameters_down_to_the_allowed_workfeed_query_keys":0,"P\\Tests\\Unit\\Workfeed\\WorkfeedRouteWiringTest::__pest_evaluable_it_registers_employee_and_department_endpoints_for_the_workfeed_module":0.004,"P\\Tests\\Unit\\Workfeed\\WorkfeedRouteWiringTest::__pest_evaluable_it_registers_shift_endpoints_for_the_workfeed_module":0.002,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_calculates_workfeed_employee_hours_for_the_hour_slot_based_on_overlap":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_extracts_department_id_from_supported_workfeed_shift_shapes":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_normalizes_wrapped_workfeed_collections_from_common_response_keys":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineSchemaConformanceTest::__pest_evaluable_it_includes_a_date_key_in_department_weather_timeline_entries":0.003,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineSchemaConformanceTest::__pest_evaluable_it_documents_the_date_key_in_the_openapi_department_weather_timeline_schema":0.005,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_builds_a_timeline_range_from_start_of_yesterday_to_end_of_today":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_builds_a_timeline_range_relative_to_an_explicit_selected_date_override":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_calculates_workfeed_employee_hours_across_multiple_departments_for_one_hour_slot":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_normalizes_department_id_input_from_scalar_csv_and_nested_array_values":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_builds_a_timeline_range_relative_to_explicit_date__from_and_date__to_override":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_resolves_forecast_day_count_for_a_given_timeline_range_with_sane_limits":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_resolves_weather_coordinates_from_valid_coordinates_only":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_returns_null_weather_coordinates_when_all_department_locations_are_invalid":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_classifies_weatherapi_no_matching_location_errors_as_location_lookup_failures":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_does_not_classify_non_location_weatherapi_errors_as_location_lookup_failures":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_returns_an_empty_forecast_fallback_when_coordinates_are_unavailable":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_builds_timeline_entries_with_mostly__clear_weather_when_forecast_payload_is_empty":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_wires_departments_weather_route_through_the_forecast_fallback_path":0.005,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_clamps_negative_ttl_to_zero":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_builds_deterministic_cache_keys_for_department_sets_and_timeline_ranges":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_builds_order_insensitive_cache_keys_for_equivalent_department_id_sets":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_falls_back_to_resolver_directly_when_cache_ttl_is_disabled":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_marks_non_started_slots_as_unknown_regardless_of_wash_hour_ratio":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherPreloadCronWiringTest::__pest_evaluable_it_registers_and_implements_cron_preloading_for_department_weather_cache":0.007,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_uses_sane_stale_ttl_defaults_and_clamps_stale_ttl_below_fresh_ttl":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_uses_sane_hot_activity_ttl_defaults_and_clamps_to_a_positive_value":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheRuntimeBehaviorTest::__pest_evaluable_it_serves_fresh_cached_payloads_without_invoking_the_resolver":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheRuntimeBehaviorTest::__pest_evaluable_it_serves_stale_cached_payloads_and_enqueues_a_refresh_signal":0.01,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheRuntimeBehaviorTest::__pest_evaluable_it_recomputes_and_rewrites_cache_payloads_when_stale_window_is_exceeded":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheRuntimeBehaviorTest::__pest_evaluable_it_records_hot_keys_order_insensitively_and_applies_preload_target_caps":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_normalizes_batched_wash_count_rows_into_hourly_slot_totals":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_wires_department_weather_route_to_use_batched_wash_aggregation":0.007,"P\\Tests\\Unit\\Orders\\AttachmentsListManyTest::__pest_evaluable_it_groups_attachments_by_object_id_and_preserves_empty_object_groups":0,"P\\Tests\\Unit\\Orders\\AttachmentsListManyTest::__pest_evaluable_it_keeps_listMany_payload_parity_with_list_for_one_object_id":0,"P\\Tests\\Unit\\Orders\\EconomicModuleOrdersBatchHelpersTest::__pest_evaluable_it_ensures_economic_module_rows_in_one_sanitized_batch":0,"P\\Tests\\Unit\\Orders\\EconomicModuleOrdersBatchHelpersTest::__pest_evaluable_it_returns_id_keyed_economic_module_payload_with_null_defaults":0,"P\\Tests\\Unit\\Orders\\OrdersRouteListBatchingWiringTest::__pest_evaluable_it_wires_GET__orders_through_batched_enrichment_and_stripe_snapshot_caching":0.006,"P\\Tests\\Unit\\Orders\\UsersCashierNamesBatchTest::__pest_evaluable_it_returns_cashier_names_from_cache_and_fetches_missing_ones_in_batch":0,"P\\Tests\\Unit\\Orders\\UsersCashierNamesBatchTest::__pest_evaluable_it_returns_deterministic_map_for_duplicate_and_unsorted_cashier_ids":0,"P\\Tests\\Unit\\Orders\\UsersCashierNamesBatchWiringTest::__pest_evaluable_it_implements_batched_cashier_name_lookup_with_cache_first_fallback_behavior":0.006,"P\\Tests\\Unit\\Orders\\UsersCashierNamesBatchWiringTest::__pest_evaluable_it_sanitizes_and_deduplicates_cashier_ids_before_batch_lookup":0.003,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_counts_overtime_minutes_when_a_shift_carries_an_extended_approval_end_timestamp":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_counts_unapproved_overtime_from_a_bounded_shift_updateTime_fallback":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_does_not_treat_late_unapproved_administrative_edits_as_overtime":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_changes_weather_timeline_cache_key_when_department_weather_targets_change":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherStatusTargetsTest::__pest_evaluable_it_evaluates_healthy_degraded_and_unhealthy_statuses_from_configured_department_targets":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherStatusTargetsTest::__pest_evaluable_it_returns_unknown_when_configured_targets_are_missing_for_department_status_evaluation":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherStatusTargetsTest::__pest_evaluable_it_aggregates_multi_department_slot_statuses_using_worst_severity_and_unknown_fallback_rules":0.046,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsOpenApiSpecTest::__pest_evaluable_it_documents_department_weather_target_endpoints_and_reusable_schemas_in_openapi":0.006,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsOpenApiSpecTest::__pest_evaluable_it_documents_unknown_weather_status_behavior_when_targets_are_missing":0.005,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsRouteWiringTest::__pest_evaluable_it_registers_department_weather_target_routes_with_explicit_read_and_manage_permissions":0.004,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsRouteWiringTest::__pest_evaluable_it_persists_department_weather_targets_using_canonical_department_variable_keys":0.003,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_machine_relay_status_get_and_set_endpoints":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_batches_sequential_machine_relay_status_requests_into_a_single_Shelly_get_call":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_respects_the_1_request_per_second_Shelly_gate_for_back_to_back_requests":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_retries_missing_Shelly_status_payloads_until_relay_status_becomes_ready":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_times_out_with_a_clear_Shelly_readiness_error_when_payload_remains_missing":0.001,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_uses_direct_set_switch_and_seeds_cache_so_immediate_status_read_does_not_call_Shelly_get":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_self_serve_lane_gate_open_endpoint":0.004,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_in_progress_self_serve_wash_details_endpoint":0.003,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_adds_vehicle_type_product_on_STOP_when_program_selector_is_on__then_turns_off_cleaner_machine_and_selector_relays":0.132,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_skips_vehicle_type_product_add_when_program_selector_is_off_and_only_disables_configured_relays":0.001,"P\\Tests\\Unit\\Selfserve\\DepartmentSelfServeEnabledRelaySyncWiringTest::__pest_evaluable_it_syncs_lane_relay_states_when_department_self_serve_enabled_flag_changes":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_supports_hard_relay_set_even_when_lane_status_is_CLOSED":0,"P\\Tests\\Unit\\Selfserve\\SelfserveStartCleanerRelayWiringTest::__pest_evaluable_it_enables_cleaner_relay_on_wash_start_command_and_webhook_flow":0.009,"P\\Tests\\Unit\\Selfserve\\SelfserveWashCompletionRelayWiringTest::__pest_evaluable_it_forces_machine_relay_off_when_a_self_serve_wash_session_is_completed":0.003,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_opens_exit_port_by_switching_relay__in__id_on":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_opens_entrance_port_by_switching_relay__out__id_on":0,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_in_progress_self_serve_wash_start_and_machine_relay_fields":0.006,"P\\Tests\\Unit\\Selfserve\\SelfserveConditionEvaluatorTest::__pest_evaluable_it_evaluates_typed_task_gates_with_strict_semantics":0,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_validates_typed_task_gates_for_known_references":0,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_fails_validation_when_typed_task_gates_reference_unknown_entities":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_self_serve_config_draft_publish_rollback_lifecycle_endpoints":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_keeps_legacy_self_serve_CRUD_routes_syncing_canonical_drafts":0.017,"P\\Tests\\Unit\\Selfserve\\SelfserveStartCleanerRelayWiringTest::__pest_evaluable_it_keeps_cleaner_relay_enable_wired_into_machine_relay_start_paths":0.008,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_stores_config_json_with_apostrophes_without_violating_json_constraints":0.277,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_encodes_config_json_payloads_with_apostrophes_before_persistence":0,"P\\Tests\\Unit\\Selfserve\\SelfserveWashCompletionRelayWiringTest::__pest_evaluable_it_forces_machine_and_cleaner_relays_off_when_a_self_serve_wash_session_is_completed":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_vehicle_type_override_into_self_serve_preview_and_synchronization_routes":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_uses_local_demo_responses_and_skips_Shelly_cloud_calls_for_demo_relay_ids":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_returns_default_OFF_status_for_demo_relay_ids_without_Shelly_lookups":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_excludes_demo_relay_ids_from_Shelly_status_batch_payloads":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_keeps_demo_relay_gate_open_queued_but_skips_Shelly_switch_calls":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_allowed_services_route_through_machine_relay_visibility_sync":0.002,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_enables_MACHINE_relay_when_MACHINE_is_visible_in_allowed_services":0.002,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_turns_MACHINE_relay_off_immediately_when_MACHINE_is_not_visible":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_does_not_enable_MACHINE_relay_when_allowEnable_is_false_even_if_MACHINE_is_visible":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_is_a_safe_no_op_when_MACHINE_relay_is_not_configured":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRelayVisibilitySyncWiringTest::__pest_evaluable_it_synchronizes_machine_relay_from_visible_services_during_session_synchronization":0.01,"P\\Tests\\Unit\\Selfserve\\SelfserveRelayVisibilitySyncWiringTest::__pest_evaluable_it_adds_explicit_relay_disable_session_helper_for_visibility_driven_OFF_transitions":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_self_serve_property_gate_command_permissions":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneCommandEnumTest::__pest_evaluable_it_parses_property_gate_lane_commands":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_opens_entrance_gate_for_OPEN__PROPERTY__ACCESS__GATE_command":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_opens_exit_gate_for_OPEN__PROPERTY__EXIT__GATE_command":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_blocks_property_gate_commands_when_department_self_serve_is_disabled":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_throws_a_clear_error_when_entrance_gate_is_missing_for_property_access_command":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_wraps_low_level_gate_errors_for_property_access_command_failures":0.002,"P\\Tests\\Unit\\Selfserve\\SelfserveWashFlowMachineAllowedWiringTest::__pest_evaluable_it_reads_machine_allowed_state_from_session_summary_payload_safely":0.004,"P\\Tests\\Unit\\Selfserve\\DbObjectPaginationLegacyColumnCompatibilityTest::__pest_evaluable_it_guards_pagination_against_searchable_fields_missing_from_legacy_schemas":0.339,"P\\Tests\\Unit\\Selfserve\\SelfserveSchemaBootstrapCompatibilityTest::__pest_evaluable_it_adds_dynamic__images__vehicle__type_column_for_legacy_selfserve_wash_session_task_schemas":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceIncludedMinutesTest::__pest_evaluable_it_computes_billable_minutes_when_elapsed_minutes_exceed_included_minutes":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceIncludedMinutesTest::__pest_evaluable_it_computes_zero_billable_minutes_when_elapsed_minutes_equal_included_minutes":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceIncludedMinutesTest::__pest_evaluable_it_computes_zero_billable_minutes_when_included_minutes_exceed_elapsed_minutes":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceIncludedMinutesTest::__pest_evaluable_it_handles_zero_and_low_elapsed_wash_time_edge_cases":0,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_self_serve_machine_wash_included_minutes_in_config_schemas":0.006,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_machine_wash_included_minutes_into_self_serve_module_config":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_blocks_explicit_relay_writes_when_department_self_serve_is_disabled":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_returns_disabled_no_op_from_machine_relay_visibility_sync_when_department_self_serve_is_disabled":0,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_property_gate_lane_commands_and_sanitized_gate_failure_responses":0.008,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_workspace_id_is_missing_for_gate_calls":0.019,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_channel_id_is_missing_for_gate_calls":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_with_terminal_status_details_when_call_never_reaches_accepted_state":0.072,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_hangs_up_when_call_reaches_accepted_state":0.013,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_hangs_up_immediately_when_status_transitions_to_accepted":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_maps_legacy_timeout_option_to_documented_ringTimeout_payload_field":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_clamps_derived_ringTimeout_to_Bird_documented_max_when_gate_timeout_is_high":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_passes_documented_hangup_cause_when_provided":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_drops_unsupported_hangup_cause_values_from_request_payload":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_workspace_id_is_missing_for_gate_flash_calls":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_creates_gate_flash_call_with_documented_ringTimeout_payload":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_polls_flash_call_and_succeeds_once_accepted":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_flash_gate_flow_when_terminal_failure_status_is_returned":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_does_not_fallback_to_regular_gate_call_when_flash_succeeds":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_falls_back_to_regular_gate_call_when_flash_fails":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_wraps_low_level_gate_errors_for_property_exit_command_failures":0.002,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_falls_back_to_regular_gate_call_when_flash_caller_id_is_not_confirmed":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_maps_voice_call_facade_methods_to_documented_endpoints_and_methods":0.039,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_maps_recordings_insights_log_and_flash_methods_to_documented_resources":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_encodes_path_segments_before_building_outbound_endpoints":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_serializes_query_parameters_for_GET_transport_requests":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_maps_4xx_and_5xx_transport_failures_into_informative_exceptions":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_returns_raw_payload_for_malformed_JSON_responses_and_null_for_empty_responses":0.007,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_documents_all_Bird_voice_call_parity_endpoints_including_gather_recordings_insights_and_log":0.007,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_documents_flash_hangup_endpoint_and_marks_end_alias_as_deprecated":0.005,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_defines_request_and_response_schemas_for_Bird_call_command_recording_insight_log_and_flash_payloads":0.004,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_accepts_valid_payloads_for_create_and_nested_call_flow_commands":0,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_rejects_unknown_fields_and_invalid_enum_values_in_strict_schemas":0.014,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_supports_CSV_normalization_in_schema_validation_for_log_filters":0,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_validates_flash_hangup_payloads_for_both_supported_request_shapes":0,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_fails_before_forward_step_when_strict_validation_fails_and_forwards_when_valid":0,"P\\Tests\\Unit\\Bird\\BirdRouteWiringTest::__pest_evaluable_it_registers_full_Bird_voice_call_route_surface_with_strict_validation_and_permissions":0.005,"P\\Tests\\Unit\\Bird\\BirdRouteWiringTest::__pest_evaluable_it_registers_flash_hangup_endpoint_and_keeps_end_alias_wired_as_compatibility_path":0.004,"P\\Tests\\Unit\\Bird\\BirdRouteWiringTest::__pest_evaluable_it_keeps_Bird_number_and_webhook_routes_intact":0.006,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_handles_malformed_and_empty_response_bodies_without_throwing_transport_errors":0.005,"P\\Tests\\Unit\\Selfserve\\DepartmentGatesRelaysRouteWiringTest::__pest_evaluable_it_validates_department_gate_config_on_both_create_and_update_routes":0.043,"P\\Tests\\Unit\\Selfserve\\SelfserveSchemaBootstrapCompatibilityTest::__pest_evaluable_it_adds_wash__started__at_column_for_legacy_selfserve_wash_session_schemas":0.004,"P\\Tests\\Unit\\Selfserve\\SelfserveWashStartedAtWiringTest::__pest_evaluable_it_stores_wash__started__at_in_self_serve_wash_sessions_when_machine_start_is_triggered":0.003,"P\\Tests\\Unit\\Selfserve\\SelfserveWashStartedAtWiringTest::__pest_evaluable_it_passes_lane_wash_start_time_into_the_session_machine_start_marker":0.004,"P\\Tests\\Unit\\Selfserve\\SelfserveWashStartedAtWiringTest::__pest_evaluable_it_resolves_in_progress_wash__started__at_from_session_with_compatibility_fallbacks":0.003,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_normalizes_say_payload_and_applies_hangup_default":0.019,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_normalizes_log_query_csv_and_integer_fields":0,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_normalizes_nested_create_call_payload_sections_and_drops_unknown_keys":0,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_keeps_gather_nested_say_payload_unchanged_when_hangup_is_omitted":0,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_supports_no_body_and_flash_hangup_payload_normalization":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_respects_the_2_second_Shelly_gate_for_back_to_back_requests":0.023,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_enforces_a_2_second_gap_between_sequential_switch_requests_used_by_wash_start_and_stop_flows":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_keeps_back_to_back_get_switch_requests_ordered_through_the_relay_controller":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_executes_sequential_switch_requests_used_by_wash_start_and_stop_flows":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_does_not_print_Shelly_switch_responses_to_output":0.067,"P\\Tests\\Unit\\Selfserve\\ShellyGlobalRateLimitWiringTest::__pest_evaluable_it_enforces_a_global_2_second_Shelly_gate_in_sendPostRequest":0.005,"P\\Tests\\Unit\\Selfserve\\ShellyGlobalRateLimitWiringTest::__pest_evaluable_it_uses_Redis_NX_PX_semantics_for_cross_request_Shelly_rate_limiting":0.002,"P\\Tests\\Unit\\Selfserve\\ShellyGlobalRateLimitBehaviorTest::__pest_evaluable_it_enforces_the_2_second_Shelly_gate_across_separate_request_contexts":0,"P\\Tests\\Unit\\Selfserve\\ShellyGlobalRateLimitBehaviorTest::__pest_evaluable_it_does_not_delay_when_the_Shelly_gate_is_already_expired":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_adds_vehicle_type_product_on_STOP_when_program_selector_relay_is_online__then_turns_off_cleaner_and_machine_relays":0.538,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_skips_vehicle_type_product_add_when_program_selector_relay_is_offline_and_only_disables_configured_relays":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_bills_primary_product_when_selector_relay_is_online_even_if_relay_output_is_off":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceModeBillingTest::__pest_evaluable_it_bills_manual_self_serve_stop_using_full_elapsed_minutes_without_included_minute_reduction":0.001,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceModeBillingTest::__pest_evaluable_it_keeps_included_minute_reduction_for_automatic_mode":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_on_first_dtmf_input_captured_within_the_300_second_window":0.005,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_does_not_send_Slack_when_dtmf_input_repeats_without_change":0.008,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_again_when_dtmf_input_changes_within_the_window":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_keeps_gathering_and_does_not_hang_up_before_300_seconds_have_elapsed":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_announces_timeout_waits_10_seconds_and_sends_hangup_once_at_or_after_300_seconds":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_keeps_polling_until_terminal_status_and_only_then_finalizes":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_finalizes_immediately_when_webhook_payload_is_already_terminal_before_timeout_logic":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_does_not_duplicate_timeout_or_hangup_actions_across_retries_and_lock_contention":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_keeps_state_when_polling_fails_so_completion_is_not_falsely_reported":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_when_dtmf_input_repeats_without_change":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_answers_immediately_once_and_does_not_re_answer_on_subsequent_webhook_retries":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_configures_gather_with_retry_loop_semantics_until_input_is_entered":0.004,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_when_gather_result_provides_keys_field_instead_of_dtmf":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_when_gather_conditions_variable_keys_carries_the_entered_value":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_configures_gather_to_check_every_2_seconds_with_retry_loop_semantics_until_input_is_entered":0,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_ignores_non_numeric_customer__number_values_from_request":0.042,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_casts_numeric_customer__number_strings_to_int_before_lookup":0,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_prefers_user__id_when_both_user__id_and_customer__number_are_valid":0,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_falls_back_to_customer__number_when_user__id_is_invalid":0,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_normalizes_request_identifiers_before_user_lookups":0.004,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_rejects_non_positive_and_non_digit_request_values":0.003,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_uses_pagination_results_when_present":0.006,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_falls_back_to_collection_count_when_pagination_metadata_is_missing":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_returns_zero_when_neither_pagination_nor_collection_is_available":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_counts_object_based_collections_when_pagination_metadata_is_missing":0,"P\\Tests\\Unit\\Invoicing\\EconomicPaymentTermsRouteCollectionExtractionTest::__pest_evaluable_it_uses_collection_when_present":0,"P\\Tests\\Unit\\Invoicing\\EconomicPaymentTermsRouteCollectionExtractionTest::__pest_evaluable_it_falls_back_to_paymentTerms_when_collection_is_missing":0,"P\\Tests\\Unit\\Invoicing\\EconomicPaymentTermsRouteCollectionExtractionTest::__pest_evaluable_it_supports_top_level_array_payloads":0,"P\\Tests\\Unit\\Invoicing\\EconomicPaymentTermsRouteCollectionExtractionTest::__pest_evaluable_it_returns_an_empty_array_when_no_known_collection_shape_exists":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_uses_grant__2_in_economic__endpoint__t_when_explicitly_requested_and_configured":0.009,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_falls_back_to_grant__1_in_economic__endpoint__t_when_grant__2_is_missing":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_for_missing_required_primary_grant_in_economic__endpoint__t":0.014,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_for_missing_app_secret_in_economic__endpoint__t":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_uses_grant__2_in_legacy_economic__m_when_available":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_falls_back_to_grant__1_in_legacy_economic__m_when_grant__2_is_missing":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_for_missing_required_primary_grant_in_legacy_economic__m":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_for_missing_app_secret_in_legacy_economic__m":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_uses_unfiltered_total_when_no_customer_filters_are_active":0.004,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_uses_filtered_total_when_search_is_active":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_uses_filtered_total_when_barred_filter_is_active":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_treats__null__search_and_barred_values_as_no_filter":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_falls_back_to_filtered_total_when_unfiltered_total_is_missing":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRouteEconomicFailureHandlingTest::__pest_evaluable_it_maps_e_conomic_integration_failures_in_customer_listing_to_explicit_502_responses":0.014,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRouteEconomicFailureHandlingTest::__pest_evaluable_it_logs_LIST__CUSTOMERS_success_only_after_pagination_and_customer_mapping_are_completed":0.009,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRouteEconomicFailureHandlingTest::__pest_evaluable_it_guards_against_malformed_customer_list_payloads_before_calling_paginate":0.011,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_deterministic_upstream_exceptions_for_non_2xx_endpoint_trait_responses":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_deterministic_upstream_exceptions_for_non_2xx_legacy_economic__m_responses":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_returns_raw_payload_unchanged_on_successful_HTTP_statuses":0,"P\\Tests\\Unit\\Invoicing\\EconomicCustomersListResponseValidationTest::__pest_evaluable_it_accepts_valid_list_payloads_that_include_collection_and_pagination_results":0.02,"P\\Tests\\Unit\\Invoicing\\EconomicCustomersListResponseValidationTest::__pest_evaluable_it_throws_when_pagination_is_missing_from_the_response_payload":0,"P\\Tests\\Unit\\Invoicing\\EconomicCustomersListResponseValidationTest::__pest_evaluable_it_throws_when_upstream_responds_with_an_error_shaped_payload":0,"P\\Tests\\Unit\\Router\\RouterThrowableHandlingTest::__pest_evaluable_it_catches_throwables_during_auto_route_loading_and_maps_them_to_internal_server_errors":0.003,"P\\Tests\\Unit\\Users\\EconomicCustomerZeroHandlingTest::__pest_evaluable_it_does_not_request_e_conomic_customer_data_when_customer_number_is_zero":0.101,"P\\Tests\\Unit\\Users\\EconomicCustomerZeroHandlingTest::__pest_evaluable_it_short_circuits_e_conomic_customer_lookup_for_non_positive_customer_numbers":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueRouteRegistrationTest::__pest_evaluable_it_registers_queued_economic_invoice_endpoints_in_economicInvoiceRoute":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueRouteRegistrationTest::__pest_evaluable_it_registers_collected_invoice_queue_endpoints_in_orderInvoicesRoute":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueSchemaBootstrapTest::__pest_evaluable_it_defines_economic_transfer_queue_jobs_schema_bootstrap_table_and_tracking_columns":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueSchemaBootstrapTest::__pest_evaluable_it_provides_queue_processor_class_constants_and_processing_entrypoint":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueCronIntegrationTest::__pest_evaluable_it_registers_economic_transfer_queue_cron_task_and_handler":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_economic_transfer_queue_paths_in_openapi":0.01,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_economic_transfer_queue_schemas_in_openapi":0.007,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_skips_order_items_with_zero_quantity_for_e_conomic_export":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_skips_order_items_with_zero_price_for_e_conomic_export":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_keeps_positive_quantity_and_price_items_billable_for_e_conomic_export":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_wires_zero_cost_and_zero_quantity_skip_guard_into_transfer_line_builder":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicInvoiceDraftZeroItemSkipWiringTest::__pest_evaluable_it_skips_zero_cost_and_zero_quantity_items_in_legacy_economic_draft_helper":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_skips_malformed_order_item_payloads_for_e_conomic_export_safety":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueHardeningTest::__pest_evaluable_it_hardens_transfer_queue_with_type_validation_retry_caps_and_stale_lock_recovery":0.004,"P\\Tests\\Unit\\Router\\AutoloadRedisCacheValidationTest::__pest_evaluable_it_validates_cached_autoload_paths_before_returning_and_clears_stale_cache_entries":0.003,"P\\Tests\\Unit\\Orders\\OrdersRegistrationDateRangeQueryTest::__pest_evaluable_it_applies_created__at_bounds_directly_in_SQL_when_filtering_orders_by_registration_number":0,"P\\Tests\\Unit\\Orders\\OrdersRegistrationDateRangeQueryTest::__pest_evaluable_it_rejects_an_inverted_date_range_for_registration_lookups":0,"P\\Tests\\Unit\\Orders\\OrdersRegistrationDateRangeQueryTest::__pest_evaluable_it_returns_early_when_registration_number_is_blank":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueCronIntegrationTest::__pest_evaluable_it_wires_queue_worker_class_loading_for_CLI_queue_action":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_guards_all_economic_invoice_queue_endpoints_before_constructing_queue_service":0.012,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_guards_all_collected_invoice_queue_endpoints_before_constructing_queue_service":0.011,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_uses_a_consistent_unavailable_service_contract_for_missing_queue_dependencies":0.009,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_gracefully_handles_unavailable_queue_dependencies_on_collected_invoice_queue_endpoints":0.005,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceEconomicQueueResponseContractTest::__pest_evaluable_it_returns_the_queue_job_id_in_POST__collected_invoices_economic_enqueue_response":0.204,"P\\Tests\\Unit\\Invoicing\\UserCollectedInvoiceUpdateRouteValidationTest::__pest_evaluable_it_requires_id_and_at_least_one_mutable_field_for_PUT__collected_invoices_in_user_route":0.004,"P\\Tests\\Unit\\Invoicing\\UserCollectedInvoiceUpdateRouteValidationTest::__pest_evaluable_it_supports_independent_po__number_and_closed__at_updates_for_PUT__collected_invoices_in_user_route":0.175,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceEconomicQueueResponseContractTest::__pest_evaluable_it_returns_queued_contract_for_POST__collected_invoices_stripe_book":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicDraftQueueOnlyRouteBehaviorTest::__pest_evaluable_it_keeps_order_draft_export_route_queue_only":0.006,"P\\Tests\\Unit\\Invoicing\\EconomicDraftQueueOnlyRouteBehaviorTest::__pest_evaluable_it_keeps_collected_invoice_draft_producing_routes_queue_only_in_orderInvoicesRoute":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_guards_collected_invoice_and_stripe_draft_producing_endpoints_before_constructing_queue_service":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_unavailable_queue_dependency_responses_for_async_economic_transfer_endpoints":0.007,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueuePayloadValidationTest::__pest_evaluable_it_normalizes_order_payloads_to_strict_positive_integer_ids":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueuePayloadValidationTest::__pest_evaluable_it_normalizes_collected_invoice_payload_booleans_to_strict_bool_values":0.007,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueuePayloadValidationTest::__pest_evaluable_it_rejects_invalid_transfer_payloads_before_enqueue_write_attempts":0.036,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_processes_queued_transfer_jobs_to_completion":0.284,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_deduplicates_active_jobs_per_transfer_target":0.012,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_rejects_invalid_payloads_without_inserting_queue_rows":0.011,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_supports_fail_retry_and_reprocess_lifecycle_transitions":0.006,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_keeps_queue_guards_on_economic_invoice_queue_status_and_retry_routes":0.012,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_supports_synchronous_fallback_branches_before_queue_enqueue_on_economic_invoice_export_routes":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_keeps_queue_status_endpoints_guarded_while_collected_invoice_export_routes_support_synchronous_fallback":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_uses_a_consistent_unavailable_service_contract_for_queue_status_lifecycle_endpoints":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicDraftQueueOnlyRouteBehaviorTest::__pest_evaluable_it_supports_synchronous_fallback_and_queued_processing_for_order_draft_export_route":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicDraftQueueOnlyRouteBehaviorTest::__pest_evaluable_it_supports_synchronous_fallback_and_queued_processing_for_collected_invoice_draft_producing_routes":0.004,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceEconomicQueueResponseContractTest::__pest_evaluable_it_documents_both_synchronous_fallback_and_queued_response_contracts_for_POST__collected_invoices_economic":0.236,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceEconomicQueueResponseContractTest::__pest_evaluable_it_documents_both_synchronous_fallback_and_queued_response_contracts_for_POST__collected_invoices_stripe_book":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_200_fallback_plus_202_queue_contracts_for_export_endpoints_and_keeps_503_on_queue_lifecycle_endpoints":0.009,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueRouteHardeningTest::__pest_evaluable_it_returns_pagination_metadata_and_strict_status_handling_for_collected_invoice_queue_list":0.014,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueRouteHardeningTest::__pest_evaluable_it_enforces_retry_constraints_for_collected_invoice_queue_jobs_before_retry_execution":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_collected_queue_list_metadata_and_strict_status_filter_enum_in_openapi":0,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_builds_a_completed_collected_invoice_queue_summary_from_payload_and_result":0.195,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_prefers_queue_error_messages_for_failed_jobs_and_keeps_null_safe_outcome_fields":0.003,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_uses_deterministic_status_message_fallback_when_no_explicit_message_exists":0.003,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_handles_object_payload_result_values_and_malformed_fields_without_throwing":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueWorkerTickRouteTest::__pest_evaluable_it_ticks_collected_invoice_transfer_queue_from_queue_list_and_status_routes":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueWorkerTickRouteTest::__pest_evaluable_it_ticks_order_transfer_queue_from_draft_and_invoice_status_routes":0.009,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodQueueOverlayTest::__pest_evaluable_it_marks_queued_transactions_and_clears_requires__action_when_all_actionable_work_is_already_queued":0.826,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodQueueOverlayTest::__pest_evaluable_it_keeps_requires__action_true_when_a_customer_still_has_unqueued_actionable_transactions":0.045,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodQueueOverlayTest::__pest_evaluable_it_blocks_fixed_pricing_or_subscription_customers_with_no_transactions_when_a_relevant_queue_job_exists":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerCommandQueueTest::__pest_evaluable_it_queues_admin_commands__exposes_agent_poll_result_handlers__and_keeps_heartbeats_from_mutating_discovery_state":0.003,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerCommandQueueTest::__pest_evaluable_it_defines_the_dispatchable_gateway_guard_on_the_loaded_manager_class":0.009,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"recent heartbeat stays online\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"late heartbeat degrades after one minute\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"stale heartbeat goes offline after five minutes\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"explicit offline reports stay offline even when heartbeat is fresh\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"missing heartbeat is treated as offline\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_marks_ready_discovery_as_stale_when_the_gateway_heartbeat_has_expired":0.351,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_the_edge_gateway_management_REST_endpoints":0.021,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_public_installer__claim__heartbeat__command_polling__and_internal_broker_auth_endpoints":0.004,"P\\Tests\\Unit\\Selfserve\\EdgeBrokerClientConfigTest::__pest_evaluable_it_uses_the_same_default_broker_url_and_shared_secret_fallback_as_the_docker_stack":0.267,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_install_script_urls_with_forwarded_https_scheme_when_proxied":0.336,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_appends_forwarded_ports_when_the_forwarded_host_omits_them":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_infers_https_for_the_staging_api_host_when_only_the_https_port_is_present":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_prefers_EDGE__PUBLIC__API__URL_when_explicitly_configured":0.168,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_normalizes_public_broker_overrides_to_https_and_browser_shell_urls_to_wss":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_keeps_localhost_broker_overrides_on_plain_http_and_ws_for_local_development":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_includes_node_pty_build_prerequisites_in_the_generated_install_script":0.007,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_prefers_EDGE__PUBLIC__API__URL_when_explicitly_configured_and_derives_the_broker_from_the_api_origin":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_normalizes_public_broker_overrides_to_https__strips_paths__and_browser_shell_urls_to_wss":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_merges_incoming_heartbeat_metadata_with_existing_gateway_metadata":0.006,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_the_v2_operator_facing_edge_gateway_routes":0.004,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_PHP_edge_agent_routes_for_operations_and_legacy_relay_command_polling":0.005,"P\\Tests\\Unit\\Selfserve\\EdgeGatewaySchemaBootstrapTest::__pest_evaluable_it_defines_the_v2_edge_gateway_schema_bootstrap_tables":0.004,"P\\Tests\\Unit\\Selfserve\\EdgeGatewaySchemaBootstrapTest::__pest_evaluable_it_stores_operation_metadata_and_event_timelines_for_management_workflows":0.004,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_builds_the_installer_around_the_PHP_agent_artifacts_and_management_polling_config":0.011,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_exposes_update_payload__credential_rotation__and_operation_endpoints_without_shell_transport_wiring":0.013,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerCommandQueueTest::__pest_evaluable_it_keeps_relay_dispatch_and_discovery_queueing_on_the_edge_gateway_manager":0.017,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerCommandQueueTest::__pest_evaluable_it_loads_relay_command_helpers_on_the_manager_and_gateway_operations_on_the_dedicated_service":0.016,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_relay_fallback_and_transport_health_details_without_shell_or_update_runtime_state":0.364,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_resolves_edge_agent_artifacts_from_the_source_tree_layout":0.445,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_includes_the_container_mounted_artifact_directory_as_a_candidate":0.021,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_reads_install_artifacts_through_the_shared_locator":0.008,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_builds_update_payloads_with_checksums_from_resolved_artifact_paths":0.427,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_resolves_edge_agent_artifacts_from_a_supported_runtime_layout":0.017,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_install_script_urls_with_the_PHP_agent_artifacts_and_forwarded_https_scheme":0.001,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_explains_the_legacy_dist_mount_mismatch_when_php_artifacts_are_unavailable":0.001,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_prioritizes_mounted_and_baked_in_artifact_directories_before_repo_fallbacks":0.022,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_falls_back_to_baked_in_artifacts_when_the_mount_path_is_absent":0.001,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_prioritizes_router_resources_before_mounted_and_baked_in_artifact_directories":0.022,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_lists_orders_for_an_admin_scoped_user_and_limits_the_results_to_the_permitted_departments":1.109,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_lists_only_the_targeted_customer_orders_for_subuser_sessions":2.935,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_returns_the_current_auth_and_permission_failures_when_order_listing_is_not_allowed":1.375,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_creates_orders_through_the_real_endpoint":0.982,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_order_creation_requests":3.423,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_updates_orders_through_the_primary_endpoint":1.13,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_reassigns_invoice_collections_when_changing_an_order_across_the_draft_customer_boundary":1.615,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_supports_legacy_field_value_metadata_updates_through_the_primary_endpoint":5.592,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_updates_through_the_primary_order_endpoint":1.29,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_updates_orders_through_the_legacy_alias_endpoint":1.517,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_supports_legacy_field_value_metadata_updates_through_the_alias_endpoint":4.136,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_updates_through_the_legacy_alias_endpoint":0.512,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_unsupported_legacy_field_value_updates_on_both_update_endpoints":0.965,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_deletes_orders_through_the_real_endpoint":1.045,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_order_delete_requests":1.64,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_regenerates_attached_wash_certificates_when_certificate_metadata_changes_through_the_primary_endpoint":3.683,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_regenerates_attached_wash_certificates_for_legacy_field_value_updates_through_the_alias_endpoint":3.194,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayOperationLegacySchemaCompatibilityTest::__pest_evaluable_it_keeps_the_legacy_operation__type_column_compatible_with_v2_operation_queueing":0.015,"P\\Tests\\Unit\\Bookings\\OrderBookingsListCacheTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_clamps_negative_ttl_to_zero":0,"P\\Tests\\Unit\\Bookings\\OrderBookingsListCacheTest::__pest_evaluable_it_builds_deterministic_keys_for_equivalent_contexts":0,"P\\Tests\\Unit\\Bookings\\OrderBookingsListCacheTest::__pest_evaluable_it_stores_and_retrieves_full_order_bookings_payloads":0,"P\\Tests\\Unit\\Bookings\\OrderBookingsListCacheTest::__pest_evaluable_it_ignores_malformed_cached_payloads_and_clears_order_bookings_list_caches":0,"P\\Tests\\Unit\\Bookings\\OrderBookingsRouteCacheWiringTest::__pest_evaluable_it_caches_the_paginated_order_bookings_list_response_and_invalidates_it_on_booking_changes":0.008,"P\\Tests\\Unit\\Bookings\\VehicleSearchBookedMetadataRouteContractTest::__pest_evaluable_it_keeps_booked_vehicle_search_metadata_aligned_with_filtered_pending_order_bookings":0.005,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsCacheTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_clamps_negative_ttl_to_zero":0.012,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsCacheTest::__pest_evaluable_it_builds_deterministic_keys_for_equivalent_count_contexts":0.012,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsCacheTest::__pest_evaluable_it_stores_and_retrieves_normalized_booking_counts":0.014,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsCacheTest::__pest_evaluable_it_ignores_malformed_payloads_and_clears_order_bookings_count_caches":0.078,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsRouteWiringTest::__pest_evaluable_it_adds_a_cached_order_bookings_counts_endpoint_and_invalidates_it_on_booking_changes":0.008,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayFleetUsageStatisticsTest::__pest_evaluable_it_summarizes_fleet_usage_statistics_for_the_dashboard_landing_view":0,"P\\Tests\\Api\\ApiCoverageManifestTest::__pest_evaluable_it_keeps_every_selected_API_operation_covered_by_happy_path_and_failure_tests":0.271,"P\\Tests\\Api\\ApiCoverageManifestTest::__pest_evaluable_it_keeps_the_OpenAPI_manifest_entries_aligned_with_the_API_spec":0.097,"P\\Tests\\Api\\ApiFixturesCleanupTest::__pest_evaluable_it_removes_generated_customer_traces_during_fixture_cleanup":8.099,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_in_with_valid_customer_credentials":4.515,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_login_payloads_and_credentials":1.271,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_returns_the_cached_auth_session_payload_for_a_valid_token":0.888,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_includes_economic_runtime_config_for_uncached_auth_sessions":1.349,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_auth_session_tokens":0.698,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_out_and_invalidates_the_token_for_future_session_calls":1.365,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_out_and_invalidates_cached_subuser_sessions":1.932,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_logout_tokens":0.393,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_the_raw_202_gather_webhook_contract_over_HTTP":0.788,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_still_prompts_for_department_selection_when_only_one_department_is_eligible":0.732,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_accepts_the_legacy_initial_webhook_body_with_top_level_call_identifiers":0.692,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_native_flow_gather_data_after_a_top_level_department_selection_when_distinct_gate_choices_exist":1.515,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_opens_the_gate_immediately_after_a_top_level_department_selection_when_entrance_and_exit_share_the_same_gate":1.719,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_uses_a_multi_digit_gather_contract_when_10_departments_are_eligible":0.587,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_a_raw_400_transport_error_for_malformed_webhook_payloads":0.419,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_lists_only_visible_departments_and_can_return_a_single_department_with_the_slack_webhook":1.048,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_department_listing_when_the_permission_is_missing":0.378,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_creates_departments_through_the_real_endpoint":0.59,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_create_requests":1.554,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_updates_departments_through_the_real_endpoint":0.788,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_update_requests":1.552,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_lists_department_categories_for_a_department":1.006,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_category_requests":1.191,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_lists_the_draft_customer_config_entry_in_economic_config_responses":0.947,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_round_trips_the_draft_customer_config_value_through_economic_config_updates":3.28,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_order_draft_exports_for_the_configured_draft_customer":0.86,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_booked_invoice_exports_for_the_configured_draft_customer":1.127,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_collected_invoice_exports_for_the_configured_draft_customer":0.888,"P\\Tests\\Api\\PingApiTest::__pest_evaluable_it_returns_the_ping_contract":0.877,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_setup_required_error_when_department_terminal_readers_are_requested_without_terminal_setup":1.281,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_sends_a_Stripe_invoice_by_email_and_persists_the_hosted_invoice_association":5.434,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_conflict_when_a_Stripe_hosted_invoice_is_already_active_for_the_order":4.756,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_allows_sending_a_new_Stripe_hosted_invoice_when_the_existing_association_is_already_terminal":3.943,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_voids_an_unpaid_Stripe_hosted_invoice_and_clears_the_local_order_association":3.746,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_refuses_to_cancel_a_paid_Stripe_hosted_invoice":4.131,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_setup_required_error_when_creating_a_payment_intent_for_a_department_without_terminal_setup":0.726,"P\\Tests\\Api\\VehiclesApiTest::__pest_evaluable_it_returns_the_newest_vehicle_last__order__id_that_still_has_order_items":1.326,"P\\Tests\\Api\\VehiclesApiTest::__pest_evaluable_it_returns_a_null_vehicle_last__order__id_when_no_order_with_items_exists":1.159,"P\\Tests\\Unit\\Users\\EconomicCustomerModelParsingTest::__pest_evaluable_it_parses_cached_economic_customer_payloads_that_use_snake__case_customer__number":0.246,"P\\Tests\\Unit\\Users\\EconomicCustomerModelParsingTest::__pest_evaluable_it_leaves_the_economic_customer_model_empty_when_no_valid_customer_number_is_present":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayFleetUsageStatisticsTest::__pest_evaluable_it_derives_fleet_usage_directly_from_cached_gateway_row_summaries":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_install_script_urls_with_the_compose_edge_gateway_artifacts_and_forwarded_https_scheme":0.182,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayMetadataUpdateContractTest::__pest_evaluable_it_adds_a_gateway_metadata_update_endpoint_with_label_and_primary_assignment_fields":0.01,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayMetadataUpdateContractTest::__pest_evaluable_it_reassigns_department_primary_gateways_through_dedicated_manager_helpers":0.007,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayShellPollingTransportTest::__pest_evaluable_it_removes_shell_access_from_the_edge_gateway_HTTP_contracts":0.005,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_builds_the_installer_around_the_compose_stack_artifacts_and_management_polling_config":0.053,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_deterministic_cache_keys":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_stores_and_retrieves_cached_list_and_detail_payloads":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_syncs_gateway_snapshots_into_cached_list_payloads_and_refreshes_fleet_usage":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_removes_deleted_gateways_from_cached_list_and_detail_payloads":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_exposes_update_payload__credential_rotation__cancel_endpoints__and_operation_endpoints_without_shell_transport_wiring":0.012,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_registers_module_scoped_edge_gateway_operator_routes":0.007,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_registers_edge_gateway_module_config_endpoints":0.006,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_registers_edge_gateway_config_endpoints_from_the_module_route_directory":0.011,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_keeps_only_the_module_facade_in_the_global_classes_directory_and_conditionally_loads_module_routes":0.005,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayInstallSessionLifecycleTest::__pest_evaluable_it_caps_install_session_diagnostics_and_events_while_preserving_the_first_start_timestamp":0.026,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayInstallSessionLifecycleTest::__pest_evaluable_it_clears_terminal_failure_details_after_a_successful_claim_update":0.014,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayInstallSessionLifecycleTest::__pest_evaluable_it_marks_expired_non_terminal_install_sessions_as_terminal_when_read_back":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_websocket_broker_urls_on_the_traefik_broker_path":0,"P\\Tests\\Unit\\Selfserve\\DepartmentGateConfigRelayTest::__pest_evaluable_it_validates_relay_gate_configs_and_keeps_relay_specific_fields_in_the_payload":0.025,"P\\Tests\\Unit\\Selfserve\\DepartmentGateConfigRelayTest::__pest_evaluable_it_rejects_relay_gate_configs_without_a_logical_relay_id":0.014,"P\\Tests\\Unit\\Bird\\DepartmentGatesRelayOpenTest::__pest_evaluable_it_dispatches_relay_backed_gates_through_the_edge_gateway_relay_manager":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayDepartmentWorkspaceContractTest::__pest_evaluable_it_defines_the_department_hardware_workspace_service_payload_surface":0.011,"P\\Tests\\Unit\\Selfserve\\PlateScannerWorkspaceContractTest::__pest_evaluable_it_adds_lane_aware_scanner_management_and_a_dedicated_rotate_key_action":0.01,"P\\Tests\\Unit\\Selfserve\\PlateScannerWorkspaceContractTest::__pest_evaluable_it_uses_the_scanner_default_lane_before_requiring_an_explicit_lane__id_in_machine_button_webhooks":0.005,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_maps_gateway_relay_status_responses_into_the_Shelly_cloud_payload_shape":0.01,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_maps_gateway_relay_switch_responses_into_the_Shelly_cloud_payload_shape":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_requires_a_valid_department_id_for_gateway_transport_requests":0.009,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_rejects_unsupported_gateway_transport_endpoints":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_surfaces_binding_lookup_failures_while_resolving_relay_state_through_the_gateway_transport":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_surfaces_offline_gateway_failures_while_dispatching_relay_switch_commands":0,"P\\Tests\\Api\\PlateScannersApiTest::__pest_evaluable_it_returns_the_updated_lane_id_after_editing_a_scanner_whose_null_lane_was_already_cached":21.835,"P\\Tests\\Api\\PlateScannersApiTest::__pest_evaluable_it_rejects_plate_scanner_edits_when_the_permission_is_missing":7.837,"P\\Tests\\Unit\\Selfserve\\ShellyRelayInventoryTest::__pest_evaluable_it_normalizes_owned_Shelly_devices_into_relay_select_options":0,"P\\Tests\\Unit\\Selfserve\\ShellyRelayInventoryTest::__pest_evaluable_it_fails_fast_when_Shelly_inventory_does_not_include_owned_devices_status":0,"P\\Tests\\Unit\\Selfserve\\DepartmentLaneRelayOptionsRouteWiringTest::__pest_evaluable_it_registers_a_department_lane_relay_options_endpoint_backed_by_Shelly_inventory":0.003,"P\\Tests\\Unit\\Selfserve\\DepartmentLaneRelayNullificationRouteWiringTest::__pest_evaluable_it_nullifies_department_lane_relay_fields_when_blank_select_values_are_submitted":0.004,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_serves_installer_artifacts_and_recovers_gateway_runtime_status_after_fresh_heartbeats":109.487,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_polls_operations_and_commands__submits_results__and_records_broker_presence_for_task_pages":229.768,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_rejects_missing_and_invalid_edge_agent_tokens":12.815,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_validates_broker_sessions_and_ingests_presence__telemetry__logs__and_shell_lifecycle_data":198.915,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_builds_broker_backlog_and_completes_gateway_operations_through_broker_endpoints":192.229,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_rejects_invalid_edge_broker_shared_secrets":7.59,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_creates_install_tokens__tracks_installer_status__and_exposes_claimed_gateway_detail_to_authorized_operators":52.202,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_manages_edge_gateway_metadata__bindings__operations__sessions__rotation__cutover__and_deletion":143.121,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_rejects_operator_edge_routes_when_module_permission_or_department_access_is_missing":17.564,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_persists_install_session_updates_and_derives_gateway_runtime_status_from_heartbeats":31.971,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_assembles_tasks__logs__statistics__operations__commands__and_shell_lifecycle_state_from_persisted_records":150.363,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_localhost_websocket_broker_urls_on_the_local_traefik_api_prefix":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_keeps_root_host_api_urls_unprefixed_when_the_request_is_not_under_the_local_api_alias":0,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_imports_a_matching_e_conomic_customer_into_the_local_system_when_no_local_record_exists":0.282,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_reports_when_the_local_customer_already_has_a_login_account":0,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_creates_a_new_e_conomic_customer_and_returns_a_created_result_for_new_rows":0.012,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_creates_the_economic_record_for_an_existing_local_account_when_no_matching_upstream_customer_exists":0,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_rejects_CVR_conflicts_when_the_upstream_customer_number_does_not_match_the_submitted_phone_number":0.02,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_registers_the_customer_import_route_and_wires_it_through_the_mass_import_service":0.099,"P\\Tests\\Unit\\Users\\UsersCustomerNamesCacheTest::__pest_evaluable_it_builds_customer_name_cache_payloads_from_economic_data_or_display_name_fallbacks":0,"P\\Tests\\Unit\\Users\\UsersCustomerNamesCacheTest::__pest_evaluable_it_guards_bulk_customer_name_cache_writes_behind_a_resolved_payload_check":0.001,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_ignores_and_soft_deletes_edge_gateways_whose_department_no_longer_exists":16.516,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_only_trusts_broker_presence_while_the_broker_heartbeat_is_fresh":0.68,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_refreshes_broker_presence_from_broker_telemetry_heartbeats":0.005,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_resolves_the_injected_gateway_transport_when_a_department_is_in_gateway_mode":0,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_resolves_the_injected_cloud_transport_when_a_department_is_in_cloud_mode":0,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_lets_relay_tests_override_the_department_transport_without_changing_department_mode":0,"P\\Tests\\Unit\\Selfserve\\ShellyRelayInventoryTest::__pest_evaluable_it_falls_back_to_local_device_and_control_names_when_Shelly_cloud_list_metadata_is_unavailable":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_uses_local_only_gateway_dispatch_for_explicit_local_transport_overrides":0,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_marks_non_injected_local_overrides_as_local_only_gateway_transport":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_opens_exit_port_by_switching_relay__out__id_on":0.224,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_opens_entrance_port_by_switching_relay__in__id_on":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_forwards_Shelly_toggle__after_timers_to_gateway_relay_switches":0,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_marks_non_injected_local_and_gateway_overrides_as_local_only_gateway_transport":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_preserves_local_gateway_diagnostic_metadata_on_relay_status_snapshots":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_includes_positive_relay_timers_in_Shelly_switch_payloads":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_applies_Shelly_transport_overrides_across_self_serve_relay_side_effect_routes":0.049,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayLegacyRouteShimTest::__pest_evaluable_it_keeps_guarded_legacy_root_shims_for_moved_edge_gateway_routes":0.014,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_persists_gateway_cutover_relay_bindings_used_by_self_serve_Shelly_dispatch":18.006,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_passes_explicit_timer_values_when_opening_lane_gates":0}} \ No newline at end of file +{"version":"pest_3.8.6","defects":{"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_self_serve_machine_type__eligibility__summary__and_webhook_endpoints":1,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_defines_reusable_self_serve_wash_and_machine_type_schemas":1,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_redistributes_booked_department_75_net_amounts_using_fixed_pricing_and_wash_subscription_weights":7,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_keeps_classified_booked_department_75_amounts_undistributed_when_no_monthly_basis_exists":8,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_keeps_unclassified_booked_department_75_lines_undistributed_with_warnings":8,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_documents_v2_historical_distribution_and_pricing_history_paths_in_openapi":1,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_defines_new_reusable_v2_schemas_for_normalization_comparison_versioning_and_distribution":1,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_supports_bulk_booked_invoice_line_payloads_with_top_level_department_numbers":7,"P\\Tests\\Unit\\Redis\\RedisAtomicReservationTest::__pest_evaluable_it_claims_a_slot_atomically_with_nx_and_expiration":8,"P\\Tests\\Unit\\Redis\\RedisAtomicReservationTest::__pest_evaluable_it_returns_false_when_the_slot_is_already_claimed_and_clamps_ttl_to_one_second":8,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_documents_economic_v2_invoice_paths_in_openapi":1,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_aligns_legacy_compare_schema_with_runtime_payload_by_removing_stale_required_order__ids":1,"P\\Tests\\Unit\\Search\\SystemSearchEntityTypeCoverageTest::__pest_evaluable_it_documents_every_supported_search_entity_type_in_openapi_enum":1,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_system_wide_search_endpoints_in_openapi":1,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_debug__intent_and_parser_metadata_schema_in_openapi":1,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_e_conomic_indexed_customer_matching_and_synonym_behavior":1,"P\\Tests\\Integration\\Database\\DbConnectionTest::__pest_evaluable_it_can_connect_to_a_configured_MySQL_instance_in_integration_mode":1,"P\\Tests\\Integration\\Invoicing\\EconomicV2BackfillAndDistributionIntegrationTest::__pest_evaluable_it_runs_best_effort_backfill_repeatedly_without_introducing_duplicate_same_start_rows":1,"P\\Tests\\Integration\\Invoicing\\EconomicV2BackfillAndDistributionIntegrationTest::__pest_evaluable_it_resolves_version_aware_distribution_payload_shapes_over_a_real_date_range":1,"P\\Tests\\Integration\\Invoicing\\EconomicV2VersioningServiceIntegrationTest::__pest_evaluable_it_creates_closes_and_rotates_fixed_pricing_versions_without_overlap":1,"P\\Tests\\Integration\\Invoicing\\EconomicV2VersioningServiceIntegrationTest::__pest_evaluable_it_tracks_vehicle_and_discount_version_lifecycles_with_closure_semantics":1,"P\\Tests\\Integration\\Permissions\\LegacyPermissionRedisCacheScriptTest::__pest_evaluable_it_keeps_legacy_route_permission_redis_cache_script_green":1,"P\\Tests\\Unit\\Goals\\GoalsOpenApiSpecTest::__pest_evaluable_it_documents_advanced_goals_target_duration_fields_in_openapi":1,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineSchemaConformanceTest::__pest_evaluable_it_documents_the_date_key_in_the_openapi_department_weather_timeline_schema":1,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_builds_timeline_entries_with_mostly__clear_weather_when_forecast_payload_is_empty":8,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_wires_departments_weather_route_through_the_forecast_fallback_path":7,"P\\Tests\\Unit\\Orders\\AttachmentsListManyTest::__pest_evaluable_it_groups_attachments_by_object_id_and_preserves_empty_object_groups":8,"P\\Tests\\Unit\\Orders\\AttachmentsListManyTest::__pest_evaluable_it_keeps_listMany_payload_parity_with_list_for_one_object_id":8,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsOpenApiSpecTest::__pest_evaluable_it_documents_department_weather_target_endpoints_and_reusable_schemas_in_openapi":1,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsOpenApiSpecTest::__pest_evaluable_it_documents_unknown_weather_status_behavior_when_targets_are_missing":1,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_respects_the_1_request_per_second_Shelly_gate_for_back_to_back_requests":8,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_in_progress_self_serve_wash_start_and_machine_relay_fields":1,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_stores_config_json_with_apostrophes_without_violating_json_constraints":8,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_adds_vehicle_type_product_on_STOP_when_program_selector_is_on__then_turns_off_cleaner_machine_and_selector_relays":7,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_skips_vehicle_type_product_add_when_program_selector_is_off_and_only_disables_configured_relays":7,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_self_serve_machine_wash_included_minutes_in_config_schemas":1,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_workspace_id_is_missing_for_gate_calls":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_channel_id_is_missing_for_gate_calls":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_with_terminal_status_details_when_call_never_reaches_accepted_state":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_hangs_up_when_call_reaches_accepted_state":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_hangs_up_immediately_when_status_transitions_to_accepted":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_maps_legacy_timeout_option_to_documented_ringTimeout_payload_field":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_clamps_derived_ringTimeout_to_Bird_documented_max_when_gate_timeout_is_high":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_passes_documented_hangup_cause_when_provided":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_drops_unsupported_hangup_cause_values_from_request_payload":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_workspace_id_is_missing_for_gate_flash_calls":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_creates_gate_flash_call_with_documented_ringTimeout_payload":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_polls_flash_call_and_succeeds_once_accepted":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_flash_gate_flow_when_terminal_failure_status_is_returned":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_does_not_fallback_to_regular_gate_call_when_flash_succeeds":8,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_falls_back_to_regular_gate_call_when_flash_fails":8,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_property_gate_lane_commands_and_sanitized_gate_failure_responses":1,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_returns_raw_payload_for_malformed_JSON_responses_and_null_for_empty_responses":8,"P\\Tests\\Unit\\Bird\\BirdRouteWiringTest::__pest_evaluable_it_keeps_Bird_number_and_webhook_routes_intact":7,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_handles_malformed_and_empty_response_bodies_without_throwing_transport_errors":8,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherStatusTargetsTest::__pest_evaluable_it_aggregates_multi_department_slot_statuses_using_worst_severity_and_unknown_fallback_rules":7,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_adds_vehicle_type_product_on_STOP_when_program_selector_relay_is_online__then_turns_off_cleaner_and_machine_relays":7,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_bills_primary_product_when_selector_relay_is_online_even_if_relay_output_is_off":7,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_documents_all_Bird_voice_call_parity_endpoints_including_gather_recordings_insights_and_log":1,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_documents_flash_hangup_endpoint_and_marks_end_alias_as_deprecated":1,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_defines_request_and_response_schemas_for_Bird_call_command_recording_insight_log_and_flash_payloads":1,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueRouteRegistrationTest::__pest_evaluable_it_registers_collected_invoice_queue_endpoints_in_orderInvoicesRoute":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_uses_a_consistent_unavailable_service_contract_for_missing_queue_dependencies":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_wires_zero_cost_and_zero_quantity_skip_guard_into_transfer_line_builder":7,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_processes_queued_transfer_jobs_to_completion":1,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_deduplicates_active_jobs_per_transfer_target":1,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_rejects_invalid_payloads_without_inserting_queue_rows":1,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_supports_fail_retry_and_reprocess_lifecycle_transitions":1,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_supports_synchronous_fallback_branches_before_queue_enqueue_on_economic_invoice_export_routes":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_keeps_queue_status_endpoints_guarded_while_collected_invoice_export_routes_support_synchronous_fallback":7,"P\\Tests\\Unit\\Invoicing\\UserCollectedInvoiceUpdateRouteValidationTest::__pest_evaluable_it_supports_independent_po__number_and_closed__at_updates_for_PUT__collected_invoices_in_user_route":7,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueRouteHardeningTest::__pest_evaluable_it_returns_pagination_metadata_and_strict_status_handling_for_collected_invoice_queue_list":7,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueRouteHardeningTest::__pest_evaluable_it_enforces_retry_constraints_for_collected_invoice_queue_jobs_before_retry_execution":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_collected_queue_list_metadata_and_strict_status_filter_enum_in_openapi":7,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_builds_a_completed_collected_invoice_queue_summary_from_payload_and_result":8,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_prefers_queue_error_messages_for_failed_jobs_and_keeps_null_safe_outcome_fields":8,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_uses_deterministic_status_message_fallback_when_no_explicit_message_exists":8,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_handles_object_payload_result_values_and_malformed_fields_without_throwing":8,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueWorkerTickRouteTest::__pest_evaluable_it_ticks_collected_invoice_transfer_queue_from_queue_list_and_status_routes":7,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueWorkerTickRouteTest::__pest_evaluable_it_ticks_order_transfer_queue_from_draft_and_invoice_status_routes":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_builds_the_installer_around_the_PHP_agent_artifacts_and_management_polling_config":8,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_exposes_update_payload__credential_rotation__and_operation_endpoints_without_shell_transport_wiring":8,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_relay_fallback_and_transport_health_details_without_shell_or_update_runtime_state":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_resolves_edge_agent_artifacts_from_the_source_tree_layout":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_prioritizes_mounted_and_baked_in_artifact_directories_before_repo_fallbacks":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_prioritizes_router_resources_before_mounted_and_baked_in_artifact_directories":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_lists_orders_for_an_admin_scoped_user_and_limits_the_results_to_the_permitted_departments":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_lists_only_the_targeted_customer_orders_for_subuser_sessions":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_returns_the_current_auth_and_permission_failures_when_order_listing_is_not_allowed":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_creates_orders_through_the_real_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_order_creation_requests":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_updates_orders_through_the_primary_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_reassigns_invoice_collections_when_changing_an_order_across_the_draft_customer_boundary":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_supports_legacy_field_value_metadata_updates_through_the_primary_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_updates_through_the_primary_order_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_updates_orders_through_the_legacy_alias_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_supports_legacy_field_value_metadata_updates_through_the_alias_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_updates_through_the_legacy_alias_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_unsupported_legacy_field_value_updates_on_both_update_endpoints":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_deletes_orders_through_the_real_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_order_delete_requests":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_regenerates_attached_wash_certificates_when_certificate_metadata_changes_through_the_primary_endpoint":7,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_regenerates_attached_wash_certificates_for_legacy_field_value_updates_through_the_alias_endpoint":7,"P\\Tests\\Api\\ApiCoverageManifestTest::__pest_evaluable_it_keeps_every_selected_API_operation_covered_by_happy_path_and_failure_tests":1,"P\\Tests\\Api\\ApiCoverageManifestTest::__pest_evaluable_it_keeps_the_OpenAPI_manifest_entries_aligned_with_the_API_spec":1,"P\\Tests\\Api\\ApiFixturesCleanupTest::__pest_evaluable_it_removes_generated_customer_traces_during_fixture_cleanup":1,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_in_with_valid_customer_credentials":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_login_payloads_and_credentials":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_returns_the_cached_auth_session_payload_for_a_valid_token":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_includes_economic_runtime_config_for_uncached_auth_sessions":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_auth_session_tokens":1,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_out_and_invalidates_the_token_for_future_session_calls":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_out_and_invalidates_cached_subuser_sessions":7,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_logout_tokens":1,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_the_raw_202_gather_webhook_contract_over_HTTP":1,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_still_prompts_for_department_selection_when_only_one_department_is_eligible":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_accepts_the_legacy_initial_webhook_body_with_top_level_call_identifiers":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_native_flow_gather_data_after_a_top_level_department_selection_when_distinct_gate_choices_exist":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_opens_the_gate_immediately_after_a_top_level_department_selection_when_entrance_and_exit_share_the_same_gate":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_uses_a_multi_digit_gather_contract_when_10_departments_are_eligible":7,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_a_raw_400_transport_error_for_malformed_webhook_payloads":1,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_lists_only_visible_departments_and_can_return_a_single_department_with_the_slack_webhook":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_department_listing_when_the_permission_is_missing":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_creates_departments_through_the_real_endpoint":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_create_requests":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_updates_departments_through_the_real_endpoint":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_update_requests":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_lists_department_categories_for_a_department":7,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_category_requests":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_lists_the_draft_customer_config_entry_in_economic_config_responses":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_round_trips_the_draft_customer_config_value_through_economic_config_updates":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_order_draft_exports_for_the_configured_draft_customer":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_booked_invoice_exports_for_the_configured_draft_customer":7,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_collected_invoice_exports_for_the_configured_draft_customer":7,"P\\Tests\\Api\\PingApiTest::__pest_evaluable_it_returns_the_ping_contract":1,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_setup_required_error_when_department_terminal_readers_are_requested_without_terminal_setup":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_sends_a_Stripe_invoice_by_email_and_persists_the_hosted_invoice_association":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_conflict_when_a_Stripe_hosted_invoice_is_already_active_for_the_order":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_allows_sending_a_new_Stripe_hosted_invoice_when_the_existing_association_is_already_terminal":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_voids_an_unpaid_Stripe_hosted_invoice_and_clears_the_local_order_association":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_refuses_to_cancel_a_paid_Stripe_hosted_invoice":8,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_setup_required_error_when_creating_a_payment_intent_for_a_department_without_terminal_setup":8,"P\\Tests\\Api\\VehiclesApiTest::__pest_evaluable_it_returns_the_newest_vehicle_last__order__id_that_still_has_order_items":7,"P\\Tests\\Api\\VehiclesApiTest::__pest_evaluable_it_returns_a_null_vehicle_last__order__id_when_no_order_with_items_exists":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_syncs_gateway_snapshots_into_cached_list_payloads_and_refreshes_fleet_usage":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_keeps_only_the_module_facade_in_the_global_classes_directory_and_conditionally_loads_module_routes":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_install_script_urls_with_the_compose_edge_gateway_artifacts_and_forwarded_https_scheme":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_builds_the_installer_around_the_compose_stack_artifacts_and_management_polling_config":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_exposes_update_payload__credential_rotation__cancel_endpoints__and_operation_endpoints_without_shell_transport_wiring":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_the_v2_operator_facing_edge_gateway_routes":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewaySchemaBootstrapTest::__pest_evaluable_it_defines_the_v2_edge_gateway_schema_bootstrap_tables":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewaySchemaBootstrapTest::__pest_evaluable_it_stores_operation_metadata_and_event_timelines_for_management_workflows":7,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_prefers_EDGE__PUBLIC__API__URL_when_explicitly_configured":7,"P\\Tests\\Api\\PlateScannersApiTest::__pest_evaluable_it_returns_the_updated_lane_id_after_editing_a_scanner_whose_null_lane_was_already_cached":7,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_serves_installer_artifacts_and_recovers_gateway_runtime_status_after_fresh_heartbeats":1,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_polls_operations_and_commands__submits_results__and_records_broker_presence_for_task_pages":7,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_builds_broker_backlog_and_completes_gateway_operations_through_broker_endpoints":7,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_creates_install_tokens__tracks_installer_status__and_exposes_claimed_gateway_detail_to_authorized_operators":8,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_manages_edge_gateway_metadata__bindings__operations__sessions__rotation__cutover__and_deletion":8,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_assembles_tasks__logs__statistics__operations__commands__and_shell_lifecycle_state_from_persisted_records":7,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_rejects_invalid_edge_broker_shared_secrets":8,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_rejects_operator_edge_routes_when_module_permission_or_department_access_is_missing":8,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_rejects_missing_and_invalid_edge_agent_tokens":1,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_persists_gateway_cutover_relay_bindings_used_by_self_serve_Shelly_dispatch":7},"times":{"P\\Tests\\Unit\\Auth\\CreateTokenTest::__pest_evaluable_it_creates_a_64_char_auth_token_for_an_existing_user":0.11,"P\\Tests\\Unit\\Auth\\CreateTokenTest::__pest_evaluable_it_throws_a_clear_exception_when_customer_user_is_missing":0.017,"P\\Tests\\Unit\\Auth\\LegacyAuthScriptParityTest::__pest_evaluable_it_keeps_passkey_challenge_legacy_script_green_during_migration":0.028,"P\\Tests\\Unit\\Auth\\LegacyAuthScriptParityTest::__pest_evaluable_it_keeps_register_CVR_legacy_script_green_during_migration":0.029,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_builds_deterministic_department_digit_map_and_caps_to_9_options":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_resolves_department_ids_by_selected_digit":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_resolves_gate_type_digit_to_entrance_or_exit":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_stores__loads_and_clears_ivr_state_with_ttl":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_validates_state_caller_fingerprint_matching":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteIvrTest::__pest_evaluable_it_builds_department_and_gate_prompts":0,"P\\Tests\\Unit\\Permissions\\PermissionNodeDefinitionTest::__pest_evaluable_it_creates_permission_nodes_linked_to_subuser_permission_keys":0,"P\\Tests\\Unit\\Permissions\\PermissionNodeDefinitionTest::__pest_evaluable_it_rejects_empty_permission_definitions":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_normalizes_button_arrays__json_and_csv_inputs":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_rejects_invalid_button_inputs":0.012,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_normalizes_vehicle_type_values_and_null_semantics":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_rejects_invalid_vehicle_type_values":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_rejects_non_numeric_vehicle_type_strings":0,"P\\Tests\\Unit\\Selfserve\\NormalizationTest::__pest_evaluable_it_keeps_lane_service_enum_contract_for_MACHINE":0,"P\\Tests\\Unit\\Subusers\\SubuserGrantInitializationTest::__pest_evaluable_it_initializes_booking_node_grants_without_DB_dependency":0,"P\\Tests\\Unit\\Subusers\\SubuserGrantInitializationTest::__pest_evaluable_it_initializes_selfserve_node_grants_without_DB_dependency":0,"P\\Tests\\Unit\\Subusers\\SubusersRoutePermissionLinkTest::__pest_evaluable_it_keeps_subusers_route_list_permission_linked_to_SUBUSERS__LIST_node":0.005,"P\\Tests\\Unit\\Search\\SystemSearchEntityTypeCoverageTest::__pest_evaluable_it_keeps_route_and_service_entity_type_registries_in_sync_with_expanded_coverage":0,"P\\Tests\\Unit\\Search\\SystemSearchEntityTypeCoverageTest::__pest_evaluable_it_documents_every_supported_search_entity_type_in_openapi_enum":0.009,"P\\Tests\\Unit\\Search\\SystemSearchEconomicCustomerIndexWiringTest::__pest_evaluable_it_wires_local_e_conomic_customer_index_into_customer_related_search_entities":0.003,"P\\Tests\\Unit\\Search\\SystemSearchEconomicCustomerIndexWiringTest::__pest_evaluable_it_registers_cron_tasks_that_keep_the_e_conomic_search_index_refreshed":0.003,"P\\Tests\\Unit\\Search\\SystemSearchInvalidationHooksTest::__pest_evaluable_it_marks_system_search_cache_dirty_from_generic_db_object_mutation_flows":0.004,"P\\Tests\\Unit\\Search\\SystemSearchInvalidationHooksTest::__pest_evaluable_it_marks_system_search_cache_dirty_from_object_property_mutations":0.003,"P\\Tests\\Unit\\Search\\SystemSearchInvalidationHooksTest::__pest_evaluable_it_marks_system_search_cache_dirty_when_module_config_values_change":0.002,"P\\Tests\\Unit\\Search\\SystemSearchInvalidationHooksTest::__pest_evaluable_it_registers_cron_maintenance_task_for_system_search_cache":0.002,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_redacts_obvious_sensitive_fragments_before_sending_query_to_intent_parser":0.001,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_builds_payload_with_redacted_query_and_parses_strict_JSON_output":0,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_falls_back_safely_when_OpenAI_is_disabled":0,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_handles_malformed_OpenAI_response_payloads_without_throwing":0,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_uses_parser_cache_for_identical_query_and_allowed_type_combinations":0,"P\\Tests\\Unit\\Search\\SystemSearchOpenAiIntentParserTest::__pest_evaluable_it_caps_alias_and_hint_payloads_from_OpenAI_and_filters_hints_to_allowed_types":0.006,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_system_wide_search_endpoints_in_openapi":0.007,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_debug__intent_and_parser_metadata_schema_in_openapi":0.007,"P\\Tests\\Unit\\Search\\SystemSearchOpenApiSpecTest::__pest_evaluable_it_documents_e_conomic_indexed_customer_matching_and_synonym_behavior":0.005,"P\\Tests\\Unit\\Search\\SystemSearchRouteBehaviorTest::__pest_evaluable_it_normalizes_type_lists_from_csv_json_and_arrays":0,"P\\Tests\\Unit\\Search\\SystemSearchRouteBehaviorTest::__pest_evaluable_it_parses_booleans_and_clamps_integers_using_route_defaults":0,"P\\Tests\\Unit\\Search\\SystemSearchRouteBehaviorTest::__pest_evaluable_it_exposes_expected_searchable_entity_types":0,"P\\Tests\\Unit\\Search\\SystemSearchRouteWiringTest::__pest_evaluable_it_registers_system_wide_search_GET_and_POST_endpoints_with_intent_debug_support":0.003,"P\\Tests\\Unit\\Search\\SystemSearchRouteWiringTest::__pest_evaluable_it_registers_superuser_cache_clear_and_rebuild_endpoints_for_system_search":0.003,"P\\Tests\\Unit\\Search\\SystemSearchRouteWiringTest::__pest_evaluable_it_passes_permission_and_own_scope_context_into_system_search_service":0.003,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_does_not_invoke_intent_parser_when_lexical_confidence_is_already_high":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_invokes_parser_on_low_confidence_lexical_results_and_applies_hints_only_boosts":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_never_lets_parser_entity_hints_override_explicit_include_filters":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_returns_fallback_parser_metadata_when_parser_fails_gracefully":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_scopes_query_cache_by_permission_context_to_avoid_cross_user_cache_leakage":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_caps_AI_driven_expanded_terms_to_prevent_query_amplification":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_expands_danish_discount_wording_into_lexical_discount_synonyms":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_invokes_parser_for_intent_driven_natural_language_queries_even_when_lexical_score_is_high":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_uses_association_hints_to_pull_related_customer_records_from_non_customer_matches":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_prefers_newer_records_when_relevance_scores_are_comparable":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_keeps_explicit_identifier_matches_ahead_of_newer_but_weaker_records":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_promotes_invoices_orders_order_bookings_and_customers_in_ranking":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_never_prioritizes_cancelled_bookings_over_active_bookings":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_heavily_demotes_configured_low_priority_entity_types_in_ranking":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_tokenizes_unicode_names_without_stripping_non_ascii_letters":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_does_not_treat_explicit_identifier_queries_as_intent_driven":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_requires_broader_term_coverage_for_multi_word_scoring":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_enriches_object_attachment_results_with_associated_customer_context":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_includes_the_economic_customer_index_in_cache_dependencies_for_customer_scoped_results":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_falls_back_to_invoice_date_ranges_when_invoice_names_are_missing":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_derives_xlvask_customer_numbers_only_from_digits_only_extern_ids":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_replaces_unnamed_user_titles_with_the_customer_context_name":0,"P\\Tests\\Unit\\Search\\SystemSearchServiceIntentFlowTest::__pest_evaluable_it_uses_the_goal_criteria_label_for_department_goal_titles":0,"P\\Tests\\Integration\\Search\\SystemSearchCacheIntegrationTest::__pest_evaluable_it_reuses_parser_cache_entries_for_repeated_natural_language_intent_requests":0.106,"P\\Tests\\Integration\\Search\\SystemSearchCacheIntegrationTest::__pest_evaluable_it_clears_parser_cache_namespace_via_clearAll_to_force_a_fresh_parse":0,"P\\Tests\\Integration\\Search\\SystemSearchCacheIntegrationTest::__pest_evaluable_it_bumps_per_table_cache_versions_when_a_dirty_table_marker_is_registered":0.081,"P\\Tests\\Unit\\Invoicing\\EconomicV2DistributionServiceFallbackTest::__pest_evaluable_it_falls_back_to_system_orders_for_fixed_pricing_when_regular_orders_yield_no_customers":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2DistributionServiceFallbackTest::__pest_evaluable_it_falls_back_to_system_orders_for_wash_subscriptions_when_regular_orders_yield_no_customers":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2CliBackfillCommandTest::__pest_evaluable_it_registers_economic_v2_backfill_command_in_cli_dispatcher":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2CliBackfillCommandTest::__pest_evaluable_it_provides_a_backfill_cron_script_entrypoint":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_returns_exact__match_when_totals_lines_and_departments_are_identical":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_returns_total__mismatch_when_only_totals_differ":0.015,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_detects_line_level_mismatches_for_quantity_and_price":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_detects_departmental_distribution_mismatches":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2CompareEngineTest::__pest_evaluable_it_returns_missing__target_when_draft_or_booked_target_is_unavailable":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2LineNormalizerTest::__pest_evaluable_it_normalizes_draft_invoice_lines_including_departmental_distributions":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2LineNormalizerTest::__pest_evaluable_it_marks_text_only_zero_value_lines_as_non_billable_and_keeps_deterministic_key":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicV2LineNormalizerTest::__pest_evaluable_it_normalizes_booked_invoices_and_computes_net_total_delta_from_lines":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2LineNormalizerTest::__pest_evaluable_it_contains_internal_normalization_path_with_departmental_metadata_support":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_documents_economic_v2_invoice_paths_in_openapi":0.009,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_documents_v2_historical_distribution_and_pricing_history_paths_in_openapi":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_aligns_legacy_compare_schema_with_runtime_payload_by_removing_stale_required_order__ids":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2OpenApiSpecTest::__pest_evaluable_it_defines_new_reusable_v2_schemas_for_normalization_comparison_versioning_and_distribution":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2RevenueAndBarredSupportTest::__pest_evaluable_it_supports_barred_filtering_when_listing_e_conomic_customers":0.006,"P\\Tests\\Unit\\Invoicing\\EconomicV2RevenueAndBarredSupportTest::__pest_evaluable_it_implements_a_dedicated_v2_e_conomic_revenue_statistics_service_and_route":0.006,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_registers_all_collected_invoice_economic_v2_routes_with_explicit_permissions":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_registers_version_aware_distribution_and_pricing_history_v2_routes":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_caches_v2_distribution_responses_with_a_configurable_redis_ttl":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_writes_fixed_pricing_versions_from_create_and_delete_flows":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_writes_vehicle_subscription_versions_for_create_update_delete_flows":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_writes_discount_override_versions_from_superuser_discounts_route":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicV2RouteAndVersioningHooksTest::__pest_evaluable_it_keeps_legacy_compare_endpoint_path_for_backward_compatibility":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicV2VersioningServiceStructureTest::__pest_evaluable_it_implements_effective_range_lifecycle_methods_for_all_versioned_entities":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicV2VersioningServiceStructureTest::__pest_evaluable_it_closes_previous_active_interval_before_inserting_a_new_version":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2VersioningServiceStructureTest::__pest_evaluable_it_includes_best_effort_backfill_with_provenance_and_confidence_metadata":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicV2VersioningServiceStructureTest::__pest_evaluable_it_anchors_historical_resolution_on_order_created__at_timestamps_in_distribution_service":0.004,"P\\Tests\\Unit\\Invoicing\\InvoicingOrdersCalculationsHardeningTest::__pest_evaluable_it_guards_against_empty_order_ids_in_net_amount_calculation":0.007,"P\\Tests\\Unit\\Invoicing\\InvoicingOrdersCalculationsHardeningTest::__pest_evaluable_it_guards_against_empty_customer_arrays_in_date_range_transaction_fetches":0.003,"P\\Tests\\Unit\\Invoicing\\InvoicingOrdersCalculationsHardeningTest::__pest_evaluable_it_uses_centralized_duplicate_filtering_for_possible_duplicate_detection":0.003,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteCacheHelpersTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_clamps_negative_ttl_to_zero":0,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteCacheHelpersTest::__pest_evaluable_it_builds_deterministic_cache_keys_per_scope_and_date_range":0.007,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteCacheHelpersTest::__pest_evaluable_it_falls_back_to_resolver_directly_when_cache_ttl_is_disabled":0,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteGuardsTest::__pest_evaluable_it_requires_superuser_permission_for_invoicing_period_distribution_all_endpoint":0.017,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodRouteGuardsTest::__pest_evaluable_it_uses_shared_date_range_normalization_across_invoicing_period_endpoints":0.032,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodUtilsTest::__pest_evaluable_it_normalizes_a_valid_invoicing_date_range_to_full_day_timestamps":0,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodUtilsTest::__pest_evaluable_it_rejects_invalid_date_formats":0.012,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodUtilsTest::__pest_evaluable_it_rejects_descending_date_ranges":0,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodUtilsTest::__pest_evaluable_it_finds_duplicate_orders_regardless_of_original_input_order":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2DistributionServiceFallbackTest::__pest_evaluable_it_runs_best_effort_backfill_when_fixed_pricing_version_history_is_empty":0,"P\\Tests\\Unit\\Selfserve\\SelfserveConditionEvaluatorTest::__pest_evaluable_it_evaluates_self_serve_conditions_with_combined_AND_and_OR_semantics":0,"P\\Tests\\Unit\\Selfserve\\SelfserveConditionEvaluatorTest::__pest_evaluable_it_prefers_condition_results_over_question_answers_when_evaluating_task_gates":0,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_self_serve_machine_type__eligibility__summary__and_webhook_endpoints":0.008,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_defines_reusable_self_serve_wash_and_machine_type_schemas":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_self_serve_machine_types__eligibility__summaries__and_machine_start_webhook_routes":0.084,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_keeps_machine_type_support_wired_into_lanes__tasks__and_conditions_routes":0.024,"P\\Tests\\Unit\\N8n\\N8nRouteHelpersTest::__pest_evaluable_it_normalizes_webhook_methods_and_falls_back_to_POST_for_unsupported_verbs":0,"P\\Tests\\Unit\\N8n\\N8nRouteHelpersTest::__pest_evaluable_it_filters_request_parameters_down_to_the_allowed_n8n_query_keys":0,"P\\Tests\\Unit\\N8n\\N8nRouteWiringTest::__pest_evaluable_it_registers_workflow_lifecycle_endpoints_for_the_n8n_module":0.002,"P\\Tests\\Unit\\N8n\\N8nRouteWiringTest::__pest_evaluable_it_registers_execution_and_webhook_trigger_endpoints_for_the_n8n_module":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_redistributes_booked_department_75_net_amounts_using_fixed_pricing_and_wash_subscription_weights":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_keeps_classified_booked_department_75_amounts_undistributed_when_no_monthly_basis_exists":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_keeps_unclassified_booked_department_75_lines_undistributed_with_warnings":0,"P\\Tests\\Unit\\Invoicing\\EconomicEndpointUrlEncodingTest::__pest_evaluable_it_encodes_raw_filter_query_values_that_include_timestamps":0,"P\\Tests\\Unit\\Invoicing\\EconomicEndpointUrlEncodingTest::__pest_evaluable_it_avoids_double_encoding_query_values_that_are_already_escaped":0,"P\\Tests\\Unit\\Invoicing\\EconomicV2BookedDepartment75DistributionTest::__pest_evaluable_it_supports_bulk_booked_invoice_line_payloads_with_top_level_department_numbers":0,"P\\Tests\\Unit\\Redis\\RedisAtomicReservationTest::__pest_evaluable_it_claims_a_slot_atomically_with_nx_and_expiration":0,"P\\Tests\\Unit\\Redis\\RedisAtomicReservationTest::__pest_evaluable_it_returns_false_when_the_slot_is_already_claimed_and_clamps_ttl_to_one_second":0,"P\\Tests\\Unit\\Bookings\\OrderBookingRouteIdempotencyGuardTest::__pest_evaluable_it_guards_order_booking_creation_with_redis_backed_idempotency":0.24,"P\\Tests\\Unit\\DynamicImages\\DynamicImagePreRenderCronWiringTest::__pest_evaluable_it_registers_dynamic_image_pre_render_cron_task_and_related_helpers":0.005,"P\\Tests\\Integration\\Database\\DbConnectionTest::__pest_evaluable_it_can_connect_to_a_configured_MySQL_instance_in_integration_mode":0.226,"P\\Tests\\Integration\\Invoicing\\EconomicV2BackfillAndDistributionIntegrationTest::__pest_evaluable_it_runs_best_effort_backfill_repeatedly_without_introducing_duplicate_same_start_rows":0.017,"P\\Tests\\Integration\\Invoicing\\EconomicV2BackfillAndDistributionIntegrationTest::__pest_evaluable_it_resolves_version_aware_distribution_payload_shapes_over_a_real_date_range":0.014,"P\\Tests\\Integration\\Invoicing\\EconomicV2VersioningServiceIntegrationTest::__pest_evaluable_it_creates_closes_and_rotates_fixed_pricing_versions_without_overlap":0.011,"P\\Tests\\Integration\\Invoicing\\EconomicV2VersioningServiceIntegrationTest::__pest_evaluable_it_tracks_vehicle_and_discount_version_lifecycles_with_closure_semantics":0.016,"P\\Tests\\Integration\\Permissions\\LegacyPermissionRedisCacheScriptTest::__pest_evaluable_it_keeps_legacy_route_permission_redis_cache_script_green":0.013,"P\\Tests\\Unit\\Permissions\\AllowOwnOrDepartmentAccessForbiddenTest::__pest_evaluable_it_returns_both_own_and_elevated_permissions_when_both_are_missing":0,"P\\Tests\\Unit\\Permissions\\AllowOwnOrDepartmentAccessForbiddenTest::__pest_evaluable_it_returns_only_elevated_permission_when_own_permission_exists_but_own_context_fails":0,"P\\Tests\\Unit\\Permissions\\AllowOwnOrDepartmentAccessForbiddenTest::__pest_evaluable_it_allows_elevated_permission_path_without_forbidden_and_validates_department_access":0,"P\\Tests\\Unit\\Permissions\\ForbiddenResponseWiringTest::__pest_evaluable_it_routes_and_trait_use_forbidden_responses_for_permission_and_ownership_denials":0.018,"P\\Tests\\Unit\\Permissions\\GroupPermissionSessionInvalidationWiringTest::__pest_evaluable_it_invalidates_related_user_permission_and_auth_session_caches_when_group_permissions_change":0.004,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_parses_advanced_target_duration_from_snake__case_fields":0.066,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_parses_advanced_target_duration_from_camelCase_aliases":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_normalizes_ENTIRE__DURATION_to_ignore_target__duration__every":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_defaults_recurring_target__duration__every_to_1_when_omitted":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetDurationTest::__pest_evaluable_it_keeps_strict_legacy_mode_when_target__duration_is_invalid":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_computes_weekly_target_using_touched_ISO_weeks_for_March_2026":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_applies_target__duration__every_for_weekly_cadence":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_prorates_ENTIRE__DURATION_target_by_overlap_days":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_splits_advanced_target_by_override_weights_per_department":0,"P\\Tests\\Unit\\Goals\\GoalsCriteriaTargetMathTest::__pest_evaluable_it_preserves_legacy_target_behavior_when_target__duration_is_missing":0,"P\\Tests\\Unit\\Goals\\GoalsLegacyRendererScriptsTest::__pest_evaluable_it_keeps_legacy_monthly_renderer_script_green":0.147,"P\\Tests\\Unit\\Goals\\GoalsLegacyRendererScriptsTest::__pest_evaluable_it_keeps_legacy_department_daily_renderer_script_green":0.147,"P\\Tests\\Unit\\Goals\\GoalsOpenApiSpecTest::__pest_evaluable_it_documents_advanced_goals_target_duration_fields_in_openapi":0.007,"P\\Tests\\Unit\\Workfeed\\WorkfeedClientConformanceTest::__pest_evaluable_it_uses_company_scoped_workfeed_endpoints_and_raw_Authorization_header":0.003,"P\\Tests\\Unit\\Workfeed\\WorkfeedClientConformanceTest::__pest_evaluable_it_normalizes_documented_shift_query_parameters":0.001,"P\\Tests\\Unit\\Workfeed\\WorkfeedConfigRouteWiringTest::__pest_evaluable_it_registers_module_config_endpoints_for_workfeed":0.004,"P\\Tests\\Unit\\Workfeed\\WorkfeedRouteHelpersTest::__pest_evaluable_it_filters_request_parameters_down_to_the_allowed_workfeed_query_keys":0,"P\\Tests\\Unit\\Workfeed\\WorkfeedRouteWiringTest::__pest_evaluable_it_registers_employee_and_department_endpoints_for_the_workfeed_module":0.004,"P\\Tests\\Unit\\Workfeed\\WorkfeedRouteWiringTest::__pest_evaluable_it_registers_shift_endpoints_for_the_workfeed_module":0.002,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_calculates_workfeed_employee_hours_for_the_hour_slot_based_on_overlap":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_extracts_department_id_from_supported_workfeed_shift_shapes":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_normalizes_wrapped_workfeed_collections_from_common_response_keys":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineSchemaConformanceTest::__pest_evaluable_it_includes_a_date_key_in_department_weather_timeline_entries":0.003,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineSchemaConformanceTest::__pest_evaluable_it_documents_the_date_key_in_the_openapi_department_weather_timeline_schema":0.005,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_builds_a_timeline_range_from_start_of_yesterday_to_end_of_today":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_builds_a_timeline_range_relative_to_an_explicit_selected_date_override":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_calculates_workfeed_employee_hours_across_multiple_departments_for_one_hour_slot":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_normalizes_department_id_input_from_scalar_csv_and_nested_array_values":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_builds_a_timeline_range_relative_to_explicit_date__from_and_date__to_override":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_resolves_forecast_day_count_for_a_given_timeline_range_with_sane_limits":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_resolves_weather_coordinates_from_valid_coordinates_only":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_returns_null_weather_coordinates_when_all_department_locations_are_invalid":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_classifies_weatherapi_no_matching_location_errors_as_location_lookup_failures":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_does_not_classify_non_location_weatherapi_errors_as_location_lookup_failures":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_returns_an_empty_forecast_fallback_when_coordinates_are_unavailable":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_builds_timeline_entries_with_mostly__clear_weather_when_forecast_payload_is_empty":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherFallbackBehaviorTest::__pest_evaluable_it_wires_departments_weather_route_through_the_forecast_fallback_path":0.005,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_clamps_negative_ttl_to_zero":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_builds_deterministic_cache_keys_for_department_sets_and_timeline_ranges":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_builds_order_insensitive_cache_keys_for_equivalent_department_id_sets":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_falls_back_to_resolver_directly_when_cache_ttl_is_disabled":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTimelineRangeTest::__pest_evaluable_it_marks_non_started_slots_as_unknown_regardless_of_wash_hour_ratio":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherPreloadCronWiringTest::__pest_evaluable_it_registers_and_implements_cron_preloading_for_department_weather_cache":0.007,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_uses_sane_stale_ttl_defaults_and_clamps_stale_ttl_below_fresh_ttl":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_uses_sane_hot_activity_ttl_defaults_and_clamps_to_a_positive_value":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheRuntimeBehaviorTest::__pest_evaluable_it_serves_fresh_cached_payloads_without_invoking_the_resolver":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheRuntimeBehaviorTest::__pest_evaluable_it_serves_stale_cached_payloads_and_enqueues_a_refresh_signal":0.01,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheRuntimeBehaviorTest::__pest_evaluable_it_recomputes_and_rewrites_cache_payloads_when_stale_window_is_exceeded":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheRuntimeBehaviorTest::__pest_evaluable_it_records_hot_keys_order_insensitively_and_applies_preload_target_caps":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_normalizes_batched_wash_count_rows_into_hourly_slot_totals":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_wires_department_weather_route_to_use_batched_wash_aggregation":0.007,"P\\Tests\\Unit\\Orders\\AttachmentsListManyTest::__pest_evaluable_it_groups_attachments_by_object_id_and_preserves_empty_object_groups":0,"P\\Tests\\Unit\\Orders\\AttachmentsListManyTest::__pest_evaluable_it_keeps_listMany_payload_parity_with_list_for_one_object_id":0,"P\\Tests\\Unit\\Orders\\EconomicModuleOrdersBatchHelpersTest::__pest_evaluable_it_ensures_economic_module_rows_in_one_sanitized_batch":0,"P\\Tests\\Unit\\Orders\\EconomicModuleOrdersBatchHelpersTest::__pest_evaluable_it_returns_id_keyed_economic_module_payload_with_null_defaults":0,"P\\Tests\\Unit\\Orders\\OrdersRouteListBatchingWiringTest::__pest_evaluable_it_wires_GET__orders_through_batched_enrichment_and_stripe_snapshot_caching":0.006,"P\\Tests\\Unit\\Orders\\UsersCashierNamesBatchTest::__pest_evaluable_it_returns_cashier_names_from_cache_and_fetches_missing_ones_in_batch":0,"P\\Tests\\Unit\\Orders\\UsersCashierNamesBatchTest::__pest_evaluable_it_returns_deterministic_map_for_duplicate_and_unsorted_cashier_ids":0,"P\\Tests\\Unit\\Orders\\UsersCashierNamesBatchWiringTest::__pest_evaluable_it_implements_batched_cashier_name_lookup_with_cache_first_fallback_behavior":0.006,"P\\Tests\\Unit\\Orders\\UsersCashierNamesBatchWiringTest::__pest_evaluable_it_sanitizes_and_deduplicates_cashier_ids_before_batch_lookup":0.003,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_counts_overtime_minutes_when_a_shift_carries_an_extended_approval_end_timestamp":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_counts_unapproved_overtime_from_a_bounded_shift_updateTime_fallback":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherWorkfeedHoursTest::__pest_evaluable_it_does_not_treat_late_unapproved_administrative_edits_as_overtime":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherCacheHelpersTest::__pest_evaluable_it_changes_weather_timeline_cache_key_when_department_weather_targets_change":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherStatusTargetsTest::__pest_evaluable_it_evaluates_healthy_degraded_and_unhealthy_statuses_from_configured_department_targets":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherStatusTargetsTest::__pest_evaluable_it_returns_unknown_when_configured_targets_are_missing_for_department_status_evaluation":0,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherStatusTargetsTest::__pest_evaluable_it_aggregates_multi_department_slot_statuses_using_worst_severity_and_unknown_fallback_rules":0.046,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsOpenApiSpecTest::__pest_evaluable_it_documents_department_weather_target_endpoints_and_reusable_schemas_in_openapi":0.006,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsOpenApiSpecTest::__pest_evaluable_it_documents_unknown_weather_status_behavior_when_targets_are_missing":0.005,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsRouteWiringTest::__pest_evaluable_it_registers_department_weather_target_routes_with_explicit_read_and_manage_permissions":0.004,"P\\Tests\\Unit\\Workfeed\\DepartmentWeatherTargetsRouteWiringTest::__pest_evaluable_it_persists_department_weather_targets_using_canonical_department_variable_keys":0.003,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_machine_relay_status_get_and_set_endpoints":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_batches_sequential_machine_relay_status_requests_into_a_single_Shelly_get_call":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_respects_the_1_request_per_second_Shelly_gate_for_back_to_back_requests":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_retries_missing_Shelly_status_payloads_until_relay_status_becomes_ready":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_times_out_with_a_clear_Shelly_readiness_error_when_payload_remains_missing":0.001,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_uses_direct_set_switch_and_seeds_cache_so_immediate_status_read_does_not_call_Shelly_get":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_self_serve_lane_gate_open_endpoint":0.004,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_in_progress_self_serve_wash_details_endpoint":0.003,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_adds_vehicle_type_product_on_STOP_when_program_selector_is_on__then_turns_off_cleaner_machine_and_selector_relays":0.132,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_skips_vehicle_type_product_add_when_program_selector_is_off_and_only_disables_configured_relays":0.001,"P\\Tests\\Unit\\Selfserve\\DepartmentSelfServeEnabledRelaySyncWiringTest::__pest_evaluable_it_syncs_lane_relay_states_when_department_self_serve_enabled_flag_changes":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_supports_hard_relay_set_even_when_lane_status_is_CLOSED":0,"P\\Tests\\Unit\\Selfserve\\SelfserveStartCleanerRelayWiringTest::__pest_evaluable_it_enables_cleaner_relay_on_wash_start_command_and_webhook_flow":0.009,"P\\Tests\\Unit\\Selfserve\\SelfserveWashCompletionRelayWiringTest::__pest_evaluable_it_forces_machine_relay_off_when_a_self_serve_wash_session_is_completed":0.003,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_opens_exit_port_by_switching_relay__in__id_on":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_opens_entrance_port_by_switching_relay__out__id_on":0,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_in_progress_self_serve_wash_start_and_machine_relay_fields":0.006,"P\\Tests\\Unit\\Selfserve\\SelfserveConditionEvaluatorTest::__pest_evaluable_it_evaluates_typed_task_gates_with_strict_semantics":0,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_validates_typed_task_gates_for_known_references":0,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_fails_validation_when_typed_task_gates_reference_unknown_entities":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_self_serve_config_draft_publish_rollback_lifecycle_endpoints":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_keeps_legacy_self_serve_CRUD_routes_syncing_canonical_drafts":0.017,"P\\Tests\\Unit\\Selfserve\\SelfserveStartCleanerRelayWiringTest::__pest_evaluable_it_keeps_cleaner_relay_enable_wired_into_machine_relay_start_paths":0.008,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_stores_config_json_with_apostrophes_without_violating_json_constraints":0.277,"P\\Tests\\Unit\\Selfserve\\SelfserveConfigVersioningTest::__pest_evaluable_it_encodes_config_json_payloads_with_apostrophes_before_persistence":0,"P\\Tests\\Unit\\Selfserve\\SelfserveWashCompletionRelayWiringTest::__pest_evaluable_it_forces_machine_and_cleaner_relays_off_when_a_self_serve_wash_session_is_completed":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_vehicle_type_override_into_self_serve_preview_and_synchronization_routes":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_uses_local_demo_responses_and_skips_Shelly_cloud_calls_for_demo_relay_ids":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_returns_default_OFF_status_for_demo_relay_ids_without_Shelly_lookups":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_excludes_demo_relay_ids_from_Shelly_status_batch_payloads":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_keeps_demo_relay_gate_open_queued_but_skips_Shelly_switch_calls":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_allowed_services_route_through_machine_relay_visibility_sync":0.002,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_enables_MACHINE_relay_when_MACHINE_is_visible_in_allowed_services":0.002,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_turns_MACHINE_relay_off_immediately_when_MACHINE_is_not_visible":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_does_not_enable_MACHINE_relay_when_allowEnable_is_false_even_if_MACHINE_is_visible":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_is_a_safe_no_op_when_MACHINE_relay_is_not_configured":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRelayVisibilitySyncWiringTest::__pest_evaluable_it_synchronizes_machine_relay_from_visible_services_during_session_synchronization":0.01,"P\\Tests\\Unit\\Selfserve\\SelfserveRelayVisibilitySyncWiringTest::__pest_evaluable_it_adds_explicit_relay_disable_session_helper_for_visibility_driven_OFF_transitions":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_self_serve_property_gate_command_permissions":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneCommandEnumTest::__pest_evaluable_it_parses_property_gate_lane_commands":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_opens_entrance_gate_for_OPEN__PROPERTY__ACCESS__GATE_command":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_opens_exit_gate_for_OPEN__PROPERTY__EXIT__GATE_command":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_blocks_property_gate_commands_when_department_self_serve_is_disabled":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_throws_a_clear_error_when_entrance_gate_is_missing_for_property_access_command":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_wraps_low_level_gate_errors_for_property_access_command_failures":0.002,"P\\Tests\\Unit\\Selfserve\\SelfserveWashFlowMachineAllowedWiringTest::__pest_evaluable_it_reads_machine_allowed_state_from_session_summary_payload_safely":0.004,"P\\Tests\\Unit\\Selfserve\\DbObjectPaginationLegacyColumnCompatibilityTest::__pest_evaluable_it_guards_pagination_against_searchable_fields_missing_from_legacy_schemas":0.339,"P\\Tests\\Unit\\Selfserve\\SelfserveSchemaBootstrapCompatibilityTest::__pest_evaluable_it_adds_dynamic__images__vehicle__type_column_for_legacy_selfserve_wash_session_task_schemas":0.007,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceIncludedMinutesTest::__pest_evaluable_it_computes_billable_minutes_when_elapsed_minutes_exceed_included_minutes":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceIncludedMinutesTest::__pest_evaluable_it_computes_zero_billable_minutes_when_elapsed_minutes_equal_included_minutes":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceIncludedMinutesTest::__pest_evaluable_it_computes_zero_billable_minutes_when_included_minutes_exceed_elapsed_minutes":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceIncludedMinutesTest::__pest_evaluable_it_handles_zero_and_low_elapsed_wash_time_edge_cases":0,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_self_serve_machine_wash_included_minutes_in_config_schemas":0.006,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_wires_machine_wash_included_minutes_into_self_serve_module_config":0.005,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_blocks_explicit_relay_writes_when_department_self_serve_is_disabled":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_returns_disabled_no_op_from_machine_relay_visibility_sync_when_department_self_serve_is_disabled":0,"P\\Tests\\Unit\\Selfserve\\SelfserveOpenApiSpecTest::__pest_evaluable_it_documents_property_gate_lane_commands_and_sanitized_gate_failure_responses":0.008,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_workspace_id_is_missing_for_gate_calls":0.019,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_channel_id_is_missing_for_gate_calls":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_with_terminal_status_details_when_call_never_reaches_accepted_state":0.072,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_hangs_up_when_call_reaches_accepted_state":0.013,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_hangs_up_immediately_when_status_transitions_to_accepted":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_maps_legacy_timeout_option_to_documented_ringTimeout_payload_field":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_clamps_derived_ringTimeout_to_Bird_documented_max_when_gate_timeout_is_high":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_passes_documented_hangup_cause_when_provided":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_drops_unsupported_hangup_cause_values_from_request_payload":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_fast_when_workspace_id_is_missing_for_gate_flash_calls":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_creates_gate_flash_call_with_documented_ringTimeout_payload":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_polls_flash_call_and_succeeds_once_accepted":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_fails_flash_gate_flow_when_terminal_failure_status_is_returned":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_does_not_fallback_to_regular_gate_call_when_flash_succeeds":0,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_falls_back_to_regular_gate_call_when_flash_fails":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePropertyGateCommandTest::__pest_evaluable_it_wraps_low_level_gate_errors_for_property_exit_command_failures":0.002,"P\\Tests\\Unit\\Bird\\BirdGateCallFlowTest::__pest_evaluable_it_falls_back_to_regular_gate_call_when_flash_caller_id_is_not_confirmed":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_maps_voice_call_facade_methods_to_documented_endpoints_and_methods":0.039,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_maps_recordings_insights_log_and_flash_methods_to_documented_resources":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_encodes_path_segments_before_building_outbound_endpoints":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_serializes_query_parameters_for_GET_transport_requests":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_maps_4xx_and_5xx_transport_failures_into_informative_exceptions":0,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_returns_raw_payload_for_malformed_JSON_responses_and_null_for_empty_responses":0.007,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_documents_all_Bird_voice_call_parity_endpoints_including_gather_recordings_insights_and_log":0.007,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_documents_flash_hangup_endpoint_and_marks_end_alias_as_deprecated":0.005,"P\\Tests\\Unit\\Bird\\BirdOpenApiSpecTest::__pest_evaluable_it_defines_request_and_response_schemas_for_Bird_call_command_recording_insight_log_and_flash_payloads":0.004,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_accepts_valid_payloads_for_create_and_nested_call_flow_commands":0,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_rejects_unknown_fields_and_invalid_enum_values_in_strict_schemas":0.014,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_supports_CSV_normalization_in_schema_validation_for_log_filters":0,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_validates_flash_hangup_payloads_for_both_supported_request_shapes":0,"P\\Tests\\Unit\\Bird\\BirdRequestValidationTest::__pest_evaluable_it_fails_before_forward_step_when_strict_validation_fails_and_forwards_when_valid":0,"P\\Tests\\Unit\\Bird\\BirdRouteWiringTest::__pest_evaluable_it_registers_full_Bird_voice_call_route_surface_with_strict_validation_and_permissions":0.005,"P\\Tests\\Unit\\Bird\\BirdRouteWiringTest::__pest_evaluable_it_registers_flash_hangup_endpoint_and_keeps_end_alias_wired_as_compatibility_path":0.004,"P\\Tests\\Unit\\Bird\\BirdRouteWiringTest::__pest_evaluable_it_keeps_Bird_number_and_webhook_routes_intact":0.006,"P\\Tests\\Unit\\Bird\\BirdModuleClientMappingTest::__pest_evaluable_it_handles_malformed_and_empty_response_bodies_without_throwing_transport_errors":0.005,"P\\Tests\\Unit\\Selfserve\\DepartmentGatesRelaysRouteWiringTest::__pest_evaluable_it_validates_department_gate_config_on_both_create_and_update_routes":0.043,"P\\Tests\\Unit\\Selfserve\\SelfserveSchemaBootstrapCompatibilityTest::__pest_evaluable_it_adds_wash__started__at_column_for_legacy_selfserve_wash_session_schemas":0.004,"P\\Tests\\Unit\\Selfserve\\SelfserveWashStartedAtWiringTest::__pest_evaluable_it_stores_wash__started__at_in_self_serve_wash_sessions_when_machine_start_is_triggered":0.003,"P\\Tests\\Unit\\Selfserve\\SelfserveWashStartedAtWiringTest::__pest_evaluable_it_passes_lane_wash_start_time_into_the_session_machine_start_marker":0.004,"P\\Tests\\Unit\\Selfserve\\SelfserveWashStartedAtWiringTest::__pest_evaluable_it_resolves_in_progress_wash__started__at_from_session_with_compatibility_fallbacks":0.003,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_normalizes_say_payload_and_applies_hangup_default":0.019,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_normalizes_log_query_csv_and_integer_fields":0,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_normalizes_nested_create_call_payload_sections_and_drops_unknown_keys":0,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_keeps_gather_nested_say_payload_unchanged_when_hangup_is_omitted":0,"P\\Tests\\Unit\\Bird\\BirdPayloadClassesTest::__pest_evaluable_it_supports_no_body_and_flash_hangup_payload_normalization":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_respects_the_2_second_Shelly_gate_for_back_to_back_requests":0.023,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_enforces_a_2_second_gap_between_sequential_switch_requests_used_by_wash_start_and_stop_flows":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_keeps_back_to_back_get_switch_requests_ordered_through_the_relay_controller":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_executes_sequential_switch_requests_used_by_wash_start_and_stop_flows":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_does_not_print_Shelly_switch_responses_to_output":0.067,"P\\Tests\\Unit\\Selfserve\\ShellyGlobalRateLimitWiringTest::__pest_evaluable_it_enforces_a_global_2_second_Shelly_gate_in_sendPostRequest":0.005,"P\\Tests\\Unit\\Selfserve\\ShellyGlobalRateLimitWiringTest::__pest_evaluable_it_uses_Redis_NX_PX_semantics_for_cross_request_Shelly_rate_limiting":0.002,"P\\Tests\\Unit\\Selfserve\\ShellyGlobalRateLimitBehaviorTest::__pest_evaluable_it_enforces_the_2_second_Shelly_gate_across_separate_request_contexts":0,"P\\Tests\\Unit\\Selfserve\\ShellyGlobalRateLimitBehaviorTest::__pest_evaluable_it_does_not_delay_when_the_Shelly_gate_is_already_expired":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_adds_vehicle_type_product_on_STOP_when_program_selector_relay_is_online__then_turns_off_cleaner_and_machine_relays":0.538,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_skips_vehicle_type_product_add_when_program_selector_relay_is_offline_and_only_disables_configured_relays":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneStopFlowTest::__pest_evaluable_it_bills_primary_product_when_selector_relay_is_online_even_if_relay_output_is_off":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceModeBillingTest::__pest_evaluable_it_bills_manual_self_serve_stop_using_full_elapsed_minutes_without_included_minute_reduction":0.001,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneInvoiceModeBillingTest::__pest_evaluable_it_keeps_included_minute_reduction_for_automatic_mode":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_on_first_dtmf_input_captured_within_the_300_second_window":0.005,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_does_not_send_Slack_when_dtmf_input_repeats_without_change":0.008,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_again_when_dtmf_input_changes_within_the_window":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_keeps_gathering_and_does_not_hang_up_before_300_seconds_have_elapsed":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_announces_timeout_waits_10_seconds_and_sends_hangup_once_at_or_after_300_seconds":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_keeps_polling_until_terminal_status_and_only_then_finalizes":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_finalizes_immediately_when_webhook_payload_is_already_terminal_before_timeout_logic":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_does_not_duplicate_timeout_or_hangup_actions_across_retries_and_lock_contention":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_keeps_state_when_polling_fails_so_completion_is_not_falsely_reported":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_when_dtmf_input_repeats_without_change":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_answers_immediately_once_and_does_not_re_answer_on_subsequent_webhook_retries":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_configures_gather_with_retry_loop_semantics_until_input_is_entered":0.004,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_when_gather_result_provides_keys_field_instead_of_dtmf":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_sends_Slack_when_gather_conditions_variable_keys_carries_the_entered_value":0,"P\\Tests\\Unit\\Bird\\BirdVoiceWebhooksRouteCallLifecycleTest::__pest_evaluable_it_configures_gather_to_check_every_2_seconds_with_retry_loop_semantics_until_input_is_entered":0,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_ignores_non_numeric_customer__number_values_from_request":0.042,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_casts_numeric_customer__number_strings_to_int_before_lookup":0,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_prefers_user__id_when_both_user__id_and_customer__number_are_valid":0,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_falls_back_to_customer__number_when_user__id_is_invalid":0,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_normalizes_request_identifiers_before_user_lookups":0.004,"P\\Tests\\Unit\\Users\\UsersAutomaticGetTargetUserFromRequestTest::__pest_evaluable_it_rejects_non_positive_and_non_digit_request_values":0.003,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_uses_pagination_results_when_present":0.006,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_falls_back_to_collection_count_when_pagination_metadata_is_missing":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_returns_zero_when_neither_pagination_nor_collection_is_available":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_counts_object_based_collections_when_pagination_metadata_is_missing":0,"P\\Tests\\Unit\\Invoicing\\EconomicPaymentTermsRouteCollectionExtractionTest::__pest_evaluable_it_uses_collection_when_present":0,"P\\Tests\\Unit\\Invoicing\\EconomicPaymentTermsRouteCollectionExtractionTest::__pest_evaluable_it_falls_back_to_paymentTerms_when_collection_is_missing":0,"P\\Tests\\Unit\\Invoicing\\EconomicPaymentTermsRouteCollectionExtractionTest::__pest_evaluable_it_supports_top_level_array_payloads":0,"P\\Tests\\Unit\\Invoicing\\EconomicPaymentTermsRouteCollectionExtractionTest::__pest_evaluable_it_returns_an_empty_array_when_no_known_collection_shape_exists":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_uses_grant__2_in_economic__endpoint__t_when_explicitly_requested_and_configured":0.009,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_falls_back_to_grant__1_in_economic__endpoint__t_when_grant__2_is_missing":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_for_missing_required_primary_grant_in_economic__endpoint__t":0.014,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_for_missing_app_secret_in_economic__endpoint__t":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_uses_grant__2_in_legacy_economic__m_when_available":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_falls_back_to_grant__1_in_legacy_economic__m_when_grant__2_is_missing":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_for_missing_required_primary_grant_in_legacy_economic__m":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_for_missing_app_secret_in_legacy_economic__m":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_uses_unfiltered_total_when_no_customer_filters_are_active":0.004,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_uses_filtered_total_when_search_is_active":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_uses_filtered_total_when_barred_filter_is_active":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_treats__null__search_and_barred_values_as_no_filter":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRoutePaginationFallbackTest::__pest_evaluable_it_falls_back_to_filtered_total_when_unfiltered_total_is_missing":0,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRouteEconomicFailureHandlingTest::__pest_evaluable_it_maps_e_conomic_integration_failures_in_customer_listing_to_explicit_502_responses":0.014,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRouteEconomicFailureHandlingTest::__pest_evaluable_it_logs_LIST__CUSTOMERS_success_only_after_pagination_and_customer_mapping_are_completed":0.009,"P\\Tests\\Unit\\Invoicing\\CustomerSearchRouteEconomicFailureHandlingTest::__pest_evaluable_it_guards_against_malformed_customer_list_payloads_before_calling_paginate":0.011,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_deterministic_upstream_exceptions_for_non_2xx_endpoint_trait_responses":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_throws_deterministic_upstream_exceptions_for_non_2xx_legacy_economic__m_responses":0,"P\\Tests\\Unit\\Invoicing\\EconomicAuthTokenFallbackTest::__pest_evaluable_it_returns_raw_payload_unchanged_on_successful_HTTP_statuses":0,"P\\Tests\\Unit\\Invoicing\\EconomicCustomersListResponseValidationTest::__pest_evaluable_it_accepts_valid_list_payloads_that_include_collection_and_pagination_results":0.02,"P\\Tests\\Unit\\Invoicing\\EconomicCustomersListResponseValidationTest::__pest_evaluable_it_throws_when_pagination_is_missing_from_the_response_payload":0,"P\\Tests\\Unit\\Invoicing\\EconomicCustomersListResponseValidationTest::__pest_evaluable_it_throws_when_upstream_responds_with_an_error_shaped_payload":0,"P\\Tests\\Unit\\Router\\RouterThrowableHandlingTest::__pest_evaluable_it_catches_throwables_during_auto_route_loading_and_maps_them_to_internal_server_errors":0.003,"P\\Tests\\Unit\\Users\\EconomicCustomerZeroHandlingTest::__pest_evaluable_it_does_not_request_e_conomic_customer_data_when_customer_number_is_zero":0.101,"P\\Tests\\Unit\\Users\\EconomicCustomerZeroHandlingTest::__pest_evaluable_it_short_circuits_e_conomic_customer_lookup_for_non_positive_customer_numbers":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueRouteRegistrationTest::__pest_evaluable_it_registers_queued_economic_invoice_endpoints_in_economicInvoiceRoute":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueRouteRegistrationTest::__pest_evaluable_it_registers_collected_invoice_queue_endpoints_in_orderInvoicesRoute":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueSchemaBootstrapTest::__pest_evaluable_it_defines_economic_transfer_queue_jobs_schema_bootstrap_table_and_tracking_columns":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueSchemaBootstrapTest::__pest_evaluable_it_provides_queue_processor_class_constants_and_processing_entrypoint":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueCronIntegrationTest::__pest_evaluable_it_registers_economic_transfer_queue_cron_task_and_handler":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_economic_transfer_queue_paths_in_openapi":0.01,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_economic_transfer_queue_schemas_in_openapi":0.007,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_skips_order_items_with_zero_quantity_for_e_conomic_export":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_skips_order_items_with_zero_price_for_e_conomic_export":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_keeps_positive_quantity_and_price_items_billable_for_e_conomic_export":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_wires_zero_cost_and_zero_quantity_skip_guard_into_transfer_line_builder":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicInvoiceDraftZeroItemSkipWiringTest::__pest_evaluable_it_skips_zero_cost_and_zero_quantity_items_in_legacy_economic_draft_helper":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicTransferOrderItemSkipTest::__pest_evaluable_it_skips_malformed_order_item_payloads_for_e_conomic_export_safety":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueHardeningTest::__pest_evaluable_it_hardens_transfer_queue_with_type_validation_retry_caps_and_stale_lock_recovery":0.004,"P\\Tests\\Unit\\Router\\AutoloadRedisCacheValidationTest::__pest_evaluable_it_validates_cached_autoload_paths_before_returning_and_clears_stale_cache_entries":0.003,"P\\Tests\\Unit\\Orders\\OrdersRegistrationDateRangeQueryTest::__pest_evaluable_it_applies_created__at_bounds_directly_in_SQL_when_filtering_orders_by_registration_number":0,"P\\Tests\\Unit\\Orders\\OrdersRegistrationDateRangeQueryTest::__pest_evaluable_it_rejects_an_inverted_date_range_for_registration_lookups":0,"P\\Tests\\Unit\\Orders\\OrdersRegistrationDateRangeQueryTest::__pest_evaluable_it_returns_early_when_registration_number_is_blank":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueCronIntegrationTest::__pest_evaluable_it_wires_queue_worker_class_loading_for_CLI_queue_action":0.003,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_guards_all_economic_invoice_queue_endpoints_before_constructing_queue_service":0.012,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_guards_all_collected_invoice_queue_endpoints_before_constructing_queue_service":0.011,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_uses_a_consistent_unavailable_service_contract_for_missing_queue_dependencies":0.009,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_gracefully_handles_unavailable_queue_dependencies_on_collected_invoice_queue_endpoints":0.005,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceEconomicQueueResponseContractTest::__pest_evaluable_it_returns_the_queue_job_id_in_POST__collected_invoices_economic_enqueue_response":0.204,"P\\Tests\\Unit\\Invoicing\\UserCollectedInvoiceUpdateRouteValidationTest::__pest_evaluable_it_requires_id_and_at_least_one_mutable_field_for_PUT__collected_invoices_in_user_route":0.004,"P\\Tests\\Unit\\Invoicing\\UserCollectedInvoiceUpdateRouteValidationTest::__pest_evaluable_it_supports_independent_po__number_and_closed__at_updates_for_PUT__collected_invoices_in_user_route":0.175,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceEconomicQueueResponseContractTest::__pest_evaluable_it_returns_queued_contract_for_POST__collected_invoices_stripe_book":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicDraftQueueOnlyRouteBehaviorTest::__pest_evaluable_it_keeps_order_draft_export_route_queue_only":0.006,"P\\Tests\\Unit\\Invoicing\\EconomicDraftQueueOnlyRouteBehaviorTest::__pest_evaluable_it_keeps_collected_invoice_draft_producing_routes_queue_only_in_orderInvoicesRoute":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_guards_collected_invoice_and_stripe_draft_producing_endpoints_before_constructing_queue_service":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_unavailable_queue_dependency_responses_for_async_economic_transfer_endpoints":0.007,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueuePayloadValidationTest::__pest_evaluable_it_normalizes_order_payloads_to_strict_positive_integer_ids":0,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueuePayloadValidationTest::__pest_evaluable_it_normalizes_collected_invoice_payload_booleans_to_strict_bool_values":0.007,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueuePayloadValidationTest::__pest_evaluable_it_rejects_invalid_transfer_payloads_before_enqueue_write_attempts":0.036,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_processes_queued_transfer_jobs_to_completion":0.284,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_deduplicates_active_jobs_per_transfer_target":0.012,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_rejects_invalid_payloads_without_inserting_queue_rows":0.011,"P\\Tests\\Integration\\Invoicing\\EconomicTransferQueueIntegrationTest::__pest_evaluable_it_supports_fail_retry_and_reprocess_lifecycle_transitions":0.006,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_keeps_queue_guards_on_economic_invoice_queue_status_and_retry_routes":0.012,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_supports_synchronous_fallback_branches_before_queue_enqueue_on_economic_invoice_export_routes":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_keeps_queue_status_endpoints_guarded_while_collected_invoice_export_routes_support_synchronous_fallback":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueAvailabilityGuardTest::__pest_evaluable_it_uses_a_consistent_unavailable_service_contract_for_queue_status_lifecycle_endpoints":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicDraftQueueOnlyRouteBehaviorTest::__pest_evaluable_it_supports_synchronous_fallback_and_queued_processing_for_order_draft_export_route":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicDraftQueueOnlyRouteBehaviorTest::__pest_evaluable_it_supports_synchronous_fallback_and_queued_processing_for_collected_invoice_draft_producing_routes":0.004,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceEconomicQueueResponseContractTest::__pest_evaluable_it_documents_both_synchronous_fallback_and_queued_response_contracts_for_POST__collected_invoices_economic":0.236,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceEconomicQueueResponseContractTest::__pest_evaluable_it_documents_both_synchronous_fallback_and_queued_response_contracts_for_POST__collected_invoices_stripe_book":0.004,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_200_fallback_plus_202_queue_contracts_for_export_endpoints_and_keeps_503_on_queue_lifecycle_endpoints":0.009,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueRouteHardeningTest::__pest_evaluable_it_returns_pagination_metadata_and_strict_status_handling_for_collected_invoice_queue_list":0.014,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueRouteHardeningTest::__pest_evaluable_it_enforces_retry_constraints_for_collected_invoice_queue_jobs_before_retry_execution":0.005,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueOpenApiSpecTest::__pest_evaluable_it_documents_collected_queue_list_metadata_and_strict_status_filter_enum_in_openapi":0,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_builds_a_completed_collected_invoice_queue_summary_from_payload_and_result":0.195,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_prefers_queue_error_messages_for_failed_jobs_and_keeps_null_safe_outcome_fields":0.003,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_uses_deterministic_status_message_fallback_when_no_explicit_message_exists":0.003,"P\\Tests\\Unit\\Invoicing\\CollectedInvoiceQueueDetailsSummaryBuilderTest::__pest_evaluable_it_handles_object_payload_result_values_and_malformed_fields_without_throwing":0.002,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueWorkerTickRouteTest::__pest_evaluable_it_ticks_collected_invoice_transfer_queue_from_queue_list_and_status_routes":0.008,"P\\Tests\\Unit\\Invoicing\\EconomicTransferQueueWorkerTickRouteTest::__pest_evaluable_it_ticks_order_transfer_queue_from_draft_and_invoice_status_routes":0.009,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodQueueOverlayTest::__pest_evaluable_it_marks_queued_transactions_and_clears_requires__action_when_all_actionable_work_is_already_queued":0.826,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodQueueOverlayTest::__pest_evaluable_it_keeps_requires__action_true_when_a_customer_still_has_unqueued_actionable_transactions":0.045,"P\\Tests\\Unit\\Invoicing\\InvoicingPeriodQueueOverlayTest::__pest_evaluable_it_blocks_fixed_pricing_or_subscription_customers_with_no_transactions_when_a_relevant_queue_job_exists":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerCommandQueueTest::__pest_evaluable_it_queues_admin_commands__exposes_agent_poll_result_handlers__and_keeps_heartbeats_from_mutating_discovery_state":0.003,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerCommandQueueTest::__pest_evaluable_it_defines_the_dispatchable_gateway_guard_on_the_loaded_manager_class":0.009,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"recent heartbeat stays online\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"late heartbeat degrades after one minute\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"stale heartbeat goes offline after five minutes\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"explicit offline reports stay offline even when heartbeat is fresh\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_effective_gateway_status_from_heartbeat_freshness with data set \"dataset \"missing heartbeat is treated as offline\"\"":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_marks_ready_discovery_as_stale_when_the_gateway_heartbeat_has_expired":0.351,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_the_edge_gateway_management_REST_endpoints":0.021,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_public_installer__claim__heartbeat__command_polling__and_internal_broker_auth_endpoints":0.004,"P\\Tests\\Unit\\Selfserve\\EdgeBrokerClientConfigTest::__pest_evaluable_it_uses_the_same_default_broker_url_and_shared_secret_fallback_as_the_docker_stack":0.267,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_install_script_urls_with_forwarded_https_scheme_when_proxied":0.336,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_appends_forwarded_ports_when_the_forwarded_host_omits_them":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_infers_https_for_the_staging_api_host_when_only_the_https_port_is_present":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_prefers_EDGE__PUBLIC__API__URL_when_explicitly_configured":0.168,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_normalizes_public_broker_overrides_to_https_and_browser_shell_urls_to_wss":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_keeps_localhost_broker_overrides_on_plain_http_and_ws_for_local_development":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_includes_node_pty_build_prerequisites_in_the_generated_install_script":0.007,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_prefers_EDGE__PUBLIC__API__URL_when_explicitly_configured_and_derives_the_broker_from_the_api_origin":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_normalizes_public_broker_overrides_to_https__strips_paths__and_browser_shell_urls_to_wss":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_merges_incoming_heartbeat_metadata_with_existing_gateway_metadata":0.006,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_the_v2_operator_facing_edge_gateway_routes":0.004,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayRouteWiringTest::__pest_evaluable_it_registers_PHP_edge_agent_routes_for_operations_and_legacy_relay_command_polling":0.005,"P\\Tests\\Unit\\Selfserve\\EdgeGatewaySchemaBootstrapTest::__pest_evaluable_it_defines_the_v2_edge_gateway_schema_bootstrap_tables":0.004,"P\\Tests\\Unit\\Selfserve\\EdgeGatewaySchemaBootstrapTest::__pest_evaluable_it_stores_operation_metadata_and_event_timelines_for_management_workflows":0.004,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_builds_the_installer_around_the_PHP_agent_artifacts_and_management_polling_config":0.011,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_exposes_update_payload__credential_rotation__and_operation_endpoints_without_shell_transport_wiring":0.013,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerCommandQueueTest::__pest_evaluable_it_keeps_relay_dispatch_and_discovery_queueing_on_the_edge_gateway_manager":0.08,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerCommandQueueTest::__pest_evaluable_it_loads_relay_command_helpers_on_the_manager_and_gateway_operations_on_the_dedicated_service":0.014,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_derives_relay_fallback_and_transport_health_details_without_shell_or_update_runtime_state":0.364,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_resolves_edge_agent_artifacts_from_the_source_tree_layout":0.445,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_includes_the_container_mounted_artifact_directory_as_a_candidate":0.021,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_reads_install_artifacts_through_the_shared_locator":0.008,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_builds_update_payloads_with_checksums_from_resolved_artifact_paths":0.427,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_resolves_edge_agent_artifacts_from_a_supported_runtime_layout":0.017,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_install_script_urls_with_the_PHP_agent_artifacts_and_forwarded_https_scheme":0.001,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_explains_the_legacy_dist_mount_mismatch_when_php_artifacts_are_unavailable":0.001,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_prioritizes_mounted_and_baked_in_artifact_directories_before_repo_fallbacks":0.022,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_falls_back_to_baked_in_artifacts_when_the_mount_path_is_absent":0.001,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayArtifactLocatorTest::__pest_evaluable_it_prioritizes_router_resources_before_mounted_and_baked_in_artifact_directories":0.022,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_lists_orders_for_an_admin_scoped_user_and_limits_the_results_to_the_permitted_departments":1.109,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_lists_only_the_targeted_customer_orders_for_subuser_sessions":2.935,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_returns_the_current_auth_and_permission_failures_when_order_listing_is_not_allowed":1.375,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_creates_orders_through_the_real_endpoint":0.982,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_order_creation_requests":3.423,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_updates_orders_through_the_primary_endpoint":1.13,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_reassigns_invoice_collections_when_changing_an_order_across_the_draft_customer_boundary":1.615,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_supports_legacy_field_value_metadata_updates_through_the_primary_endpoint":5.592,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_updates_through_the_primary_order_endpoint":1.29,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_updates_orders_through_the_legacy_alias_endpoint":1.517,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_supports_legacy_field_value_metadata_updates_through_the_alias_endpoint":4.136,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_updates_through_the_legacy_alias_endpoint":0.512,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_unsupported_legacy_field_value_updates_on_both_update_endpoints":0.965,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_deletes_orders_through_the_real_endpoint":1.045,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_rejects_invalid_order_delete_requests":1.64,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_regenerates_attached_wash_certificates_when_certificate_metadata_changes_through_the_primary_endpoint":3.683,"P\\Tests\\Api\\OrdersApiTest::__pest_evaluable_it_regenerates_attached_wash_certificates_for_legacy_field_value_updates_through_the_alias_endpoint":3.194,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayOperationLegacySchemaCompatibilityTest::__pest_evaluable_it_keeps_the_legacy_operation__type_column_compatible_with_v2_operation_queueing":0.015,"P\\Tests\\Unit\\Bookings\\OrderBookingsListCacheTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_clamps_negative_ttl_to_zero":0,"P\\Tests\\Unit\\Bookings\\OrderBookingsListCacheTest::__pest_evaluable_it_builds_deterministic_keys_for_equivalent_contexts":0,"P\\Tests\\Unit\\Bookings\\OrderBookingsListCacheTest::__pest_evaluable_it_stores_and_retrieves_full_order_bookings_payloads":0,"P\\Tests\\Unit\\Bookings\\OrderBookingsListCacheTest::__pest_evaluable_it_ignores_malformed_cached_payloads_and_clears_order_bookings_list_caches":0,"P\\Tests\\Unit\\Bookings\\OrderBookingsRouteCacheWiringTest::__pest_evaluable_it_caches_the_paginated_order_bookings_list_response_and_invalidates_it_on_booking_changes":0.008,"P\\Tests\\Unit\\Bookings\\VehicleSearchBookedMetadataRouteContractTest::__pest_evaluable_it_keeps_booked_vehicle_search_metadata_aligned_with_filtered_pending_order_bookings":0.005,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsCacheTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_clamps_negative_ttl_to_zero":0.012,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsCacheTest::__pest_evaluable_it_builds_deterministic_keys_for_equivalent_count_contexts":0.012,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsCacheTest::__pest_evaluable_it_stores_and_retrieves_normalized_booking_counts":0.014,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsCacheTest::__pest_evaluable_it_ignores_malformed_payloads_and_clears_order_bookings_count_caches":0.078,"P\\Tests\\Unit\\Bookings\\OrderBookingsCountsRouteWiringTest::__pest_evaluable_it_adds_a_cached_order_bookings_counts_endpoint_and_invalidates_it_on_booking_changes":0.008,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayFleetUsageStatisticsTest::__pest_evaluable_it_summarizes_fleet_usage_statistics_for_the_dashboard_landing_view":0,"P\\Tests\\Api\\ApiCoverageManifestTest::__pest_evaluable_it_keeps_every_selected_API_operation_covered_by_happy_path_and_failure_tests":0.271,"P\\Tests\\Api\\ApiCoverageManifestTest::__pest_evaluable_it_keeps_the_OpenAPI_manifest_entries_aligned_with_the_API_spec":0.097,"P\\Tests\\Api\\ApiFixturesCleanupTest::__pest_evaluable_it_removes_generated_customer_traces_during_fixture_cleanup":8.099,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_in_with_valid_customer_credentials":4.515,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_login_payloads_and_credentials":1.271,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_returns_the_cached_auth_session_payload_for_a_valid_token":0.888,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_includes_economic_runtime_config_for_uncached_auth_sessions":1.349,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_auth_session_tokens":0.698,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_out_and_invalidates_the_token_for_future_session_calls":1.365,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_logs_out_and_invalidates_cached_subuser_sessions":1.932,"P\\Tests\\Api\\AuthApiTest::__pest_evaluable_it_rejects_invalid_logout_tokens":0.393,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_the_raw_202_gather_webhook_contract_over_HTTP":0.788,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_still_prompts_for_department_selection_when_only_one_department_is_eligible":0.732,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_accepts_the_legacy_initial_webhook_body_with_top_level_call_identifiers":0.692,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_native_flow_gather_data_after_a_top_level_department_selection_when_distinct_gate_choices_exist":1.515,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_opens_the_gate_immediately_after_a_top_level_department_selection_when_entrance_and_exit_share_the_same_gate":1.719,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_uses_a_multi_digit_gather_contract_when_10_departments_are_eligible":0.587,"P\\Tests\\Api\\BirdVoiceWebhookApiTest::__pest_evaluable_it_returns_a_raw_400_transport_error_for_malformed_webhook_payloads":0.419,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_lists_only_visible_departments_and_can_return_a_single_department_with_the_slack_webhook":1.048,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_department_listing_when_the_permission_is_missing":0.378,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_creates_departments_through_the_real_endpoint":0.59,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_create_requests":1.554,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_updates_departments_through_the_real_endpoint":0.788,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_update_requests":1.552,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_lists_department_categories_for_a_department":1.006,"P\\Tests\\Api\\DepartmentsApiTest::__pest_evaluable_it_rejects_invalid_department_category_requests":1.191,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_lists_the_draft_customer_config_entry_in_economic_config_responses":0.947,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_round_trips_the_draft_customer_config_value_through_economic_config_updates":3.28,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_order_draft_exports_for_the_configured_draft_customer":0.86,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_booked_invoice_exports_for_the_configured_draft_customer":1.127,"P\\Tests\\Api\\EconomicDraftCustomerApiTest::__pest_evaluable_it_rejects_collected_invoice_exports_for_the_configured_draft_customer":0.888,"P\\Tests\\Api\\PingApiTest::__pest_evaluable_it_returns_the_ping_contract":0.877,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_setup_required_error_when_department_terminal_readers_are_requested_without_terminal_setup":1.281,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_sends_a_Stripe_invoice_by_email_and_persists_the_hosted_invoice_association":5.434,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_conflict_when_a_Stripe_hosted_invoice_is_already_active_for_the_order":4.756,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_allows_sending_a_new_Stripe_hosted_invoice_when_the_existing_association_is_already_terminal":3.943,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_voids_an_unpaid_Stripe_hosted_invoice_and_clears_the_local_order_association":3.746,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_refuses_to_cancel_a_paid_Stripe_hosted_invoice":4.131,"P\\Tests\\Api\\StripeApiTest::__pest_evaluable_it_returns_a_setup_required_error_when_creating_a_payment_intent_for_a_department_without_terminal_setup":0.726,"P\\Tests\\Api\\VehiclesApiTest::__pest_evaluable_it_returns_the_newest_vehicle_last__order__id_that_still_has_order_items":1.326,"P\\Tests\\Api\\VehiclesApiTest::__pest_evaluable_it_returns_a_null_vehicle_last__order__id_when_no_order_with_items_exists":1.159,"P\\Tests\\Unit\\Users\\EconomicCustomerModelParsingTest::__pest_evaluable_it_parses_cached_economic_customer_payloads_that_use_snake__case_customer__number":0.246,"P\\Tests\\Unit\\Users\\EconomicCustomerModelParsingTest::__pest_evaluable_it_leaves_the_economic_customer_model_empty_when_no_valid_customer_number_is_present":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayFleetUsageStatisticsTest::__pest_evaluable_it_derives_fleet_usage_directly_from_cached_gateway_row_summaries":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_install_script_urls_with_the_compose_edge_gateway_artifacts_and_forwarded_https_scheme":0.182,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayMetadataUpdateContractTest::__pest_evaluable_it_adds_a_gateway_metadata_update_endpoint_with_label_and_primary_assignment_fields":0.01,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayMetadataUpdateContractTest::__pest_evaluable_it_reassigns_department_primary_gateways_through_dedicated_manager_helpers":0.007,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayShellPollingTransportTest::__pest_evaluable_it_removes_shell_access_from_the_edge_gateway_HTTP_contracts":0.005,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_builds_the_installer_around_the_compose_stack_artifacts_and_management_polling_config":0.053,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_uses_sane_ttl_defaults_and_deterministic_cache_keys":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_stores_and_retrieves_cached_list_and_detail_payloads":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_syncs_gateway_snapshots_into_cached_list_payloads_and_refreshes_fleet_usage":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayViewCacheTest::__pest_evaluable_it_removes_deleted_gateways_from_cached_list_and_detail_payloads":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayUpdateLifecycleTest::__pest_evaluable_it_exposes_update_payload__credential_rotation__cancel_endpoints__and_operation_endpoints_without_shell_transport_wiring":0.012,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_registers_module_scoped_edge_gateway_operator_routes":0.007,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_registers_edge_gateway_module_config_endpoints":0.006,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_registers_edge_gateway_config_endpoints_from_the_module_route_directory":0.011,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayModuleRouteWiringTest::__pest_evaluable_it_keeps_only_the_module_facade_in_the_global_classes_directory_and_conditionally_loads_module_routes":0.005,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayInstallSessionLifecycleTest::__pest_evaluable_it_caps_install_session_diagnostics_and_events_while_preserving_the_first_start_timestamp":0.026,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayInstallSessionLifecycleTest::__pest_evaluable_it_clears_terminal_failure_details_after_a_successful_claim_update":0.014,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayInstallSessionLifecycleTest::__pest_evaluable_it_marks_expired_non_terminal_install_sessions_as_terminal_when_read_back":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_websocket_broker_urls_on_the_traefik_broker_path":0,"P\\Tests\\Unit\\Selfserve\\DepartmentGateConfigRelayTest::__pest_evaluable_it_validates_relay_gate_configs_and_keeps_relay_specific_fields_in_the_payload":0.025,"P\\Tests\\Unit\\Selfserve\\DepartmentGateConfigRelayTest::__pest_evaluable_it_rejects_relay_gate_configs_without_a_logical_relay_id":0.014,"P\\Tests\\Unit\\Bird\\DepartmentGatesRelayOpenTest::__pest_evaluable_it_dispatches_relay_backed_gates_through_the_edge_gateway_relay_manager":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayDepartmentWorkspaceContractTest::__pest_evaluable_it_defines_the_department_hardware_workspace_service_payload_surface":0.011,"P\\Tests\\Unit\\Selfserve\\PlateScannerWorkspaceContractTest::__pest_evaluable_it_adds_lane_aware_scanner_management_and_a_dedicated_rotate_key_action":0.01,"P\\Tests\\Unit\\Selfserve\\PlateScannerWorkspaceContractTest::__pest_evaluable_it_uses_the_scanner_default_lane_before_requiring_an_explicit_lane__id_in_machine_button_webhooks":0.005,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_maps_gateway_relay_status_responses_into_the_Shelly_cloud_payload_shape":0.01,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_maps_gateway_relay_switch_responses_into_the_Shelly_cloud_payload_shape":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_requires_a_valid_department_id_for_gateway_transport_requests":0.009,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_rejects_unsupported_gateway_transport_endpoints":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_surfaces_binding_lookup_failures_while_resolving_relay_state_through_the_gateway_transport":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_surfaces_offline_gateway_failures_while_dispatching_relay_switch_commands":0,"P\\Tests\\Api\\PlateScannersApiTest::__pest_evaluable_it_returns_the_updated_lane_id_after_editing_a_scanner_whose_null_lane_was_already_cached":21.835,"P\\Tests\\Api\\PlateScannersApiTest::__pest_evaluable_it_rejects_plate_scanner_edits_when_the_permission_is_missing":7.837,"P\\Tests\\Unit\\Selfserve\\ShellyRelayInventoryTest::__pest_evaluable_it_normalizes_owned_Shelly_devices_into_relay_select_options":0.102,"P\\Tests\\Unit\\Selfserve\\ShellyRelayInventoryTest::__pest_evaluable_it_fails_fast_when_Shelly_inventory_does_not_include_owned_devices_status":0.011,"P\\Tests\\Unit\\Selfserve\\DepartmentLaneRelayOptionsRouteWiringTest::__pest_evaluable_it_registers_a_department_lane_relay_options_endpoint_backed_by_Shelly_inventory":0.003,"P\\Tests\\Unit\\Selfserve\\DepartmentLaneRelayNullificationRouteWiringTest::__pest_evaluable_it_nullifies_department_lane_relay_fields_when_blank_select_values_are_submitted":0.004,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_serves_installer_artifacts_and_recovers_gateway_runtime_status_after_fresh_heartbeats":109.487,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_polls_operations_and_commands__submits_results__and_records_broker_presence_for_task_pages":229.768,"P\\Tests\\Api\\EdgeGatewayAgentApiTest::__pest_evaluable_it_rejects_missing_and_invalid_edge_agent_tokens":12.815,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_validates_broker_sessions_and_ingests_presence__telemetry__logs__and_shell_lifecycle_data":198.915,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_builds_broker_backlog_and_completes_gateway_operations_through_broker_endpoints":192.229,"P\\Tests\\Api\\EdgeGatewayBrokerApiTest::__pest_evaluable_it_rejects_invalid_edge_broker_shared_secrets":7.59,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_creates_install_tokens__tracks_installer_status__and_exposes_claimed_gateway_detail_to_authorized_operators":52.202,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_manages_edge_gateway_metadata__bindings__operations__sessions__rotation__cutover__and_deletion":143.121,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_rejects_operator_edge_routes_when_module_permission_or_department_access_is_missing":17.564,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_persists_install_session_updates_and_derives_gateway_runtime_status_from_heartbeats":31.971,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_assembles_tasks__logs__statistics__operations__commands__and_shell_lifecycle_state_from_persisted_records":150.363,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_builds_localhost_websocket_broker_urls_on_the_local_traefik_api_prefix":0,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerUrlTest::__pest_evaluable_it_keeps_root_host_api_urls_unprefixed_when_the_request_is_not_under_the_local_api_alias":0,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_imports_a_matching_e_conomic_customer_into_the_local_system_when_no_local_record_exists":0.282,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_reports_when_the_local_customer_already_has_a_login_account":0,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_creates_a_new_e_conomic_customer_and_returns_a_created_result_for_new_rows":0.012,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_creates_the_economic_record_for_an_existing_local_account_when_no_matching_upstream_customer_exists":0,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_rejects_CVR_conflicts_when_the_upstream_customer_number_does_not_match_the_submitted_phone_number":0.02,"P\\Tests\\Unit\\Customers\\CustomerMassImportServiceTest::__pest_evaluable_it_registers_the_customer_import_route_and_wires_it_through_the_mass_import_service":0.099,"P\\Tests\\Unit\\Users\\UsersCustomerNamesCacheTest::__pest_evaluable_it_builds_customer_name_cache_payloads_from_economic_data_or_display_name_fallbacks":0,"P\\Tests\\Unit\\Users\\UsersCustomerNamesCacheTest::__pest_evaluable_it_guards_bulk_customer_name_cache_writes_behind_a_resolved_payload_check":0.001,"P\\Tests\\Api\\EdgeGatewayOperatorApiTest::__pest_evaluable_it_ignores_and_soft_deletes_edge_gateways_whose_department_no_longer_exists":16.516,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_only_trusts_broker_presence_while_the_broker_heartbeat_is_fresh":0.68,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayManagerHeartbeatStatusTest::__pest_evaluable_it_refreshes_broker_presence_from_broker_telemetry_heartbeats":0.005,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_resolves_the_injected_gateway_transport_when_a_department_is_in_gateway_mode":0,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_resolves_the_injected_cloud_transport_when_a_department_is_in_cloud_mode":0,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_lets_relay_tests_override_the_department_transport_without_changing_department_mode":0,"P\\Tests\\Unit\\Selfserve\\ShellyRelayInventoryTest::__pest_evaluable_it_falls_back_to_local_device_and_control_names_when_Shelly_cloud_list_metadata_is_unavailable":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_uses_local_only_gateway_dispatch_for_explicit_local_transport_overrides":0,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_marks_non_injected_local_overrides_as_local_only_gateway_transport":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_opens_exit_port_by_switching_relay__out__id_on":0.224,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_opens_entrance_port_by_switching_relay__in__id_on":0,"P\\Tests\\Unit\\Selfserve\\GatewayShellyTransportTest::__pest_evaluable_it_forwards_Shelly_toggle__after_timers_to_gateway_relay_switches":0,"P\\Tests\\Unit\\Selfserve\\ShellyTransportResolverTest::__pest_evaluable_it_marks_non_injected_local_and_gateway_overrides_as_local_only_gateway_transport":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_preserves_local_gateway_diagnostic_metadata_on_relay_status_snapshots":0,"P\\Tests\\Unit\\Selfserve\\SelfserveLaneRelayShellyBatchingTest::__pest_evaluable_it_includes_positive_relay_timers_in_Shelly_switch_payloads":0,"P\\Tests\\Unit\\Selfserve\\SelfserveRouteWiringTest::__pest_evaluable_it_applies_Shelly_transport_overrides_across_self_serve_relay_side_effect_routes":0.049,"P\\Tests\\Unit\\Selfserve\\EdgeGatewayLegacyRouteShimTest::__pest_evaluable_it_keeps_guarded_legacy_root_shims_for_moved_edge_gateway_routes":0.014,"P\\Tests\\Integration\\EdgeGateway\\EdgeGatewayBackendIntegrationTest::__pest_evaluable_it_persists_gateway_cutover_relay_bindings_used_by_self_serve_Shelly_dispatch":18.006,"P\\Tests\\Unit\\Selfserve\\SelfserveLanePortControllerTest::__pest_evaluable_it_passes_explicit_timer_values_when_opening_lane_gates":0,"P\\Tests\\Unit\\Selfserve\\ShellyRelayInventoryTest::__pest_evaluable_it_keeps_Shelly_1_Mini_Gen3_type__model__and_generation_aligned_with_Shelly_metadata":0}} \ No newline at end of file diff --git a/services/nginx/app/classes/shelly_relay_inventory.php b/services/nginx/app/classes/shelly_relay_inventory.php index 9a70d4b4..7970cc99 100644 --- a/services/nginx/app/classes/shelly_relay_inventory.php +++ b/services/nginx/app/classes/shelly_relay_inventory.php @@ -190,7 +190,12 @@ class shelly_relay_inventory $device['_dev_info']['code'] ?? null, $device['code'] ?? null, ]); + $device_model = $this->extractDeviceModel($device, $device_code, $catalog_entry); + if ($device_code === '' && $device_model !== null) { + $device_code = $device_model; + } $device_type = $this->extractDeviceType($device, $device_code, $catalog_entry); + $device_generation = $this->extractDeviceGeneration($device, $device_code, $device_type, $catalog_entry); $control_type = $this->extractControlType($device); $control_name = $this->extractControlName($device); $online = $this->extractOnlineState($device); @@ -214,6 +219,8 @@ class shelly_relay_inventory 'cloud_name' => $cloud_name !== '' ? $cloud_name : null, 'device_type' => $device_type, 'code' => $device_code !== '' ? $device_code : null, + 'device_model' => $device_model, + 'device_generation' => $device_generation, 'control_type' => $control_type, 'control_name' => $control_name !== '' ? $control_name : null, 'local_ip' => $local_ip, @@ -295,19 +302,155 @@ class shelly_relay_inventory */ private function extractDeviceType(array $device, string $device_code, ?array $catalog_entry = null): ?string { - $device_type = $this->extractFirstString([ - $device['_dev_info']['model'] ?? null, + $candidates = [ $device['_dev_info']['type'] ?? null, - $device['model'] ?? null, $device['type'] ?? null, $device['settings']['device']['type'] ?? null, + $device['_dev_info']['model'] ?? null, + $device['model'] ?? null, + $device['_dev_info']['app'] ?? null, + $device['app'] ?? null, $catalog_entry['type'] ?? null, $device_code, - ]); + ]; + + foreach ($candidates as $candidate) { + $normalized = trim((string)($candidate ?? '')); + if ($normalized !== '' && !$this->looksLikeShellyModelCode($normalized)) { + return $normalized; + } + } + + $device_type = $this->extractFirstString($candidates); return $device_type !== '' ? $device_type : null; } + /** + * @param array $device + */ + private function extractDeviceModel(array $device, string $device_code, ?array $catalog_entry = null): ?string + { + $candidates = [ + $device_code, + $device['_dev_info']['model'] ?? null, + $device['model'] ?? null, + $catalog_entry['type'] ?? null, + $catalog_entry['model'] ?? null, + $device['_dev_info']['type'] ?? null, + $device['type'] ?? null, + ]; + + foreach ($candidates as $candidate) { + $normalized = trim((string)($candidate ?? '')); + if ($normalized !== '' && $this->looksLikeShellyModelCode($normalized)) { + return $normalized; + } + } + + return null; + } + + /** + * @param array $device + */ + private function extractDeviceGeneration( + array $device, + string $device_code, + ?string $device_type, + ?array $catalog_entry = null + ): ?int { + foreach ([ + $device['_dev_info']['gen'] ?? null, + $device['_dev_info']['generation'] ?? null, + $device['gen'] ?? null, + $device['generation'] ?? null, + $device['settings']['device']['gen'] ?? null, + $device['settings']['device']['generation'] ?? null, + $device['status']['sys']['gen'] ?? null, + $device['status']['sys']['generation'] ?? null, + $catalog_entry['gen'] ?? null, + $catalog_entry['generation'] ?? null, + ] as $candidate) { + $generation = $this->normalizeDeviceGeneration($candidate); + if ($generation !== null) { + return $generation; + } + } + + foreach ([ + $device_code, + $device_type, + $device['_dev_info']['model'] ?? null, + $device['_dev_info']['type'] ?? null, + $device['_dev_info']['app'] ?? null, + $device['model'] ?? null, + $device['type'] ?? null, + $device['app'] ?? null, + $catalog_entry['type'] ?? null, + $catalog_entry['model'] ?? null, + ] as $candidate) { + $generation = $this->inferDeviceGenerationFromString((string)($candidate ?? '')); + if ($generation !== null) { + return $generation; + } + } + + return null; + } + + private function normalizeDeviceGeneration(mixed $value): ?int + { + if (is_int($value)) { + return $value > 0 ? $value : null; + } + + if (is_numeric($value)) { + $generation = (int)$value; + return $generation > 0 ? $generation : null; + } + + return $this->inferDeviceGenerationFromString((string)($value ?? '')); + } + + private function inferDeviceGenerationFromString(string $value): ?int + { + $normalized = trim($value); + if ($normalized === '') { + return null; + } + + if (preg_match('/\bgen(?:eration)?\s*([1-9]\d*)\b/i', $normalized, $matches) === 1) { + return (int)$matches[1]; + } + + $upper = strtoupper($normalized); + if (preg_match('/\bS([3-9])(?:[A-Z0-9]+)?-[A-Z0-9-]+\b/', $upper, $matches) === 1) { + return (int)$matches[1]; + } + + if (preg_match('/\b(?:SHELLY\s+)?(?:PLUS|PRO)\b/i', $normalized) === 1 + || preg_match('/\bSP[A-Z0-9]+-[A-Z0-9-]+\b/', $upper) === 1) { + return 2; + } + + if (preg_match('/\bSH[A-Z0-9]+-?[A-Z0-9-]*\b/', $upper) === 1) { + return 1; + } + + return null; + } + + private function looksLikeShellyModelCode(string $value): bool + { + $normalized = strtoupper(trim($value)); + if ($normalized === '') { + return false; + } + + return preg_match('/^(?:S[1-9]|SP|SN|SH)[A-Z0-9]+-[A-Z0-9-]+$/', $normalized) === 1; + } + /** * @param array $device */ diff --git a/services/nginx/app/modules/edgegateway/classes/edge_gateway_manager.php b/services/nginx/app/modules/edgegateway/classes/edge_gateway_manager.php index d1e08474..2a019b58 100644 --- a/services/nginx/app/modules/edgegateway/classes/edge_gateway_manager.php +++ b/services/nginx/app/modules/edgegateway/classes/edge_gateway_manager.php @@ -148,6 +148,83 @@ class edge_gateway_manager ]; } + private function buildShellReadinessDiagnostics(edge_gateways_o $gateway): array + { + $gatewayId = (int)$gateway->id; + $brokerUrl = $this->buildBrokerPublicUrl(); + $wsUrl = $this->buildBrokerPublicWebSocketUrl('/ws/browser-shell'); + $presence = $this->readBrokerPresence($gatewayId); + $lastSeenAt = isset($presence['last_seen_at']) ? (string)$presence['last_seen_at'] : null; + $ageSeconds = self::heartbeatAgeSeconds($lastSeenAt); + $connected = self::isBrokerPresenceConnected($presence); + $configuredBrokerUrl = trim((string)(getenv('EDGE_PUBLIC_BROKER_URL') ?: '')); + $derivedWarning = null; + + if ($configuredBrokerUrl === '') { + $apiBaseUrl = rtrim($this->getApiBaseUrl(), '/'); + $apiPath = (string)(parse_url($apiBaseUrl, PHP_URL_PATH) ?: ''); + $apiHost = (string)(parse_url($apiBaseUrl, PHP_URL_HOST) ?: ''); + if ($apiPath === '/api' && !in_array($apiHost, ['localhost', '127.0.0.1'], true)) { + $derivedWarning = 'BROKER_PUBLIC_URL_DERIVED_WITH_API_PREFIX'; + } + } + + $diagnostics = [ + 'ready' => false, + 'reason_code' => 'BROKER_NOT_READY', + 'message' => 'Gateway shell is not ready.', + 'gateway_id' => $gatewayId, + 'broker_url' => $brokerUrl, + 'ws_url' => $wsUrl, + 'public_broker_url_configured' => $configuredBrokerUrl !== '', + 'derived_warning' => $derivedWarning, + 'broker_presence' => [ + 'connected' => !empty($presence['connected']), + 'connection_id' => isset($presence['connection_id']) ? (string)$presence['connection_id'] : null, + 'last_seen_at' => $lastSeenAt, + 'age_seconds' => $ageSeconds, + 'disconnect_reason' => isset($presence['disconnect_reason']) ? (string)$presence['disconnect_reason'] : null, + 'last_error' => isset($presence['last_error']) ? (string)$presence['last_error'] : null, + ], + ]; + + if ($brokerUrl === null || $wsUrl === null) { + return array_merge($diagnostics, [ + 'reason_code' => 'BROKER_NOT_CONFIGURED', + 'message' => 'The public edge broker URL is not configured, so a gateway shell cannot be opened.', + ]); + } + + if ($presence === []) { + return array_merge($diagnostics, [ + 'reason_code' => 'BROKER_DISCONNECTED', + 'message' => 'Gateway agent has not reported an active broker connection yet.', + ]); + } + + if (empty($presence['connected'])) { + return array_merge($diagnostics, [ + 'reason_code' => 'BROKER_DISCONNECTED', + 'message' => 'Gateway agent is not connected to the edge broker.', + ]); + } + + if (!$connected) { + return array_merge($diagnostics, [ + 'reason_code' => 'BROKER_STALE', + 'message' => 'Gateway broker presence is stale. Wait for the agent to reconnect before opening a shell.', + ]); + } + + return array_merge($diagnostics, [ + 'ready' => true, + 'reason_code' => $derivedWarning ?: 'READY', + 'message' => $derivedWarning === null + ? 'Gateway shell broker path is ready.' + : 'Gateway shell broker path is ready, but the broker URL was derived from the API URL.', + ]); + } + /** * @throws Exception */ @@ -880,12 +957,19 @@ class edge_gateway_manager return $this->dispatchRelayThroughCloud($departmentId, $logicalRelayId, null, $binding, $resolution); } - $job = $this->createCommandJob((int)$gateway->id, 'GET_RELAY_STATUS', [ + $statusRequest = [ 'relayId' => $logicalRelayId, 'deviceId' => $binding['device_id'], 'localIp' => $binding['local_ip'], 'channel' => (int)$binding['channel'], - ], null, [ + ]; + $deviceGeneration = $this->resolveRelayBindingDeviceGeneration($binding); + if ($deviceGeneration !== null) { + $statusRequest['deviceGeneration'] = $deviceGeneration; + $statusRequest['device_generation'] = $deviceGeneration; + } + + $job = $this->createCommandJob((int)$gateway->id, 'GET_RELAY_STATUS', $statusRequest, null, [ 'preferred_channel' => (string)($resolution['preferred_channel'] ?? self::DELIVERY_CHANNEL_API), 'fallback_reason' => $resolution['reason'] ?? null, 'require_fast_path' => $requireFastLocalPath, @@ -987,6 +1071,11 @@ class edge_gateway_manager 'channel' => (int)$binding['channel'], 'on' => $on, ]; + $deviceGeneration = $this->resolveRelayBindingDeviceGeneration($binding); + if ($deviceGeneration !== null) { + $request['deviceGeneration'] = $deviceGeneration; + $request['device_generation'] = $deviceGeneration; + } if ($toggleAfterSeconds !== null) { $request['toggleAfter'] = $toggleAfterSeconds; $request['toggle_after'] = $toggleAfterSeconds; @@ -1816,8 +1905,20 @@ BASH; ?string $cwd = null ): array { $gateway = $this->requireGateway($gatewayId); + $readiness = $this->buildShellReadinessDiagnostics($gateway); + if (empty($readiness['ready'])) { + throw new edge_gateway_operation_exception( + (string)$readiness['message'], + (string)$readiness['reason_code'], + 409, + $readiness + ); + } + $sessionToken = bin2hex(random_bytes(32)); $expiresAt = $this->formatDateTime(time() + self::SHELL_SESSION_TTL_SECONDS); + $brokerUrl = $this->buildBrokerPublicUrl(); + $wsUrl = $this->buildBrokerPublicWebSocketUrl('/ws/browser-shell'); $sessionObject = new edge_gateway_shell_sessions_o(); $sessionId = $sessionObject->add_object([ @@ -1835,6 +1936,9 @@ BASH; 'transcript' => null, 'metadata_json' => [ 'root_dir' => self::DEFAULT_INSTALL_DIR, + 'shell_diagnostics' => $readiness, + 'requested_broker_url' => $brokerUrl, + 'requested_ws_url' => $wsUrl, 'shortcut_paths' => [ self::DEFAULT_INSTALL_DIR, self::DEFAULT_RUNTIME_DIR, @@ -1860,8 +1964,9 @@ BASH; 'token' => $sessionToken, 'gateway_id' => (int)$gateway->id, 'expires_at' => $expiresAt, - 'broker_url' => $this->buildBrokerPublicUrl(), - 'ws_url' => $this->buildBrokerPublicWebSocketUrl('/ws/browser-shell'), + 'broker_url' => $brokerUrl, + 'ws_url' => $wsUrl, + 'diagnostics' => $readiness, ]; } @@ -1916,11 +2021,20 @@ BASH; /** * @throws Exception */ - public function closeShellSessionByToken(string $plainToken, string $transcript = '', ?string $reason = null): array - { + public function closeShellSessionByToken( + string $plainToken, + string $transcript = '', + ?string $reason = null, + array $details = [] + ): array { $session = $this->findShellSessionByToken($plainToken); $metadata = (array)($session->metadata_json->value() ?? []); + $closeDiagnostics = $this->normalizeShellCloseDiagnostics($reason, $details); $metadata['close_reason'] = $reason; + $metadata['close_message'] = $closeDiagnostics['message'] ?? null; + $metadata['close_code'] = $closeDiagnostics['code'] ?? null; + $metadata['close_stage'] = $closeDiagnostics['stage'] ?? null; + $metadata['close_diagnostics'] = $closeDiagnostics; $metadata['transcript_bytes'] = strlen($transcript); $session->status->set($reason === 'agent_exit' ? 'COMPLETED' : 'CLOSED'); @@ -1941,6 +2055,54 @@ BASH; return $session->asArray(); } + private function normalizeShellCloseDiagnostics(?string $reason, array $details = []): array + { + $nestedDetails = isset($details['details']) && is_array($details['details']) ? (array)$details['details'] : []; + $message = self::trimInstallSessionText( + $details['message'] ?? $nestedDetails['message'] ?? null, + self::INSTALL_SESSION_OUTPUT_LIMIT + ); + $stage = self::trimInstallSessionText( + $details['stage'] ?? $details['failure_stage'] ?? $nestedDetails['stage'] ?? null, + 128 + ); + $codeValue = $details['code'] ?? $details['close_code'] ?? $nestedDetails['code'] ?? null; + $code = is_numeric($codeValue) ? (int)$codeValue : null; + $diagnostics = [ + 'reason' => self::trimInstallSessionText($reason, 128), + 'message' => $message, + 'code' => $code, + 'stage' => $stage, + 'was_clean' => array_key_exists('was_clean', $details) ? (bool)$details['was_clean'] : null, + 'connection_id' => self::trimInstallSessionText( + $details['connection_id'] ?? $details['broker_connection_id'] ?? $nestedDetails['connection_id'] ?? null, + 128 + ), + 'broker_url' => self::trimInstallSessionText($details['broker_url'] ?? $nestedDetails['broker_url'] ?? null, 512), + 'ws_url' => self::trimInstallSessionText( + $this->redactShellDiagnosticUrl($details['ws_url'] ?? $nestedDetails['ws_url'] ?? null), + 512 + ), + 'closed_at' => $this->now(), + ]; + + return array_filter($diagnostics, static fn(mixed $value): bool => $value !== null && $value !== ''); + } + + private function redactShellDiagnosticUrl(mixed $value): ?string + { + if ($value === null) { + return null; + } + + $url = trim((string)$value); + if ($url === '') { + return null; + } + + return (string)preg_replace('/([?&](?:token|agentToken|agent_token)=)[^&]*/i', '$1***', $url); + } + /** * @throws Exception */ @@ -3135,6 +3297,170 @@ BASH; ); } + private function resolveRelayBindingDeviceGeneration(array $binding): ?int + { + $metadata = isset($binding['metadata']) && is_array($binding['metadata']) + ? (array)$binding['metadata'] + : []; + + $generation = $this->resolveShellyDeviceGenerationFromPayload(array_merge($metadata, $binding)); + if ($generation !== null) { + return $generation; + } + + $inventoryDevice = $this->findInventoryDeviceForRelayBinding($binding); + if ($inventoryDevice !== null) { + $generation = $this->resolveShellyDeviceGenerationFromPayload($inventoryDevice); + if ($generation !== null) { + return $generation; + } + } + + $deviceId = trim((string)($binding['device_id'] ?? '')); + $relayId = trim((string)($binding['relay_id'] ?? '')); + foreach ($this->listShellyRelayOptionsForLocalIpLookup() as $option) { + $optionDeviceId = trim((string)($option['device_id'] ?? '')); + $optionRelayId = trim((string)($option['id'] ?? '')); + if ($optionDeviceId !== $deviceId && $optionRelayId !== $relayId && $optionRelayId !== $deviceId) { + continue; + } + + $generation = $this->resolveShellyDeviceGenerationFromPayload($option); + if ($generation !== null) { + return $generation; + } + } + + return null; + } + + private function findInventoryDeviceForRelayBinding(array $binding): ?array + { + $gatewayId = (int)($binding['gateway_id'] ?? 0); + $deviceId = trim((string)($binding['device_id'] ?? '')); + if ($gatewayId <= 0 || $deviceId === '') { + return null; + } + + $rows = (new edge_gateway_device_inventory_o())->getFieldsWhere([ + 'gateway_id' => $gatewayId, + 'device_id' => $deviceId, + 'deleted_at' => null, + ], ['id']); + if ($rows === []) { + return null; + } + + $inventoryObject = (new edge_gateway_device_inventory_o())->select((int)$rows[0]['id']); + return $inventoryObject->exists() ? $inventoryObject->asArray() : null; + } + + private function normalizeDeviceCapabilities(array $device): array + { + $capabilities = isset($device['capabilities']) && is_array($device['capabilities']) + ? (array)$device['capabilities'] + : []; + + if (!isset($capabilities['generation'])) { + $generation = $this->resolveShellyDeviceGenerationFromPayload($device); + if ($generation !== null) { + $capabilities['generation'] = $generation; + } + } + + return $capabilities; + } + + private function resolveShellyDeviceGenerationFromPayload(array $payload): ?int + { + $metadata = isset($payload['metadata']) && is_array($payload['metadata']) ? (array)$payload['metadata'] : []; + $capabilities = isset($payload['capabilities']) && is_array($payload['capabilities']) ? (array)$payload['capabilities'] : []; + + foreach ([ + $payload['deviceGeneration'] ?? null, + $payload['device_generation'] ?? null, + $payload['generation'] ?? null, + $payload['gen'] ?? null, + $capabilities['generation'] ?? null, + $metadata['deviceGeneration'] ?? null, + $metadata['device_generation'] ?? null, + $metadata['generation'] ?? null, + $metadata['gen'] ?? null, + $metadata['capabilities']['generation'] ?? null, + ] as $candidate) { + $generation = $this->normalizeShellyDeviceGeneration($candidate); + if ($generation !== null) { + return $generation; + } + } + + foreach ([ + $payload['device_model'] ?? null, + $payload['deviceModel'] ?? null, + $payload['model'] ?? null, + $payload['device_type'] ?? null, + $payload['deviceType'] ?? null, + $payload['type'] ?? null, + $payload['code'] ?? null, + $metadata['device_model'] ?? null, + $metadata['deviceModel'] ?? null, + $metadata['model'] ?? null, + $metadata['device_type'] ?? null, + $metadata['deviceType'] ?? null, + $metadata['type'] ?? null, + $metadata['code'] ?? null, + ] as $candidate) { + $generation = $this->inferShellyDeviceGenerationFromString((string)($candidate ?? '')); + if ($generation !== null) { + return $generation; + } + } + + return null; + } + + private function normalizeShellyDeviceGeneration(mixed $value): ?int + { + if (is_int($value)) { + return $value > 0 ? $value : null; + } + + if (is_numeric($value)) { + $generation = (int)$value; + return $generation > 0 ? $generation : null; + } + + return $this->inferShellyDeviceGenerationFromString((string)($value ?? '')); + } + + private function inferShellyDeviceGenerationFromString(string $value): ?int + { + $normalized = trim($value); + if ($normalized === '') { + return null; + } + + if (preg_match('/\bgen(?:eration)?\s*([1-9]\d*)\b/i', $normalized, $matches) === 1) { + return (int)$matches[1]; + } + + $upper = strtoupper($normalized); + if (preg_match('/\bS([3-9])(?:[A-Z0-9]+)?-[A-Z0-9-]+\b/', $upper, $matches) === 1) { + return (int)$matches[1]; + } + + if (preg_match('/\b(?:SHELLY\s+)?(?:PLUS|PRO)\b/i', $normalized) === 1 + || preg_match('/\bSP[A-Z0-9]+-[A-Z0-9-]+\b/', $upper) === 1) { + return 2; + } + + if (preg_match('/\bSH[A-Z0-9]+-?[A-Z0-9-]*\b/', $upper) === 1) { + return 1; + } + + return null; + } + private function backfillRelayBindingLocalIpFromInventory(int $gatewayId, string $deviceId, ?string $localIp): void { $localIp = $this->normalizeLocalIp($localIp); @@ -3170,6 +3496,7 @@ BASH; } $localIp = $this->extractDeviceLocalIp($device); + $capabilities = $this->normalizeDeviceCapabilities($device); $rows = (new edge_gateway_device_inventory_o())->getFieldsWhere([ 'gateway_id' => $gatewayId, 'device_id' => $deviceId, @@ -3183,7 +3510,7 @@ BASH; 'local_ip' => $localIp, 'model' => $device['model'] ?? null, 'channel_count' => (int)($device['channel_count'] ?? $device['channels'] ?? 1), - 'capabilities_json' => (array)($device['capabilities'] ?? []), + 'capabilities_json' => $capabilities, 'online' => (bool)($device['online'] ?? true), 'last_seen_at' => $this->now(), 'metadata_json' => (array)($device['metadata'] ?? []), @@ -3198,7 +3525,7 @@ BASH; } $inventoryObject->model->set($device['model'] ?? null); $inventoryObject->channel_count->set((int)($device['channel_count'] ?? $device['channels'] ?? 1)); - $inventoryObject->capabilities_json->set((array)($device['capabilities'] ?? [])); + $inventoryObject->capabilities_json->set($capabilities); $inventoryObject->online->set((bool)($device['online'] ?? true)); $inventoryObject->last_seen_at->set($this->now()); $inventoryObject->metadata_json->set((array)($device['metadata'] ?? [])); @@ -3575,6 +3902,27 @@ BASH; $metadata['consumer_contexts'] = $consumerContexts; $metadata['consumers'] = $consumerContexts; + foreach (['device_type', 'device_model', 'code'] as $field) { + $value = trim((string)($binding[$field] ?? $metadata[$field] ?? '')); + if ($value !== '') { + $metadata[$field] = $value; + } + } + + $generation = $this->normalizeShellyDeviceGeneration( + $binding['deviceGeneration'] + ?? $binding['device_generation'] + ?? $binding['generation'] + ?? $metadata['deviceGeneration'] + ?? $metadata['device_generation'] + ?? $metadata['generation'] + ?? null + ); + if ($generation !== null) { + $metadata['device_generation'] = $generation; + $metadata['generation'] = $generation; + } + if (isset($binding['last_resolution']) && is_array($binding['last_resolution'])) { $metadata['last_resolution'] = (array)$binding['last_resolution']; } diff --git a/services/nginx/app/modules/edgegateway/classes/edge_gateway_operation_exception.php b/services/nginx/app/modules/edgegateway/classes/edge_gateway_operation_exception.php index c673bef3..f232a26f 100644 --- a/services/nginx/app/modules/edgegateway/classes/edge_gateway_operation_exception.php +++ b/services/nginx/app/modules/edgegateway/classes/edge_gateway_operation_exception.php @@ -9,7 +9,8 @@ class edge_gateway_operation_exception extends Exception public function __construct( string $message, public readonly string $errorCode, - public readonly int $status = 400 + public readonly int $status = 400, + public readonly array $details = [] ) { parent::__construct($message, $status); } diff --git a/services/nginx/app/modules/edgegateway/routes/edgeGatewaysRoute.php b/services/nginx/app/modules/edgegateway/routes/edgeGatewaysRoute.php index 2c031081..edd14b3f 100644 --- a/services/nginx/app/modules/edgegateway/routes/edgeGatewaysRoute.php +++ b/services/nginx/app/modules/edgegateway/routes/edgeGatewaysRoute.php @@ -184,7 +184,15 @@ class edgeGatewaysRoute $cwd = isset($payload['cwd']) ? (string)$payload['cwd'] : null; $cols = isset($payload['cols']) ? (int)$payload['cols'] : null; $rows = isset($payload['rows']) ? (int)$payload['rows'] : null; - $response->success($this->manager()->createShellSession($gatewayId, $this->actorUserId(), $reason, $cols, $rows, $cwd), 201); + try { + $response->success($this->manager()->createShellSession($gatewayId, $this->actorUserId(), $reason, $cols, $rows, $cwd), 201); + } catch (edge_gateway_operation_exception $exception) { + $response->error([ + 'message' => $exception->getMessage(), + 'error_code' => $exception->errorCode, + 'diagnostics' => $exception->details, + ], $exception->status); + } } private function handleGatewayUpdate(): void @@ -698,7 +706,20 @@ class edgeGatewaysRoute $response->success($this->manager()->closeShellSessionByToken( (string)self::getParameter('token'), isset($payload['transcript']) ? (string)$payload['transcript'] : '', - isset($payload['reason']) ? (string)$payload['reason'] : null + isset($payload['reason']) ? (string)$payload['reason'] : null, + [ + 'message' => isset($payload['message']) ? (string)$payload['message'] : null, + 'code' => isset($payload['code']) ? (int)$payload['code'] : null, + 'close_code' => isset($payload['close_code']) ? (int)$payload['close_code'] : null, + 'stage' => isset($payload['stage']) ? (string)$payload['stage'] : null, + 'failure_stage' => isset($payload['failure_stage']) ? (string)$payload['failure_stage'] : null, + 'was_clean' => isset($payload['was_clean']) ? (bool)$payload['was_clean'] : null, + 'connection_id' => isset($payload['connection_id']) ? (string)$payload['connection_id'] : null, + 'broker_connection_id' => isset($payload['broker_connection_id']) ? (string)$payload['broker_connection_id'] : null, + 'broker_url' => isset($payload['broker_url']) ? (string)$payload['broker_url'] : null, + 'ws_url' => isset($payload['ws_url']) ? (string)$payload['ws_url'] : null, + 'details' => isset($payload['details']) && is_array($payload['details']) ? (array)$payload['details'] : [], + ] )); } diff --git a/services/nginx/app/tests/Api/EdgeGatewayBrokerApiTest.php b/services/nginx/app/tests/Api/EdgeGatewayBrokerApiTest.php index dae8e90a..5dec9bc8 100644 --- a/services/nginx/app/tests/Api/EdgeGatewayBrokerApiTest.php +++ b/services/nginx/app/tests/Api/EdgeGatewayBrokerApiTest.php @@ -132,6 +132,12 @@ it('validates broker sessions and ingests presence, telemetry, logs, and shell l ->assertEnvelope() ->assertSuccess(); + expect($shellSession->data()['diagnostics'] ?? []) + ->toHaveKey('ready', true) + ->toHaveKey('reason_code', 'READY') + ->and($shellSession->data()['diagnostics']['broker_presence']['connection_id'] ?? null) + ->toBe('broker-presence-1'); + $shellToken = (string)$shellSession->data()['token']; $validateShell = api_client()->post( @@ -172,6 +178,9 @@ it('validates broker sessions and ingests presence, telemetry, logs, and shell l 'token' => $shellToken, 'transcript' => "edge-broker-shell\n", 'reason' => 'agent_exit', + 'message' => 'Shell exited cleanly.', + 'code' => 0, + 'stage' => 'shell_active', ], edge_test_broker_headers() ); @@ -184,7 +193,15 @@ it('validates broker sessions and ingests presence, telemetry, logs, and shell l expect($closedShell->data()) ->toHaveKey('status', 'COMPLETED') ->and($closedShell->data()['transcript'] ?? null) - ->toBe("edge-broker-shell\n"); + ->toBe("edge-broker-shell\n") + ->and($closedShell->data()['metadata']['close_reason'] ?? null) + ->toBe('agent_exit') + ->and($closedShell->data()['metadata']['close_message'] ?? null) + ->toBe('Shell exited cleanly.') + ->and($closedShell->data()['metadata']['close_code'] ?? null) + ->toBe(0) + ->and($closedShell->data()['metadata']['close_stage'] ?? null) + ->toBe('shell_active'); $logsPage = api_client()->get('/edge-gateways/' . (int)$gateway['id'] . '/logs', $session['headers']); @@ -214,6 +231,35 @@ it('validates broker sessions and ingests presence, telemetry, logs, and shell l ->toBe(0.42); }); +it('rejects shell session creation while broker presence is unavailable', function (): void { + $department = api_fixtures()->createDepartment([ + 'name' => 'Edge Broker Shell Readiness Department', + ]); + $session = api_fixtures()->createEdgeOperatorSession((int)$department['id']); + $gateway = api_fixtures()->createClaimedEdgeGateway([ + 'department_id' => (int)$department['id'], + 'label' => 'Disconnected Broker Gateway', + ]); + + $response = api_client()->post( + '/edge-gateways/' . (int)$gateway['id'] . '/shell-sessions', + ['reason' => 'Should fail without broker presence'], + $session['headers'] + ); + + $response + ->assertStatus(409) + ->assertEnvelope() + ->assertSuccess(false); + + expect($response->data()) + ->toHaveKey('error_code', 'BROKER_DISCONNECTED') + ->and($response->data()['diagnostics']['ready'] ?? true) + ->toBeFalse() + ->and($response->data()['diagnostics']['broker_presence']['connected'] ?? true) + ->toBeFalse(); +}); + it('builds broker backlog and completes gateway operations through broker endpoints', function (): void { $department = api_fixtures()->createDepartment([ 'name' => 'Edge Broker Backlog Department', diff --git a/services/nginx/app/tests/Unit/Selfserve/EdgeGatewayManagerCommandQueueTest.php b/services/nginx/app/tests/Unit/Selfserve/EdgeGatewayManagerCommandQueueTest.php index 979a35f6..01152c31 100644 --- a/services/nginx/app/tests/Unit/Selfserve/EdgeGatewayManagerCommandQueueTest.php +++ b/services/nginx/app/tests/Unit/Selfserve/EdgeGatewayManagerCommandQueueTest.php @@ -25,6 +25,9 @@ it('keeps relay dispatch and discovery queueing on the edge gateway manager', fu expect($managerSource)->toContain("'channel' => (int)\$binding['channel']"); expect($managerSource)->toContain("'on' => \$on"); expect($managerSource)->toContain("'require_fast_path' => \$requireFastLocalPath"); + expect($managerSource)->toContain('private function resolveRelayBindingDeviceGeneration'); + expect($managerSource)->toContain('private function normalizeDeviceCapabilities'); + expect($managerSource)->toContain("\$request['device_generation'] = \$deviceGeneration;"); expect($managerSource)->toContain("\$request['toggle_after'] = \$toggleAfterSeconds;"); expect($managerSource)->toContain('private function expireTimedOutRelayStatusCommandJobs'); expect($managerSource)->toContain("AND command_type = 'GET_RELAY_STATUS'"); @@ -72,6 +75,10 @@ it('loads relay command helpers on the manager and gateway operations on the ded expect($reflection->getMethod('claimNextCommandJob')->isPrivate())->toBeTrue(); expect($reflection->hasMethod('syncDeviceInventory'))->toBeTrue(); expect($reflection->getMethod('syncDeviceInventory')->isPrivate())->toBeTrue(); + expect($reflection->hasMethod('resolveRelayBindingDeviceGeneration'))->toBeTrue(); + expect($reflection->getMethod('resolveRelayBindingDeviceGeneration')->isPrivate())->toBeTrue(); + expect($reflection->hasMethod('normalizeDeviceCapabilities'))->toBeTrue(); + expect($reflection->getMethod('normalizeDeviceCapabilities')->isPrivate())->toBeTrue(); expect($reflection->hasMethod('resolveRelayBindingLocalIp'))->toBeTrue(); expect($reflection->getMethod('resolveRelayBindingLocalIp')->isPrivate())->toBeTrue(); expect($reflection->hasMethod('backfillRelayBindingLocalIpFromInventory'))->toBeTrue(); diff --git a/services/nginx/app/tests/Unit/Selfserve/ShellyRelayInventoryTest.php b/services/nginx/app/tests/Unit/Selfserve/ShellyRelayInventoryTest.php index 966f91c1..d73db9f9 100644 --- a/services/nginx/app/tests/Unit/Selfserve/ShellyRelayInventoryTest.php +++ b/services/nginx/app/tests/Unit/Selfserve/ShellyRelayInventoryTest.php @@ -102,6 +102,8 @@ it('normalizes owned Shelly devices into relay select options', function (): voi 'cloud_name' => 'Gate From Shelly Cloud', 'device_type' => 'Shelly Plus 1PM', 'code' => 'SPSW-001PE16EU', + 'device_model' => 'SPSW-001PE16EU', + 'device_generation' => 2, 'control_type' => 'Switch', 'control_name' => 'Entrance Relay', 'local_ip' => '10.32.0.11', @@ -116,6 +118,8 @@ it('normalizes owned Shelly devices into relay select options', function (): voi 'cloud_name' => 'Program Picker From Shelly Cloud', 'device_type' => 'Shelly Pro 2PM', 'code' => 'SPSW-201XE16EU', + 'device_model' => 'SPSW-201XE16EU', + 'device_generation' => 2, 'control_type' => 'Relay', 'control_name' => 'Program Picker', 'local_ip' => '10.32.0.12', @@ -130,6 +134,8 @@ it('normalizes owned Shelly devices into relay select options', function (): voi 'cloud_name' => null, 'device_type' => 'Shelly 1', 'code' => 'SHSW-1', + 'device_model' => 'SHSW-1', + 'device_generation' => 1, 'control_type' => 'Relay', 'control_name' => null, 'local_ip' => null, @@ -184,6 +190,8 @@ it('falls back to local device and control names when Shelly cloud list metadata 'cloud_name' => null, 'device_type' => 'Shelly Plus 1PM', 'code' => 'SPSW-001PE16EU', + 'device_model' => 'SPSW-001PE16EU', + 'device_generation' => 2, 'control_type' => 'Switch', 'control_name' => 'Entrance Relay', 'local_ip' => '10.32.0.21', @@ -193,6 +201,68 @@ it('falls back to local device and control names when Shelly cloud list metadata ]); }); +it('keeps Shelly 1 Mini Gen3 type, model, and generation aligned with Shelly metadata', function (): void { + $inventory = (new shelly_relay_inventory()) + ->setInventoryFetcher(static function (): array { + return [ + 'isok' => true, + 'data' => [ + 'devices_status' => [ + 'device-key-1' => [ + '_dev_info' => [ + 'id' => 'e4b3231f6410', + 'model' => 'S3SW-001X8EU', + 'type' => 'Shelly 1 Mini Gen3', + 'online' => 1, + ], + 'name' => 'Roskilde indkørselsport', + 'wifi_sta' => [ + 'ip' => '192.168.1.2', + ], + 'status' => [ + 'switch:0' => [ + 'output' => false, + ], + ], + ], + ], + ], + ]; + }) + ->setDeviceListFetcher(static function (): array { + return [ + 'isok' => true, + 'data' => [ + 'devices' => [ + 'e4b3231f6410' => [ + 'id' => 'e4b3231f6410', + 'name' => 'Roskilde indkørselsport', + 'type' => 'S3SW-001X8EU', + 'cloud_online' => true, + ], + ], + ], + ]; + }); + + expect($inventory->listRelayOptions())->toBe([[ + 'id' => 'e4b3231f6410', + 'name' => 'Roskilde indkørselsport (Shelly 1 Mini Gen3)', + 'device_id' => 'e4b3231f6410', + 'device_name' => 'Roskilde indkørselsport', + 'cloud_name' => 'Roskilde indkørselsport', + 'device_type' => 'Shelly 1 Mini Gen3', + 'code' => 'S3SW-001X8EU', + 'device_model' => 'S3SW-001X8EU', + 'device_generation' => 3, + 'control_type' => 'Switch', + 'control_name' => null, + 'local_ip' => '192.168.1.2', + 'status_color' => 'Green', + 'online' => true, + ]]); +}); + it('fails fast when Shelly inventory does not include owned devices status', function (): void { $inventory = (new shelly_relay_inventory())->setInventoryFetcher(static function (): array { return [