Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
ad4b10f
feat: Configure npm with `.npmrc`, update Dockerfile to include it an…
igun997 Dec 2, 2025
3c23eb6
refactor: improve type safety in scan and verify API routes and ensur…
igun997 Dec 2, 2025
f888816
Merge pull request #19 from cds-id/bugfix/onboarding
igun997 Dec 2, 2025
2eefec3
feat: add complete database seeding script and command for realistic …
igun997 Dec 2, 2025
1195cee
Merge pull request #20 from cds-id/bugfix/onboarding
igun997 Dec 2, 2025
c17c184
feat: Implement statistics cards and scan location maps for managemen…
igun997 Dec 2, 2025
93c01a5
Merge pull request #21 from cds-id/feature/map-distribution
igun997 Dec 2, 2025
519c698
feat: Add pagination to manage pages and introduce tests for AI agent…
igun997 Dec 2, 2025
15d9450
Merge pull request #22 from cds-id/feature/test-unit
igun997 Dec 2, 2025
7430a5c
fix: apply codeowner to prevent crash
igun997 Dec 2, 2025
197363d
feat: Add initial landing page with hero, features, and CTA sections.
inact25 Dec 2, 2025
72b03e0
Update .github/CODEOWNERS
igun997 Dec 2, 2025
7f141c6
Merge branch 'develop' into feature/test-unit
igun997 Dec 2, 2025
5b18e1f
Merge pull request #23 from cds-id/feature/test-unit
igun997 Dec 2, 2025
078800e
Merge pull request #24 from cds-id/revamp/landing
igun997 Dec 2, 2025
86c2682
Feature/test unit (#25)
igun997 Dec 3, 2025
67f10dd
feat: introduce explorer and landing pages, enhance scan features, an…
igun997 Dec 3, 2025
cf1373f
Merge pull request #26 from cds-id/feature/landing
igun997 Dec 3, 2025
4d33ecf
Add chown option to COPY command for public directory.
igun997 Dec 3, 2025
ed67725
Merge pull request #27 from cds-id/feature/landing
igun997 Dec 3, 2025
8336ff9
feat: Implement NFT collectible management, claiming, and smart contr…
igun997 Dec 3, 2025
677a227
feat: Implement NFT collectible minting, claiming, and management wit…
igun997 Dec 3, 2025
079d579
feat: Add NFT display and pagination to explorer page with new API en…
igun997 Dec 3, 2025
7fa73a7
feat: add NFT management actions and statistics, and remove developer…
igun997 Dec 3, 2025
290eaf9
Merge pull request #28 from cds-id/feature/collectible
igun997 Dec 3, 2025
549c55c
feat: Add and conditionally display NFTClaimCard on the scan page aft…
igun997 Dec 3, 2025
9b38263
Merge pull request #29 from cds-id/feature/collectible
igun997 Dec 3, 2025
c883249
refactor: move `formatAddress` utility from `useWeb3` hook to `consta…
igun997 Dec 3, 2025
0d8f422
Merge pull request #30 from cds-id/feature/collectible
igun997 Dec 3, 2025
aaa83e3
refactor: Remove manual location mismatch detection, deferring logic …
igun997 Dec 3, 2025
967bac1
feat: introduce NFT Collectible functionality and remove tag status a…
igun997 Dec 3, 2025
b62fcf3
feat: Add contributors leaderboard and GitHub badges to README.
igun997 Dec 3, 2025
be99411
Merge pull request #31 from cds-id/bugfix/verify-page
igun997 Dec 3, 2025
0d5d003
style: Adjust image container styling and layout across landing page …
igun997 Dec 4, 2025
e7d110c
feat: enhance explorer tabs with responsive layout, overflow handling…
igun997 Dec 4, 2025
333941d
Merge pull request #32 from cds-id/bugfix/landing
igun997 Dec 4, 2025
0edd469
feat: Add smart contract audit scan report and document `CONTRACT_OWN…
igun997 Dec 4, 2025
7e1d731
feat: Implement a comprehensive support ticket system with new databa…
igun997 Dec 4, 2025
44f8e78
feat: Implement a comprehensive support ticket system, introducing ne…
igun997 Dec 4, 2025
20b37cb
feat: Enhance support ticket reopening logic and refactor header for …
igun997 Dec 4, 2025
b6118ad
Merge pull request #33 from cds-id/feature/ticket-issues
igun997 Dec 4, 2025
70bc0b0
feat: Redesign login and register pages with a new two-column layout,…
igun997 Dec 4, 2025
bbb867e
Merge pull request #34 from cds-id/feature/login
igun997 Dec 4, 2025
b329504
feat: Implement new UI components for tag management, including stamp…
igun997 Dec 4, 2025
186ab53
chore: lowercase CI build job name in CI workflow.
igun997 Dec 4, 2025
01c23d4
Merge pull request #35 from cds-id/feature/code-quality
igun997 Dec 4, 2025
84369e1
feat: implement new FAQ page with search, categories, and accordion c…
igun997 Dec 4, 2025
4ba8a07
Merge pull request #36 from cds-id/feature/faqs
igun997 Dec 4, 2025
8eb2c98
chore(deps): bump next from 16.0.6 to 16.0.7
dependabot[bot] Dec 4, 2025
ea1cbaf
chore(deps): bump jws from 4.0.0 to 4.0.1
dependabot[bot] Dec 4, 2025
a2c018c
Merge pull request #38 from cds-id/dependabot/npm_and_yarn/jws-4.0.1
igun997 Dec 4, 2025
40a87d1
Merge branch 'develop' into dependabot/npm_and_yarn/next-16.0.7
igun997 Dec 4, 2025
9fdda57
Merge pull request #37 from cds-id/dependabot/npm_and_yarn/next-16.0.7
igun997 Dec 4, 2025
d10682f
Remove RocketJourney component and GSAP dependencies, refine Features…
igun997 Dec 5, 2025
8883985
Merge pull request #39 from cds-id/feature/faqs
igun997 Dec 5, 2025
e8a0013
Merge pull request #40 from cds-id/feature/optimize-landing
igun997 Dec 6, 2025
82e8c85
docs: guide for imphen 2025
igun997 Dec 6, 2025
fb3bde1
Merge pull request #41 from cds-id/feature/optimize-landing
igun997 Dec 6, 2025
a0b1d21
feat: Refine UI animations, improve code structure, update documentat…
igun997 Dec 6, 2025
e6e5e81
style: update text color to #606060, refactor footer animations to CS…
igun997 Dec 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,21 @@ BLOCKCHAIN_RPC_URL="https://sepolia.base.org"
BLOCKCHAIN_EXPLORER_URL="https://sepolia.basescan.org"
BLOCKCHAIN_NETWORK="Base Sepolia"
CONTRACT_ADDRESS="0x2b9D6D96E2538f351931A4f35Ce4A5A072f879d5"
NFT_CONTRACT_ADDRESS="your_nft_contract_address"
NEXT_PUBLIC_NFT_CONTRACT_ADDRESS="your_nft_contract_address"
CHAIN_ID="84532"
ADMIN_WALLET="your_private_key"
# Optional: Set owner address different from deployer (for contract deployment)
CONTRACT_OWNER="your_owner_wallet_address"

# Gemini API (for NFT art generation)
GEMINI_API_KEY="your_gemini_api_key"

# Kolosal AI (for fraud detection)
KOLOSAL_API_KEY="your_kolosal_api_key"

# BaseScan API (for explorer)
BASESCAN_API_KEY="your_basescan_api_key"

# Mapbox (for scan location maps)
NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN="your_mapbox_access_token"
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# CODEOWNERS file for etags repository
# Code owners will be automatically requested for review when someone opens a PR that modifies code they own.

# API routes
/src/app/api/** @igun997
/src/app/manage/** @igun997
88 changes: 85 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ on:
branches: ['develop', 'feature/*', 'fix/*']

jobs:
build:
lint:
name: Lint
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

Expand All @@ -25,13 +25,95 @@ jobs:
- name: Run Linting
run: npm run lint

typecheck:
name: Typecheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run Typecheck
run: npm run typecheck

test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run Tests
run: npm run test -- --run
run: npm run test -- --run --coverage

- name: Upload Coverage Report
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: coverage/
retention-days: 7

build:
name: build
runs-on: ubuntu-latest
needs: [lint, typecheck, test]
steps:
- uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build
env:
NEXT_TELEMETRY_DISABLED: 1

lighthouse:
name: Lighthouse
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build
env:
NEXT_TELEMETRY_DISABLED: 1

- name: Run Lighthouse CI
uses: treosh/lighthouse-ci-action@v12
with:
configPath: './lighthouserc.json'
uploadArtifacts: true
temporaryPublicStorage: true
14 changes: 14 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Deploy

on:
push:
branches: ['develop', 'master']

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Trigger Deployment
run: |
curl -f -X POST "${{ secrets.DEPLOY_WEBHOOK_URL }}" || exit 1
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
legacy-peer-deps=true
loglevel=error
101 changes: 91 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

Etags is a Next.js 16 application for product tagging and blockchain stamping. It manages brands, products, and tags with blockchain transaction tracking for authentication/verification purposes.

**Node.js requirement:** 20.x (LTS)

## Commands

- `npm run dev` - Start development server
Expand All @@ -21,8 +23,9 @@ Etags is a Next.js 16 application for product tagging and blockchain stamping. I
- `npm run test` - Run tests in watch mode
- `npm run test -- --run` - Run tests once (CI mode)
- `npm run test -- --coverage` - Run tests with coverage
- `npm run test -- src/lib/actions/auth.test.ts` - Run a single test file

Test files use `*.test.{ts,tsx}` naming convention and are located throughout `src/`.
Test files use `*.test.{ts,tsx}` naming convention and are located throughout `src/`. Test setup is in `src/tests/setup.ts` with mocks in `src/tests/mocks.ts`. Coverage is configured only for `src/lib/actions/**/*.ts`.

### Database (Prisma with MySQL)

Expand All @@ -32,6 +35,11 @@ Test files use `*.test.{ts,tsx}` naming convention and are located throughout `s
- `npm run db:studio` - Open Prisma Studio GUI
- `npm run db:create-admin` - Create admin user (default: admin@example.com / admin123)
- `npm run db:create-admin -- email@example.com password123 "Name"` - Create admin with custom credentials
- `npm run db:seed` - Seed basic sample data
- `npm run db:seed-fraud` - Add fraud scan patterns to existing tags
- `npm run db:seed-complete` - Complete seed with brands, users, products, tags, and suspicious scans
- `npm run db:seed-complete -- --upload-r2` - Same as above but uploads QR codes to R2
- `npm run db:seed-complete -- --clean` - Clean existing data before seeding

## Architecture

Expand Down Expand Up @@ -62,6 +70,8 @@ Test files use `*.test.{ts,tsx}` naming convention and are located throughout `s
- `@/lib/explorer.ts` - Blockchain explorer integration
- `@/lib/rate-limit.ts` - Rate limiting for API endpoints
- `@/lib/csrf.ts` - CSRF protection
- `@/lib/nft-collectible.ts` - NFT minting and claim processing
- `@/lib/gemini-image.ts` - Gemini API for NFT art generation

### Server Actions

Expand All @@ -77,6 +87,8 @@ Server actions are organized in `src/lib/actions/`:
- `onboarding.ts` - User onboarding flow
- `my-brand.ts` - Brand user self-management
- `ai-agent.ts` - AI agent integration
- `nfts.ts` - NFT collectible management and stats
- `support-tickets.ts` - Web3 support ticket CRUD and messaging

### Routes

Expand All @@ -86,39 +98,50 @@ Server actions are organized in `src/lib/actions/`:
- `/manage/brands` - Brand management
- `/manage/products` - Product CRUD with `/new` and `/[id]/edit`
- `/manage/tags` - Tag management with `/new` and `/[id]/edit`
- `/manage/nfts` - NFT collectible monitoring with `/[id]` detail view
- `/manage/tickets` - Support ticket management with `/[id]` detail view
- `/manage/users` - User management (admin only)
- `/manage/profile` - User profile settings

**Public Routes:**

- `/` - Public landing page
- `/login` - Login page (redirects to /manage if authenticated)
- `/register` - User registration page
- `/scan` - QR code scanner for tag verification
- `/verify/[code]` - Tag verification page with product details
- `/explorer` - Blockchain transaction explorer
- `/explorer/tx/[hash]` - Transaction detail page
- `/support` - Web3 support tickets (NFT holders connect wallet to submit issues)
- `/faqs` - Frequently asked questions page
- `/docs` - Swagger API documentation UI

**API Routes:**

- `/api/docs` - OpenAPI JSON spec
- `/api/scan` - Tag scan endpoint (records scans with fingerprint)
- `/api/scan/claim` - Claim a tag as owner
- `/api/scan/claim-nft` - Claim NFT collectible for first-hand claimers
- `/api/verify` - Tag verification API
- `/api/explorer` - Blockchain explorer API
- `/api/csrf` - CSRF token endpoint
- `/api/tags/[code]/designed` - Get designed QR code for tag
- `/api/tags/template-preview` - Preview QR template designs
- `/api/ai-agent` - AI agent chat endpoint for dashboard

### Database Schema

Core models in `prisma/schema.prisma`:

- **User** - Admin/brand users with role-based access (`role`: admin or brand)
- **User** - Admin/brand users with role-based access (`role`: admin or brand), linked to brand via `brand_id`
- **Brand** - Product brand management with logo and descriptions
- **Product** - Products with JSON metadata, linked to brands
- **Tag** - Product tags with blockchain stamping (`is_stamped`, `hash_tx`, `chain_status`)
- **TagScan** - Scan history with fingerprinting, location, and claim status
- **Product** - Products with JSON metadata (`name`, `description`, `price`, `images[]`), linked to brands
- **Tag** - Product tags with blockchain stamping (`is_stamped`, `hash_tx`, `chain_status`), stores `product_ids` as JSON array
- **TagScan** - Scan history with fingerprinting, location, claim status, and ownership tracking (`is_first_hand`, `source_info`)
- **TagNFT** - NFT collectibles minted for first-hand claimers (`token_id`, `owner_address`, `image_url`, `metadata_url`, `mint_tx_hash`)
- **SupportTicket** - Web3 support tickets linked to tags and brands (`wallet_address`, `category`, `status`, `priority`)
- **TicketMessage** - Ticket conversation thread with sender type (customer/brand/admin)
- **TicketAttachment** - File attachments for tickets stored in R2

### Tag Blockchain Lifecycle

Expand All @@ -137,10 +160,43 @@ The blockchain contract (ETagRegistry) supports: `createTag`, `updateStatus`, `r

1. User scans QR code → `/scan` page
2. Browser collects fingerprint (FingerprintJS) and location
3. POST to `/api/scan` records the scan in `TagScan`
3. POST to `/api/scan` records the scan in `TagScan` with sequential `scan_number`
4. Redirects to `/verify/[code]` showing product info
5. User can claim ownership via `/api/scan/claim`
6. AI fraud detection analyzes scan location vs distribution info
5. User can claim ownership via `/api/scan/claim` (sets `is_claimed`, asks about `is_first_hand`)
6. AI fraud detection analyzes scan patterns and location vs distribution info

### NFT Collectible Claim Flow

First-hand tag claimers on Web3 browsers can mint an NFT collectible:

1. User claims tag as first-hand owner on `/verify/[code]`
2. System detects Web3 wallet (MetaMask, etc.) via `window.ethereum`
3. User connects wallet and switches to Base Sepolia (Chain ID: 84532)
4. POST to `/api/scan/claim-nft` triggers NFT minting:
- Generates unique art via Gemini API (`gemini-3-pro-image-preview`)
- Uploads image and metadata to R2: `nfts/{tagCode}/`
- Admin wallet mints NFT via ETagCollectible contract (user doesn't pay gas)
- NFT transferred directly to user's wallet
5. TagNFT record created with `token_id`, `owner_address`, `mint_tx_hash`
6. Admin monitors NFTs at `/manage/nfts`

**Smart Contracts:**

- `ETagCollectible.sol` - ERC721 NFT contract with one-NFT-per-tag enforcement
- Functions: `mintTo()`, `isTagMinted()`, `getTokenByTag()`, `grantMinter()`, `pause()`

### Web3 Support Ticket Flow

NFT holders can submit product complaints via wallet connection:

1. User visits `/support` and connects wallet (MetaMask, etc.)
2. System queries blockchain for user's owned NFTs via ETagCollectible contract
3. User selects a product/tag and submits ticket with category (`defect`, `quality`, `missing_parts`, `warranty`, `other`)
4. Ticket routes to brand (if brand has users), otherwise to admin
5. Brand/admin responds via `/manage/tickets/[id]`
6. User views responses by reconnecting wallet at `/support`

Ticket statuses: `open` → `in_progress` → `resolved` → `closed`

### Pre-commit Hook

Expand All @@ -153,7 +209,28 @@ Runs `typecheck` and `lint-staged` (which runs Prettier on staged files) before

### CI/CD (GitHub Actions)

Runs on push to `master` and PRs to `develop`, `feature/*`, `fix/*`. Pipeline: lint → typecheck → test → build.
Triggers:

- Push to `master` branch
- Pull requests targeting `develop`, `feature/*`, `fix/*` branches

Pipeline: lint → typecheck → test → build

### Smart Contracts

Solidity contracts are in `smartcontracts/` directory with separate Hardhat setup:

- `ETagRegistry.sol` - Main contract for tag lifecycle management (create, validate, update status, revoke)
- `ETagCollectible.sol` - ERC721 NFT contract for collectibles (one NFT per tag)

Contract commands (run from `smartcontracts/` directory):

- `npm run compile` - Compile contracts
- `npm run test` - Run contract tests
- `npm run deploy:local` - Deploy to local Hardhat node
- `npm run deploy:sepolia` - Deploy to Base Sepolia testnet

See `smartcontracts/README.md` for full contract development documentation.

## Environment Variables

Expand All @@ -164,7 +241,11 @@ Copy `.env.example` to `.env` and configure:
- `AUTH_TRUST_HOST` - Set to `true` for production deployments
- `R2_ACCOUNT_ID`, `R2_ACCESS_KEY_ID`, `R2_SECRET_ACCESS_KEY`, `R2_BUCKET` - Cloudflare R2 credentials
- `R2_PUBLIC_DOMAIN` - Public URL for R2 bucket assets
- `BLOCKCHAIN_RPC_URL`, `CONTRACT_ADDRESS`, `CHAIN_ID`, `ADMIN_WALLET` - Blockchain config
- `BLOCKCHAIN_RPC_URL`, `CONTRACT_ADDRESS`, `CHAIN_ID`, `ADMIN_WALLET`, `BLOCKCHAIN_NETWORK` - Blockchain config
- `CONTRACT_OWNER` - Optional: Owner address different from deployer (for contract deployment)
- `BLOCKCHAIN_EXPLORER_URL` - Block explorer URL (default: Base Sepolia)
- `NFT_CONTRACT_ADDRESS`, `NEXT_PUBLIC_NFT_CONTRACT_ADDRESS` - ETagCollectible NFT contract address
- `GEMINI_API_KEY` - Gemini API for NFT art generation
- `KOLOSAL_API_KEY` - Kolosal AI for fraud detection
- `BASESCAN_API_KEY` - BaseScan API for explorer features
- `NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN` - Mapbox token for scan location maps
Loading