Sashité for Developers
  1. Sashité for Developers
  2. Nostr
  3. NIPs
  4. Validation

NIP-XX

Validation

draft optional

This NIP defines a Nostr event kind by which a validator — any pubkey a consumer chooses to trust — publishes its verdict on one Composition (kind 3440): the certificate survives the mechanical check and realizes the stipulation the event carries, or it does not, for a stated reason. A valid verdict is the one signal an engine-free consumer can lean on, and it is the one that admits a Composition to the activity surfaces.

Abstract

Defines kind: 3441, a regular event signed by a validator, referencing the Composition it judges and naming its composer. content carries a single status token — one reserved value, valid, meaning the certificate checked out and realizes the stipulation; every other value a decline, for that reason. The event carries nothing else — no derived tags: under exact binding a valid verdict means that the certificate’s derived outcome and depth equal the Composition’s objective and moves, so any value published here would copy the stipulation one hop from where it is signed — a second copy that can only drift. The display statement is read off the Composition, which every consumer loads anyway as the substrate.

A Validation is reactive — it judges what already exists — and final for the (validator, Composition) pair. Its subject is parameter-free: the legality of a move and the exhaustiveness of a branch are rule-system facts, not authority policy, so two honest validators cannot durably disagree about anything except an advantage criterion.

Motivation

The check is mechanical and anyone can run it — so why an event at all? Three reasons, sharpened by the cheapness of the check. Engine-free consumers need a signature to lean on, and one string comparison against valid — the statement it confirms, objective and bound, already standing on the Composition they hold. Composers need a terminating answer with a reason they can act on: the position is illegal, a defence is missing, your certificate proves a mate in 3 and you stipulated 2 are answers a client can turn into a repair; a bare “declined” is not. And the network needs the check to be replayable: a validator’s verdict is a public claim any engine-holder can refute in linear time, which makes validator trust cheap to establish and cheap to withdraw.

Specification

Event kind

kind: 3441 — a regular event per NIP-01: immutable once signed and broadcast.

Signer — the validator

Any pubkey MAY act as a validator; consumers choose which to trust, exactly as they choose rating authorities. Several validators MAY judge the same Composition independently, and divergence — beyond advantage-criterion differences and outright error — is itself a public, checkable signal.

Validator discretion

A validator examines what it chooses — typically every Composition for the games it serves, discovered by kind subscription, or by a #p subscription on its own pubkey where composers address it (kind 3440 §Addressing validators). Being addressed binds nothing: the validator-marked p tag is a routing hint, so a named validator owes no answer and an unnamed one is not thereby disqualified from judging. A composer MAY name several validators on one Composition, so finding another validator’s name on a Composition is no reason to leave it alone. An unjudged Composition is unjudged, not invalid.

What a validator MUST NOT do is publish two contradictory verdicts for one Composition — the subject is immutable and the check parameter-free, so there is nothing for a second verdict to know that the first could not. Consumers resolve an equivocating validator deterministically, per the (validator, Composition) slot: on conflict, the canonical verdict is the one with the smallest established canonical timing, ties by smallest id (Canonical Timing §Meta-resolution). A verdict whose canonical timing cannot be established never wins a conflict; if neither conflicting verdict’s can be, the validator has no canonical verdict for that Composition — its voice is void there, which is equivocation’s own reward. A validator with a single verdict for a Composition needs no timing at all: an unopposed verdict is canonical as it stands.

Timing

Never attested, and belonging to no session: a Validation’s canonical timing follows the undesignated self-timed rule (Canonical Timing §Canonical timing of an event) — its own created_at, established by retrieval from a profile-conforming timing relay the consumer trusts. It is consumed only by the slot rule above, so it matters only under equivocation: a validator who intends its verdicts to prevail in any conflict SHOULD publish them via a strict timing relay; an honest, non-equivocating validator needs nothing.

Tags

Tag Cardinality Value Description
e composition exactly one event id, optional relay hint, marker composition the Composition (kind 3440) this verdict judges
p composer exactly one pubkey, optional relay hint, role marker composer the Composition’s signer — routes the verdict to them via one #p subscription
alt 0 or 1 human-readable string NIP-31 fallback (e.g. "A validated Sanki puzzle.")
L 0 or 1 a theme namespace NIP-32 label namespace, present only on valid (§Themes)
l 0..n a theme token, marked with that namespace one per theme the validator read in the certificate

