mirror of
https://github.com/THU-MAIC/OpenMAIC.git
synced 2026-10-02 01:15:18 +08:00
* feat(storage): RuntimeStore contract — interface + backend-agnostic suite (#869) * feat(storage): BrowserRuntimeStore — IndexedDB backend for the runtime layer (#869) * test(storage): runtime version-skew coverage; run the storage suite in CI (#869) Backend-specific tests seed raw session rows (mirroring the document backend's reStampStage) to cover the version-skew surface the public API cannot express: a stale stamp fails loud while the runtime ladder is empty, a future stamp reads through unchanged but rejects appendRecord and setSessionStatus, and a stamp-stripped row hits the no-unversioned-epoch guard. Also covers the injected payloadValidators override (the contract case deferred to the backend test, as document-contract does for scene validators). The @openmaic/storage suite — including the pre-existing DocumentStore / KV / asset contracts — never ran in CI at all; add the missing step after the dsl one. README gains the RuntimeStore section. * fix(storage): harden RuntimeStore writes and listings per cross-review (#869) - mergeLearner now takes the same gates as every other write: rejects empty learner keys, self-merges return 0 without a transaction, future-stamped rows throw (mutating a newer client's data), and every re-keyed envelope is validated before put — any throw aborts the whole merge atomically instead of contaminating the target partition. - listSessions sorts by the instant a timestamp denotes (Date.parse), not by string order, which mis-ranks numeric zone offsets; and it tolerates corrupt rows by omission (the listDocuments precedent) so one poison row cannot make a partition unenumerable — direct reads stay fail-loud. - appendRecord validates the ACTUAL completed record (with the assigned seq) inside the transaction, on top of the pre-flight, and derives seq from a key cursor's primaryKey instead of deserializing the previous record's payload. - Docstrings now enumerate the corrupt-stamp throw paths and no longer claim every query is partition-scoped (mergeLearner is the one deliberate cross-stage sweep). - The stale-row test comment no longer promises an impossible one-line flip; the IDBKeyRange shim moves to test/setup.ts alongside the other guarded shims. * fix(storage): mergeLearner migrates stale sessions before re-keying (#869) The re-key previously spread the RAW stored row, unlike setSessionStatus and appendRecord which migrate a stale session in place before mutating it. Once the runtime ladder gains a real step, that would either write an old runtimeDslVersion into the target partition or fail validation when a migration adds required fields. Build the updated row from migrateSession(row) instead (order: future-guard, migrate, re-key, validate, put). Observable today (empty ladder): a below-epoch stale row makes the merge abort with the ladder's no-migration-path error — pinned by a new backend test with nothing moved. * fix(storage): reads gate stored sessions through envelope validation (#869) Reads previously ran only version resolution, so a row with a valid runtimeDslVersion but corrupt other fields (a non-ISO createdAt, a bogus status) came back as-is — contradicting the documented corrupt-row semantics, which covered only version corruption. Extend the same policy to the whole envelope: getSession validates the migrated row and fails loud as a stored-row integrity error; listSessions omits rows whose envelope validation fails, exactly like version-resolution failures. setSessionStatus and appendRecord need no change: the status update validates the full post-update envelope before writing (catching corrupt non-status fields), and appendRecord's own writes are already validated.