Skip to content

Comments

Implement Identity Tokens Blueprint with Frontend and Tests#15

Open
DeveloperAmrit wants to merge 2 commits intoStabilityNexus:mainfrom
DeveloperAmrit:fix-14-blueprint
Open

Implement Identity Tokens Blueprint with Frontend and Tests#15
DeveloperAmrit wants to merge 2 commits intoStabilityNexus:mainfrom
DeveloperAmrit:fix-14-blueprint

Conversation

@DeveloperAmrit
Copy link

@DeveloperAmrit DeveloperAmrit commented Feb 7, 2026

Fixes #14

Description:
This PR introduces the foundational implementation for the Identity Tokens project, aligning with the blueprint requirements. The changes include the smart contract, frontend scaffolding, and testing infrastructure to enable decentralized identity token creation and endorsement.

  1. Smart Contract Implementation
  • Contract: IdentityToken.sol
    • Implements ERC-721 with ERC721Enumerable for token enumeration.
    • Supports on-chain metadata via setProfile and setAttribute.
    • Endorsement graph implemented using EnumerableSet:
      • _endorsedBy: Tracks who endorsed a token.
      • _endorsing: Tracks who a token has endorsed.
    • Events for profile updates, endorsements, and revocations.
  • Libraries:
    • DataTypes.sol: Defines IdentityProfile and Endorsement structs.
    • Events.sol: Added ProfileUpdated event.
    • Errors.sol: Custom errors for gas efficiency.
  1. Frontend Scaffolding
  • Framework: Next.js 14 with Tailwind CSS.
  • Components:
    • IdentityManager: Handles minting and profile updates.
    • Endorser: Handles endorsements with connection types.
  • Configuration:
    • Tailwind CSS and PostCSS configured.
    • Added global.css for styling.
  1. Testing
  • Tests: IdentityToken.t.sol
    • testMint: Verifies token creation and ownership.
    • testSetProfile: Verifies metadata storage.
    • testEndorse: Verifies endorsement graph updates.
  • Deployment Script: DeployIdentityToken.s.sol for easy deployment.
  1. Fixes
  • Resolved Tailwind CSS issues by installing autoprefixer and updating configurations.

How to Test:

  1. Contracts:
  • Run forge test to verify contract functionality.
  • Deploy using forge script script/DeployIdentityToken.s.sol.
  1. Frontend:
  • Navigate to web/ and run:
npm install
npm run dev
  • Test the IdentityManager and Endorser components.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced Identity Token NFT system with on-chain profiles featuring name, social links, and personal details
    • Launched endorsement framework allowing users to create and manage mutual attestations
    • Deployed web application interface for minting tokens, updating identities, and endorsing other users
  • Tests

    • Added test coverage for token minting, profile management, and endorsement functionality

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 7, 2026

📝 Walkthrough

Walkthrough

This PR introduces a complete IdentityToken ERC721 contract with profile management, attribute storage, and a bidirectional endorsement graph system. It includes a Forge deployment script, comprehensive tests, and a Next.js web frontend with UI components for minting, profile management, and endorsements. Placeholder sample code is removed.

Changes

