fix: complete state-contract naming cleanup
This commit is contained in:
@@ -700,15 +700,14 @@ Deno.test("Memory changes preserve server order without interpreting opaque iden
|
||||
assertEquals(parseSubjektivMemoryReadResponse({ ...detailFixture(), change_id: "z/earlier", current_change_id: "a/current" }).change_id, "z/earlier");
|
||||
});
|
||||
|
||||
Deno.test("Memory identities reject numeric counters, empty and oversized strings, and legacy fields", () => {
|
||||
Deno.test("Memory identities reject numeric counters, empty and oversized strings, and unknown fields", () => {
|
||||
for (const value of [3, "", "x".repeat(513)]) {
|
||||
assertThrows(() => parseSubjektivMemoryReadResponse({ ...detailFixture(), change_id: value }), "bounded identifier");
|
||||
assertThrows(() => parseSubjektivMemoryReadResponse({ ...detailFixture(), current_change_id: value }), "bounded identifier");
|
||||
assertThrows(() => parseSubjektivSubjectResponse({ ...subject(), memory_fingerprint: value }), "bounded identifier");
|
||||
}
|
||||
assertThrows(() => parseSubjektivMemoryReadResponse({ ...detailFixture(), revision: 2 }), "unknown field");
|
||||
assertThrows(() => parseSubjektivSubjectResponse({ ...subject(), behavior_revision: 2 }), "unknown field");
|
||||
assertThrows(() => parseSubjektivSubjectResponse({ ...subject(), store_revision: 12 }), "unknown field");
|
||||
assertThrows(() => parseSubjektivMemoryReadResponse({ ...detailFixture(), unexpected_field: true }), "unknown field");
|
||||
assertThrows(() => parseSubjektivSubjectResponse({ ...subject(), unexpected_field: true }), "unknown field");
|
||||
});
|
||||
|
||||
Deno.test("Behavior CAS sends the observed text byte-for-byte including empty content", async () => {
|
||||
|
||||
@@ -93,6 +93,19 @@ Deno.test("profile settings requests use scoped API and strictly validate respon
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("profile source byte counts accept nonnegative safe integers and reject missing or malformed values", () => {
|
||||
for (const sizeBytes of [0, 128, Number.MAX_SAFE_INTEGER]) {
|
||||
const value = profileSettingsFixture();
|
||||
(value.sources as Record<string, unknown>[])[0].size_bytes = sizeBytes;
|
||||
assertEquals(parseProfileSettingsResponse(value).sources[0].size_bytes, sizeBytes);
|
||||
}
|
||||
for (const sizeBytes of [undefined, null, -1, 1.5, Number.MAX_SAFE_INTEGER + 1, "128"]) {
|
||||
const value = profileSettingsFixture();
|
||||
(value.sources as Record<string, unknown>[])[0].size_bytes = sizeBytes;
|
||||
assertThrows(() => parseProfileSettingsResponse(value), ProfileApiError);
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("workspace metadata requests use generated DTO shapes", async () => {
|
||||
const originalFetch = globalThis.fetch;
|
||||
const requests: Array<{ url: string; init?: RequestInit }> = [];
|
||||
@@ -247,8 +260,7 @@ Deno.test("Workspace signing identity parser validates active and pending public
|
||||
value.private_material_ref = "must-not-be-accepted";
|
||||
},
|
||||
(value: Record<string, unknown>) => {
|
||||
(value.identity as Record<string, unknown>).revision =
|
||||
Number.MAX_SAFE_INTEGER + 1;
|
||||
(value.identity as Record<string, unknown>).unexpected_field = true;
|
||||
},
|
||||
(value: Record<string, unknown>) => {
|
||||
(value.identity as Record<string, unknown>).public_key = "x".repeat(
|
||||
@@ -287,7 +299,7 @@ Deno.test("workspace metadata parser rejects incomplete or stale response fields
|
||||
workspace_id: "workspace-test",
|
||||
display_name: "Workspace",
|
||||
created_at: "2026-01-01T00:00:00Z",
|
||||
revision: "sha256:metadata",
|
||||
updated_at: "2026-01-02T00:00:00Z",
|
||||
source: "workspace-config",
|
||||
diagnostics: [],
|
||||
workspace_path: "/legacy/path",
|
||||
|
||||
@@ -199,10 +199,10 @@ Deno.test("Runtime validators reject unknown object keys and enum variants", ()
|
||||
});
|
||||
|
||||
Deno.test("Runtime validators reject invalid binding identities and bounded collection overflow", () => {
|
||||
const unsafeRevision = structuredClone(detail());
|
||||
Object.assign(unsafeRevision.trust_key, { binding_id: 1 });
|
||||
const invalidBinding = structuredClone(detail());
|
||||
Object.assign(invalidBinding.trust_key, { binding_id: 1 });
|
||||
assertThrows(
|
||||
() => parseWorkspaceRuntimeDetail(unsafeRevision),
|
||||
() => parseWorkspaceRuntimeDetail(invalidBinding),
|
||||
"must be a string",
|
||||
);
|
||||
|
||||
@@ -506,11 +506,11 @@ Deno.test("Runtime trust replacement preserves binding conflicts without retryin
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("Runtime trust replacement rejects legacy counter conflict responses", async () => {
|
||||
Deno.test("Runtime trust replacement rejects unknown fields and missing binding identity in conflict responses", async () => {
|
||||
const fetchImpl = (() => Promise.resolve(Response.json({
|
||||
error: "stale_binding",
|
||||
message: "Stale trust",
|
||||
current_revision: 3,
|
||||
unexpected_field: true,
|
||||
}, { status: 409 }))) as typeof fetch;
|
||||
try {
|
||||
await createRemoteRuntime("workspace-a", {
|
||||
|
||||
@@ -161,11 +161,11 @@ Deno.test("Skill parser fails closed on unknown fields and newer enum values", (
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("Skill parser rejects removed revision fields and oversized collections or strings", () => {
|
||||
const legacyRevision = catalogFixture();
|
||||
(legacyRevision.projection as Record<string, unknown>).config_revision = 1;
|
||||
Deno.test("Skill parser rejects unknown projection fields and oversized collections or strings", () => {
|
||||
const legacyCounter = catalogFixture();
|
||||
(legacyCounter.projection as Record<string, unknown>).unexpected_field = 1;
|
||||
assertContractError(
|
||||
() => parseSkillCatalogResponse(legacyRevision),
|
||||
() => parseSkillCatalogResponse(legacyCounter),
|
||||
"unknown fields",
|
||||
);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ Deno.test("workspace creation rejects missing and malformed repository response
|
||||
for (
|
||||
const value of [undefined, false, {}, {
|
||||
...currentInitialRepository,
|
||||
source_revision: -1,
|
||||
source_fingerprint: -1,
|
||||
}]
|
||||
) {
|
||||
assertThrows(
|
||||
@@ -152,13 +152,13 @@ Deno.test("stale repository aliases fail closed at the JSON boundary", () => {
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("repository JSON rejects removed source revision counters", () => {
|
||||
Deno.test("repository JSON rejects unknown fields", () => {
|
||||
const stale = structuredClone(repositoryList) as Record<string, unknown>;
|
||||
const items = stale.items as Array<Record<string, unknown>>;
|
||||
items[0].source_revision = 1;
|
||||
items[0].unexpected_field = 1;
|
||||
assertThrows(
|
||||
() => parseRepositoryListResponse(stale),
|
||||
".source_revision is not part of the wire contract",
|
||||
".unexpected_field is not part of the wire contract",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -322,6 +322,21 @@ Deno.test("Workspace deletion DTOs fail closed and preserve durable operation st
|
||||
}),
|
||||
"unexpected is not part",
|
||||
);
|
||||
assertThrows(
|
||||
() =>
|
||||
parseWorkspaceDeletionPreflightResponse({
|
||||
...preflight,
|
||||
expected_workspace_updated_at: "x".repeat(129),
|
||||
}),
|
||||
".expected_workspace_updated_at is too long",
|
||||
);
|
||||
for (const parse of [parseWorkspaceDeletionPreflightResponse, parseWorkspaceDeletionOperationResponse]) {
|
||||
const value = parse === parseWorkspaceDeletionPreflightResponse ? preflight : operation;
|
||||
assertThrows(
|
||||
() => parse({ ...value, blockers: [{ ...operation.blockers[0], kind: "unknown_blocker" }] }),
|
||||
".kind is invalid",
|
||||
);
|
||||
}
|
||||
assertThrows(
|
||||
() =>
|
||||
parseWorkspaceDeletionOperationResponse({
|
||||
|
||||
Reference in New Issue
Block a user