Files
Hare c78f7f7d80 feat: replace revision counters with domain state contracts
Use content digests, key fingerprints, binding and trust identities, immutable mutation receipts, and observation tokens instead of state-update ordinals across API, storage, Runtime, and Web contracts.

Preserve historical replay and secret material through frozen migrations; preflight uncertain removals before cutover, resume provisioning receipts, validate encrypted migration candidates, and align fresh/upgraded schemas. Include reviewed regression fixes, generated artifacts, and validation evidence.
2026-10-10 15:55:20 +09:00

141 lines
5.9 KiB
TypeScript

import { assert, assertEquals, assertRejects } from "@std/assert";
import { createDriveFixture, fixtureRootId } from "../../../../tools/web-ux/drive-fixture/api.ts";
import { createDriveClient, DriveRequestError } from "../../src/lib/workspace/drive/api.ts";
function setup() {
const fixture = createDriveFixture();
const fetchFixture: typeof fetch = async (input, init) => {
const request = new Request(new URL(String(input), "http://127.0.0.1"), init);
const response = await fixture.handler(request);
if (!response) throw new Error(`Unimplemented fixture ${request.url}`);
return response;
};
return { fixture, client: createDriveClient(fetchFixture), fetchFixture };
}
const ref = (workspace_id: string, node_id: string) => ({ workspace_id, node_id });
Deno.test("browser fixture preserves decimal identity, bounded reads, binary and page cursors", async () => {
const { client, fetchFixture } = setup();
const root = await client.root("drive-paged");
assertEquals(root.entry.node_id, fixtureRootId);
const first = await client.list("drive-paged", root.entry, { limit: 100 });
const second = await client.list("drive-paged", root.entry, {
limit: 100,
after: first.next_after,
});
assertEquals(first.entries.length, 100);
assertEquals(second.entries.length, 100);
assert(
!second.entries.some((entry) =>
first.entries.some((other) => other.entry.node_id === entry.entry.node_id)
),
);
const text = await client.readText("drive-paged", ref("drive-paged", "9"));
assertEquals(text.truncated, true);
assert(new TextEncoder().encode(text.text).length <= 65536);
const image = await client.metadata("drive-paged", ref("drive-paged", "5"));
const imageBytes = await client.image("drive-paged", image);
assertEquals(imageBytes.size, image.size);
assert(imageBytes.size < 256 * 1024);
const png = new Uint8Array(await imageBytes.arrayBuffer());
const dimensions = new DataView(png.buffer);
assertEquals([dimensions.getUint32(16), dimensions.getUint32(20)], [1200, 800]);
const escapedWire = await fetchFixture(
"/api/w/drive-paged/drive/read-text?entry_workspace_id=drive-paged&id=11&max_bytes=65536",
);
const escapedLength = (await escapedWire.arrayBuffer()).byteLength;
assert(escapedLength > 256 * 1024 && escapedLength < 512 * 1024);
const escaped = await client.readText("drive-paged", ref("drive-paged", "11"));
assertEquals(escaped.text, "\u0000".repeat(65536));
assertEquals(escaped.truncated, false);
});
Deno.test("browser fixture two last_mutation_ids conflict without committing the losing request", async () => {
const { client } = setup();
const entry = await client.metadata("home-owner", ref("home-owner", "3"));
await client.mutate("home-owner", "tab-one", {
operation: "update_text",
id: entry.entry,
expected_mutation_id: entry.last_mutation_id,
text: "first actor",
content_type: "text/markdown",
});
const failure = await assertRejects(
() =>
client.mutate("home-owner", "tab-two", {
operation: "update_text",
id: entry.entry,
expected_mutation_id: entry.last_mutation_id,
text: "second actor draft",
content_type: "text/markdown",
}),
DriveRequestError,
);
assertEquals((failure as DriveRequestError).code, "conflict");
assertEquals((await client.status("home-owner", "tab-one")).state, "committed");
assertEquals((await client.status("home-owner", "tab-two")).state, "uncommitted");
assertEquals((await client.readText("home-owner", entry.entry)).text, "first actor");
});
Deno.test("browser fixture upload unknown is reconciled by receipt and denied writes never commit", async () => {
const { client, fetchFixture } = setup();
await fetchFixture("/__fixture/fault", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ workspace: "home-owner", mode: "unknown" }),
});
const root = await client.root("home-owner");
const failure = await assertRejects(
() =>
client.upload("home-owner", "upload-one", new Blob(["upload bytes"]), {
operation: "create",
parent: root.entry,
name: "upload.txt",
content_type: "text/plain",
}),
DriveRequestError,
);
assertEquals((failure as DriveRequestError).code, "outcome_unknown");
assertEquals((await client.status("home-owner", "upload-one")).state, "committed");
const memberRoot = await client.root("home-member");
const denied = await assertRejects(
() =>
client.mutate("home-member", "member-one", {
operation: "create_folder",
parent: memberRoot.entry,
name: "denied",
}),
DriveRequestError,
);
assertEquals((denied as DriveRequestError).code, "denied");
assertEquals((await client.status("home-member", "member-one")).state, "uncommitted");
});
Deno.test("browser fixture rename and move retain identity while delete and recreate do not reuse links", async () => {
const { client } = setup();
let entry = await client.metadata("home-owner", ref("home-owner", "3"));
const latest = entry.latest_url;
const moved = await client.mutate("home-owner", "move", {
operation: "relocate",
id: entry.entry,
expected_mutation_id: entry.last_mutation_id,
parent: ref("home-owner", "2"),
name: "renamed.md",
});
entry = moved.entry!;
assertEquals(entry.latest_url, latest);
await client.mutate("home-owner", "delete", {
operation: "delete",
id: entry.entry,
expected_mutation_id: entry.last_mutation_id,
});
const replacement = await client.mutate("home-owner", "recreate", {
operation: "create_text",
parent: ref("home-owner", "2"),
name: "renamed.md",
text: "new entity",
content_type: "text/markdown",
});
assert(replacement.entry!.entry.node_id !== entry.entry.node_id);
const missing = await assertRejects(
() => client.metadata("home-owner", entry.entry),
DriveRequestError,
);
assertEquals((missing as DriveRequestError).code, "not_found");
});