Skip to content

feat(gateway): bind kernel capabilities to Capability Kits and list a kit's live hosts (kits K3a) - #598

Draft
LamaSu wants to merge 3 commits into
feat/kits-registry-k1from
feat/kits-operator-binding-k3
Draft

LamaSu wants to merge 3 commits into
feat/kits-registry-k1from
feat/kits-operator-binding-k3

Conversation

@LamaSu

@LamaSu LamaSu commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Kits K3a: operator binding. Vision criterion 3 (an operator binds capacity and advertises capacity and pricing) and criterion 1 (a buyer searches kits and the live operators hosting them). Ledger rows R8 (binding grants no money authority) and R41 (a payment destination is not execution authority).

Stacked on #511 (the durable Capability Kit registry). Base is feat/kits-registry-k1. Retarget to master after #511 merges; CI runs on PRs into master only.

What it adds (gateway only; no DDL; packages/spec untouched)

  • POST /api/kits/:digest/bindings, body {csdUrl, kernelId, capabilityId}:

    • binds a kernel capability the caller owns to one CSD of a published kit version;
    • append-only and idempotent per tuple;
    • quota: 50 binds per principal per 24 h.
  • POST /api/kits/:digest/bindings/:bindingId/withdraw: the kernel's current owner writes an immutable withdrawal. The first withdrawal wins.

  • GET /api/kits/:digest/operators?presence=online|any: the buyer view of a kit's active hosts. Each host shows:

    • presence, which is online only with a heartbeat 5 minutes old or newer;
    • lastSeenAt;
    • availability, in the AvailabilitySummary shape only;
    • listPrice: the capability's recorded pricing, basis: "capability_record";
    • assuranceTierCap: 0;
    • identityStatus.

    It shows no operator address, principal or principal hash.

  • GET /api/operators/me/binding: OperatorBindingDTO v0, exactly as merged in feat(spec): Capability Kit manifest identity, OperatorBindingDTO and OpportunityDTO v0 contracts (interface-only; not before wave D) #397. payee is null until N21 has a store, and moneyAuthority is "none".

  • Storage: new areas in the kit registry's write-once file store (bindings/, binding-withdrawals/, binding-quota/). They reuse its exclusive-create, no-symlink and canonical-verification primitives. The operator chose file storage for kits (R6, option a).

  • Identity (services/operator-identity.ts), recorded on every binding:

    • proven: WP-A's provenWallet, or a SIWE session with no API key;
    • self_asserted: an API key whose operator id equals the kernel's operatorAddress exactly. That is the same compare the kernel upsert uses when it assigns ownership.

Not in this PR (named exposures)

  • Self-asserted identity: a self-asserted bind inherits the platform's open row N2. K3a labels it per binding and doesn't fix it.
  • Presence: heartbeats have no owner check (N6), so presence is only as true as heartbeats are.
  • Price: listPrice is the recorded price. The A2A and paid-job quote paths don't use it yet; the next slice, K3b, connects them.
  • Assurance tier: assuranceTierCap is 0, because the server keeps no proven per-kernel tier.

Provenance and review

  • Code: GPT-6.1 Sol (codex 0.159.1, effort ultra), written from the kits lane's brief.
    • dce4f1b is round 1.
    • 9b5822e is round 2: the lane's review fixes F1 to F4 (exact self-asserted compare; check, quota and create in one queued step; DTO-safe unmapped capacity; separate skipped counters) plus a nit.
  • Review: pack k3a-r1-operator-binding-9b5822e4 is with the orchestrator for a fresh Claude Opus 5.5 review, under the operator's 10/06 15:09 rule. The verdict is pending.
  • Head 15970be merges feat(gateway): durable, write-once, verified Capability Kit registry (kits K1 slice 1) #511's head 4186471 (master 2f5b21d) into the reviewed 9b5822e. The merge is clean, and its tree equals git merge-tree --write-tree 9b5822e4 41864713.
    • The K3a delta is unchanged: 8 of its 9 files are byte-identical (same patch-id).
    • server.ts adds the same two lines at moved offsets.

Checks at 15970be (run by the lane)

Check Result
operator-identity, kits-scope, capability-availability, kits-registry, kits-bindings 17 + 15 + 14 + 56 + 75 = 177/177
gateway tsc --noEmit exit 0
full gateway vitest 283 files: 6004 passed, 13 skipped, 3 todo
lane mutation run (at 9b5822e) 34/34 killed
secret scan over the diff 0

🤖 Generated with Claude Code

https://claude.ai/code/session_01RkdS4kBJNfFzaDBUCX8kQg

LamaSu and others added 3 commits October 6, 2026 15:39
… kit's live hosts (kits K3a)

Operator binding, first slice (ledger R8 and R41; vision criteria 3 and 1).

- POST /api/kits/:digest/bindings binds a kernel capability the caller owns
  to a CSD of a published kit version. Append-only and idempotent per tuple.
- POST /api/kits/:digest/bindings/:bindingId/withdraw writes a second
  immutable record. The kernel's current owner withdraws.
- GET /api/kits/:digest/operators lists a kit's hosts, with presence (a
  5-minute heartbeat), the AvailabilitySummary shape, the recorded list price
  and the identity tier. It carries no operator address or principal.
- GET /api/operators/me/binding serves OperatorBindingDTO v0. payee is null
  (no payout-destination store yet); moneyAuthority is "none".
- Bindings live in the kit registry's write-once file store: no DDL.
- services/operator-identity.ts holds the identity tiers and the kernel-owner
  rule. capability-availability.ts imports its helpers from there, unchanged.

Code written by GPT-6.1 Sol (codex 0.159.1, effort ultra) from the lane's
brief. Reviewed by the kits lane. Review fixes follow in the next commit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RkdS4kBJNfFzaDBUCX8kQg
…ic bind, DTO-safe unmapped capacity

The kits lane's review of the K3a slice:
- A self_asserted principal owns a kernel only on exact string equality with
  its operatorAddress (no trimming), as the kernel upsert compares when it
  assigns ownership. Empty, blank and zero-address owners stay refused.
- The idempotency check, the quota claim and the create run in one queued
  registry step (createBindingIfAbsent). Two concurrent identical binds now
  return the same binding, and spend one claim.
- /api/operators/me/binding omits capability rows whose type can't be a
  legacyType (1-120 characters), so one such row can't make the projection fail.
- Binding scans keep their own skipped list (skippedBindings). The kit
  listing's skipped is unchanged.
- Quota claims for bindings record the kit digest being bound.

Code written by GPT-6.1 Sol (codex 0.159.1, effort ultra). Each new test failed
on the unfixed code. Lane checks at this head: full gateway suite 5145 passed,
13 skipped, 3 todo; tsc clean; lane mutation run 34/34 killed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RkdS4kBJNfFzaDBUCX8kQg
…operator-binding-k3

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RkdS4kBJNfFzaDBUCX8kQg

This branch had an error being deployed

1 failed deployment
trusted-checks — 15970bed Deployed Oct 7, 2026 by LamaSu via post-verdicts #197
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant