fix: harden bounded state sidecars
N-05: the conditional-validator key was a colon join over components that may themselves contain colons, so two distinct valid bindings could collide and one definition's ETag could be prepared for another. The key is now a validated, byte-bounded fixed tuple encoded with JSON.stringify. N-09: capture localStorage exactly once and compare StorageEvent.storageArea against that object identity, so a pulse from sessionStorage or any other area is rejected instead of matching on key and value alone. The pulse key is registered in the storage registry as CACHE_INVALIDATION_PULSE. N-10: race loadPage against the caller signal and re-check before observing a page, so a non-cooperative loader can neither hold loadAll forever nor have a post-abort completion accumulated into a successful result. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b893d95b36
commit
4fe924ee0f
@@ -12,6 +12,45 @@ const profile = {
|
||||
} as const;
|
||||
|
||||
describe("bounded cursor pagination runtime", () => {
|
||||
it("returns PAGINATION_ABORTED when a non-cooperative page resolves after abort", async () => {
|
||||
const controller = new AbortController();
|
||||
let releasePage: ((page: unknown) => void) | undefined;
|
||||
const loadPage = vi.fn(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
releasePage = resolve as (page: unknown) => void;
|
||||
}),
|
||||
);
|
||||
const runtime = createCursorPaginationRuntime({
|
||||
definitionId: "bounded",
|
||||
profile,
|
||||
loadPage: loadPage as never,
|
||||
});
|
||||
|
||||
const loading = runtime.loadAll({ signal: controller.signal });
|
||||
await Promise.resolve();
|
||||
controller.abort();
|
||||
|
||||
const result = await loading;
|
||||
expect(result).toMatchObject({
|
||||
ok: false,
|
||||
error: { kind: "REQUEST_ABORTED", code: "PAGINATION_ABORTED" },
|
||||
});
|
||||
|
||||
// The late page completion must be ignored, not accumulated.
|
||||
releasePage?.({
|
||||
ok: true,
|
||||
value: {
|
||||
items: ["late"],
|
||||
nextCursor: null,
|
||||
hasMore: false,
|
||||
snapshotToken: "snapshot-1",
|
||||
},
|
||||
});
|
||||
await Promise.resolve();
|
||||
expect(loadPage).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("loads a stable finite chain without exposing cursors in its value", async () => {
|
||||
const loadPage = vi
|
||||
.fn()
|
||||
|
||||
Reference in New Issue
Block a user