feat: storage lease + audit family, node key lifecycle, GPU job hints (roadmap v0.3–v0.5)#5
Merged
NetworkTheoryAppliedResearchInstitute merged 4 commits intoJul 13, 2026
Conversation
CapabilityListing gains first-class storage and GPU advertisement so
phones, TVs, and NAS nodes can join as storage/GPU contributors:
- WorkloadOptIn gains Storage (advisory, same SPEC 5.1 discipline as
Compute/Print; mirrors the coordinator's existing
compute/storage/printing opt-out trichotomy).
- Capacity gains StorageCommitMB: long-lived storage committed to the
network (shard hosting), deliberately distinct from DiskMB job
scratch. Encryption, sharding, and audit of stored data are
frontend/agent concerns outside the protocol; the wire never carries
stored content.
- New GPUs []GPUCapability{API, Model, VRAMMB}, mirroring Printers.
Advertising a GPU is the opt-in; API in {vulkan, nnapi, cuda, metal}.
- JobSpec.Workload doc comment admits "storage".
CanonicalBytes changes (GPUs after Printers; StorageCommitMB after
DiskMB; OptIn.Storage after OptIn.Print): a breaking v0 encoding
change while v0 is declared UNSTABLE. testdata/vectors.json
regenerated; testdata/reproduce_spec.py updated and passing 43/43
against the new golden file. Consumers (Cloudy, SoHoLINK) must bump
in lockstep; tag v0.2.0 at merge.
Signed-off-by: Jodson Graves <info@ntari.org>
Completes the roadmap additions (Development/SCP-completion-roadmap.md v0.3-v0.5) so the protocol covers the full substrate scope before its consumers calcify around gaps. Storage lease + audit (new package lease, SPEC 4.7-4.10). Storage is a LEASE, not a job: StorageLease is the coordinator-signed offer (opaque 32-byte ShardRef + quantized SizeClass only -- the wire never carries true sizes or content; encryption/padding/sharding stay frontend-side), fee terms inline, renewal = same LeaseID with strictly higher Seq. LeaseDecline/LeaseRelease are the node's signed exits (local_policy remains the opt-out path; sovereignty includes leaving). ProofChallenge is UNSIGNED and pull-fetched (commits no one); ProofResponse is the node-signed, self-contained possession fact -- the storage counterpart of JobReport -- with the digest formula standardized as SHA-256(Nonce || uint64be(Offset) || uint64be(Length) || range), byte-identical to the expectation Cloudy precomputes at seal time. (LeaseID, Nonce) is single-use at the verifier: replays are dead. Node key lifecycle (identity/keylife.go, SPEC 4.11-4.12). KeyRotation is signed by the CURRENT key (a rotation signed by the successor is self-installation and must fail -- tested); strictly monotonic Seq per node. KeyRevocation is signed by the key being killed and MUST be honored unconditionally -- a thief can produce one too, and the safe reading is always 'stop trusting it'; re-enrollment is out-of-band. Closes the 'first-write-wins forever' gap before real member hardware. GPU job hints (employment, SPEC 4.3). JobSpec gains advisory GPUAPI + GPUMinVRAMMB routing hints, same discipline as PrinterKind, so assignments can request what listings can now advertise. Coordinator surface: StorageCoordinator and KeyLifecycleCoordinator are OPTIONAL capability interfaces, not new Coordinator methods, so a coordinator adopts compute/print without implementing storage yet; consumers discover support by type assertion. Breaking v0 canonical change (Assignment gains two fields; six new domain tags). Vectors regenerated: 12 message cases; the stdlib-only Python reproducer gained the six encoders and passes 55/55 against the new golden file. Transport httpjson routes for the new families ride with the SoHoLINK-side implementation (named follow-up). Signed-off-by: Jodson Graves <info@ntari.org>
…proof bounds Addresses the protocol findings from the 2026-07-09 substrate audit. M3 — KeyRotation.Verify now rejects a rotation naming a malformed successor (NewPublicKey != 32 bytes, or unknown Algo), matching the operator rotation path. Broader: all message Verify methods route through the new canon.VerifySig, which guards public-key AND signature length before ed25519.Verify — a wrong-length key on the wire can no longer panic a verifier (it did before; only the operator path was guarded). M4 — KeyRevocation.Verify(trustedPub) now requires RevokedPublicKey == trustedPub and self-signature by that key, closing the victim-revocation vector (a stranger's self-signed revocation naming a victim's NodeID fails against the victim's trusted key). SPEC §4.12 'honor unconditionally' wording superseded by the mandatory trusted-key binding. L4 — canon.Buffer.Time latches canon.ErrTimeOutOfRange (via Buffer.Err()) and appends nothing instead of silently wrapping an out-of-range instant; new canon.ValidTime for producers. SPEC §3 documents the enforcement. Closes the 584-year aliasing conformance defect. L5 — new lease.ProofOverShard bounds-checks Offset/Length before slicing so a malicious challenge yields lease.ErrChallengeRange, not a node-side slice panic. ProofDigest (the raw primitive, byte-identical to the vectors) is unchanged. L10 — StorageLease.SizeClass is now a named lease.SizeClass type documenting the 'agreed quantized class, never a true size' §5 invariant (intent-marking, not value-enforcing — class values remain frontend policy). NIT — OperatorRotation.Verify checks duplicate-key then algo-mismatch in two ordered passes, so the returned error is deterministic regardless of map iteration order. NO canonical-byte change: all 55 conformance vectors still match the Python reproducer byte-for-byte; new regression tests cover each guard. Still bound for the v0.2.0 tag. Signed-off-by: Jodson Graves <info@ntari.org>
NetworkTheoryAppliedResearchInstitute
changed the base branch from
feat/storage-gpu-listing
to
main
July 13, 2026 10:36
Signed-off-by: Jodson Graves <info@ntari.org> # Conflicts: # employment/employment.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Completes the roadmap additions so SCP covers the full substrate scope — the 'complete the protocol first, thread the consumers around it' directive. Stacked on #3 (listing fields); merge order #4 (CI) → #3 → this.
Storage lease + audit — new
leasepackage (SPEC §4.7–4.10)Storage is a lease, not a job:
StorageLease(coordinator-signed; opaque 32-byteShardRef+ quantizedSizeClassonly — the wire never carries true sizes or content),LeaseDecline/LeaseRelease(node-signed exits;local_policyopt-out; sovereignty includes leaving), and the audit pair: unsigned pull-fetchedProofChallenge+ node-signed self-containedProofResponse— the storage counterpart of JobReport, the fact storage payout derives from. Digest formula standardized (SHA-256(Nonce‖Offset‖Length‖range)), byte-identical to what Cloudy'sinternal/storageprecomputes at seal time.(LeaseID, Nonce)single-use ⇒ replays dead.Node key lifecycle —
identity/keylife.go(SPEC §4.11–4.12)KeyRotationsigned by the current key (successor self-installation fails — tested), strict Seq monotonicity.KeyRevocationsigned by the dying key, honored unconditionally; re-enrollment out-of-band. Closes the first-write-wins-forever gap.GPU job hints —
employment(SPEC §4.3)JobSpec.GPUAPI+GPUMinVRAMMB, advisory likePrinterKind— assignments can now request what listings advertise.Coordinator surface
StorageCoordinator+KeyLifecycleCoordinatoras optional capability interfaces (type-asserted), so SoHoLINK can bump without implementing storage on day one.Verification
After merge
Tag v0.2.0 (one tag for the whole pre-consumer window rather than v0.2/0.3/0.4/0.5 separately — fewer coordinated bumps), then bump Cloudy + SoHoLINK in lockstep. Named follow-up: httpjson transport routes for the new families ride with the SoHoLINK-side implementation.
🤖 Generated with Claude Code