feat(#689): Stellar DID layer, cross-campaign reputation score & privacy-preserving KYC attestations - #731
Merged
dotunv merged 1 commit intoAug 30, 2026
Conversation
…serving KYC attestations ## What Implements issue Savitura#689 end-to-end across the Soroban contract layer, backend services/routes, and frontend UI. ## Soroban contract (contracts/soroban/contracts/contributor_identity/) - New contributor_identity Rust contract (soroban-sdk 21.3.0) - Stores ContributorIdentity { did, attestations, reputation_score, last_updated } in persistent storage keyed by contributor Address - Functions: initialize, �dd_issuer, emove_issuer, egister (idempotent), �dd_attestation, evoke_attestation, update_reputation (clamped 0-1000), get_identity, has_attestation, �erify_proof - has_attestation enforces revocation on-chain (&& !att.revoked) - �erify_proof enforces hash match on-chain (&& att.proof_hash == proof_hash) - Added to Cargo workspace ## Database (backend/db/migrations/20260829_contributor_identity_reputation.sql) - contributor_identities (user_id, public_key, did, contract_registered_at) - kyc_attestations (proof_hash only — never raw docs or Persona inquiry content) - campaign_requirements (min_reputation_score 0-1000, required_attestations JSONB) - eputation_events append-only audit log ## Backend service (backend/src/services/contributorIdentityService.js) - egisterIdentity — builds DID, calls contract, stores DB row; idempotent - issueKycAttestation — proof_hash = SHA-256(personaInquiryId), no PII on-chain - updateReputationScore — deltas: +5 contribution_made, +10 contribution_to_successful_campaign, 0 failed, -20 dispute - getContributorProfile — returns zero personal data (no name/email/doc/inquiry ID) - �erifyAttestation — dual DB + on-chain check with RPC fallback - �ssertContributorMeetsRequirements — throws 403 CONTRIBUTOR_REQUIREMENTS_NOT_MET with structured missing[] array ## Backend routes - POST/GET /api/contributor/identity/register|:publicKey|:publicKey/verify - POST/GET /api/campaigns/:id/requirements (creator-only write, public read) - Contribution gate added to both /prepare and custodial POST / - KYC webhook fires issueKycAttestation fire-and-forget after Persona approval ## Frontend - ReputationGauge — SVG radial gauge, tiers: Newcomer/Contributor/Trusted/Veteran/Champion - AttestationsPanel — 3 KYC tiers with Get Verified CTAs, no PII displayed - ContributorIdentityPage at /profile/identity — DID, gauge, attestations, stats - Campaign page: ContributorEligibilityBadge (eligible / requirements not met + gap) and CampaignRequirementsNotice for logged-out visitors - CreateCampaign step 3: reputation slider (0-500) + KYC attestation checkboxes ## Acceptance criteria - register creates verifiable on-chain ContributorIdentity record - has_attestation returns false for revoked attestation (enforced on-chain) - verify_proof returns false on hash mismatch (enforced on-chain) - +10 reputation on campaign success - 403 CONTRIBUTOR_REQUIREMENTS_NOT_MET for score 299 vs min 300 - Eligibility indicator shows KYC gap (Basic vs Standard) - getContributorProfile schema contains zero personal data Closes Savitura#689
|
@TheHalalHunter 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! 🚀 |
Closed
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #689
Summary
Implements issue #689 end-to-end: a Stellar DID layer anchored to contributor public keys, an on-chain cross-campaign reputation score, and privacy-preserving KYC attestations where only a SHA-256 hash is stored on-chain — never the underlying document.
Changes
Soroban contract — contracts/soroban/contracts/contributor_identity/
egister(caller, did) — idempotent; emits IdentityRegistered
evoke_attestation(issuer, subject, index) — original issuer only; sets
evoked = true
Database — �ackend/db/migrations/20260829_contributor_identity_reputation.sql
eputation_events — append-only audit log of every reputation delta
Backend service — �ackend/src/services/contributorIdentityService.js
egisterIdentity(publicKey, userId) — idempotent; calls contract + inserts DB row
Backend routes
Frontend
Acceptance criteria
egister creates an on-chain ContributorIdentity record verifiable via getLedgerEntries
Deployment notes
pm run migrate to apply 20260829_contributor_identity_reputation.sql