diff --git a/src/app/api/v1/accounts/route.ts b/src/app/api/v1/accounts/route.ts index 43c6fda..340d805 100644 --- a/src/app/api/v1/accounts/route.ts +++ b/src/app/api/v1/accounts/route.ts @@ -1,6 +1,7 @@ import { NextRequest, NextResponse } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { listAiAccounts, saveAiAccount } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; function isValidRole(value: string): value is "primary" | "backup" | "api_fallback" { return value === "primary" || value === "backup" || value === "api_fallback"; @@ -13,10 +14,10 @@ function isValidProvider(value: string): value is "master_codex_node" | "openai_ export async function GET(request: NextRequest) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const result = await listAiAccounts(); - return NextResponse.json({ ok: true, ...result }); + return jsonNoStore({ ok: true, ...result }); } export async function POST(request: NextRequest) { diff --git a/src/app/api/v1/app-logs/route.ts b/src/app/api/v1/app-logs/route.ts index 3c3dbaa..bfec46a 100644 --- a/src/app/api/v1/app-logs/route.ts +++ b/src/app/api/v1/app-logs/route.ts @@ -2,11 +2,12 @@ import { NextRequest, NextResponse } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { authorizeDeviceWriteRequest } from "@/lib/boss-device-auth"; import { appendAppLog, readState } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET(request: NextRequest) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const limit = Math.min(Math.max(Number(request.nextUrl.searchParams.get("limit") ?? "20"), 1), 100); @@ -40,7 +41,7 @@ export async function GET(request: NextRequest) { const entries = filtered.slice(0, limit); const nextCursor = filtered.length > limit ? entries.at(-1)?.createdAt : null; - return NextResponse.json({ + return jsonNoStore({ ok: true, entries, nextCursor, diff --git a/src/app/api/v1/audits/summary/route.ts b/src/app/api/v1/audits/summary/route.ts index bf154cf..6aac099 100644 --- a/src/app/api/v1/audits/summary/route.ts +++ b/src/app/api/v1/audits/summary/route.ts @@ -1,13 +1,14 @@ -import { NextRequest, NextResponse } from "next/server"; +import { NextRequest } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { getAuditSummaryView } from "@/lib/boss-projections"; import { readState } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET(request: NextRequest) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const state = await readState(); - return NextResponse.json({ ok: true, ...getAuditSummaryView(state) }); + return jsonNoStore({ ok: true, ...getAuditSummaryView(state) }); } diff --git a/src/app/api/v1/devices/[deviceId]/skills/route.ts b/src/app/api/v1/devices/[deviceId]/skills/route.ts index 7b413fc..d7f408c 100644 --- a/src/app/api/v1/devices/[deviceId]/skills/route.ts +++ b/src/app/api/v1/devices/[deviceId]/skills/route.ts @@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { authorizeDeviceWriteRequest } from "@/lib/boss-device-auth"; import { readState, upsertDeviceSkills } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET( request: NextRequest, @@ -9,16 +10,16 @@ export async function GET( ) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const { deviceId } = await context.params; const state = await readState(); const device = state.devices.find((item) => item.id === deviceId); if (!device) { - return NextResponse.json({ ok: false, message: "DEVICE_NOT_FOUND" }, { status: 404 }); + return jsonNoStore({ ok: false, message: "DEVICE_NOT_FOUND" }, { status: 404 }); } - return NextResponse.json({ + return jsonNoStore({ ok: true, device, skills: state.deviceSkills diff --git a/src/app/api/v1/devices/enrollments/route.ts b/src/app/api/v1/devices/enrollments/route.ts index f2927af..e24b037 100644 --- a/src/app/api/v1/devices/enrollments/route.ts +++ b/src/app/api/v1/devices/enrollments/route.ts @@ -1,14 +1,15 @@ import { NextRequest, NextResponse } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { createDeviceEnrollment, readState } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET(request: NextRequest) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const state = await readState(); - return NextResponse.json({ ok: true, enrollments: state.deviceEnrollments }); + return jsonNoStore({ ok: true, enrollments: state.deviceEnrollments }); } export async function POST(request: NextRequest) { diff --git a/src/app/api/v1/ops/summary/route.ts b/src/app/api/v1/ops/summary/route.ts index 568f668..47b68b9 100644 --- a/src/app/api/v1/ops/summary/route.ts +++ b/src/app/api/v1/ops/summary/route.ts @@ -1,13 +1,14 @@ -import { NextRequest, NextResponse } from "next/server"; +import { NextRequest } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { getOpsSummaryView } from "@/lib/boss-projections"; import { readState } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET(request: NextRequest) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const state = await readState(); - return NextResponse.json({ ok: true, ...getOpsSummaryView(state) }); + return jsonNoStore({ ok: true, ...getOpsSummaryView(state) }); } diff --git a/src/app/api/v1/projects/[projectId]/agent-controls/route.ts b/src/app/api/v1/projects/[projectId]/agent-controls/route.ts index d06f3e5..24911c3 100644 --- a/src/app/api/v1/projects/[projectId]/agent-controls/route.ts +++ b/src/app/api/v1/projects/[projectId]/agent-controls/route.ts @@ -6,6 +6,7 @@ import { updateProjectAgentControls, } from "@/lib/boss-data"; import { getClawBackendAvailability } from "@/lib/execution/backends/claw-config"; +import { jsonNoStore } from "@/lib/api-response"; const reasoningEffortValues = new Set(["low", "medium", "high"]); @@ -16,19 +17,19 @@ export async function GET( const { projectId } = await context.params; const projectExists = await hasPersistedProject(projectId); if (!projectExists) { - return NextResponse.json({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); + return jsonNoStore({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); } const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const [controls, clawAvailability] = await Promise.all([ getProjectAgentControls(projectId, session.account), getClawBackendAvailability(), ]); - return NextResponse.json({ ok: true, controls, clawAvailability }); + return jsonNoStore({ ok: true, controls, clawAvailability }); } export async function POST( diff --git a/src/app/api/v1/projects/[projectId]/dispatch-plans/route.ts b/src/app/api/v1/projects/[projectId]/dispatch-plans/route.ts index 45de39c..76697eb 100644 --- a/src/app/api/v1/projects/[projectId]/dispatch-plans/route.ts +++ b/src/app/api/v1/projects/[projectId]/dispatch-plans/route.ts @@ -1,6 +1,7 @@ -import { NextRequest, NextResponse } from "next/server"; +import { NextRequest } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { listDispatchPlansByProject, readState } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET( request: NextRequest, @@ -8,19 +9,19 @@ export async function GET( ) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const { projectId } = await context.params; const state = await readState(); const project = state.projects.find((item) => item.id === projectId); if (!project) { - return NextResponse.json({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); + return jsonNoStore({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); } if (!project.isGroup) { - return NextResponse.json({ ok: false, message: "PROJECT_NOT_GROUP_CHAT" }, { status: 400 }); + return jsonNoStore({ ok: false, message: "PROJECT_NOT_GROUP_CHAT" }, { status: 400 }); } const plans = await listDispatchPlansByProject(projectId); - return NextResponse.json({ ok: true, plans }); + return jsonNoStore({ ok: true, plans }); } diff --git a/src/app/api/v1/projects/[projectId]/memories/route.ts b/src/app/api/v1/projects/[projectId]/memories/route.ts index 980f410..2d71184 100644 --- a/src/app/api/v1/projects/[projectId]/memories/route.ts +++ b/src/app/api/v1/projects/[projectId]/memories/route.ts @@ -5,6 +5,7 @@ import { hasPersistedProject, listUserMasterMemories, } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; const memoryTypeValues = new Set([ "user_preference", @@ -28,13 +29,13 @@ export async function GET( ) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const { projectId } = await context.params; const projectExists = await hasPersistedProject(projectId); if (!projectExists) { - return NextResponse.json({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); + return jsonNoStore({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); } const [globalMemories, projectMemories] = await Promise.all([ @@ -44,7 +45,7 @@ export async function GET( : listUserMasterMemories(session.account, { scope: "project", projectId }), ]); - return NextResponse.json({ + return jsonNoStore({ ok: true, projectId, memories: { diff --git a/src/app/api/v1/projects/[projectId]/orchestration-backend/route.ts b/src/app/api/v1/projects/[projectId]/orchestration-backend/route.ts index cf61a97..98986aa 100644 --- a/src/app/api/v1/projects/[projectId]/orchestration-backend/route.ts +++ b/src/app/api/v1/projects/[projectId]/orchestration-backend/route.ts @@ -5,6 +5,7 @@ import { getProjectOrchestrationBackendState, updateProjectOrchestrationBackend, } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; function normalizeRequestedBackendId(value: unknown) { return value === "omx-team" ? "omx-team" : "boss-native-orchestrator"; @@ -13,12 +14,12 @@ function normalizeRequestedBackendId(value: unknown) { async function readGroupProjectOrNotFound(projectId: string) { const project = await getProject(projectId); if (!project) { - return { ok: false as const, response: NextResponse.json({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }) }; + return { ok: false as const, response: jsonNoStore({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }) }; } if (!project.isGroup) { return { ok: false as const, - response: NextResponse.json({ ok: false, message: "PROJECT_NOT_GROUP_CHAT" }, { status: 400 }), + response: jsonNoStore({ ok: false, message: "PROJECT_NOT_GROUP_CHAT" }, { status: 400 }), }; } return { ok: true as const, project }; @@ -30,7 +31,7 @@ export async function GET( ) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const { projectId } = await context.params; @@ -41,10 +42,10 @@ export async function GET( const state = await getProjectOrchestrationBackendState(projectId); if (!state) { - return NextResponse.json({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); + return jsonNoStore({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); } - return NextResponse.json({ + return jsonNoStore({ ok: true, ...state, requestedBackendId: projectCheck.project.orchestrationBackendOverride ?? null, diff --git a/src/app/api/v1/projects/[projectId]/participants/route.ts b/src/app/api/v1/projects/[projectId]/participants/route.ts index c32834a..5bc2d1a 100644 --- a/src/app/api/v1/projects/[projectId]/participants/route.ts +++ b/src/app/api/v1/projects/[projectId]/participants/route.ts @@ -1,6 +1,7 @@ import { NextRequest, NextResponse } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { isDispatchableThreadProject, readState, replaceGroupChatMembers } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; type ConversationParticipant = { projectId: string; @@ -124,16 +125,16 @@ export async function GET( ) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const { projectId } = await context.params; const state = await readState(); const payload = buildParticipantsPayload(state, projectId); if (!payload) { - return NextResponse.json({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); + return jsonNoStore({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); } - return NextResponse.json(payload); + return jsonNoStore(payload); } export async function POST( diff --git a/src/app/api/v1/projects/[projectId]/prompt-profile/route.ts b/src/app/api/v1/projects/[projectId]/prompt-profile/route.ts index 9aa4192..7ce1225 100644 --- a/src/app/api/v1/projects/[projectId]/prompt-profile/route.ts +++ b/src/app/api/v1/projects/[projectId]/prompt-profile/route.ts @@ -10,6 +10,7 @@ import { updateUserMasterPrompt, } from "@/lib/boss-data"; import { getClawBackendAvailability } from "@/lib/execution/backends/claw-config"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET( request: NextRequest, @@ -17,13 +18,13 @@ export async function GET( ) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const { projectId } = await context.params; const projectExists = await hasPersistedProject(projectId); if (!projectExists) { - return NextResponse.json({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); + return jsonNoStore({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); } const [promptPolicy, userPrompt, projectControls, clawAvailability] = await Promise.all([ @@ -33,7 +34,7 @@ export async function GET( getClawBackendAvailability(), ]); - return NextResponse.json({ + return jsonNoStore({ ok: true, projectId, promptPolicy, diff --git a/src/app/api/v1/projects/[projectId]/thread-status/route.ts b/src/app/api/v1/projects/[projectId]/thread-status/route.ts index 9639966..557440f 100644 --- a/src/app/api/v1/projects/[projectId]/thread-status/route.ts +++ b/src/app/api/v1/projects/[projectId]/thread-status/route.ts @@ -1,7 +1,8 @@ -import { NextRequest, NextResponse } from "next/server"; +import { NextRequest } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { readState } from "@/lib/boss-data"; import { getProjectDetailView } from "@/lib/boss-projections"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET( request: NextRequest, @@ -9,14 +10,14 @@ export async function GET( ) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const { projectId } = await context.params; const state = await readState(); const detail = getProjectDetailView(state, projectId, session.account); if (!detail) { - return NextResponse.json({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); + return jsonNoStore({ ok: false, message: "PROJECT_NOT_FOUND" }, { status: 404 }); } const threadStatusDocument = @@ -26,7 +27,7 @@ export async function GET( .sort((a, b) => b.createdAt.localeCompare(a.createdAt)) .slice(0, 5); - return NextResponse.json({ + return jsonNoStore({ ok: true, projectId, threadStatusDocument, diff --git a/src/app/api/v1/threads/[threadId]/context-budget/route.ts b/src/app/api/v1/threads/[threadId]/context-budget/route.ts index 4774b1b..9a2018a 100644 --- a/src/app/api/v1/threads/[threadId]/context-budget/route.ts +++ b/src/app/api/v1/threads/[threadId]/context-budget/route.ts @@ -1,7 +1,8 @@ -import { NextRequest, NextResponse } from "next/server"; +import { NextRequest } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { getThreadContextDetailView } from "@/lib/boss-projections"; import { readState } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET( request: NextRequest, @@ -9,15 +10,15 @@ export async function GET( ) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const { threadId } = await context.params; const state = await readState(); const detail = getThreadContextDetailView(state, threadId); if (!detail) { - return NextResponse.json({ ok: false, message: "THREAD_NOT_FOUND" }, { status: 404 }); + return jsonNoStore({ ok: false, message: "THREAD_NOT_FOUND" }, { status: 404 }); } - return NextResponse.json({ ok: true, ...detail }); + return jsonNoStore({ ok: true, ...detail }); } diff --git a/src/app/api/v1/user/ota/route.ts b/src/app/api/v1/user/ota/route.ts index 949a9eb..116fcd6 100644 --- a/src/app/api/v1/user/ota/route.ts +++ b/src/app/api/v1/user/ota/route.ts @@ -1,14 +1,15 @@ import { NextRequest, NextResponse } from "next/server"; import { requireRequestSession } from "@/lib/boss-auth"; import { checkForOta, getOtaStatus, performOta } from "@/lib/boss-data"; +import { jsonNoStore } from "@/lib/api-response"; export async function GET(request: NextRequest) { const session = await requireRequestSession(request); if (!session) { - return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); + return jsonNoStore({ ok: false, message: "UNAUTHORIZED" }, { status: 401 }); } const status = await getOtaStatus(); - return NextResponse.json({ ok: true, ...status }); + return jsonNoStore({ ok: true, ...status }); } export async function POST(request: NextRequest) { diff --git a/tests/live-data-cache-headers.test.ts b/tests/live-data-cache-headers.test.ts index 5ce034f..b6ebce8 100644 --- a/tests/live-data-cache-headers.test.ts +++ b/tests/live-data-cache-headers.test.ts @@ -14,6 +14,21 @@ let getFolderRoute: (typeof import("../src/app/api/v1/conversation-folders/[fold let getProjectDetailRoute: (typeof import("../src/app/api/v1/projects/[projectId]/route"))["GET"]; let getDevicesRoute: (typeof import("../src/app/api/v1/devices/route"))["GET"]; let getSettingsRoute: (typeof import("../src/app/api/v1/settings/route"))["GET"]; +let getThreadStatusRoute: (typeof import("../src/app/api/v1/projects/[projectId]/thread-status/route"))["GET"]; +let getOpsSummaryRoute: (typeof import("../src/app/api/v1/ops/summary/route"))["GET"]; +let getAuditSummaryRoute: (typeof import("../src/app/api/v1/audits/summary/route"))["GET"]; +let getAppLogsRoute: (typeof import("../src/app/api/v1/app-logs/route"))["GET"]; +let getParticipantsRoute: (typeof import("../src/app/api/v1/projects/[projectId]/participants/route"))["GET"]; +let getDispatchPlansRoute: (typeof import("../src/app/api/v1/projects/[projectId]/dispatch-plans/route"))["GET"]; +let getAgentControlsRoute: (typeof import("../src/app/api/v1/projects/[projectId]/agent-controls/route"))["GET"]; +let getOrchestrationBackendRoute: (typeof import("../src/app/api/v1/projects/[projectId]/orchestration-backend/route"))["GET"]; +let getThreadContextBudgetRoute: (typeof import("../src/app/api/v1/threads/[threadId]/context-budget/route"))["GET"]; +let getAccountsRoute: (typeof import("../src/app/api/v1/accounts/route"))["GET"]; +let getOtaRoute: (typeof import("../src/app/api/v1/user/ota/route"))["GET"]; +let getDeviceSkillsRoute: (typeof import("../src/app/api/v1/devices/[deviceId]/skills/route"))["GET"]; +let getDeviceEnrollmentsRoute: (typeof import("../src/app/api/v1/devices/enrollments/route"))["GET"]; +let getPromptProfileRoute: (typeof import("../src/app/api/v1/projects/[projectId]/prompt-profile/route"))["GET"]; +let getProjectMemoriesRoute: (typeof import("../src/app/api/v1/projects/[projectId]/memories/route"))["GET"]; async function setup() { if (runtimeRoot) return; @@ -22,7 +37,31 @@ async function setup() { process.env.BOSS_RUNTIME_ROOT = runtimeRoot; process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json"); - const [homeRoute, conversationsRoute, folderRoute, projectRoute, devicesRoute, settingsRoute, dataModule, authModule] = + const [ + homeRoute, + conversationsRoute, + folderRoute, + projectRoute, + devicesRoute, + settingsRoute, + threadStatusRoute, + opsSummaryRoute, + auditSummaryRoute, + appLogsRoute, + participantsRoute, + dispatchPlansRoute, + agentControlsRoute, + orchestrationBackendRoute, + threadContextBudgetRoute, + accountsRoute, + otaRoute, + deviceSkillsRoute, + deviceEnrollmentsRoute, + promptProfileRoute, + projectMemoriesRoute, + dataModule, + authModule, + ] = await Promise.all([ import("../src/app/api/v1/conversations/home/route.ts"), import("../src/app/api/v1/conversations/route.ts"), @@ -30,6 +69,21 @@ async function setup() { import("../src/app/api/v1/projects/[projectId]/route.ts"), import("../src/app/api/v1/devices/route.ts"), import("../src/app/api/v1/settings/route.ts"), + import("../src/app/api/v1/projects/[projectId]/thread-status/route.ts"), + import("../src/app/api/v1/ops/summary/route.ts"), + import("../src/app/api/v1/audits/summary/route.ts"), + import("../src/app/api/v1/app-logs/route.ts"), + import("../src/app/api/v1/projects/[projectId]/participants/route.ts"), + import("../src/app/api/v1/projects/[projectId]/dispatch-plans/route.ts"), + import("../src/app/api/v1/projects/[projectId]/agent-controls/route.ts"), + import("../src/app/api/v1/projects/[projectId]/orchestration-backend/route.ts"), + import("../src/app/api/v1/threads/[threadId]/context-budget/route.ts"), + import("../src/app/api/v1/accounts/route.ts"), + import("../src/app/api/v1/user/ota/route.ts"), + import("../src/app/api/v1/devices/[deviceId]/skills/route.ts"), + import("../src/app/api/v1/devices/enrollments/route.ts"), + import("../src/app/api/v1/projects/[projectId]/prompt-profile/route.ts"), + import("../src/app/api/v1/projects/[projectId]/memories/route.ts"), import("../src/lib/boss-data.ts"), import("../src/lib/boss-auth.ts"), ]); @@ -40,6 +94,21 @@ async function setup() { getProjectDetailRoute = projectRoute.GET; getDevicesRoute = devicesRoute.GET; getSettingsRoute = settingsRoute.GET; + getThreadStatusRoute = threadStatusRoute.GET; + getOpsSummaryRoute = opsSummaryRoute.GET; + getAuditSummaryRoute = auditSummaryRoute.GET; + getAppLogsRoute = appLogsRoute.GET; + getParticipantsRoute = participantsRoute.GET; + getDispatchPlansRoute = dispatchPlansRoute.GET; + getAgentControlsRoute = agentControlsRoute.GET; + getOrchestrationBackendRoute = orchestrationBackendRoute.GET; + getThreadContextBudgetRoute = threadContextBudgetRoute.GET; + getAccountsRoute = accountsRoute.GET; + getOtaRoute = otaRoute.GET; + getDeviceSkillsRoute = deviceSkillsRoute.GET; + getDeviceEnrollmentsRoute = deviceEnrollmentsRoute.GET; + getPromptProfileRoute = promptProfileRoute.GET; + getProjectMemoriesRoute = projectMemoriesRoute.GET; createAuthSession = dataModule.createAuthSession; AUTH_SESSION_COOKIE = authModule.AUTH_SESSION_COOKIE; } @@ -105,3 +174,91 @@ test("live conversation and device routes disable cache storage", async () => { ); assertNoStoreHeader(settingsResponse); }); + +test("live detail and summary routes disable cache storage", async () => { + await setup(); + + const threadStatusResponse = await getThreadStatusRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/projects/master-agent/thread-status"), + { params: Promise.resolve({ projectId: "master-agent" }) }, + ); + assertNoStoreHeader(threadStatusResponse); + + const opsSummaryResponse = await getOpsSummaryRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/ops/summary"), + ); + assertNoStoreHeader(opsSummaryResponse); + + const auditSummaryResponse = await getAuditSummaryRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/audits/summary"), + ); + assertNoStoreHeader(auditSummaryResponse); + + const appLogsResponse = await getAppLogsRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/app-logs?limit=10"), + ); + assertNoStoreHeader(appLogsResponse); + + const participantsResponse = await getParticipantsRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/projects/audit-collab/participants"), + { params: Promise.resolve({ projectId: "audit-collab" }) }, + ); + assertNoStoreHeader(participantsResponse); + + const dispatchPlansResponse = await getDispatchPlansRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/projects/audit-collab/dispatch-plans"), + { params: Promise.resolve({ projectId: "audit-collab" }) }, + ); + assertNoStoreHeader(dispatchPlansResponse); + + const agentControlsResponse = await getAgentControlsRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/projects/master-agent/agent-controls"), + { params: Promise.resolve({ projectId: "master-agent" }) }, + ); + assertNoStoreHeader(agentControlsResponse); + + const orchestrationBackendResponse = await getOrchestrationBackendRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/projects/audit-collab/orchestration-backend"), + { params: Promise.resolve({ projectId: "audit-collab" }) }, + ); + assertNoStoreHeader(orchestrationBackendResponse); + + const threadContextBudgetResponse = await getThreadContextBudgetRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/threads/thread-audit-chief/context-budget"), + { params: Promise.resolve({ threadId: "thread-audit-chief" }) }, + ); + assertNoStoreHeader(threadContextBudgetResponse); + + const accountsResponse = await getAccountsRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/accounts"), + ); + assertNoStoreHeader(accountsResponse); + + const otaResponse = await getOtaRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/user/ota"), + ); + assertNoStoreHeader(otaResponse); + + const deviceSkillsResponse = await getDeviceSkillsRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/devices/mac-studio/skills"), + { params: Promise.resolve({ deviceId: "mac-studio" }) }, + ); + assertNoStoreHeader(deviceSkillsResponse); + + const deviceEnrollmentsResponse = await getDeviceEnrollmentsRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/devices/enrollments"), + ); + assertNoStoreHeader(deviceEnrollmentsResponse); + + const promptProfileResponse = await getPromptProfileRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/projects/master-agent/prompt-profile"), + { params: Promise.resolve({ projectId: "master-agent" }) }, + ); + assertNoStoreHeader(promptProfileResponse); + + const projectMemoriesResponse = await getProjectMemoriesRoute( + await createAuthedRequest("http://127.0.0.1:3000/api/v1/projects/master-agent/memories"), + { params: Promise.resolve({ projectId: "master-agent" }) }, + ); + assertNoStoreHeader(projectMemoriesResponse); +});