Track HiveGrid Cloud planning reference

This commit is contained in:
david committed 2026-06-26 20:48:01 +02:00
1 parent b3d5ea6764
commit e341c5938a
5784 files changed
+1104929 -3

No files matched your search

@@ -0,0 +1,97 @@
import { describe, expect, it, vi } from "vitest";
import {
createDeniedIsolationError,
expectJsonResponse,
expectStatusLog,
isolationAdminSession,
isolationAdminUser,
isolationApiKeyLogA,
isolationApiKeyLogB,
isolationInactiveApiKey,
isolationInactiveApiKeyLog,
isolationInvalidBearerToken,
isolationRevokedBearerSession,
isolationTenantA,
isolationTenantARelationship,
isolationTenantARow,
isolationTenantB,
isolationTenantBRelationship,
isolationTenantBRow,
makeAdminHostGetRequest,
makeInactiveApiKeyGetRequest,
makeInvalidBearerSessionGetRequest,
makeRevokedBearerSessionGetRequest,
makeTenantASessionJsonRequest,
resetIsolationMocks,
type IsolationMocks,
} from "./user-session-isolation";
describe("user-session isolation fixtures", () => {
it("keeps tenant A and tenant B rows and relationships distinct", () => {
expect(isolationTenantARow.tenantId).toBe(isolationTenantA.id);
expect(isolationTenantBRow.tenantId).toBe(isolationTenantB.id);
expect(isolationTenantARow.tenantId).not.toBe(isolationTenantBRow.tenantId);
expect(isolationTenantARelationship.parent.item.tenantId).toBe(isolationTenantA.id);
expect(isolationTenantBRelationship.parent.item.tenantId).toBe(isolationTenantB.id);
});
it("keeps admin fixtures tenant-neutral and cross-tenant capable", () => {
expect(isolationAdminUser.tenantId).toBe(null);
expect(isolationAdminSession.tenantId).toBe(null);
expect(isolationAdminSession.isSuperAdmin).toBe(true);
expect(isolationAdminSession.canAccessTenants).toEqual([isolationTenantA.id, isolationTenantB.id]);
});
it("keeps inactive API-key fixtures distinct from active tenant keys", () => {
expect(isolationInactiveApiKey.active).toBe(false);
expect(isolationInactiveApiKey.id).toBe(isolationInactiveApiKeyLog.apiKeyId);
expect(isolationInactiveApiKeyLog.id).not.toBe(isolationApiKeyLogA.id);
expect(isolationInactiveApiKeyLog.id).not.toBe(isolationApiKeyLogB.id);
expect(isolationInactiveApiKeyLog.apiKeyId).not.toBe(isolationApiKeyLogA.apiKeyId);
expect(isolationInactiveApiKeyLog.apiKeyId).not.toBe(isolationApiKeyLogB.apiKeyId);
});
it("builds tenant/session JSON requests and parses JSON responses", async () => {
const request = makeTenantASessionJsonRequest("POST", "/api/parents", { name: "Tenant A" });
expect(request.method).toBe("POST");
expect(request.url).toBe("https://example.test/api/parents");
await expect(request.json()).resolves.toEqual({ name: "Tenant A" });
const body = await expectJsonResponse<{ ok: true }>(Response.json({ ok: true }, { status: 201, headers: { "Server-Timing": "unit" } }), 201);
expect(body).toEqual({ ok: true });
});
it("builds admin-host and revoked credential requests with synthetic headers", () => {
const adminRequest = makeAdminHostGetRequest("/api-keys/logs");
const inactiveApiKeyRequest = makeInactiveApiKeyGetRequest("/api/parents");
const revokedBearerRequest = makeRevokedBearerSessionGetRequest("/api/parents");
const invalidBearerRequest = makeInvalidBearerSessionGetRequest("/api/parents");
expect(adminRequest.url).toBe("https://admin.example.test/api-keys/logs");
expect(inactiveApiKeyRequest.headers.get("Authorization")).toBe(`Bearer ${isolationInactiveApiKey.key}`);
expect(revokedBearerRequest.headers.get("Cookie")).toBe(`session=${isolationRevokedBearerSession.token}`);
expect(invalidBearerRequest.headers.get("Cookie")).toBe(`session=${isolationInvalidBearerToken}`);
expect(isolationRevokedBearerSession.token).not.toBe(isolationInvalidBearerToken);
});
it("resets shared mocks and supports denied access status assertions", async () => {
const mocks = {
createMetrics: vi.fn(),
getTranslations: vi.fn(),
setApiKeyLogStatus: vi.fn(),
reportUsage: vi.fn(),
} satisfies IsolationMocks;
resetIsolationMocks(mocks);
const metrics = (await mocks.createMetrics()) as { getServerTimingHeader: () => Record<string, string> };
const deniedError = createDeniedIsolationError("API Key does not have access to tenant B row", 403, isolationApiKeyLogA);
await mocks.setApiKeyLogStatus(isolationApiKeyLogA.id, { status: deniedError.status, error: deniedError.message, startTime: performance.now() });
expect(metrics.getServerTimingHeader()).toEqual({ "Server-Timing": "unit;dur=1" });
await expect(mocks.getTranslations()).resolves.toEqual({ t: expect.any(Function) });
expectStatusLog(mocks.setApiKeyLogStatus, isolationApiKeyLogA.id, 403, deniedError.message);
});
});
@@ -0,0 +1,299 @@
type MockFunction = {
(...args: unknown[]): unknown;
mockResolvedValue(value: unknown): MockFunction;
};
declare const expect: {
(actual: unknown): {
toBe(expected: unknown): void;
toBeTruthy(): void;
toHaveBeenCalledWith(...expected: unknown[]): void;
};
any(constructor: unknown): unknown;
objectContaining(value: Record<string, unknown>): unknown;
};
declare const vi: {
fn(implementation?: (...args: unknown[]) => unknown): MockFunction;
clearAllMocks(): void;
resetModules(): void;
};
export const isolationTenantA = {
id: "tenant_session_iso_a",
name: "Tenant Session Isolation A",
slug: "tenant-session-isolation-a",
};
export const isolationTenantB = {
id: "tenant_session_iso_b",
name: "Tenant Session Isolation B",
slug: "tenant-session-isolation-b",
};
export const isolationUserA = {
id: "user_session_iso_a",
email: "user-a@example.test",
tenantId: isolationTenantA.id,
};
export const isolationUserB = {
id: "user_session_iso_b",
email: "user-b@example.test",
tenantId: isolationTenantB.id,
};
export const isolationAdminUser = {
id: "user_session_iso_admin",
email: "admin@example.test",
tenantId: null,
admin: true,
};
export const isolationAdminSession = {
userId: isolationAdminUser.id,
tenantId: null,
isSuperAdmin: true,
canAccessTenants: [isolationTenantA.id, isolationTenantB.id],
};
export const isolationApiKeyLogA = {
id: "api_key_log_session_iso_a",
apiKeyId: "api_key_session_iso_a",
};
export const isolationApiKeyLogB = {
id: "api_key_log_session_iso_b",
apiKeyId: "api_key_session_iso_b",
};
export const isolationInactiveApiKeyLog = {
id: "api_key_log_session_iso_inactive",
apiKeyId: "api_key_session_iso_inactive",
};
export const isolationInactiveApiKey = {
id: isolationInactiveApiKeyLog.apiKeyId,
key: "sk_test_session_iso_inactive",
tenantId: isolationTenantA.id,
active: false,
};
export const isolationRevokedBearerSession = {
id: "session_session_iso_revoked",
userId: isolationUserA.id,
tenantId: isolationTenantA.id,
token: "bearer_session_iso_revoked",
revokedAt: "2024-01-01T00:00:00.000Z",
};
export const isolationInvalidBearerToken = "bearer_session_iso_invalid";
export const isolationTiming = {
startTime: 1_700_000_000_000,
serverTiming: "unit;dur=1",
};
export const isolationParentEntity = {
id: "entity_session_iso_parent",
name: "Parent",
slug: "parents",
title: "Parent",
titlePlural: "Parents",
properties: [],
};
export const isolationChildEntity = {
id: "entity_session_iso_child",
name: "Child",
slug: "children",
title: "Child",
titlePlural: "Children",
properties: [],
};
export const isolationTenantARow = {
id: "row_session_iso_a",
entityId: isolationParentEntity.id,
tenantId: isolationTenantA.id,
createdByUserId: isolationUserA.id,
values: [{ name: "name", textValue: "Tenant A row" }],
};
export const isolationTenantBRow = {
id: "row_session_iso_b",
entityId: isolationParentEntity.id,
tenantId: isolationTenantB.id,
createdByUserId: isolationUserB.id,
values: [{ name: "name", textValue: "Tenant B row" }],
};
export const isolationTenantAChildRow = {
id: "row_session_iso_a_child",
entityId: isolationChildEntity.id,
tenantId: isolationTenantA.id,
createdByUserId: isolationUserA.id,
values: [{ name: "name", textValue: "Tenant A child row" }],
};
export const isolationTenantBChildRow = {
id: "row_session_iso_b_child",
entityId: isolationChildEntity.id,
tenantId: isolationTenantB.id,
createdByUserId: isolationUserB.id,
values: [{ name: "name", textValue: "Tenant B child row" }],
};
export const isolationTenantARelationship = {
id: "relationship_session_iso_a",
parentId: isolationTenantARow.id,
childId: isolationTenantAChildRow.id,
tenantId: isolationTenantA.id,
parent: { entity: isolationParentEntity, item: isolationTenantARow },
child: { entity: isolationChildEntity, item: isolationTenantAChildRow },
};
export const isolationTenantBRelationship = {
id: "relationship_session_iso_b",
parentId: isolationTenantBRow.id,
childId: isolationTenantBChildRow.id,
tenantId: isolationTenantB.id,
parent: { entity: isolationParentEntity, item: isolationTenantBRow },
child: { entity: isolationChildEntity, item: isolationTenantBChildRow },
};
export const isolationUsage = {
title: "api.usage",
value: 50,
remaining: 10,
};
export const isolationAccessTenantASession = {
tenant: isolationTenantA,
userId: isolationUserA.id,
entity: isolationParentEntity,
apiKeyLog: isolationApiKeyLogA,
usage: isolationUsage,
};
export const isolationAccessTenantBSession = {
tenant: isolationTenantB,
userId: isolationUserB.id,
entity: isolationParentEntity,
apiKeyLog: isolationApiKeyLogB,
usage: isolationUsage,
};
export const isolationRelationshipAccessTenantASession = {
tenant: isolationTenantA,
userId: isolationUserA.id,
apiKeyLog: isolationApiKeyLogA,
parentRow: isolationTenantARow,
childRow: isolationTenantAChildRow,
};
export const isolationRelationshipAccessTenantBSession = {
tenant: isolationTenantB,
userId: isolationUserB.id,
apiKeyLog: isolationApiKeyLogB,
parentRow: isolationTenantBRow,
childRow: isolationTenantBChildRow,
};
export type IsolationMocks = {
createMetrics: ReturnType<typeof vi.fn>;
getTranslations: ReturnType<typeof vi.fn>;
setApiKeyLogStatus: ReturnType<typeof vi.fn>;
reportUsage: ReturnType<typeof vi.fn>;
};
export function makeJsonRequest(method: string, url: string, body?: unknown): Request {
return new Request(url, {
method,
body: body === undefined ? undefined : JSON.stringify(body),
headers: body === undefined ? undefined : { "Content-Type": "application/json" },
});
}
export function makeTenantASessionJsonRequest(method: string, path: string, body?: unknown): Request {
return makeJsonRequest(method, `https://example.test${path}`, body);
}
export function makeTenantBSessionJsonRequest(method: string, path: string, body?: unknown): Request {
return makeJsonRequest(method, `https://example.test${path}`, body);
}
export function makeGetRequest(path: string): Request {
return new Request(`https://example.test${path}`, { method: "GET" });
}
export function makeAdminHostGetRequest(path: string): Request {
return new Request(`https://admin.example.test${path}`, { method: "GET" });
}
export function makeApiKeyGetRequest(path: string, apiKey: string): Request {
return new Request(`https://example.test${path}`, {
method: "GET",
headers: { Authorization: `Bearer ${apiKey}` },
});
}
export function makeInactiveApiKeyGetRequest(path: string): Request {
return makeApiKeyGetRequest(path, isolationInactiveApiKey.key);
}
export function makeBearerSessionGetRequest(path: string, token: string): Request {
return new Request(`https://example.test${path}`, {
method: "GET",
headers: { Cookie: `session=${token}` },
});
}
export function makeRevokedBearerSessionGetRequest(path: string): Request {
return makeBearerSessionGetRequest(path, isolationRevokedBearerSession.token);
}
export function makeInvalidBearerSessionGetRequest(path: string): Request {
return makeBearerSessionGetRequest(path, isolationInvalidBearerToken);
}
export function makeTenantASessionGetRequest(path: string): Request {
return makeGetRequest(path);
}
export function makeTenantBSessionGetRequest(path: string): Request {
return makeGetRequest(path);
}
export async function expectJsonResponse<TBody = unknown>(response: Response, status: number): Promise<TBody> {
expect(response.status).toBe(status);
expect(response.headers.get("Server-Timing")).toBeTruthy();
return (await response.json()) as TBody;
}
export function expectStatusLog(setApiKeyLogStatus: ReturnType<typeof vi.fn>, logId: string, status: number, error?: string): void {
expect(setApiKeyLogStatus).toHaveBeenCalledWith(
logId,
expect.objectContaining({
status,
startTime: expect.any(Number),
...(error === undefined ? {} : { error }),
}),
);
}
export function createDeniedIsolationError(message: string, status = 403, apiKeyLog = isolationApiKeyLogA): Error & { status: number; apiKeyLog: typeof isolationApiKeyLogA } {
return Object.assign(new Error(message), { status, apiKeyLog });
}
export function resetIsolationMocks(mocks: IsolationMocks): void {
vi.clearAllMocks();
vi.resetModules();
mocks.createMetrics.mockResolvedValue({
time: vi.fn((value) => value),
getServerTimingHeader: () => ({ "Server-Timing": isolationTiming.serverTiming }),
});
mocks.getTranslations.mockResolvedValue({ t: (value: string) => value });
mocks.setApiKeyLogStatus.mockResolvedValue(undefined);
mocks.reportUsage.mockResolvedValue(undefined);
}