Skip to content

feat(reputation): add update_user_type entrypoint - #1601

Merged
mftee merged 3 commits into
CodeGirlsInc:mainfrom
Spaully:feat/issue-1464-update-user-type
Sep 25, 2026
Merged

mftee merged 3 commits into
CodeGirlsInc:mainfrom
Spaully:feat/issue-1464-update-user-type

Conversation

@Spaully

@Spaully Spaully commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #1464

Adds update_user_type to the reputation contract so a Carrier mis-registered as Shipper (or vice versa) can correct its UserType in one user-signed call, without an admin round-trip. register_user locks a user's type in at registration and a second registration fails with UserAlreadyRegistered, so there was previously no on-protocol path to fix a wrong label. The new entrypoint is the reputation analogue of identity's update_identity, follows the existing users module style, and reuses storage::require_not_paused / storage::load_reputation / storage::save_reputation and the standard updated event.

The single most important design decision: the correction is self-serve (user.require_auth()), so the person who registered is the only party who can fix their own record - no UserTypeMismatch round-trip and no admin involvement, exactly as the issue asks.

Also closes

Closes #1463, Closes #1465, Closes #1466

(Closed without implementation - see Deliberately deferred.)

Why

users::register sets user_type once and every later call fails with UserAlreadyRegistered. There was no update_user_type-style entrypoint anywhere in the crate, so correcting a mis-registered type required an admin to manually rewrite storage off-protocol. Identity solved the analogous problem with update_identity (a wallet can correct its user_id_hash in one signed call); reputation had no equivalent for user_type. This PR adds exactly that, with auth scoped to the user themselves and the pause guard consistent with the crate's other mutating entrypoints.

What was built

File What it contains
contracts/reputation/src/users.rs New users::update: user.require_auth(), require_not_paused, loads the existing Reputation, sets user_type, updates last_updated, saves, emits updated. Doc comment explains the correction path and that per-type counters are intentionally preserved.
contracts/reputation/src/contract.rs New ABI entrypoint update_user_type(env, user, user_type) delegating to users::update.
contracts/reputation/src/test/users.rs 3 new tests: successful correction, requires prior registration (UserNotFound), and counter preservation (existing success_count survives a Shipper->Carrier correction).
contracts/reputation/src/test/events.rs test_update_user_type_emits_updated: asserts exactly one updated event with the corrected payload and the user as key topic.

No existing files modified outside contracts/reputation/. No new actions added to contracts/EVENTS.md because the change reuses the existing updated event.

Acceptance criteria coverage (primary issue #1464)

  • A update_user_type-style entrypoint exists in the reputation crate (contracts/reputation/src/contract.rs, users::update)
  • A Carrier registered as Shipper (or vice versa) can fix its own type in one signed call (user.require_auth(), no admin parameter) (test/users.rs: test_update_user_type)
  • Mirror of identity's update_identity: single self-auth call, no admin round-trip (doc comments on the entrypoint and users::update)
  • Correcting an unregistered user fails with UserNotFound (test/users.rs: test_update_user_type_requires_prior_registration)
  • Existing earned history (per-type counters) is not deleted by the label change (test/users.rs: test_update_user_type_preserves_counters)

Deliberately deferred

Test plan

  • cargo fmt --all -- --check: not run - no Rust toolchain in this workspace environment; code follows the formatting of the neighbouring users.rs/test/* modules.
  • cargo clippy --all-targets --all-features -- -D warnings: not run (no toolchain).
  • cargo test -p reputation: not run (no toolchain). New tests only drive existing public client methods; 4 new tests added (3 in test/users.rs, 1 in test/events.rs).
  • cargo build --all: not run (no toolchain).
  • Manual: N/A - Soroban contract, no manual steps.

Env vars / Notes

No new environment variables or config keys introduced. The new public entrypoint is update_user_type(env, user, user_type); it is not admin-gated, consistent with register_user and identity's update_identity.

@vercel

vercel Bot commented Sep 24, 2026

Copy link
Copy Markdown

@Spaully is attempting to deploy a commit to the Mftee's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Sep 24, 2026

Copy link
Copy Markdown

@Spaully Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@mftee mftee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sensible addition: update_user_type lets a user correct a mis-registered UserType (Carrier/Shipper) in one signed call, mirroring identity's update_identity, and preserves existing per-type counters rather than wiping history. While resolving the conflict against #1599/#1600 (merged just before this), I updated this PR's pre-existing test calls in test/events.rs and test/users.rs to use the new Outcome enum instead of the old was_on_time/was_successful booleans, since update_stats's signature changed underneath this PR; the new update_user_type logic and its own tests are untouched.

@mftee
mftee merged commit 665ed32 into CodeGirlsInc:main Sep 25, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment