Files
zeekayandHanzo Dev a2874e29b0 fix(six): one word, one body, one shape across the three SDKs
Thirteen places where this SDK and the other two answered the same question
differently. Every one is now what the served handler reads, or what HIP-0044
says where the handler is silent.

Where this SDK was already right, the other two moved: `put` lets the store
decide whether a document exists, `Filter.order` and `links(project)` are real
capabilities the routes serve, `Import` carries what the handler answers, and
`Fact` keeps the server's own three. Where it was not:

- search speaks kinds, not doctype addresses. `/v1/search` matches `doctypes`
  against kb.page, kb.memory and kb.source EXACTLY and silently drops anything
  else (knowledge/subsystem.go, sanitizeDocTypes), so `{kinds: ['page']}` — the
  word the contract uses — narrowed the query to nothing at all, and `Hit.kind`
  came back in a different vocabulary than `Doc.kind`. The mapping is `kb.ts`'s
  `doctype` and `kind`, applied at the boundary in both directions; a doctype
  from another corpus passes through untouched.
- A write body is field data and nothing else. The framework validates against
  DocType.Fields and drops what it does not declare, and `name` is not a field
  of any of the three: a page is named from `slug`, a memory and a source are
  hash-named. Every member of Doc but `kind` is now optional, so a caller writes
  what it has instead of passing empty strings for `project` and `url` — which
  were going out on the wire as empty fields the store dropped anyway.
- import(format, data, project). Two values and an option are not an aggregate,
  so kb.Source is gone — which also leaves one Source in this package, graph's.
- policy_denied and entitlement_required do not exist. Neither string appears
  anywhere in hanzoai/cloud, so a 403 read as denied on one of them would hand
  an unauthenticated caller a cure for a refusal nobody made. The refusal set is
  the two codes cloud emits.
- audit.list reports the server's own count. A per-page count under a `request`
  filter is not "what the filter matched across every page"; the caller now gets
  the count the server matched for the filter the server applied.
- The fourth outcome is Fault. RFC 9457's problem detail is a body a 402 carries
  and this client reads as a `denied` arm, so naming the outcome with no
  decision in it `Problem` gave one word two meanings. `Error` is taken — by the
  global here, by Go's builtin, by Python's hierarchy. `Fault` collides with
  nothing in any of the three.
- Money counts minor units, not cents: hundredths for USD, whole yen for JPY,
  thousandths for KWD.
- Balance.reserved, not held. The wire says `holds`; `held` is an arm.
- Vocabulary.rules, because it is a list. The wire member stays `rule`.
- A client with no credential raises a Fault carrying no code. `no_credential`
  is not a code any server sends, and a code is what a caller branches on.

HIP-0044 is amended where the code was right and the document was not.

tsc, tsc -p tsconfig.esm.json, smoke, 30 node tests and the examples project all
clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 16:27:05 -07:00
..