Skip to content

Pull Request: Credential Sharing Contract#120

Merged
Josie123-Dev merged 13 commits into
GuardZero144:mainfrom
ImperiumAbuja:me/gf
Jul 19, 2026
Merged

Pull Request: Credential Sharing Contract#120
Josie123-Dev merged 13 commits into
GuardZero144:mainfrom
ImperiumAbuja:me/gf

Conversation

@Wilfred007

Copy link
Copy Markdown
Contributor

Summary
Extends the existing DataSharing Soroban smart contract with a full-featured credential sharing system for health credentials. Adds granular permission levels (View, Download, Re-share), time-limited access with expiry, revocation with audit trail, and on-chain event tracking for all sharing operations.
Changes
New Types (types.rs)

  • SharingPermission enum: View (read-only status verification), Download (full credential access), ReShare (can share with others)
  • CredentialShareEvent struct: captures share_id, owner, recipient, permission, action, and timestamp for audit events
    New Error Variants (errors.rs)
  • PermissionDenied (21) - returned when a share holder lacks sufficient permission for an operation
  • ShareExpired (22) - returned when attempting operations on an expired share
  • CannotReShare (23) - returned when a non-ReShare holder attempts to re-share
    Storage Layer (storage.rs)
  • SharingDataKey enum with persistent storage keys: ShareCounter, ShareRecord(u64), ShareByOwner(Address), ShareByRecipient(Address)
    Event Emission (events.rs)
  • emit_credential_share_event() - publishes on-chain events for share/revoke/extend/re-share operations with owner, share ID, and full event payload
    Contract Functions (data_sharing.rs)
  • share_credential(owner, recipient, credential_hash, encrypted_key, permission, duration_seconds) -> u64 - creates a time-limited credential share with specified permission level, emits event, populates owner/recipient indices
  • check_credential_access(grantee, credential_hash) -> bool - verifies if a grantee has active, non-expired access to a credential by scanning recipient index
  • get_credential_share(share_id) -> CredentialShare - retrieves full share details including permission, expiry, and revocation status
  • get_shares_by_owner(owner) -> Vec - lists all share IDs created by an owner
  • get_shares_by_recipient(recipient) -> Vec - lists all share IDs received by a recipient
  • revoke_credential_share(share_id, reason) -> Result<(), Error> - soft-deletes a share with reason and timestamp for audit, emits revocation event
  • extend_credential_share(share_id, additional_seconds) -> Result<(), Error> - extends share expiry, emits extension event
  • re_share_credential(share_id, new_recipient, new_permission, duration_seconds) -> Result<u64, Error> - creates a new share from an existing ReShare holder, enforces permission check and recipient authorization
    Data Model (CredentialShare struct)
    owner, recipient, credential_hash, encrypted_key,
    permission, access_expiry, is_active, shared_at,
    revoked_at, revocation_reason
    Storage Pattern
    Uses persistent storage with TTL management (matching verification.rs pattern):
  • Counter in instance storage
  • Per-share records in persistent storage with bump_persistent() TTL extension
  • Owner/recipient indices for efficient party-based lookups
    Testing
    117 tests passing (13 new credential sharing tests):
    Happy Path (7 tests)
  • test_share_credential_and_retrieve - share creation and full data retrieval
  • test_check_credential_access_active - access verification for active shares
  • test_check_credential_access_denied_for_unknown - no access for unregistered parties
  • test_revoke_credential_share - revocation disables access and preserves reason
  • test_extend_credential_share - extension grants additional time window
  • test_share_credential_expires - expired shares deny access
  • test_re_share_credential - ReShare permission creates independent sub-shares
    Edge Cases (6 tests)
  • test_re_share_denied_without_permission - View/Download holders cannot re-share
  • test_revoke_expired_share - revoking expired shares still records reason
  • test_get_shares_by_owner_and_recipient - index queries return correct counts
  • test_get_nonexistent_credential_share_panics - invalid ID panics
  • test_revoke_nonexistent_credential_share_panics - invalid ID panics
  • test_re_share_credential - third party receives View access via ReShare chain
    Auth Rules
  • share_credential: owner must authorize
  • revoke_credential_share: owner must authorize
  • extend_credential_share: owner must authorize
  • re_share_credential: current recipient must authorize (only if permission == ReShare)
  • Read functions: no auth required
    Tradeoffs
  • Index writes on share creation: Each share_credential and re_share_credential call appends to two persistent storage indices (owner, recipient). This increases gas cost per share creation but enables O(1) party-based lookups. The alternative (scan all shares) would be prohibitively expensive for large share volumes.
  • Persistent vs instance storage: New credential sharing uses persistent storage with TTL (matching verification.rs), while legacy SharedData remains in instance storage. This adds a migration consideration if the old sharing API is ever deprecated.
  • ReShare cascading: Re-shared shares are independent records with their own expiry. A re-share does not inherit the original share's TTL - the original holder controls the new share's duration. This prevents cascading expiry issues but means revoking the original share does not automatically revoke re-shares.
  • Event emission overhead: Every mutation emits an on-chain event. This increases transaction cost but provides a complete audit trail required for health credential compliance.
    Out of Scope
  • Frontend integration for the new credential sharing API
  • Backend API endpoints for credential sharing (existing data-sharing NestJS module handles this)
  • Migration of legacy SharedData shares to the new CredentialShare format
  • Batch sharing (sharing with multiple recipients in one transaction)

Closes #88

@vercel

vercel Bot commented Jul 19, 2026

Copy link
Copy Markdown

@Akatenvictor is attempting to deploy a commit to the Josie's projects Team on Vercel.

A member of the Team first needs to authorize it.

Add PermissionDenied, ShareExpired, and CannotReShare error variants
to support the credential sharing feature with permission checks,
time-limited access, and re-sharing authorization.
SharingPermission provides three granular access levels for credential
sharing: View (read-only status), Download (full credential access),
and ReShare (can share with others). CredentialShareEvent captures
sharing activity for on-chain audit trail.
Defines typed storage keys for credential sharing: ShareCounter for
auto-incrementing IDs, ShareRecord for per-share data, and index keys
for owner/recipient lookups. Uses persistent storage for TTL management.
Emits on-chain events for all credential sharing operations (share,
revoke, extend, re-share) with owner, share ID, and full event payload
for off-chain indexing and audit compliance.
Defines the CredentialShare data model with permission levels, revocation
tracking, and TTL-based persistent storage. Includes read/write helpers
that manage entry expiration for long-lived credential shares.
Creates credential shares with granular View/Download/ReShare permissions,
time-limited access, persistent storage with TTL, and emits on-chain
events for audit trail. Owner authorization required.
check_credential_access verifies if a grantee has active, non-expired
access to a credential. get_credential_share retrieves full share details.
Owner/recipient index functions enable listing all shares for a party.
Revoke stores reason and timestamp for audit trail. Extend allows owner
to add time. Re-share requires ReShare permission on original share and
recipient authorization, creating a new share with independent expiry.
All operations emit events.
Tests cover: share and retrieve, access check active/denied, revoke with
reason, extend with expiry, time-based expiry, and re-share with
permission propagation. All tests use the new credential sharing API.
Tests cover: re-share denied without ReShare permission, revoking expired
shares preserves reason, owner/recipient index queries, and panics on
nonexistent share IDs. Validates error handling and authorization guards.
share_credential and re_share_credential now populate ShareByOwner and
ShareByRecipient persistent storage indices, enabling lookup functions
and access checks to find shares by party. Remove unused symbol_short
import.
@Josie123-Dev

Copy link
Copy Markdown
Member

Kindly check failing ci checks @Wilfred007

Fix cargo fmt --check failures in CI by reformatting long function
signatures, chained method calls, and import statements to match
standard rustfmt rules.
@Wilfred007

Copy link
Copy Markdown
Contributor Author

Kindly check failing ci checks @Wilfred007

Okay, I'm on it

Remove 27 needless &env borrows where env is already &Env. Rename
SharingDataKey variants (ShareCounter->Counter, ShareRecord->Record,
ShareByOwner->ByOwner, ShareByRecipient->ByRecipient) to satisfy
clippy::enum_variant_names lint.
@Wilfred007

Copy link
Copy Markdown
Contributor Author

Kindly confirm ci check pass @Josie123-Dev

@Josie123-Dev
Josie123-Dev merged commit 4329853 into GuardZero144:main Jul 19, 2026
1 of 2 checks passed
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.

[Medium] Add Credential Sharing contract

3 participants