Skip to content

feat(antd, sdks): SHA-256 from uploads and on manifest entries (DO NOT MERGE until the ant-client release with #229) - #347

Draft
Nic-dorman wants to merge 6 commits into
mainfrom
nic/v2-1564-antd-sha256
Draft

Nic-dorman wants to merge 6 commits into
mainfrom
nic/v2-1564-antd-sha256

Conversation

@Nic-dorman

@Nic-dorman Nic-dorman commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Draft. DO NOT MERGE. This is blocked on WithAutonomi/ant-client#229, which adds the SHA-256 in ant-core. #229 merged on 2026-10-16 (ant-client a7cb0d0), but it is not in a release yet: it is not in ant-core 0.13.0. Do not merge this until an ant-client release ships #229 (expected next week, likely ant-core 0.14). #326 and #346, which this was stacked on, are now in main, so this targets main directly.

Temporary pin. antd/Cargo.toml pins ant-core to #229's commit 2eace73. It also adds a [patch.crates-io] that points ant-protocol at rev 718f606, mirroring ant-client main. Before this merges:

  1. Repin ant-core to the release that ships ci(ffi): cross-platform Python wheels + PyPI publishing #229, and drop the [patch].
  2. Take the PR out of draft.

Stack. This is stacked on #346 (manifest endpoints), which sits on #326 (pointer API) and #325 (repin). Merge order: #325 → #326 → #346 → this PR. Linear: V2-1564.

Don't merge this branch into the pointer stack. antd/Cargo.toml merges with no textual conflict, so a merge would silently move every pointer PR onto the dev pin.

What

  • antd:
    • sha256 (hex) is returned on the data, file and finalize upload responses, over REST and gRPC.
    • It passes through /v1/manifests/build as an optional input on each entry, and comes back out of /v1/manifests/decode. The ADR-0006 owner approved it as an optional field within format version 1.
  • antd-go: the matching fields.
  • Stubs:
    • Swift, Elixir, Python, Dart and Ruby were regenerated on Linux with each script's pinned tools. Only the data, files and upload stubs change.
    • The Kotlin proto copies are synced, and the Go stubs are regenerated.
  • Docs: OpenAPI and the llms docs gain the sha256 fields.

ec696b4's message says "WIP: SDK stubs and docs follow". e60a349 is that follow-up.

Not in this PR

  • The other SDKs' hand-written REST models (Python, JS and so on) don't read sha256 yet. Their generated gRPC stubs already carry it.
  • No live paid upload has gone through antd's new path yet. ant-core's end-to-end tests in ci(ffi): cross-platform Python wheels + PyPI publishing #229 cover the hashing itself.

Verified

Before the restack:

  • antd: 127 tests, fmt and clippy.
  • antd-go: tests, go vet, and golangci-lint v1.64.8.

On this branch after merging #346, so the pointer code is built against the dev pin too:

  • antd: clippy with -D warnings, cargo doc, and cargo test --locked. All 148 tests pass, so the pointer code builds and passes against the dev pin as well.
  • antd-go: go vet, go test, and golangci-lint v1.64.8.

CI note. This PR inherits the same two red checks as #346 (Security audit and Third-party notices) until the stack below it picks up #325's fixes.

🤖 Generated with Claude Code

Nic-dorman and others added 3 commits October 15, 2026 12:43
…ies (V2-1564)

WIP: SDK stubs and docs follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…them (V2-1564)

Swift, Elixir, Python, Dart and Ruby stubs regenerated on Linux with each
script's pinned tools; only data/files/upload change. Kotlin proto copies
synced. OpenAPI and llms docs gain the sha256 fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…6 work

This keeps the SHA-256 work stacked on V2-1570, which now sits on the
pointer API (#326). The merge had no conflicts. The ant-core dev pin
below still applies to the whole tree, so the pointer code is built
against it here as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nic-dorman and others added 3 commits October 15, 2026 15:35
Brings up the CI fixes already on the repin branch (#325): rustls 0.23.46 from main (#344, RUSTSEC-2026-0346..0349) and the notices generator reading .licenses/ (c226153, for granit-parser). No conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ds (V2-1564)

The sha256 fields added to data.proto, files.proto and upload.proto
were regenerated for the other SDKs, but not in antd-rust's committed
generated code, so its proto drift test failed (Check (antd-rust)).

Regenerated with `ANTD_REGEN_PROTO=1 cargo test --test proto_drift`,
using protoc 25.3. The only change is the `sha256` field on
PutPublicDataResponse, PutDataResponse, FinalizeUploadResponse,
PutFileResponse and PutFilePublicResponse. The gRPC mock server in
grpc_tests.rs builds those responses as struct literals, so they now
set `sha256: String::new()`.

antd-rust's models don't expose sha256 yet. That's part of the open
"other SDKs read sha256" follow-up.

fmt, clippy -D warnings, cargo doc and cargo test (154 lib tests plus
the drift test) are clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings up #325's final ant-cli-v0.3.11 repin via #326 and #346. antd/Cargo.toml and antd/Cargo.lock conflicted on the ant-core and ant-protocol pins; both keep this branch's side, the DEV PIN on WithAutonomi/ant-client#229 with its ant-protocol [patch], because the SHA-256 change needs #229 and ships with it. No other conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dirvine

dirvine commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Hermes review handoff — ant-sdk #347

Review record: WithAutonomi/ant-sdk#347@10dc29b4f0eba65273f99cb75e4e95b818024498

Linked Linear ticket: V2-1564. The PR head was read again before posting and still matches the reviewed revision. Required whole-PR panel coverage remains incomplete; this post is not approval.

Posting-time upstream check: ant-client#229 is OPEN at fa5e49c567f75e069ed8543c332392c44c38feba. Tests in this report cover #347's recorded dependency pin, not a different upstream head.

WithAutonomi/ant-sdk #347 — bounded review

Recommendation: HOLD — DO NOT MERGE; disclosed release gates and incomplete panel. This is an advisory review comment, not a formal GitHub APPROVE/REQUEST_CHANGES review or permission to merge.

  • PR: feat(antd, sdks): SHA-256 from uploads and on manifest entries (DO NOT MERGE until the ant-client release with #229) #347
  • Reviewed head: 10dc29b4f0eba65273f99cb75e4e95b818024498.
  • Reviewed diff base (merge base): 4cf292a4761fe07e0db82ba270c177382a4ef7b5.
  • GitHub target branch revision captured initially: 4cf292a4761fe07e0db82ba270c177382a4ef7b5.
  • Local checkout is clean and matches the reviewed head. The live head was read again before report generation and still matches.
  • Changed-file inventory: 52 files. Full changed-production patch coverage manifests are included with the evidence. Documentation, tests, generated stubs and locks are classified separately; a production-scope panel is not a review of all SDK builds.

Feature review

At the reviewed development pin, the SHA-256 value is propagated through the daemon's upload responses over REST/gRPC and the Go typed client, and recorded/reported on manifest entries. Local tests pass, including manifest and hash round-trips. No new blocking implementation defect was confirmed in this delta. This is not a whole-SDK feature-parity claim: the PR explicitly excludes non-Go hand-written REST client models; generated fields do not establish that Rust/Python or other typed clients return the new value.

Hard release gates

  1. feat(upload, manifest): report the uploaded file's SHA-256 and record it on manifest entries (V2-1564) ant-client#229 must merge and ship in an ant-core release. At the read used for this report it is still OPEN at fa5e49c567f75e069ed8543c332392c44c38feba, while feat(antd, sdks): SHA-256 from uploads and on manifest entries (DO NOT MERGE until the ant-client release with #229) #347 pins older commit 2eace7374d0642376e799458a4fb9e63c2b7cc4c. These are different revisions. Tests here cover the latter exact pin, not the current upstream PR head.
  2. Repin ant-core to the actual release that contains ci(ffi): cross-platform Python wheels + PyPI publishing #229. Do not assume an anticipated version number is published or includes the feature.
  3. Remove the temporary ant-protocol [patch.crates-io] override at 718f60682bb3704b68fbba0bea34f2a0416fa876, resolve the intended locked graph, and check it explicitly.
  4. Review and retest that final dependency graph. The current temporary graph moves ant-core 0.13.0 to 0.11.0, ant-protocol 5.0.0 to 4.0.0, and also moves Saorsa dependencies backwards. This is disclosed development choreography, not a new hash-code defect; it is still a hard reason not to merge the temporary pin.
  5. Resolve feat(antd, antd-go, antd-rust): pointer API with ownership transfer #326's cancellation defect in the lower stack, complete the required review coverage, and revalidate the final heads.
  6. Respect the documented order build(antd): repin ant-core 0.13.0 (ant-cli-v0.3.11) #325 → feat(antd, antd-go, antd-rust): pointer API with ownership transfer #326 → feat(antd, antd-go): ADR-0006 manifest endpoints: build, decode and link #346 → feat(antd, sdks): SHA-256 from uploads and on manifest entries (DO NOT MERGE until the ant-client release with #229) #347; remove draft/DO NOT MERGE only after the release gates are met. Do not merge feat(antd, sdks): SHA-256 from uploads and on manifest entries (DO NOT MERGE until the ant-client release with #229) #347 into the lower pointer branches merely because Cargo.toml merges without a textual conflict: that silently changes their dependency graph.

Source:

ant-sdk/antd/Cargo.toml

Lines 1 to 35 in 10dc29b

[package]
name = "antd"
version = "0.15.0"
edition = "2021"
license = "MIT OR Apache-2.0"
[dependencies]
ant-core = { git = "https://github.com/WithAutonomi/ant-client", rev = "2eace7374d0642376e799458a4fb9e63c2b7cc4c" } # DEV PIN, DO NOT MERGE: WithAutonomi/ant-client#229 (V2-1564, SHA-256 of uploads + manifest entries) on top of main 225a676 (= the 2026-10-15 train content). Repin to the first ant-core release that ships #229 before merge.
self_encryption = "0.36.0"
evmlib = "0.10.0" # must track ant-core's transitive evmlib (via ant-protocol) to avoid a second copy in the graph
ant-protocol = "=4.0.0" # resolved through the [patch.crates-io] below to the revision ant-client main pins; any other source would fork PaymentQuote/StorageCommitment in the graph
axum = { version = "0.8", features = ["macros"] }
tower-http = { version = "0.6", features = ["cors", "limit", "trace"] }
tonic = "0.12"
prost = "0.13"
tokio = { version = "1", features = ["full"] }
tokio-stream = { version = "0.1", features = ["net"] }
dirs = "6"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
hex = "0.4"
bytes = "1"
base64 = "0.22"
blake3 = "1"
rmp-serde = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
clap = { version = "4", features = ["derive", "env"] }
thiserror = "2"
futures = "0.3"
rand = "0.8"
postcard = { version = "1.1.3", features = ["use-std"] }
toml = "0.8"
zeroize = "1" # pointer owner key seeds are wiped after the key pair is derived
. Upstream: WithAutonomi/ant-client#229.

Explicit limits

  • A manifest hash is a creator-supplied claim. Build/decode round-trip is not proof that the referenced content has that hash.
  • No paid upload through the daemon's new path ran in this review. Comparison of a daemon-returned hash with an independently computed plaintext hash remains an integration gate, not a claimed result.
  • Non-Go hand-written client support and package-version/release-document alignment remain follow-up scope. The typed Rust API still drops the new hash field; do not advertise all-SDK parity.
  • The PR body's old note about red CI is stale relative to the exact-head rollup observed in this report; the current check totals below are the evidence.

Execution and CI evidence

  • Parent-run cargo test --locked, daemon: test result: ok. 148 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.38s
  • Parent-run cargo test --locked, Rust SDK (each result is a separate test binary/doc-test group):
    • test result: ok. 154 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.23s
    • test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    • test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.15s
    • test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
    • test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s
  • Local Go tests and go vet passed. Go race tests were not run for this head; do not transfer feat(antd, antd-go, antd-rust): pointer API with ownership transfer #326 race coverage to it.
  • Formatting: changed hand-written Rust sources passed edition-correct checks. The generated Rust formatting difference also reproduces on the base; it is inherited.
  • The first daemon build failed because a shared target contained stale generated protobuf outputs from another worktree. After cargo clean -p antd, the saved fresh-proto daemon run exited 0. The failed first run is retained, not reported as a passing command. Per-worktree targets should be used for future stack validation.
  • Exact-head GitHub checks at final read: {'SUCCESS': 18, 'SKIPPED': 2}. This is observed CI, distinct from local execution.
  • No paid upload, live-network pointer operation, full daemon payment E2E, browser/mobile SDK build, or complete lint/security reproduction ran locally. Unit tests and loopback probes do not establish these gates.

Actual original panel participation

The design was two independent roles (correctness and adversarial) for each of GLM 5.3/OpenRouter, local Qwen 3.8 27B, and local DS4 Flash. Production evidence was split into complete named scopes, so a role/model required multiple receipts to cover a whole PR. A receipt is not an extra independent model.

  • GLM 5.3 / OpenRouter: 0/4 scoped role receipts returned complete structured opinions; verdicts {}; missing {'Incomplete termination; unavailable seat': 4}.
  • local Qwen 3.8 27B: 4/4 scoped role receipts returned complete structured opinions; verdicts {'APPROVE': 4}; missing {}.
  • local DS4 Flash: 0/4 scoped role receipts returned complete structured opinions; verdicts {}; missing {'TimeoutError': 4}.

UNCERTAIN is unresolved, not approval. Missing, truncated and timed-out seats do not agree. These counts include complete UNCERTAIN opinions and therefore do not mean complete substantive sign-off. No whole-PR six-seat consensus exists. Recommendations without a verified defect remain provisional.

Scope-by-scope receipts

  • sha-go / correctness: glm: Incomplete termination; unavailable seat; qwen: APPROVE; ds4: TimeoutError
  • sha-go / adversarial: glm: Incomplete termination; unavailable seat; qwen: APPROVE; ds4: TimeoutError
  • sha-server / correctness: glm: Incomplete termination; unavailable seat; qwen: APPROVE; ds4: TimeoutError
  • sha-server / adversarial: glm: Incomplete termination; unavailable seat; qwen: APPROVE; ds4: TimeoutError
Changed-file scope and classification manifest
{
  "pr": 347,
  "head": "10dc29b4f0eba65273f99cb75e4e95b818024498",
  "base": "4cf292a4761fe07e0db82ba270c177382a4ef7b5",
  "changed_file_count": 52,
  "files": [
    {
      "path": "antd-dart/lib/src/generated/antd/v1/data.pb.dart",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-dart/lib/src/generated/antd/v1/data.pbjson.dart",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-dart/lib/src/generated/antd/v1/files.pb.dart",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-dart/lib/src/generated/antd/v1/files.pbjson.dart",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-dart/lib/src/generated/antd/v1/upload.pb.dart",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-dart/lib/src/generated/antd/v1/upload.pbjson.dart",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-elixir/lib/antd/v1/data.pb.ex",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-elixir/lib/antd/v1/files.pb.ex",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-elixir/lib/antd/v1/upload.pb.ex",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-go/client.go",
      "classification": "production",
      "scope": "sha-go"
    },
    {
      "path": "antd-go/client_test.go",
      "classification": "tests",
      "scope": null
    },
    {
      "path": "antd-go/grpc_client.go",
      "classification": "production",
      "scope": "sha-go"
    },
    {
      "path": "antd-go/grpc_client_test.go",
      "classification": "tests",
      "scope": null
    },
    {
      "path": "antd-go/manifest.go",
      "classification": "production",
      "scope": "sha-go"
    },
    {
      "path": "antd-go/manifest_test.go",
      "classification": "tests",
      "scope": null
    },
    {
      "path": "antd-go/models.go",
      "classification": "production",
      "scope": "sha-go"
    },
    {
      "path": "antd-go/proto/antd/v1/data.pb.go",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-go/proto/antd/v1/files.pb.go",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-go/proto/antd/v1/manifests.pb.go",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-go/proto/antd/v1/upload.pb.go",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-kotlin/lib/src/main/proto/antd/v1/data.proto",
      "classification": "production",
      "scope": "sha-go"
    },
    {
      "path": "antd-kotlin/lib/src/main/proto/antd/v1/files.proto",
      "classification": "production",
      "scope": "sha-go"
    },
    {
      "path": "antd-kotlin/lib/src/main/proto/antd/v1/upload.proto",
      "classification": "production",
      "scope": "sha-go"
    },
    {
      "path": "antd-py/src/antd/_proto/antd/v1/data_pb2.py",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-py/src/antd/_proto/antd/v1/data_pb2.pyi",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-py/src/antd/_proto/antd/v1/files_pb2.py",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-py/src/antd/_proto/antd/v1/files_pb2.pyi",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-py/src/antd/_proto/antd/v1/upload_pb2.py",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-py/src/antd/_proto/antd/v1/upload_pb2.pyi",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-ruby/lib/antd/v1/data_pb.rb",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-ruby/lib/antd/v1/files_pb.rb",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-ruby/lib/antd/v1/upload_pb.rb",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-rust/src/generated/antd.v1.rs",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-rust/src/grpc_tests.rs",
      "classification": "tests",
      "scope": null
    },
    {
      "path": "antd-swift/Sources/AntdSdk/Proto/antd/v1/data.pb.swift",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-swift/Sources/AntdSdk/Proto/antd/v1/files.pb.swift",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd-swift/Sources/AntdSdk/Proto/antd/v1/upload.pb.swift",
      "classification": "generated",
      "scope": null
    },
    {
      "path": "antd/Cargo.lock",
      "classification": "lock",
      "scope": null
    },
    {
      "path": "antd/Cargo.toml",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/openapi.yaml",
      "classification": "docs",
      "scope": null
    },
    {
      "path": "antd/proto/antd/v1/data.proto",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/proto/antd/v1/files.proto",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/proto/antd/v1/manifests.proto",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/proto/antd/v1/upload.proto",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/src/grpc/service.rs",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/src/manifests.rs",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/src/rest/data.rs",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/src/rest/files.rs",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/src/rest/manifests.rs",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/src/rest/upload.rs",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "antd/src/types.rs",
      "classification": "production",
      "scope": "sha-server"
    },
    {
      "path": "llms-full.txt",
      "classification": "docs",
      "scope": null
    }
  ],
  "scopes": [
    {
      "pr": 347,
      "scope": "sha-server",
      "head": "10dc29b4f0eba65273f99cb75e4e95b818024498",
      "base": "4cf292a4761fe07e0db82ba270c177382a4ef7b5",
      "evidence": "/Users/studio1/.hermes/cache/scratch/ant-sdk-review-evidence/347/panel-evidence/sha-server.txt",
      "bytes": 34463,
      "files": [
        "antd/Cargo.toml",
        "antd/proto/antd/v1/data.proto",
        "antd/proto/antd/v1/files.proto",
        "antd/proto/antd/v1/manifests.proto",
        "antd/proto/antd/v1/upload.proto",
        "antd/src/grpc/service.rs",
        "antd/src/manifests.rs",
        "antd/src/rest/data.rs",
        "antd/src/rest/files.rs",
        "antd/src/rest/manifests.rs",
        "antd/src/rest/upload.rs",
        "antd/src/types.rs"
      ]
    },
    {
      "pr": 347,
      "scope": "sha-go",
      "head": "10dc29b4f0eba65273f99cb75e4e95b818024498",
      "base": "4cf292a4761fe07e0db82ba270c177382a4ef7b5",
      "evidence": "/Users/studio1/.hermes/cache/scratch/ant-sdk-review-evidence/347/panel-evidence/sha-go.txt",
      "bytes": 14476,
      "files": [
        "antd-go/client.go",
        "antd-go/grpc_client.go",
        "antd-go/manifest.go",
        "antd-go/models.go",
        "antd-kotlin/lib/src/main/proto/antd/v1/data.proto",
        "antd-kotlin/lib/src/main/proto/antd/v1/files.proto",
        "antd-kotlin/lib/src/main/proto/antd/v1/upload.proto"
      ]
    }
  ]
}

Linear review comment: https://linear.app/autonominetwork/issue/V2-1564/ant-core-antd-sha-256-of-uploaded-content-computed-during-encryption#comment-e90784b9

@Nic-dorman
Nic-dorman changed the base branch from nic/v2-1570-antd-manifest-endpoints to main October 16, 2026 14:33
@Nic-dorman Nic-dorman changed the title feat(antd, sdks): SHA-256 from uploads and on manifest entries (DO NOT MERGE: dev pin on ant-client#229) feat(antd, sdks): SHA-256 from uploads and on manifest entries (DO NOT MERGE until the ant-client release with #229) Oct 16, 2026

This branch has not been deployed

No deployments
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.

2 participants