mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
docs(chord): schemas are pi-schema's in the design
Some checks are pending
CI / build-check (push) Waiting to run
CI / test (coding-agent) (push) Waiting to run
CI / test (durable) (push) Waiting to run
CI / test (other) (push) Waiting to run
CI / mcp-conformance (push) Waiting to run
Environments / daemons (push) Waiting to run
Environments / check (push) Blocked by required conditions
Environments / release-daemons (darwin-arm64, macos-latest) (push) Blocked by required conditions
Environments / release-daemons (darwin-x64, macos-latest) (push) Blocked by required conditions
Environments / release-daemons (linux-arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
Environments / release-daemons (linux-x64, ubuntu-latest) (push) Blocked by required conditions
Environments / release-daemons (windows-arm64, windows-11-arm) (push) Blocked by required conditions
Environments / release-daemons (windows-x64, windows-latest) (push) Blocked by required conditions
Environments / tests (macos-latest) (push) Waiting to run
Environments / tests (ubuntu-24.04-arm) (push) Waiting to run
Environments / tests (ubuntu-latest) (push) Waiting to run
Environments / tests (windows-11-arm) (push) Waiting to run
Environments / tests (windows-latest) (push) Waiting to run
Some checks are pending
CI / build-check (push) Waiting to run
CI / test (coding-agent) (push) Waiting to run
CI / test (durable) (push) Waiting to run
CI / test (other) (push) Waiting to run
CI / mcp-conformance (push) Waiting to run
Environments / daemons (push) Waiting to run
Environments / check (push) Blocked by required conditions
Environments / release-daemons (darwin-arm64, macos-latest) (push) Blocked by required conditions
Environments / release-daemons (darwin-x64, macos-latest) (push) Blocked by required conditions
Environments / release-daemons (linux-arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
Environments / release-daemons (linux-x64, ubuntu-latest) (push) Blocked by required conditions
Environments / release-daemons (windows-arm64, windows-11-arm) (push) Blocked by required conditions
Environments / release-daemons (windows-x64, windows-latest) (push) Blocked by required conditions
Environments / tests (macos-latest) (push) Waiting to run
Environments / tests (ubuntu-24.04-arm) (push) Waiting to run
Environments / tests (ubuntu-latest) (push) Waiting to run
Environments / tests (windows-11-arm) (push) Waiting to run
Environments / tests (windows-latest) (push) Waiting to run
This commit is contained in:
parent
c09c98d7d2
commit
b556cfe5b0
4 changed files with 10 additions and 13 deletions
|
|
@ -442,7 +442,8 @@ drops, folds or resets.
|
|||
- **JSON plus `Uint8Array` leaves**, with a bytes schema type, defined independently of the transport. Every link
|
||||
carries the same `Message` through its codec (section 22); parts are encoded at their origin; byte segments travel
|
||||
raw, never base64. Same-host calls (no link) pass values by reference.
|
||||
- Schemas are TypeBox and must describe data (no callbacks, no native types, no runtime codecs). Method arguments are
|
||||
- Schemas are plain JSON Schema built with `@earendil-works/pi-schema` (decision "The schema switch") and must
|
||||
describe data (no callbacks, no native types, no runtime codecs); `format` is an annotation, never checked. Method arguments are
|
||||
validated at the provider for every caller against closed schemas (section 5, R7, Q12, Q15); results and state are
|
||||
never validated (section 30). Values are immutable by convention once handed over (Delta's rule): nobody mutates a
|
||||
value it got, and nothing is copied or frozen to enforce it. There is no development mode (R9): one behavior
|
||||
|
|
@ -572,7 +573,7 @@ host.serve(Notes, ({ session }, principal, self) =>
|
|||
(`invalid/member` outside it).
|
||||
- **Params** (owner, 2026-10-21/22): a flat record of required fields, each `str()`, `int()`, `bool()` or `oneOf(...)`
|
||||
of string literals, constraints allowed (`str({ pattern })`, `int({ min: 0 })`); no defaults, optional, nested or
|
||||
unknown fields. Checked for every caller with one compiled closed-object TypeBox check (a missing or extra field
|
||||
unknown fields. Checked for every caller with one compiled closed-object pi-schema check (a missing or extra field
|
||||
fails `invalid/params`). The identity key is the field values in declared order, each escaped, joined with `|`.
|
||||
Params are never copied or frozen: the object keeps the caller's object, immutable by convention.
|
||||
- **Arguments (R7, Q12, Q15):** always validated with the provider's schema, whoever the caller is (trusted code is
|
||||
|
|
@ -592,8 +593,8 @@ host.serve(Notes, ({ session }, principal, self) =>
|
|||
link protocol (adding one bumps the protocol version; a receiver rejects unknown reasons; a test pins the list):
|
||||
`invalid` (`args`, `params`, `member`, `host_address`, `reentrant`, `read_after_bulk`, `cycle`), `contract_mismatch`
|
||||
(`updating`), `forbidden` (`revoked`), `gone`, `not_ready`, `released` (`ended`, `closed`, `settled`, `version`, `discarded`; none for a holder's own release), `too_large` (`part`), `unavailable` (`locked`,
|
||||
`park_timeout`, `busy`, `storage_failed`, `undeclared`: a registry no plugin serves here, slice 8), `aborted`. A failed check names TypeBox's instance path ("unknown field", "missing", else TypeBox's
|
||||
message; keys containing `/` or `~` make the path ambiguous, documented). Plugins throw `PluginError(code, message,
|
||||
`park_timeout`, `busy`, `storage_failed`, `undeclared`: a registry no plugin serves here, slice 8), `aborted`. A failed check names pi-schema's JSON Pointer path ("unknown field", "missing", else
|
||||
pi-schema's message; `~` and `/` in keys escaped as `~0`, `~1`). Plugins throw `PluginError(code, message,
|
||||
details?)` for codes of their own; anything else crosses a link as the plugin code `internal` with its message, never
|
||||
a stack or a cause; plugin errors never use Chord's codes. An error rebuilt from the wire is not copied and only its
|
||||
envelope is checked; a malformed envelope is a protocol error.
|
||||
|
|
@ -1997,7 +1998,7 @@ validation, no clone of snapshots or ops.
|
|||
- **The protocol version** travels in `hello`; hosts of different versions refuse each other (a web page reloads for
|
||||
a newer server). Error reasons and message kinds are part of it. Until p3 ships, changes keep `PROTOCOL_VERSION` 1
|
||||
(nothing is deployed); after that every message or reason change bumps it.
|
||||
- **One typed `Message`** (owner, 2026-10-22, "Wire protocol"): a TypeBox schema `MESSAGE`, a tagged union over
|
||||
- **One typed `Message`** (owner, 2026-10-22, "Wire protocol"): a pi-schema schema `MESSAGE`, a tagged union over
|
||||
`kind`, from which the protocol types derive; every decoded message is checked against it (compiled once) unless
|
||||
the link is trusted (section 3). Kinds:
|
||||
|
||||
|
|
@ -2416,7 +2417,7 @@ const accepted = checkAccepts(NotesV2, {
|
|||
providers fail at declaration naming the member; unknown keys and wrong shapes are rejected.
|
||||
- **The fingerprint** is a hash (`hash64`, portable, not a security boundary) of a schema-aware, data-only normal form
|
||||
(`NORMAL_FORM_VERSION`, tied to the protocol): annotations dropped only on schema nodes, `required`/`enum` sorted,
|
||||
union and intersection order kept (it is meaning: defaults), a whitelist of TypeBox keywords, executable features
|
||||
union and intersection order kept (it is meaning: defaults), a whitelist of JSON Schema keywords, executable features
|
||||
rejected; bytes are a `{ type: "bytes" }` data marker. Schemas are deep-copied into a private history (never frozen; immutable by convention).
|
||||
- **Schema helpers:** `str num int bool nul lit oneOf union obj arr map opt bytes unknown` and `type Static`.
|
||||
- Chord wraps state mappings as a derive and diffs per object and version (section 22); members an old consumer does not know do
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ checked, what a principal key is, what an error is. Pure functions, types and we
|
|||
Source: `packages/chord/src/next/contracts/` (declarations) and `packages/chord/src/next/data/` (per-call checks,
|
||||
principals, errors), split into files by concept. Everything else under `src/next/` is the frozen old kernel: never
|
||||
imported, never edited. Reused: `src/context/` (`Context`, `BACKGROUND_CONTEXT`, `context.telemetry`) and
|
||||
`src/json.ts` (`JsonValue`), both unchanged. Schemas are TypeBox 1.3 (`typebox` in `node_modules`).
|
||||
`src/json.ts` (`JsonValue`), both unchanged. Schemas were TypeBox 1.3 when L1 was built; since the schema switch (2026-11-01) they are pi-schema's plain JSON Schema (design §3 "Values"). The TypeBox details below are historical.
|
||||
|
||||
## 1. Values
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ if (notes.variant === "reader") console.log(notes.notes.value); // narrowed by
|
|||
| u32 header length, big-endian | header JSON (UTF-8) | part 0 | part 1 | … |
|
||||
```
|
||||
|
||||
- **One format on every link.** The header is a JSON object, a tagged union over `kind`, defined as a TypeBox schema;
|
||||
- **One format on every link.** The header is a JSON object, a tagged union over `kind`, defined as a schema (TypeBox then, pi-schema since the schema switch);
|
||||
every received header is checked with the compiled schema (the wire is a trust boundary; skipping it on trusted IPC
|
||||
links comes with IPC in slice 4). The header lists its parts: `parts: [{ json, bytes }]`, the JSON text's byte length and
|
||||
the byte lengths of the segments that follow it (`bytes: []` for state parts and arguments without bytes).
|
||||
|
|
@ -125,7 +125,7 @@ if (notes.variant === "reader") console.log(notes.notes.value); // narrowed by
|
|||
Replaces the JSON-header framing of section 2 (`| u32 header length | header JSON | parts |`); the message kinds, ids,
|
||||
races and rules of section 2 stay.
|
||||
|
||||
- **`Message`** is a tagged union defined once as a TypeBox schema (`MESSAGE`; `type Message = Static<typeof
|
||||
- **`Message`** is a tagged union defined once as a schema (TypeBox then, pi-schema since the schema switch) (`MESSAGE`; `type Message = Static<typeof
|
||||
MESSAGE>`): `hello { protocol, incarnation }`, `hold { hold, type, version, fingerprint, params }`, `release { hold
|
||||
}`, `call { call, hold, method, args? }`, `cancel { call }`, `bound { hold, variant, members: [{ member, value }],
|
||||
failed: [{ member, error }] }`, `state { holds: [{ hold, members: [{ member, ops }], failed: [...] }] }`, `failed {
|
||||
|
|
|
|||
|
|
@ -170,15 +170,11 @@ deleted (the slice's spec and code are the record). Moved here from `carry-over.
|
|||
slice 3b.)
|
||||
- **The park deadline's per-type override** is not built: a parked call waits the reference's `readyTimeout`. Build
|
||||
it only if a real case needs it. (Slice 3b spec.)
|
||||
- Failed-check paths are TypeBox's instance paths (ambiguous for keys containing `/` or `~`); documented, not fixed.
|
||||
(L1.)
|
||||
- No CBOR; revisit only if benchmarks show encoding as a bottleneck (slice 3a's and 4a's do not). (L2 decisions.)
|
||||
- **One N on every host:** a relay forwards calls at once, so a worker announcing a smaller N than the relay's could
|
||||
see more running calls of one origin than it accepts (a protocol error). Every host announces 256; per-link N, if
|
||||
ever needed, must bound the relay's forwarding too. (Slice 4a rework.)
|
||||
- **The Durable conversation view's size on re-hold** is a known cost until pi #11327 (windowed view) lands. (Slice 4.)
|
||||
- **`map(bytes())` is refused at declaration** ("unsupported keyword `~refine`"): TypeBox's `Record` copies the bytes
|
||||
schema's check as an enumerable key, which the snapshot walk refuses. An L1 bug found in slice 3a, not fixed yet.
|
||||
|
||||
### Later: reload (when a case needs it)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue