Skip to content

feat: submit review logic#61

Open
arandomogg wants to merge 2 commits intoLightForgeHub:mainfrom
arandomogg:review-logic
Open

feat: submit review logic#61
arandomogg wants to merge 2 commits intoLightForgeHub:mainfrom
arandomogg:review-logic

Conversation

@arandomogg
Copy link
Copy Markdown

@arandomogg arandomogg commented Mar 29, 2026

Summary

  • Add submit_review to reputation-scoring contract
  • Score validation (1-5), cross-contract vault completion check, duplicate prevention
  • ExpertStats accumulation (total_score, review_count) with getter
  • review_submitted event emission
  • ReviewRecord and BookingRecord mirror types
  • 10 new tests via MockVault covering all paths

Closes #54

Test plan

  • All 15 tests pass (5 existing + 10 new)
  • Zero compiler warnings

Summary by CodeRabbit

Release Notes

  • New Features

    • Users can now submit reviews for completed bookings with a 1–5 score rating
    • Expert category assignment now supported during verification and profile updates
    • Expert reputation statistics are automatically tracked and queryable
    • Review records can be retrieved for any completed booking
  • Tests

    • Added comprehensive test coverage for review submission, including validation and event emission scenarios

Ogstevyn and others added 2 commits March 29, 2026 13:17
Add category_id (u32) to ExpertRecord, propagated through add_expert,
update_profile, batch_update_profiles, and preserved across ban/unban.
Includes test for full category_id lifecycle.

Closes LightForgeHub#41

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add submit_review to reputation-scoring contract with:
- Score validation (1-5 range)
- Cross-contract vault call to verify booking is Complete
- Reviewer must be the booking user
- Duplicate review prevention per booking_id
- ExpertStats accumulation (total_score, review_count)
- review_submitted event emission
- ReviewRecord and ExpertStats types with getters
- 10 new tests covering all paths via MockVault

Closes LightForgeHub#54

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 29, 2026

📝 Walkthrough

Walkthrough

This PR extends the identity registry's expert record structure with a category_id field threaded through verification, profile update, and storage paths. It also implements review submission logic in the reputation scoring contract, including cross-contract booking validation, score bounds checking, duplicate prevention, and expert statistics tracking.

Changes

Cohort / File(s) Summary
Identity Registry - Data Model
contracts/identity-registry-contract/src/types.rs, contracts/identity-registry-contract/src/storage.rs
Added category_id: u32 field to ExpertRecord struct; updated set_expert_record() signature to accept and persist category_id; added default category_id: 0 for missing records.
Identity Registry - Public API
contracts/identity-registry-contract/src/contract.rs, contracts/identity-registry-contract/src/lib.rs
Updated verify_expert(), update_profile(), and batch_update_profiles() function signatures to include category_id parameter; wired category_id through to storage layer across batch verification, individual updates, and ban/unban operations.
Identity Registry - Tests
contracts/identity-registry-contract/src/test.rs
Updated all test invocations to pass category_id argument; added new test test_category_id_persisted_and_updated verifying field storage, updates, and preservation across ban/unban cycles.
Reputation Scoring - Data Model
contracts/reputation-scoring-contract/src/types.rs
Added cross-contract types: ReviewRecord (booking_id, reviewer, expert, score, timestamp), ExpertStats (total_score, review_count), BookingStatus enum (Pending, Complete, Rejected, Reclaimed, Cancelled), BookingRecord struct for vault deserialization.
Reputation Scoring - Core Logic
contracts/reputation-scoring-contract/src/contract.rs, contracts/reputation-scoring-contract/src/error.rs, contracts/reputation-scoring-contract/src/events.rs, contracts/reputation-scoring-contract/src/storage.rs
Implemented submit_review() with score validation (1–5), cross-contract get_booking() call, booking completion and user verification, duplicate-review prevention, expert stats updates, and event emission; added error variants (InvalidScore, BookingNotComplete, AlreadyReviewed, NotBookingUser); extended storage with Review(u64) and ExpertStats(Address) keys and associated CRUD helpers.
Reputation Scoring - Public API & Tests
contracts/reputation-scoring-contract/src/lib.rs, contracts/reputation-scoring-contract/src/test.rs
Exposed submit_review(), get_review(), and get_expert_stats() contract methods; added mock vault infrastructure and comprehensive test suite covering successful submission, score validation, duplicate prevention, booking state checks, and expert stats accumulation.

Sequence Diagram

sequenceDiagram
    participant Reviewer
    participant ReputationContract
    participant PaymentVault
    participant Storage

    Reviewer->>ReputationContract: submit_review(booking_id, score)
    
    ReputationContract->>ReputationContract: Validate score (1-5)
    ReputationContract->>ReputationContract: Check contract initialized & not paused
    ReputationContract->>Storage: Check !has_review(booking_id)
    Storage-->>ReputationContract: Review exists?
    
    ReputationContract->>PaymentVault: get_booking(booking_id)
    PaymentVault-->>ReputationContract: BookingRecord
    
    ReputationContract->>ReputationContract: Verify status == Complete
    ReputationContract->>ReputationContract: Verify reviewer == booking.user
    
    ReputationContract->>Storage: set_review(booking_id, ReviewRecord)
    ReputationContract->>Storage: Get expert stats (or default)
    ReputationContract->>Storage: Update expert stats (total_score += score, review_count++)
    
    ReputationContract->>ReputationContract: Emit review_submitted event
    ReputationContract-->>Reviewer: Ok(())
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

  • Submit Review Logic #54: Directly addresses "Submit Review Logic" requirements—implements submit_review with score validation, cross-contract booking verification, spam prevention via duplicate checks, and expert stats aggregation as specified.
  • Expert Category/Tagging System #41: Relates to the identity registry changes introducing the category_id field for expert categorization/tagging system.

Possibly related PRs

  • PR #9: Modifies the verify_expert and expert verification control flow in identity-registry-contract, which is extended by this PR's addition of category_id threading.
  • PR #53: Updates BookingRecord and BookingStatus cross-contract types (adding started_at and Cancelled variant) that this PR mirrors for review validation.
  • PR #19: Implements get_booking() and booking storage in the payment-vault contract, which is called by this PR's new submit_review() logic for cross-contract verification.

Poem

🐰 A category_id hops through the registry with grace,
While reviews bloom in the scoring space,
Cross-contract calls now verify the way,
Stats accumulate, expert by day,
Score bounds enforced—no spam in this race! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Changes to identity-registry-contract (category_id parameter additions) are outside the scope of issue #54 (reputation-scoring contract review logic). These represent unrelated feature work or scope creep. Remove or isolate identity-registry-contract changes (category_id additions) into a separate PR focused on that feature to maintain clarity and single-responsibility principle for this review-logic PR.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: submit review logic' directly summarizes the main feature added—submit_review functionality for the reputation-scoring contract.
Description check ✅ Passed The PR description provides a summary of changes aligned with the template's sections, including closed issue reference, test plan, and passing tests, though formal type-of-change checkbox markup is missing.
Linked Issues check ✅ Passed The PR implementation aligns with issue #54 requirements: ExpertStats defined with correct fields, error variants added (InvalidScore, BookingNotComplete, AlreadyReviewed, NotBookingUser), storage mappings implemented, submit_review validates score (1–5), enforces contract state, performs cross-contract vault check, prevents duplicates, updates expert stats, and emits review_submitted event.
Docstring Coverage ✅ Passed Docstring coverage is 81.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
contracts/identity-registry-contract/src/contract.rs (1)

27-35: ⚠️ Potential issue | 🟠 Major

Preserve the stored category on batch re-verification.

Line 34 is hit for any non-verified expert, including previously banned ones. That means a re-verify via batch_add_experts now resets an existing category_id to 0, even though the single-item ban/unban flows preserve it. At minimum, carry forward the stored category when a record already exists.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/identity-registry-contract/src/contract.rs` around lines 27 - 35,
When batch re-verifying experts in the loop, preserve any existing category_id
instead of unconditionally passing 0 to storage::set_expert_record; call the
storage getter (e.g. storage::get_expert_record or storage::get_expert_category
/ storage::get_expert_status variant) to read the current category for the
expert and use that value when invoking storage::set_expert_record(&env,
&expert, ExpertStatus::Verified, empty_uri, category_id) so existing categories
(e.g. for previously banned experts) are retained; if no record exists fall back
to 0.
🧹 Nitpick comments (1)
contracts/identity-registry-contract/src/lib.rs (1)

89-99: Make category_id round-trippable through the public API.

update_profile now requires callers to resend category_id, but the contract still only exposes get_status. A client doing a URI-only edit has no supported way to fetch the current value first, so it's easy to overwrite it with a stale or default category. Consider adding a getter for the stored record/category, or keeping update_profile URI-only and preserving the stored category internally.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/identity-registry-contract/src/lib.rs` around lines 89 - 99, The
public API requires callers to resend category_id in update_profile which can
lead to overwrites; either add a getter that returns the stored profile record
(including category) or change update_profile to be URI-only and preserve the
existing category internally. Locate the contract functions update_profile and
batch_update_profiles and implement one of two fixes: (A) add a new public
getter (e.g., get_profile or get_category) that returns the stored URI and
category for an Address so clients can read the current category before calling
update_profile, or (B) modify contract::update_profile (and
contract::batch_update_profiles handling) to accept only a new_uri and
read/retain the existing category from storage when updating so callers need not
supply category_id. Ensure you update public API signatures accordingly and keep
get_status behavior consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@contracts/reputation-scoring-contract/src/contract.rs`:
- Around line 82-86: The call to the vault's get_booking currently deserializes
into a bare BookingRecord causing a trap when no booking exists; change the
invoke_contract deserialization to Option<BookingRecord> (e.g., let booking_opt:
Option<BookingRecord> = env.invoke_contract(...get_booking...)) and then .ok_or
or unwrap_or_else with a clear panic/error to handle missing booking; also
update MockVault in test.rs (the mock get_booking implementation and its return
type) to return Option<BookingRecord> so tests match the real ABI.

In `@contracts/reputation-scoring-contract/src/error.rs`:
- Around line 10-13: The error-code assignments in the ReputationError enum are
incorrect: change the variant named BookingNotComplete back to
InvalidBookingState with value 5, assign AlreadyReviewed value 7, and assign
NotBookingUser value 6 so codes match Issue `#54`; update the enum variant
names/values (InvalidScore = 4, InvalidBookingState = 5, NotBookingUser = 6,
AlreadyReviewed = 7) in error.rs (so callers decoding contract errors get the
correct reasons and you have a slot for a missing-booking error when the vault
lookup is fixed).