There are deliberately no derived tags restating the stipulation. The walk derives the certificate’s outcome and depth all the same — they feed the two post-walk checks below — but on valid both equal, by those very checks, the judged Composition’s objective and moves: publishing them here would restate the stipulation — derivable data republished is drift waiting to happen — and the statement an engine-free consumer renders stands on the event it already loads. An engine-holding consumer MAY re-derive both quantities and drop a validator whose valid does not reproduce.

The theme labels are not an exception to that rule but its complement: they carry what the Composition does not already say. A stipulation states what the solver must achieve; a theme states how — the geometry, the tactical motif, the sacrifice — and nothing in kind 3440 encodes it.

Themes

A validator MAY label a valid Validation with the themes it read in the certificate: back-rank-mate, fork, deflection. Each is one NIP-32 label (l) marked with a theme namespace declared by a single L; the namespace, the token grammar and the vocabulary are the game’s business, fixed in its supporting document, never here. This NIP fixes only where themes live and what they are worth.

They live on the Validation and not on the Composition, and the reason is the whole point of putting them anywhere. A theme a composer declares is an unverifiable claim, useful for organizing and worth nothing for trusting; a theme a validator derives from the certificate is a reading of the same bytes everyone else can read, by a party a consumer already relies on for the verdict. A consumer filtering on themes is therefore filtering within what it already trusts — every event carrying a theme is, by construction, a valid verdict from a validator in its set — and no second trust decision is introduced by the feature.

Three limits, and they matter more than the mechanism:

Because they ride on the Validation, the labels are also replayable: any engine-holder can re-derive them from the Composition and see where a validator’s reading differs from theirs. A divergence is evidence about the two criteria, exactly as a divergent verdict is evidence about the two engines — with the difference that here, unlike there, both may be right.

Leaf classification

What makes a leaf achieved is the game’s binding, per its supporting document, which maps each reserved class to the game’s own terminal statuses; advantage is a non-terminal criterion the game MUST define deterministically, and a validator that has not published one answers unsupported. (The reference sanki binding is its supporting document, Puzzle Specification — Sanki §Leaf classification.) History-dependent draws — repetition, move limits — remain unrepresentable in a position-anchored certificate.

The stipulation check

The walk derives the certificate’s outcome — the weakest leaf class under the game’s outcome order (kind 3440 §Content) — and the verdict is valid only if that outcome equals the Composition’s stipulated objective. A sound certificate deriving anything else — weaker or stronger — is declined; game vocabularies SHOULD name this decline objective_mismatch, as the reference sanki vocabulary does.

Exactness in both directions is deliberate: the exercise is the composer’s, a mate certificate answers a different question than the draw that was posed, and republishing that answer under the stipulation it actually realizes costs exactly one event.

The depth check

One more comparison follows: the certificate’s derived depth MUST equal the Composition’s moves bound exactly. A sound certificate deriving any other depth — deeper or shallower — is declined; game vocabularies SHOULD name this decline depth_mismatch, the depth analogue of objective_mismatch, as the reference sanki vocabulary does.

The shallow direction is the one that earns the exactness: a “mate in 2” that admits a mate in 1 is a cooked problem — the composition tradition’s own verdict on a stipulation the position beats — and the family declines it by design rather than silently crediting the stronger answer, exactly as the stipulation check declines a stronger outcome. The two post-walk comparisons run in a fixed order — outcome against objective first, depth against moves second — and the first failure names the status (Puzzle Specification — Sanki §Canonical walk order, for the reference binding). Neither comparison is ever vacuous: a conforming Composition carries both tags exactly once (kind 3440 §Semantic constraints). The bound adds no parameter to verification, and the check stays linear and replayable.

Content

A single status token matching ^[a-z][a-z0-9_]{0,31}$. One token is reserved: valid. Every other token is a decline, and the vocabulary is game-defined, published in the game’s supporting document. A game’s vocabulary SHOULD name at least the failure classes this NIP’s verification model distinguishes — an undecodable position, an unreadable certificate, an illegal move, a missing defense, an unachieved leaf, the stipulation and depth mismatches (§The stipulation check, §The depth check), and the out-of-scope answer unsupported — so that a decline names what the composer repairs. The reference sanki vocabulary — eight decline tokens covering exactly these classes — is specified in its supporting document (Puzzle Specification — Sanki §Validation status vocabulary).

A consumer that recognizes nothing else still answers its user’s question — is this puzzle good — by one comparison against valid, and SHOULD surface unrecognized decline tokens verbatim.

