New contracts/cultnet/cultnet.raw-document-header.schema.json for
CultNetRawDocumentHeader - it has no payload/payloadEncoding members at all,
so headers must not $ref the record schema (which required both). The
response page's own schema now lists every property CultNetSnapshotResponseRawV1Message
declares as `required` (present on the wire, nil included) rather than only
the four that happened to be non-nullable - MessagePack-CSharp's map-mode
formatter writes every declared key regardless of null, so `headers`/`documents`
are always both present, one an array and the other an explicit null by
projection. The old `oneOf: [{required:[headers]},{required:[documents]}]`
matched both branches on every real page (both keys present) and so never
validated anything; it is now `oneOf` over each key's type (array vs null),
which is mutually exclusive. cultnet.raw-document-record.schema.json gained
schemaName/schemaVersion/schemaContentHash (present on every real record, not
previously in the schema at all - any real page would have failed
additionalProperties:false on them). fieldPredicate's two oneOf branches each
gained `not: {required: [the other]}`, so `values` and `number` cannot both
be present (previously only `required` was checked, which does not exclude
the sibling key).
Added MiniJsonSchemaValidator, a deliberately small draft-2020-12 subset
validator (type/required/additionalProperties/properties/items/const/enum/
pattern/minLength/minItems/oneOf/$ref, same-document and cross-document) -
no schema-validation dependency existed in this repo, and this only needs to
cover what contracts/cultnet/*.schema.json actually use. CultNetSchemaContractTests
decodes real wire bytes from a live CultNetDatabaseServer (header projection,
document projection, and a hop with edges) through MessagePackSerializer.ConvertToJson
and checks them against the committed schema files, plus three
fieldPredicate-shape tests pinning the values/number exclusivity.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
59 lines
2.7 KiB
JSON
59 lines
2.7 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://github.com/GameCult/CultLib/contracts/cultnet/cultnet.snapshot-response-raw.v1.schema.json",
|
|
"title": "CultNet Snapshot Response Raw Message v1",
|
|
"description": "R-S (docs/cultnet-selection-cut.md, fix batch 3): matches MessagePack-CSharp's map-mode output for CultNetSnapshotResponseRawV1Message - every declared key is written, nil included, so every property is `required` (present on the wire) even where its value may be null. `headers`/`documents` are still exactly one populated by projection (C5), but the OTHER key is present too, as an explicit null, not absent - the prior `oneOf: [{required:[headers]},{required:[documents]}]` matched both branches on every real page (both keys always present) and so never validated at all.",
|
|
"type": "object",
|
|
"required": [
|
|
"schemaVersion", "messageId", "matched", "asOf", "next",
|
|
"headers", "documents", "edges", "shardId", "shardEpoch", "shardLogSequence"
|
|
],
|
|
"additionalProperties": false,
|
|
"oneOf": [
|
|
{
|
|
"required": ["headers", "documents"],
|
|
"properties": { "headers": { "type": "array" }, "documents": { "type": "null" } }
|
|
},
|
|
{
|
|
"required": ["headers", "documents"],
|
|
"properties": { "headers": { "type": "null" }, "documents": { "type": "array" } }
|
|
}
|
|
],
|
|
"properties": {
|
|
"schemaVersion": { "const": "cultnet.snapshot_response_raw.v1" },
|
|
"messageId": { "type": "string", "minLength": 1 },
|
|
"matched": { "type": "integer", "minimum": 0 },
|
|
"asOf": { "type": "integer", "minimum": 0 },
|
|
"next": { "type": ["string", "null"] },
|
|
"headers": {
|
|
"type": ["array", "null"],
|
|
"items": { "$ref": "cultnet.raw-document-header.schema.json" }
|
|
},
|
|
"documents": {
|
|
"type": ["array", "null"],
|
|
"items": { "$ref": "cultnet.raw-document-record.schema.json" }
|
|
},
|
|
"edges": {
|
|
"type": ["array", "null"],
|
|
"items": {
|
|
"type": "object",
|
|
"required": ["from", "role", "to", "payloadEncoding", "payload"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"from": { "$ref": "cultnet.selection.schema.json#/$defs/recordRef" },
|
|
"role": { "type": "string", "minLength": 1 },
|
|
"to": { "$ref": "cultnet.selection.schema.json#/$defs/recordRef" },
|
|
"payloadEncoding": { "type": ["string", "null"] },
|
|
"payload": {
|
|
"type": ["string", "null"],
|
|
"contentEncoding": "base64",
|
|
"x-cult-runtime-type": "bytes"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"shardId": { "type": ["string", "null"], "minLength": 1 },
|
|
"shardEpoch": { "type": ["integer", "null"] },
|
|
"shardLogSequence": { "type": ["integer", "null"] }
|
|
}
|
|
}
|