In `@contracts/reputation-scoring-contract/src/lib.rs`:
- Around line 40-47: The exported function submit_review currently only accepts
reviewer, booking_id, and score but must also accept expert and review_uri per
issue `#54`; update the public signature of submit_review (and its Env wrapper) to
include expert: Address and review_uri: String (or Bytes if URI is binary) and
pass those new args through to contract::submit_review (i.e., change the call to
contract::submit_review(&env, &reviewer, &expert, booking_id, score,
&review_uri) or the appropriate ordering), and then update the internal
contract::submit_review function signature and any call sites/ABI export so the
new parameters are accepted and propagated.

In `@contracts/reputation-scoring-contract/src/types.rs`:
- Around line 17-20: The ExpertStats struct's field types don't match the ABI in
issue `#54`: change ExpertStats (used by get_expert_stats) from { total_score:
u64, review_count: u32 } to { total_score: u64, total_reviews: u64 } so the
on-chain shape uses a u64 counter; update the struct declaration name and field
(review_count -> total_reviews, type u32 -> u64) and adjust any code, tests or
serialization/deserialization that reference ExpertStats or review_count to use
total_reviews accordingly.

---

Outside diff comments:
In `@contracts/identity-registry-contract/src/contract.rs`:
- Around line 27-35: When batch re-verifying experts in the loop, preserve any
existing category_id instead of unconditionally passing 0 to
storage::set_expert_record; call the storage getter (e.g.
storage::get_expert_record or storage::get_expert_category /
storage::get_expert_status variant) to read the current category for the expert
and use that value when invoking storage::set_expert_record(&env, &expert,
ExpertStatus::Verified, empty_uri, category_id) so existing categories (e.g. for
previously banned experts) are retained; if no record exists fall back to 0.

---

Nitpick comments:
In `@contracts/identity-registry-contract/src/lib.rs`:
- Around line 89-99: The public API requires callers to resend category_id in
update_profile which can lead to overwrites; either add a getter that returns
the stored profile record (including category) or change update_profile to be
URI-only and preserve the existing category internally. Locate the contract
functions update_profile and batch_update_profiles and implement one of two
fixes: (A) add a new public getter (e.g., get_profile or get_category) that
returns the stored URI and category for an Address so clients can read the
current category before calling update_profile, or (B) modify
contract::update_profile (and contract::batch_update_profiles handling) to
accept only a new_uri and read/retain the existing category from storage when
updating so callers need not supply category_id. Ensure you update public API
signatures accordingly and keep get_status behavior consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c345b875-1cfd-4e79-aa48-c8f571e71046

📥 Commits

Reviewing files that changed from the base of the PR and between 2482d34 and ec7fb06.

📒 Files selected for processing (12)
  • contracts/identity-registry-contract/src/contract.rs
  • contracts/identity-registry-contract/src/lib.rs
  • contracts/identity-registry-contract/src/storage.rs
  • contracts/identity-registry-contract/src/test.rs
  • contracts/identity-registry-contract/src/types.rs
  • contracts/reputation-scoring-contract/src/contract.rs
  • contracts/reputation-scoring-contract/src/error.rs
  • contracts/reputation-scoring-contract/src/events.rs
  • contracts/reputation-scoring-contract/src/lib.rs
  • contracts/reputation-scoring-contract/src/storage.rs
  • contracts/reputation-scoring-contract/src/test.rs
  • contracts/reputation-scoring-contract/src/types.rs

@Bosun-Josh121
Copy link
Copy Markdown
Collaborator

@arandomogg pls address the major and critical code rabbit comments and also remove changes to identity-registry-contract. Thanks

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.

Submit Review Logic

3 participants