Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/27346-data-engine-rpc-retirement-wording.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@objectstack/spec': patch
---

docs(spec): the Virtual ObjectQL retirement's D3 reason says which request arms admitted a caller-supplied `context`

Clause-②: no
Metadata-protocol: none

Supersedes, in the same release, one sentence of the `feat(spec)!: retire the unserved Virtual ObjectQL request protocol from data/data-engine.zod.ts` note: "every arm admitted a caller-supplied `context` (`isSystem` included)". The corrected wording is: every read and write arm (`find`, `findOne`, `insert`, `update`, `delete`, `count`, `aggregate`) admitted a caller-supplied `context` (`isSystem` included). The `execute` arm carried an untyped options record rather than a `context` key, and the `vectorFind` arm had no `context` at all. The D3 semantic entry `data-engine-rpc-protocol-retired` carries the same correction, so `os migrate meta` and the upgrade guide read it. The `strictReadonlyWrites` docblock on `WriteObservabilityOptions` no longer names the retired "Virtual Data Engine" boundary: the option cannot be serialized and is not reachable from a REST/wire body. No schema, export or runtime behaviour changes.
4 changes: 2 additions & 2 deletions content/docs/protocol/objectql/security.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,8 @@ which the engine computes on every read and no driver has a column for, is dropp
every write in every context, `isSystem` included. The vocabulary is
open — it grows as the write path gains legal strips — so branch on `reason`
exhaustively rather than treating "not `readonly_when`" as "read-only". The listener is an in-process
callback: it is delivered by the local engine, and does **not** cross the RPC / Virtual
Data Engine boundary, so a remote caller never receives these events. Without a listener,
callback: it is delivered by the local engine, it cannot be serialized, and no REST/wire
body reaches it, so a remote caller never receives these events. Without a listener,
the only trace is a server-side `WARN` naming the object, the field, and both remedies.

