mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
test(daemon): add regression tests for headerless /raw/ reads of workspace-bound projects (#7206)
* test(daemon): add regression tests for headerless raw reads of workspace-bound projects Closes #7072. The /raw/ and /preview/ routes call authorizeProjectRequest with { mode: 'read', allowNavigationQuery: true }. Before the enforceLocalProjectDataPlaneRequest refactor, these routes delegated to enforceVerifiedWorkspaceResourceRead, which required an explicit workspace context for any workspace-bound project and returned WORKSPACE_CONTEXT_REQUIRED (400) when headers were absent — breaking local/desktop preview iframes and MCP preview URLs for projects with a personal workspace_projects binding. The two new test cases pin the corrected behaviour: a headerless request to authorizeProjectRequest with allowNavigationQuery: true must succeed (return true, not call any remote verifier) for both personal and team workspace-bound projects, matching exactly what an iframe src or a bare loopback fetch sends. * chore: retrigger CI after flaky workspace-restoration P0 * chore: retrigger CI after repeated workspace-restoration flake
This commit is contained in:
@@ -691,4 +691,78 @@ describe('createAuthorizeProjectRequest', () => {
|
||||
expect.any(String),
|
||||
);
|
||||
});
|
||||
|
||||
// Regression for https://github.com/nexu-io/open-design/issues/7072:
|
||||
// A personal project with a stale or valid workspace_projects binding must
|
||||
// be readable without workspace headers when the caller supplies no
|
||||
// workspace context at all (e.g. an iframe src, MCP preview URL, or bare
|
||||
// loopback fetch). The /raw/ and /preview/ routes call authorizeProjectRequest
|
||||
// with { mode: 'read', allowNavigationQuery: true }; returning
|
||||
// WORKSPACE_CONTEXT_REQUIRED for these headerless loopback reads broke
|
||||
// desktop preview for local-only personal projects.
|
||||
it('allows a headerless iframe raw read of a personal workspace-bound project', async () => {
|
||||
const row = {
|
||||
workspaceId: 'workspace-a',
|
||||
visibility: 'personal',
|
||||
resourceState: 'active',
|
||||
createdByWorkspaceMemberId: 'member-a',
|
||||
syncState: 'local_only',
|
||||
};
|
||||
const verify = vi.fn(async () => ({
|
||||
ok: false as const,
|
||||
status: 400 as const,
|
||||
code: 'WORKSPACE_CONTEXT_REQUIRED',
|
||||
message: 'an explicit workspace context is required',
|
||||
}));
|
||||
const sendApiError = vi.fn();
|
||||
const authorize = createAuthorizeProjectRequest({
|
||||
db: {},
|
||||
getWorkspaceProject: () => row,
|
||||
getWorkspaceProjectByProjectId: () => row,
|
||||
verifyWorkspaceRequestAuthority: verify,
|
||||
sendApiError,
|
||||
});
|
||||
|
||||
await expect(authorize(
|
||||
request({}),
|
||||
response(),
|
||||
'project-a',
|
||||
{ mode: 'read', allowNavigationQuery: true },
|
||||
)).resolves.toBe(true);
|
||||
expect(verify).not.toHaveBeenCalled();
|
||||
expect(sendApiError).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('allows a headerless iframe raw read of a team workspace-bound project', async () => {
|
||||
const row = {
|
||||
workspaceId: 'workspace-a',
|
||||
visibility: 'team',
|
||||
resourceState: 'active',
|
||||
createdByWorkspaceMemberId: 'member-a',
|
||||
syncState: 'local_only',
|
||||
};
|
||||
const verify = vi.fn(async () => ({
|
||||
ok: false as const,
|
||||
status: 400 as const,
|
||||
code: 'WORKSPACE_CONTEXT_REQUIRED',
|
||||
message: 'an explicit workspace context is required',
|
||||
}));
|
||||
const sendApiError = vi.fn();
|
||||
const authorize = createAuthorizeProjectRequest({
|
||||
db: {},
|
||||
getWorkspaceProject: () => row,
|
||||
getWorkspaceProjectByProjectId: () => row,
|
||||
verifyWorkspaceRequestAuthority: verify,
|
||||
sendApiError,
|
||||
});
|
||||
|
||||
await expect(authorize(
|
||||
request({}),
|
||||
response(),
|
||||
'project-a',
|
||||
{ mode: 'read', allowNavigationQuery: true },
|
||||
)).resolves.toBe(true);
|
||||
expect(verify).not.toHaveBeenCalled();
|
||||
expect(sendApiError).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user