There is no transient status, and none is possible: a validator judges an event it has retrieved, so the material can never be missing at the moment of the verdict. Republishing an identical Composition after a decline is therefore never the repair; every decline names something in the event to change. (The split family this kind once served carried an unavailable token for a Solution whose Problem could not be fetched; the merge removed the second event and the status with it — this suite’s Design Notes — Puzzles §What the merge deletes.)

A decline names a reason, never a value: depth_mismatch says that the bound is wrong, never which bound is right. This follows from carrying no derived tags, and it is deliberate — the value is a pure function of the certificate, which the composer holds. A repairing client re-derives it locally and proposes the correction; nothing is transported that the recipient does not already have.

Semantic constraints

A conforming Validation MUST satisfy all of the following:

  1. The e tag is present exactly once, carries the marker composition as its fourth element, and its value is a 64-character lowercase hex event id. The referenced event, once retrieved, MUST be a conforming Composition; a consumer that cannot retrieve it treats the Validation as unverified, never as non-conforming (retrievability is a fact about relays, not about the event).
  2. The p tag is present exactly once, carries the marker composer as its fourth element, and its pubkey equals the referenced Composition’s pubkey.
  3. The content matches ^[a-z][a-z0-9_]{0,31}$.
  4. If any l tag is present, exactly one L tag is present, every l carries that namespace as its third element, and the content is valid; conversely, an L tag is present only when at least one l tag is (a namespace declaring no labels is as contradictory as labels without a namespace). A verdict that declines carries no themes, so labels on one are a contradiction the event states about itself — and this is the only constraint of the three kinds that reads the content and the tags together.

A non-conforming Validation MUST be ignored and is no evidence of examination. Tags this NIP does not define are ignored, as everywhere in Nostr, and are never grounds for rejection.

Note what constraint 4 does not do: it never inspects a theme’s value. Whether back-rank-mate is a token the game defines, whether the validator was right to read it, whether the set is complete — none of that is decidable here, and a Validation carrying a theme no consumer recognizes is perfectly conforming. An unknown theme is a theme this consumer cannot filter on, and nothing worse.

The validated state

For one Composition, over the Validations a consumer can see:

A Composition is validated if and only if, for at least one validator in the consumer’s trusted set, that validator’s canonical verdict for it (§Validator discretion) is valid.

For a non-equivocating validator — the entire honest population — the canonical verdict is simply their one verdict, and the rule reads exactly as “some trusted validator said valid”. The canonical-verdict indirection exists only to make equivocation resolve deterministically instead of splitting consumers. Beyond that there is no fold, no ranking, and no tie to break across validators, because there is nothing to arbitrate: the exercise and its proof arrived together under one signature, so a Composition has exactly one certificate and a verdict is about that certificate alone. A validated Composition’s statement — “force a mate in moves” — is its own stipulation, realized exactly.

Because the rule is a reading and not a record, nothing announces it. There is no event meaning “this Composition is now a puzzle”, no flag set on the Composition — which is immutable — and nothing for the composer or the validator to publish afterwards. An application shows a validated Composition the moment its own view of the trusted set’s Validations includes a valid one, and that is the whole of the mechanism: a consumer that has both events has the state, a consumer that has only the Composition has an unvouched artifact, and neither had to be told. It is the same shape by which a Game Session (kind 3422) appears in an application because the trusted arbiter signed it — the signature of a trusted party IS the admission, and no further act completes it.

The state is pure and consumer-computable: same trusted set, same events, same answer, with no authority deciding it. It is also stable and monotone for non-equivocating validators — a verdict is final for its (validator, Composition) pair and nothing revises or retracts, so a Composition validated once stays validated for that consumer. The qualification is deliberate: an equivocating validator’s later contradictory verdict can change which of its verdicts is canonical (or void its voice entirely, §Validator discretion), and that is intended — a validator that contradicts itself has forfeited stability, not the model. A Composition declined by one validator may still be validated by another the consumer trusts; a consumer that trusts several validators and sees them disagree holds a checkable signal, not a paradox: any engine-holder can replay both verdicts and see which is wrong.

Credit

One name, attribution and nothing more: the composer — the Composition’s signer, author of both the exercise and its proof. The credit is permanent by construction: there is no second contributor to rank against, and no later event moves it. Where several Compositions share one exercise (kind 3440 §Duplication), each carries its own composer’s credit; none displaces another, and the earliest is not thereby canonical — nothing in this family selects between them, and a consumer that merges them for display SHOULD credit all of them.

Client guidelines

Security considerations

References