feat(workspace): allow creation without an initial repository
Keep bootstrap, signing identity, config and resource-key allocation atomic with optional Repository intent. Preserve repository-present fingerprints for saved receipts; replay reads current authority at the initial key and never recreates missing assets. Provide explicit repository-free CLI creation, optional TUI/Web creation inputs, nullable generated contracts, and valid empty catalog/Worker paths. Retain existing authenticated non-owner viewing policy pending the T-717 authorization decision. Validation: root cargo check; server tests 639 lib + 11 bin; server-api 70 default / 77 typescript; client 52 lib + 2 integration; tui 337; yoi 11 lib + 120 bin. OpenAPI/TS freshness, cargo fmt and diff checks pass. Web check/build, 18 model tests, 268 component tests and Chromium 8 width/theme combinations pass; before/after visual evidence is documented in web/workspace/test/visual-review. Full Web suite has one independently reproduced baseline Ticket source-policy failure.
This commit is contained in:
@@ -8,12 +8,57 @@ import {
|
||||
parseRepositoryApiError,
|
||||
parseRepositoryListApiResult,
|
||||
parseRepositoryListResponse,
|
||||
parseWorkspaceCreateResponse,
|
||||
parseWorkspaceDeletionOperationResponse,
|
||||
parseWorkspaceDeletionPreflightResponse,
|
||||
parseWorkspaceResponse,
|
||||
REPOSITORY_API_LIMITS,
|
||||
} from "../src/lib/workspace/api/workspace-model.ts";
|
||||
|
||||
import {
|
||||
creationResponse,
|
||||
currentInitialRepository,
|
||||
} from "../src/lib/workspace/api/workspace-catalog.test-fixtures.ts";
|
||||
|
||||
Deno.test("workspace creation decodes absent and deleted initial repositories as explicit null", () => {
|
||||
for (const replayed of [false, true]) {
|
||||
const parsed = parseWorkspaceCreateResponse(
|
||||
JSON.parse(JSON.stringify(creationResponse(null, replayed))),
|
||||
);
|
||||
if (parsed.repository !== null || parsed.replayed !== replayed) {
|
||||
throw new Error("nullable creation response was not preserved");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("workspace creation replay preserves the returned current repository record", () => {
|
||||
const parsed = parseWorkspaceCreateResponse(
|
||||
creationResponse(currentInitialRepository, true),
|
||||
);
|
||||
if (
|
||||
JSON.stringify(parsed.repository) !==
|
||||
JSON.stringify(currentInitialRepository)
|
||||
) throw new Error("current repository record was replaced or lost");
|
||||
});
|
||||
|
||||
Deno.test("workspace creation rejects missing and malformed repository response fields", () => {
|
||||
for (
|
||||
const value of [undefined, false, {}, {
|
||||
...currentInitialRepository,
|
||||
source_revision: -1,
|
||||
}]
|
||||
) {
|
||||
assertThrows(
|
||||
() =>
|
||||
parseWorkspaceCreateResponse({
|
||||
...creationResponse(),
|
||||
repository: value,
|
||||
}),
|
||||
"workspace create response.repository",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
function assertThrows(operation: () => unknown, expected: string): void {
|
||||
try {
|
||||
operation();
|
||||
|
||||
Reference in New Issue
Block a user