---
Expand Down
2 changes: 1 addition & 1 deletion docs/audits/2026-07-unknown-key-strictness-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ column does not move and the `strip` column falls by the count of what left.
| File | Class | Note |
|---|---|---|
| `object.zod.ts` | authorable | top-level already guarded (#1535); **all 14 inner blocks strict** — 13 at 批 20, and the held 14th (`IndexSchema`) closed 2026-08-16 once its hold's evidence was spent: the hold was the #5114 class caught pre-ship (objectui's `FALLBACK_SCHEMAS.index` had drifted, offering `where`/`brin`, and the editor PUT the whole object through `saveMetaItem`), gated on the objectui rename (#5247) and an ADR-0049 answer for `type`/`partial` (#5248). #5248 answered remove (PR #5842, `retiredKey` tombstones + protocol-17 migration); **objectui#4772 then converged the editor to the declared `name`/`fields`/`unique` surface**, so the close shipped with a curated `where` guidance entry (database-layer prescription — deliberately NOT a rename onto the retired `partial` tombstone, which would be finding 7) and per-key pins that the tombstones' own prescriptions survive the strict path. Semantic entry `object-index-unknown-keys-refused` (protocol 18). The file's row left the remaining-strip map by reaching zero; the hold's full history is preserved in that map's section prose and in `object-strictness-batch20.test.ts` §4, which flipped from pinning the strip to pinning the close |
| `data-engine.zod.ts` | wire (p) | engine contract shapes (was 14 — `DataEngineBatchRequestSchema` retired with `IDataEngine.batch?`, #4618) |
| `data-engine.zod.ts` | wire (p) | engine contract shapes (was 14 — `DataEngineBatchRequestSchema` retired with `IDataEngine.batch?`, #4618; ten more sites — `DataEngineRequestSchema` and its nine arms — retired with the Virtual ObjectQL request protocol, #27028) |
| `seed-loader.zod.ts` | wire | **re-verdicted 2026-08-14 (#4001 batch D)** — the `(p)` split's "authored" half dissolved under measurement. The seed FILE shape this file's old note meant is `SeedSchema` (`seed.zod.ts`, a registered type, strict since the registered-types batch) — it enters this file only as the `seeds[]` VALUE inside `SeedLoaderRequestSchema`, so the authored half was never one of these 12 sites. Every producer of the request/config halves is framework code, enumerated: `runtime/app-plugin.ts` ×3 (org replay / inline seed / hot-reload), `runtime/domains/packages.ts`, `metadata-protocol/protocol.ts` `applySeedBodies`, `metadata-protocol/seed-loader.ts` `validate()`, `cloud-connection` marketplace install — all `.parse()`/`.safeParse()` over config LITERALS written in code; no `defineStack` key, no metadata type, no Studio form, no CLI flag writes a loader config. `SeedIdentity` is server-constructed by design (`execution-context.zod.ts`: "never client-supplied"); graph/resolution/result/error shapes are built by the loader itself (`buildDependencyGraph`, `buildResult`). BFS from all 26 metadata-type roots + `ObjectStackSchema` (6689 nodes; `ObjectSchema` positive control REACHABLE, fresh uncarried shape negative control UNREACHABLE, synthetic-carrier flip green, same run): all 12 UNREACHABLE. Same class as `data-engine.zod.ts` — an internal service contract (`ISeedLoaderService`), machine-fed at every door |
| `field.zod.ts` | authorable | partially strict |
| `filter.zod.ts` | open | query dialect — user data flows through the predicate values; validated semantically elsewhere |
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/src/contracts/data-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ export interface WriteObservabilityOptions {
*
* This is an IN-PROCESS option, exactly like its neighbour above, and for the
* same structural reason: `WriteObservabilityOptions` is not the serializable
* `EngineUpdateOptionsSchema` bag, so nothing here crosses the RPC / Virtual
* Data Engine boundary or is reachable from a REST/wire body. A remote caller
* `EngineUpdateOptionsSchema` bag, so nothing here can be serialized, and
* none of it is reachable from a REST/wire body. A remote caller
* cannot set it, and gets NEITHER behaviour: its write is stripped and
* committed, silently from its side, exactly as before this option existed —
* a 200 whose read-only columns kept their stored values. That is deliberate
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/src/data/data-engine.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1343,8 +1343,8 @@ export type QueryWithTransportParsed = z.infer<typeof QueryWithTransportSchema>;
// `ctx.api.object(name).find(...)` and parses no request schema; the wire batch
// validates with `CrossObjectBatchRequestSchema` / `BatchUpdateRequestSchema`
// from `../api/batch.zod.ts`. As published the protocol was also unsafe to
// implement: every arm admitted a caller-supplied `context` (`isSystem`
// included), and `execute` carried a raw driver command. Its private helpers
// implement: every read and write arm admitted a caller-supplied `context`
// (`isSystem` included), and `execute` carried a raw driver command. Its private helpers
// (`RpcQueryOptionsSchema` and the `filter`-only fold) went with it;
// `RPC_QUERY_ALIAS_SLOTS` above stays, since the transport dialect and the
// engine fold by it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export const entry: SemanticMigration = {
+ 'against controls of 311, 2095 and 74 files importing `@objectstack/spec`. The one real '
+ 'boundary engine calls cross, the QuickJS hook and action sandbox, speaks '
+ '`ctx.api.object(name)` and parses no request schema. As published the protocol was also '
+ 'unsafe to implement: every arm admitted a caller-supplied `context` (`isSystem` included) '
+ 'unsafe to implement: every read and write arm admitted a caller-supplied `context` '
+ '(`isSystem` included) '
+ 'and the `execute` arm carried a raw driver command, so enforcing it would first have '
+ 'meant narrowing it and building a second data door beside REST, batch, MCP and the '
+ 'sandbox. `DataEngineContractSchema` restated the engine methods as `z.function()` '
Expand Down
Loading