fix(sdk): include private flag in the signed user.profile payload#120
Conversation
Profile saves failed with HTTP 401. The backend's canonical user.profile payload (internal/users/handler.go: userProfilePayload) includes a wallet-level `private` field, but the TS and Rust SDKs omitted it from the payload they sign. The signed canonical string therefore differed from the one the backend derives, so the freshness-bound signature never verified and the request was rejected as unauthorized. - TS: add `private?: boolean` to UserProfileUpdate and `private: update.private ?? null` to the signed user.profile payload. - Rust: add `private: Option<bool>` to UserProfileUpdate and `private` to the canonical payload. - Tests: a TS test that reconstructs the freshness signature and cryptographically verifies it covers `private`, and a Rust unit test asserting the canonical payload carries the flag (null by default, true when set). Python is unaffected (it does not sign profile updates). No website change is needed — the ProfileEditor passes the update through unchanged; rebuilding the SDK is sufficient. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@graycyrus is attempting to deploy a commit to the Vezures Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughAdds an optional ChangesPrivate flag in user profile signing payload
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Bump the crate version so the merge publishes to crates.io. The published crate is stuck at 0.5.0: the auto-publish failed on the feeds (#100), bounties (#101), and user.profile fix (#120) merges with 'crate tinyplace@0.5.0 already exists on crates.io index' because the version was never bumped. 0.6.0 covers the new feeds + bounties API modules (minor) and the profile signature fix, and aligns with the TypeScript SDK at 0.6.0. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bug
Editing a profile and clicking Save fails with:
Root cause
The backend's canonical
user.profilepayload —internal/users/handler.gouserProfilePayload— signs over these fields:Both the TypeScript and Rust SDKs omitted
privatefrom the payload they sign. The client's canonical string therefore differed from the one the backend derives (which includesprivate, defaulting tonull), so the freshness-bound signature never verified and the request was rejected as 401 Unauthorized. This broke all profile saves from the web app.Fix
private?: booleantoUserProfileUpdate, andprivate: update.private ?? nulltouserProfileSignaturePayload.private: Option<bool>toUserProfileUpdate, and"private"touser_profile_signature_payload.The signed field set now matches the backend exactly, so the signature verifies. Omitting
private(as the web ProfileEditor does) signs it asnull, which leaves the current value unchanged — matching the backend contract.Tests
v1:<ts>:<nonce>:<sig>freshness signature from the request body and cryptographically verifies (ed25519) it covers a payload includingprivate— so dropping the field again fails the test."private":nullby default and"private":truewhen set.Scope
ProfileEditorpasses the update through unchanged; the web app picks up the fix when the SDK is rebuilt (Vercel builds the SDK first).Validation
tsc --noEmit✅, full SDK suite ✅ (249 passed), website typecheck ✅ against the rebuilt SDKcargo fmt --check✅,cargo clippy --all-targets -- -D warnings✅,cargo test✅🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests