fix(server): restrict state bundle exports to board

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-08-14 08:29:24 +00:00
1 parent 37dcfe48a4
commit 3560194146
2 files changed
+17 -2

No files matched your search

+16 -2
View File
@@ -9,11 +9,16 @@ vi.mock("../services/activity-log.js", () => ({ logActivity: mockLogActivity }))
const mockRemotes = vi.hoisted(() => ({ get: vi.fn(), set: vi.fn(), clear: vi.fn() }));
vi.mock("../services/state-repo-remote.js", () => ({ stateRepoRemoteService: () => mockRemotes }));
function createApp(service: Record<string, ReturnType<typeof vi.fn>>) {
function createApp(
service: Record<string, ReturnType<typeof vi.fn>>,
actorType: "board" | "agent" = "board",
) {
const app = express();
app.use(express.json());
app.use((req, _res, next) => {
req.actor = { type: "board", userId: "board-user", source: "local_implicit" };
req.actor = actorType === "board"
? { type: "board", userId: "board-user", source: "local_implicit" }
: { type: "agent", agentId: "agent-1", companyId: "company-1" };
next();
});
app.use("/api", stateRepoRoutes({} as never, service as never, "/tmp"));
@@ -66,6 +71,15 @@ describe("state repo routes", () => {
expect(service.health).toHaveBeenCalledWith("company-1");
});
it("rejects agent credentials before exporting a company state bundle", async () => {
const service = { exportBundle: vi.fn() };
const response = await request(createApp(service, "agent"))
.get("/api/companies/company-1/state-repo/bundle");
expect(response.status).toBe(403);
expect(service.exportBundle).not.toHaveBeenCalled();
});
it("tests the configured mirror", async () => {
const service = {
testMirror: vi.fn().mockResolvedValue(undefined),
+1
View File
@@ -87,6 +87,7 @@ export function stateRepoRoutes(db: Db, service: StateRepoService, markerDir: st
router.get("/companies/:companyId/state-repo/bundle", async (req, res) => {
const companyId = req.params.companyId as string;
assertBoard(req);
assertCompanyAccess(req, companyId);
await fs.mkdir(markerDir, { recursive: true });
const outputPath = path.join(markerDir, `state-repo-${companyId}-${Date.now()}.bundle`);