mirror of
https://github.com/morluto/rea.git
synced 2026-10-27 01:45:32 +00:00
chore: merge environment state serve (6b8db198) into environment state writes
This branch already refuses a loaded state that data/get would write past the intake limit, with the size kept incrementally, so its store is kept; the serving branch's test and docs come along. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
fc403d98d4
3 files changed
+50
-3
No files matched your search
@@ -488,8 +488,10 @@ within 30 seconds, including reading the body; `mimeType`, when given, is
|
||||
`application/json`. A `file://` URL naming another host, or a UNC path such as
|
||||
`file:////server/share/state.json`, is refused before anything is opened, so a
|
||||
load never reaches a network share. A loaded document is at most 32
|
||||
MiB; an inline part also stays within the 4 MiB request body bound, so larger
|
||||
states arrive by `uri`. Anything else, including `{"parts": []}`, is `-32602
|
||||
MiB, and so is the state as `data/get` writes it back with the members a
|
||||
document may omit (`types`, `state_evidence_id`, record citations), so a
|
||||
reported state always loads again; an inline part also stays within the 4 MiB
|
||||
request body bound, so larger states arrive by `uri`. Anything else, including `{"parts": []}`, is `-32602
|
||||
invalid params`; a download that fails or answers a non-2xx status is
|
||||
`-32000`. Errors never echo the uri or the content; a file or download failure
|
||||
names its category in `error.data.reason`: `not-found`, `permission`,
|
||||
|
||||
@@ -77,7 +77,9 @@ this increment: write tools are not served from the state.
|
||||
`mimeType` when given is `application/json`) and `data/get` (`{parts:
|
||||
[{kind: "data", data: rea_state}]}`). A `file://` uri whose host is neither
|
||||
empty nor `localhost`, or whose path is a UNC path, is `-32602` before
|
||||
anything is opened. Anything else is `-32602`, including empty `parts`; a
|
||||
anything is opened. A document that `data/get` would write back past 32 MiB,
|
||||
once it adds the members a document may omit, is `-32602`, so a reported
|
||||
state always loads again. Anything else is `-32602`, including empty `parts`; a
|
||||
failed download is `-32000`; errors never echo a uri or content and name a
|
||||
coarse failure category in `error.data.reason`. Calls run one at a time in
|
||||
arrival order across requests; every message of a batch is queued when the
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
loadEnvironmentState,
|
||||
prepareServedState,
|
||||
} from "./environmentState.js";
|
||||
import { STATE_INTAKE_LIMIT_BYTES } from "./environmentStateDocument.js";
|
||||
import { EnvironmentStateStore } from "./environmentStateStore.js";
|
||||
|
||||
const fixture = environmentStateServeFixture();
|
||||
@@ -373,6 +374,48 @@ describe("EnvironmentStateStore", () => {
|
||||
expect(refused.ok).toBe(false);
|
||||
expect(store.snapshot()).toEqual(before);
|
||||
});
|
||||
|
||||
it("refuses a document that data/get would write back past what data/add loads", () => {
|
||||
const store = new EnvironmentStateStore(state);
|
||||
const { rea_state: held } = store.snapshot();
|
||||
// Without the members data/get adds back, the document fits only until they return.
|
||||
const document = {
|
||||
rea_state: {
|
||||
version: held.version,
|
||||
entities: held.entities.map(({ type, collection, id, fields }) => ({
|
||||
type,
|
||||
collection,
|
||||
id,
|
||||
fields: { ...fields },
|
||||
})),
|
||||
documents: held.documents,
|
||||
},
|
||||
};
|
||||
const entity = document.rea_state.entities[0]!;
|
||||
const { fields } = entity;
|
||||
const idField = state.types.find(
|
||||
(type) => type.collection_template === entity.type,
|
||||
)?.id_field;
|
||||
const text = Object.keys(fields).find(
|
||||
(field) => field !== idField && typeof fields[field] === "string",
|
||||
)!;
|
||||
fields[text] = `${String(fields[text])}${"a".repeat(
|
||||
STATE_INTAKE_LIMIT_BYTES -
|
||||
Buffer.byteLength(JSON.stringify(document), "utf8"),
|
||||
)}`;
|
||||
expect(Buffer.byteLength(JSON.stringify(document), "utf8")).toBe(
|
||||
STATE_INTAKE_LIMIT_BYTES,
|
||||
);
|
||||
const before = store.snapshot();
|
||||
const replaced = store.replace(document);
|
||||
expect(!replaced.ok && replaced.error.issues).toEqual([
|
||||
expect.objectContaining({
|
||||
reason: "out_of_range",
|
||||
maximum: STATE_INTAKE_LIMIT_BYTES,
|
||||
}),
|
||||
]);
|
||||
expect(store.snapshot()).toEqual(before);
|
||||
});
|
||||
});
|
||||
|
||||
describe("rea-state/v1 validation", () => {
|
||||
|
||||
Reference in new issue
Block a user