Cohort / File(s) Summary
Smart Contract Core
src/IdentityToken.sol, src/libraries/DataTypes.sol, src/libraries/Events.sol
Implements ERC721-based IdentityToken with profile mappings, attribute storage (key-value bytes), and bidirectional endorsement graph (endorsedBy/endorsing sets). Includes mint, setProfile, setAttribute, endorse, and revokeEndorsement functions with ownership checks and event emission.
Deployment & Tests
script/DeployIdentityToken.s.sol, test/IdentityToken.t.sol
Adds Forge deployment script reading PRIVATE_KEY from environment and test suite covering minting, profile setting, and endorsement graph traversal.
Removed Sample Code
script/sample.s.sol, src/sample.sol, test/sample.t.sol
Deletes placeholder sample contract and related test/deployment files.
Web Frontend Configuration
web/package.json, web/tsconfig.json, web/tailwind.config.js, web/postcss.config.js, web/next-env.d.ts, web/.gitignore
Establishes Next.js 14 project with TypeScript, Tailwind CSS, RainbowKit, and Wagmi dependencies for blockchain interaction.
Web Frontend Layout & Pages
web/src/app/layout.tsx, web/src/app/page.tsx, web/src/app/global.css
Defines Next.js App Router layout with metadata, global Tailwind directives, and tabbed interface for "My Identity" and "Endorse Others" sections.
Web Frontend Components
web/src/components/IdentityManager.tsx, web/src/components/Endorser.tsx
Adds placeholder React components with form scaffolding for minting identities, updating profiles, and managing endorsements.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant UI as Web UI
    participant Contract as IdentityToken Contract
    participant Graph as Endorsement Graph

    User->>UI: Click "Mint New Identity"
    UI->>Contract: mint()
    Contract->>Contract: tokenId++ (initialize at 1)
    Contract->>User: Return tokenId
    
    User->>UI: Set Profile (name, nationality, etc.)
    UI->>Contract: setProfile(tokenId, profile)
    Contract->>Contract: Verify ownership
    Contract->>Contract: Update profiles mapping
    Contract->>Contract: Emit ProfileUpdated
    
    User->>UI: Endorse another token
    UI->>Contract: endorse(endorserTokenId, endorsedTokenId, connectionType, validUntil)
    Contract->>Graph: Add endorserTokenId to endorsedTokenId.endorsedBy set
    Contract->>Graph: Add endorsedTokenId to endorserTokenId.endorsing set
    Contract->>Contract: Store endorsement metadata (type, timestamps, validity)
    Contract->>User: Confirm endorsement created
    
    User->>UI: Query endorsers
    UI->>Contract: getEndorsers(tokenId)
    Contract->>Graph: Return endorsedBy set for tokenId
    Contract->>UI: Return array of endorser token IDs
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • Implements the core functionality described in the IdentityToken EVM contract blueprint with ERC721 minting, profile management, attribute storage, and bidirectional endorsement graph mechanics.

Possibly related PRs

  • Modifies the same IdentityToken contract and DataTypes library that are likely referenced or extended in concurrent contract development efforts.

Poem

🐰 A token born to hold identity,
With endorsements linking you and me,
Through graphs of trust, we trace the way—
New digital bonds begin today! 💫

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: implementing Identity Tokens with both smart contracts and frontend components, supported by the comprehensive additions of IdentityToken contract, tests, and web framework.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
Contributor

@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: 5

🤖 Fix all issues with AI agents
In `@src/IdentityToken.sol`:
- Around line 51-71: The endorse function currently overwrites an existing
active endorsement silently; before modifying _endorsedBy, _endorsing, or
endorsements, check the current endorsements[endorserTokenId][endorsedTokenId]
and if it exists and is active (revokedAt == 0 and validUntil > block.timestamp)
revert (e.g. Errors.ActiveEndorsementExists()) or require explicit revocation
first; alternatively, use the boolean result from the EnumerableSet.add calls
for _endorsedBy[_endorsedTokenId].add and _endorsing[endorserTokenId].add to
detect pre-existence and combine that with the endorsement struct check to
decide whether to revert instead of overwriting, and only emit
Events.EndorsementGiven after the guard passes.
- Around line 32-36: The mint() function currently allows any address to mint
unlimited identity tokens; enforce a one-token-per-address rule by adding a
check in mint() (e.g., require(balanceOf(msg.sender) == 0, ...) or use a mapping
like hasMinted[address]) and set the flag after successful _safeMint;
alternatively, if unlimited mints are intended, add clear documentation on the
contract/interface and tests referencing mint() to explain the design choice.
Ensure the change references the mint() function and the chosen storage
(balanceOf or hasMinted) and update any related tests/comments accordingly.

In `@src/libraries/DataTypes.sol`:
- Around line 13-19: The IdentityProfile struct currently stores raw PII (name,
socialLinks, birthDate, nationality, residence); change it to store only
non-reversible representations (e.g., bytes32 or string hashes) and update any
setter/getter functions (e.g., setProfile, getProfile) to accept/return hashed
values while documenting that actual plaintext records must be stored off-chain
(IPFS/secure backend) and linked via the hash; also add clear NatSpec comments
to IdentityProfile and setProfile that warn about on-chain permanence and
require explicit consent parameter/flag when users submit PII so callers are
aware and can confirm consent.

In `@test/IdentityToken.t.sol`:
- Around line 44-60: Add negative tests to IdentityToken.t.sol to cover
endorsement and identity edge cases: write new test functions that ensure
token.endorse reverts when called by a non-owner (call endorse from an address
that doesn't own the endorsing tokenId), when attempting self-endorsement
(endorserId == targetId), when referencing a non-existent tokenId (use a tokenId
that was never minted), and when trying to create duplicate endorsements if
contract should prevent duplicates (assert revert or that endorsers array
doesn't grow). Also add tests for revokeEndorsement to verify only authorized
actors (owner of endorsing token or target as specified) can revoke and that
revoking non-existent endorsements fails, and add tests for setAttribute to
assert authorization checks (only token owner can set attributes) and that
invalid inputs revert; locate usage around token.mint(), token.endorse(...),
token.revokeEndorsement(...), token.setAttribute(...), and
token.getEndorsers(...) when implementing these tests.

In `@web/package.json`:
- Line 15: The package.json pins the "next" dependency to an insecure/outdated
version ("next": "14.1.0"); update the "next" entry to a supported
release—preferably "15.x" (e.g. "15.5.11") or at minimum bump to the latest 14.x
patch (e.g. "14.2.35") if you must stay on 14; after changing the "next" version
string in package.json, run your package manager (npm install or yarn install /
pnpm install) and test build/start scripts (next build, next dev) and any custom
Server Actions or image optimization flows to ensure compatibility.
🧹 Nitpick comments (16)
web/next-env.d.ts (1)

1-5: Consider adding next-env.d.ts to .gitignore.

This is an auto-generated file (as noted by the comment on Line 4). Next.js documentation recommends excluding it from version control since it's regenerated on each build. Adding it to web/.gitignore avoids noisy diffs.

web/package.json (2)

14-14: ethers may be redundant alongside viem + wagmi.

Both ethers and viem are Ethereum client libraries serving overlapping purposes. Since wagmi and @rainbow-me/rainbowkit are built on viem, adding ethers increases the bundle size without clear benefit. Unless there's a specific need for ethers (e.g., a dependency that requires it), consider removing it and using viem exclusively.


11-19: Dependency version ranges are inconsistently specified and overly broad.

next is pinned exactly (14.1.0) while others use very loose caret ranges (^18, ^5, ^2.0.0). Ranges like "react": "^18" could resolve to any 18.x, and future major-adjacent changes may break builds. Consider either:

  • Pinning all dependencies to specific versions for reproducibility, or
  • Using narrower caret ranges (e.g., ^18.2.0 instead of ^18)
src/libraries/DataTypes.sol (1)

22-22: Nit: trailing comment is vague.

// logic for recovery doesn't add useful context beyond what the surrounding struct fields already convey. Consider either expanding it to explain the recovery mechanism or removing it.

web/.gitignore (1)

1-1: Add next-env.d.ts to ignore auto-generated Next.js files.

The root .gitignore already covers node_modules/, out/, and .env*.local patterns. However, next-env.d.ts (auto-generated by Next.js) is not ignored at the root level and should be added to this file-specific .gitignore.

web/tsconfig.json (1)

10-10: Consider enabling strict: true for a new project.

Since this is a greenfield codebase, enabling TypeScript strict mode from the start catches common type errors early (null checks, implicit any, etc.) and avoids a costly migration later. It's much harder to enable strict mode retroactively.

Suggested change
-    "strict": false,
+    "strict": true,
web/src/app/layout.tsx (1)

3-6: Update placeholder metadata to reflect the project.

The title and description are still Next.js defaults. These values appear in browser tabs and search results.

Suggested change
 export const metadata = {
-  title: 'Next.js',
-  description: 'Generated by Next.js',
+  title: 'Identity Tokens',
+  description: 'Manage and endorse on-chain identity tokens',
 }
src/IdentityToken.sol (2)

92-92: Hardcoded 0 for the index parameter in EndorsementRevoked event is misleading.

The comment says "index 0 as using sets" but this conveys no useful information to event consumers. If the event signature includes an index field that doesn't apply, consider removing it from the event definition or passing a meaningful value.


96-102: Unbounded values() return can cause gas issues for large endorsement sets.

getEndorsers and getEndorsing return the full set via values(), which copies the entire array to memory. For tokens with many endorsements, this could exceed the block gas limit for view calls or be very expensive for on-chain callers. Consider adding paginated variants.

web/src/components/IdentityManager.tsx (1)

29-47: Associate <label> elements with their inputs for accessibility.

The labels lack htmlFor attributes and the inputs lack id attributes, which breaks screen reader association and click-to-focus behavior.

Example for the Name field
-          <label className="block text-sm font-medium text-gray-700">Name</label>
+          <label htmlFor="identity-name" className="block text-sm font-medium text-gray-700">Name</label>
           <input 
+            id="identity-name"
             type="text" 

Apply the same pattern for the Nationality input.

web/src/components/Endorser.tsx (2)

17-39: Same accessibility concern: associate labels with inputs via htmlFor/id.

Both the <input> and <select> elements lack id attributes, and the corresponding <label> elements lack htmlFor. This affects screen reader users and click-to-focus behavior. Apply the same pattern as suggested for IdentityManager.


8-11: handleEndorse doesn't validate inputs before proceeding.

Users can click "Endorse" with empty targetTokenId or no connectionType selected. Even as a scaffold, adding basic guard-returns prevents confusion during development.

Suggested guard
   const handleEndorse = async () => {
+    if (!targetTokenId || !connectionType) return;
     console.log("Endorsing token:", targetTokenId, "Type:", connectionType);
web/src/app/page.tsx (2)

14-27: Consider adding basic accessibility attributes to the tab buttons.

These buttons function as tabs but lack role="tab", aria-selected, and a wrapping role="tablist" on the container. Screen readers won't convey the tab semantics. Worth adding even in a scaffold to establish the pattern early.

♻️ Suggested improvement
-      <div className="flex gap-4 mb-8">
+      <div className="flex gap-4 mb-8" role="tablist">
         <button 
           onClick={() => setActiveTab('identity')}
-          className={`px-4 py-2 border rounded ${activeTab === 'identity' ? 'bg-blue-500 text-white' : ''}`}
+          role="tab"
+          aria-selected={activeTab === 'identity'}
+          className={`px-4 py-2 border rounded ${activeTab === 'identity' ? 'bg-blue-500 text-white' : ''}`}
         >
           My Identity
         </button>
         <button 
           onClick={() => setActiveTab('endorse')}
-          className={`px-4 py-2 border rounded ${activeTab === 'endorse' ? 'bg-blue-500 text-white' : ''}`}
+          role="tab"
+          aria-selected={activeTab === 'endorse'}
+          className={`px-4 py-2 border rounded ${activeTab === 'endorse' ? 'bg-blue-500 text-white' : ''}`}
         >
           Endorse Others
         </button>
       </div>

11-11: p-24 may clip content on smaller viewports.

6rem of padding on all sides can push content off-screen on mobile. Consider a responsive value like p-6 md:p-24.

test/IdentityToken.t.sol (2)

25-42: testSetProfile — only asserts the name field.

The destructured read (string memory name,,,,) validates only one of five struct fields. Consider asserting all fields to catch struct packing or ordering bugs.

♻️ Suggested improvement
-        (string memory name,,,,) = token.profiles(tokenId);
-        assertEq(name, "Alice");
+        (
+            string memory name,
+            string memory socialLinks,
+            uint256 birthDate,
+            string memory nationality,
+            string memory residence
+        ) = token.profiles(tokenId);
+        assertEq(name, "Alice");
+        assertEq(socialLinks, "twitter.com/alice");
+        assertEq(birthDate, 1000);
+        assertEq(nationality, "Wonderland");
+        assertEq(residence, "Rabbit Hole");

53-54: Clarify the semantic meaning of validUntil parameter value 0.

The fourth parameter to endorse() is validUntil (a timestamp for endorsement expiration), not a weight or score. While the parameter name is descriptive, passing 0 as the value is unclear—adding a comment explaining whether 0 means "no expiration" or another semantic would improve test readability.

Comment on lines +32 to +36
function mint() external returns (uint256) {
uint256 tokenId = _nextTokenId++;
_safeMint(msg.sender, tokenId);
return tokenId;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

No per-address mint limit — any address can mint unlimited identity tokens.

For an identity token system, it's likely undesirable for a single address to hold many identities. Consider adding a one-token-per-address constraint, or at minimum documenting the design intent.

Example constraint
 function mint() external returns (uint256) {
+    if (balanceOf(msg.sender) > 0) revert Errors.AlreadyHasIdentity();
     uint256 tokenId = _nextTokenId++;
     _safeMint(msg.sender, tokenId);
     return tokenId;
 }
🤖 Prompt for AI Agents
In `@src/IdentityToken.sol` around lines 32 - 36, The mint() function currently
allows any address to mint unlimited identity tokens; enforce a
one-token-per-address rule by adding a check in mint() (e.g.,
require(balanceOf(msg.sender) == 0, ...) or use a mapping like
hasMinted[address]) and set the flag after successful _safeMint; alternatively,
if unlimited mints are intended, add clear documentation on the
contract/interface and tests referencing mint() to explain the design choice.
Ensure the change references the mint() function and the chosen storage
(balanceOf or hasMinted) and update any related tests/comments accordingly.

Comment on lines +51 to +71
function endorse(uint256 endorserTokenId, uint256 endorsedTokenId, bytes32 connectionType, uint256 validUntil) external {
if (ownerOf(endorserTokenId) != msg.sender) revert Errors.NotTokenOwner();
if (endorserTokenId == endorsedTokenId) revert Errors.SelfEndorsement();

// Ensure endorsed token exists
_requireOwned(endorsedTokenId);

// Update sets
_endorsedBy[endorsedTokenId].add(endorserTokenId);
_endorsing[endorserTokenId].add(endorsedTokenId);

endorsements[endorserTokenId][endorsedTokenId] = DataTypes.Endorsement({
endorserTokenId: endorserTokenId,
connectionType: connectionType,
timestamp: block.timestamp,
validUntil: validUntil,
revokedAt: 0
});

emit Events.EndorsementGiven(endorserTokenId, endorsedTokenId, connectionType, validUntil);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

endorse silently overwrites an existing active endorsement.

If token A already actively endorses token B and calls endorse again with a different connectionType or validUntil, the previous endorsement is silently overwritten. The EnumerableSet.add returns false (already present) but this is ignored. Consider either reverting if an active endorsement exists or explicitly requiring revocation first.

Suggested guard
     _requireOwned(endorsedTokenId);

+    // Prevent overwriting an active endorsement
+    if (_endorsing[endorserTokenId].contains(endorsedTokenId)) {
+        revert Errors.AlreadyEndorsed();
+    }
+
     // Update sets
     _endorsedBy[endorsedTokenId].add(endorserTokenId);
🤖 Prompt for AI Agents
In `@src/IdentityToken.sol` around lines 51 - 71, The endorse function currently
overwrites an existing active endorsement silently; before modifying
_endorsedBy, _endorsing, or endorsements, check the current
endorsements[endorserTokenId][endorsedTokenId] and if it exists and is active
(revokedAt == 0 and validUntil > block.timestamp) revert (e.g.
Errors.ActiveEndorsementExists()) or require explicit revocation first;
alternatively, use the boolean result from the EnumerableSet.add calls for
_endorsedBy[_endorsedTokenId].add and _endorsing[endorserTokenId].add to detect
pre-existence and combine that with the endorsement struct check to decide
whether to revert instead of overwriting, and only emit Events.EndorsementGiven
after the guard passes.

Comment on lines +13 to +19
struct IdentityProfile {
string name;
string socialLinks;
uint256 birthDate;
string nationality;
string residence;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Storing PII on-chain creates permanent privacy exposure.

Fields like birthDate, nationality, and residence are personally identifiable information. Once written to the blockchain, this data is immutable and publicly visible forever — it cannot be deleted or modified in compliance with GDPR/CCPA right-to-erasure requirements.

Consider:

  • Storing only hashes of sensitive fields on-chain (for verification) with the actual data off-chain (e.g., IPFS with encryption, or a traditional backend).
  • At minimum, document the privacy implications clearly so users give informed consent before calling setProfile.
🤖 Prompt for AI Agents
In `@src/libraries/DataTypes.sol` around lines 13 - 19, The IdentityProfile struct
currently stores raw PII (name, socialLinks, birthDate, nationality, residence);
change it to store only non-reversible representations (e.g., bytes32 or string
hashes) and update any setter/getter functions (e.g., setProfile, getProfile) to
accept/return hashed values while documenting that actual plaintext records must
be stored off-chain (IPFS/secure backend) and linked via the hash; also add
clear NatSpec comments to IdentityProfile and setProfile that warn about
on-chain permanence and require explicit consent parameter/flag when users
submit PII so callers are aware and can confirm consent.

Comment on lines +44 to +60
function testEndorse() public {
vm.startPrank(user1);
uint256 tokenId1 = token.mint();
vm.stopPrank();

vm.startPrank(user2);
uint256 tokenId2 = token.mint();

// User2 endorses User1
bytes32 connectionType = keccak256("friend");
token.endorse(tokenId2, tokenId1, connectionType, 0);

uint256[] memory endorsers = token.getEndorsers(tokenId1);
assertEq(endorsers.length, 1);
assertEq(endorsers[0], tokenId2);
vm.stopPrank();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

git ls-files | grep -E "(IdentityToken|identity)" | head -20

Repository: StabilityNexus/IdentityTokens-EVM-Contracts

Length of output: 166


🏁 Script executed:

cat -n src/IdentityToken.sol

Repository: StabilityNexus/IdentityTokens-EVM-Contracts

Length of output: 5646


🏁 Script executed:

cat -n test/IdentityToken.t.sol

Repository: StabilityNexus/IdentityTokens-EVM-Contracts

Length of output: 2226


Add negative tests for endorsement and identity functions.

The endorsement and identity operations lack edge case testing critical for contract integrity:

  • Endorsing without token ownership (authorization)
  • Self-endorsement protection
  • Non-existent token endorsement
  • Duplicate/overwrite endorsement behavior
  • revokeEndorsement (function exists but completely untested)
  • setAttribute (function exists but completely untested)

Both revokeEndorsement and setAttribute contain authorization checks that need validation. The contract properly guards these operations, but the test suite should verify all guard clauses and failure modes.

🤖 Prompt for AI Agents
In `@test/IdentityToken.t.sol` around lines 44 - 60, Add negative tests to
IdentityToken.t.sol to cover endorsement and identity edge cases: write new test
functions that ensure token.endorse reverts when called by a non-owner (call
endorse from an address that doesn't own the endorsing tokenId), when attempting
self-endorsement (endorserId == targetId), when referencing a non-existent
tokenId (use a tokenId that was never minted), and when trying to create
duplicate endorsements if contract should prevent duplicates (assert revert or
that endorsers array doesn't grow). Also add tests for revokeEndorsement to
verify only authorized actors (owner of endorsing token or target as specified)
can revoke and that revoking non-existent endorsements fails, and add tests for
setAttribute to assert authorization checks (only token owner can set
attributes) and that invalid inputs revert; locate usage around token.mint(),
token.endorse(...), token.revokeEndorsement(...), token.setAttribute(...), and
token.getEndorsers(...) when implementing these tests.

"@rainbow-me/rainbowkit": "^2.0.0",
"@tanstack/react-query": "^5.0.0",
"ethers": "^6.10.0",
"next": "14.1.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Next.js 14.1.0 release date security vulnerabilities

💡 Result:

Next.js 14.1.0 release date

  • The npm package page for next@14.1.0 shows it was published “2 years ago” (relative, not an exact timestamp). [1]

Security vulnerabilities affecting Next.js 14.1.0

next@14.1.0 is within affected ranges for multiple disclosed issues; notable ones include:

  • SSRF in Server Actions (self-hosted scenarios) — affects Next.js versions >=13.4.0 and <14.1.1; fix: upgrade to 14.1.1+. [2]
  • DoS via Server Actions hanging requests — affects >=13.0.0 and <14.2.21; fix: upgrade to 14.2.21+. [3]
  • DoS in image optimization (excessive CPU consumption) — affects versions <14.2.7; fix: upgrade to 14.2.7+. [4]
  • React Server Components protocol issues (DoS / source code exposure) — advisory says Next.js 14.x users should upgrade; for the 14.x line it points users to upgrade to the latest 14.2.x (and shows 14.2.35 as the fixed version for the DoS item in that bulletin). [5]

Support status note

  • Next.js 14.x is listed as unsupported in the official Next.js support policy (security fixes are no longer guaranteed). [6]

Sources: [1] npm (next@14.1.0) • [2] Snyk entry for next@14.1.0 (SSRF fixed in 14.1.1) • [3] GitHub security advisory GHSA-7m27-7ghc-44w9 • [4] GitHub security advisory GHSA-g77x-44xx-532m • [5] Next.js security update (Dec 11, 2025) • [6] Next.js support policy.


🌐 Web query:

Next.js 14.x 15.x latest stable versions 2025 2026

💡 Result:

As of Feb 7, 2026, the latest stable patch versions in each major line are:

Major line Latest stable version Release date (per sources) Notes
Next.js 15.x 15.5.11 Jan 28, 2026 15.x is in Maintenance LTS. [1][2]
Next.js 14.x 14.2.35 Dec 11, 2025 14.x is unsupported (EOL), but 14.2.35 is a key patched release. [3][2][4]

Sources: [1][2][3][4]


🌐 Web query:

Next.js 14.1.0 security patches updates

💡 Result:

Next.js 14.1.0 is not a “patched” baseline for several newer disclosures; the fixes landed in later 14.2.x releases, and v14 security support ended Oct 26, 2025. (endoflife.date)

Security-relevant updates you should apply (from 14.1.0)

What to do

  • If you must stay on v14: upgrade to at least next@14.2.35 (covers the Dec 11, 2025 RSC fixes and is the last v14 “latest” listed). (nextjs.org)
  • For ongoing security support, plan to migrate to a supported major (per lifecycle tracking, v15/v16 are supported; v14 is not). (endoflife.date)

Citations:


next is pinned to an outdated and unsupported version (14.1.0).

Next.js 14.1.0 is vulnerable to multiple security issues including SSRF in Server Actions, DoS attacks via Server Actions and image optimization, and React Server Components protocol vulnerabilities. Next.js 14.x reached end-of-life on October 26, 2025, and no longer receives security updates.

Upgrade to Next.js 15.x (current LTS, latest: 15.5.11) for ongoing security support. If you must remain on 14.x for compatibility, upgrade to at least 14.2.35.

🤖 Prompt for AI Agents
In `@web/package.json` at line 15, The package.json pins the "next" dependency to
an insecure/outdated version ("next": "14.1.0"); update the "next" entry to a
supported release—preferably "15.x" (e.g. "15.5.11") or at minimum bump to the
latest 14.x patch (e.g. "14.2.35") if you must stay on 14; after changing the
"next" version string in package.json, run your package manager (npm install or
yarn install / pnpm install) and test build/start scripts (next build, next dev)
and any custom Server Actions or image optimization flows to ensure
compatibility.

@aniket866
Copy link
Contributor

aniket866 commented Feb 7, 2026

@DeveloperAmrit refer this advised by @KanishkSogani
#2 (comment)
I had implemented what you are proposing now but as by maintainer we will cover it gradually so that everyone will get idea of what's going on , not one person
we don't even had any prior discussion about how will the contracts will work and you have written 10 thousand+ lines of code

most of the setup files are already covered in PR #9 , we all are waiting for this to get merged only after we will start writing contracts with prior discussion on discord and after assignment of issues

@Nikuunj
Copy link

Nikuunj commented Feb 7, 2026

@DeveloperAmrit how to write 10,000 line of code in one PR

@DeveloperAmrit
Copy link
Author

DeveloperAmrit commented Feb 8, 2026

@Nikuunj If you ever pushed a new Node js proejct, the package-lock.json file has a lot of lines

image

@DeveloperAmrit
Copy link
Author

@aniket866 I read that convo, my PR only provides a blueprint for the later development of DIT contract. I read the TNT and VouchMe projects and requirements in info repo, based on that i have done these changes.

Also, web/package-lock.json has alone about 10,080 lines, so i have written code for around only 520 lines.

@DeveloperAmrit
Copy link
Author

@aniket866 This #8 has nothing to do with this PR

@aniket866
Copy link
Contributor

aniket866 commented Feb 8, 2026

@aniket866 This #8 has nothing to do with this PR

it is related and have you seen message by maintainer? neither you had any prior discussion on the discord?
once maintainer clarified everybody not to raise PR before they get issue assigned
and also we should have a healthy discussion first , what we are going to implement , not just doing LLM blindfolded

let's see maintainer @KanishkSogani 's view on this

@Nikuunj
Copy link

Nikuunj commented Feb 8, 2026

@Nikuunj If you ever pushed a new Node js proejct, the package-lock.json file has a lot of lines

image

yaa it ohkk, but what is role of /web

@aniket866
Copy link
Contributor

aniket866 commented Feb 8, 2026

@DeveloperAmrit it seems like you haven't got any idea of what to implement and where ? ,I would advise you to first wait for the basic design developed by @Nikuunj and kushal then only start raising issues , we are moving gradually

, one more thing @Nikuunj and @kushal is already working jointly on frontend part as the work assigned by mentor , because they have worked on figma designs so they have a good idea of what to implement , so maintainer allowed them to work on pages.

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.

Implement Identity Tokens Blueprint with Frontend and Tests

3 participants