# Tradeloop DPP API Specification
# ISO 20435 Digital Product Passport System
# Version: 1.0.0

================================================================================
BASE URL
================================================================================

Production:  https://inventory-csv-agent.vercel.app
Local:       http://localhost:3000

================================================================================
DOCUMENTATION
================================================================================

Interactive API (Swagger UI):    /swagger
OpenAPI Specification (JSON):    /api/swagger

================================================================================
OVERVIEW
================================================================================

This API implements ISO 20435 for Digital Product Passports (DPPs). Each physical
asset is assigned a Decentralized Identifier (DID) computed from:

  DID = SHA-256(manufacturer + partNumber + serialNumber)

The DID is a 64-character uppercase hex string. A human-readable Universal Serial
Number (USN) is derived as base58(DID)[0:12] formatted as xxxx-xxxx-xxxx.

================================================================================
AUTHENTICATION
================================================================================

No authentication required. All endpoints are public.

================================================================================
ENDPOINTS
================================================================================

## CSV Upload (Simplified)
--------------------------------------------------------------------------------
POST /api/did/register
Content-Type: multipart/form-data

Upload a CSV file. System computes hashes and registers DIDs automatically.

Required CSV columns:
  - manufacturer    Product manufacturer name
  - partNumber      Manufacturer part number
  - serialNumber    Unique serial number

Example CSV:
  manufacturer,partNumber,serialNumber
  NVIDIA,DGXA100,SN-001234567
  Apple,iPhone15Pro,IMEI-987654321

Response: Array of registered DIDs with computed hashes.

--------------------------------------------------------------------------------

## Register DID (Advanced)
--------------------------------------------------------------------------------
POST /api/did/register
Content-Type: application/json

Register a single DID with pre-computed hashes.

Request body:
{
  "did": "string",              // 64-char uppercase hex SHA-256 hash
  "dataObjects": [              // Array of data objects
    {
      "objectType": "string",   // e.g., "physicalIdentifiers"
      "data": { ... }           // Object data
    }
  ],
  "hashTree": {
    "algorithm": "SHA-256",
    "individualHashes": [...],  // SHA-256 of each stringified dataObject
    "rootHash": "string"        // SHA-256 of sorted concatenated hashes
  }
}

Response 201:
{
  "success": true,
  "did": "string",
  "usn": "xxxx-xxxx-xxxx"
}

--------------------------------------------------------------------------------

## Resolve DID
--------------------------------------------------------------------------------
GET /api/did/{did}

Retrieve a DID document.

Parameters:
  did    64-char hex string or did:pai:xxx format

Response 200:
{
  "did": "string",
  "usn": "string",
  "dataObjects": [...],
  "hashTree": {...},
  "created_at": "ISO8601",
  "updated_at": "ISO8601"
}

Response 404: DID not found
Response 410: DID deactivated (Gone)

--------------------------------------------------------------------------------

## Update DID
--------------------------------------------------------------------------------
POST /api/did/update
Content-Type: application/json

Update an existing DID document. Requires priorRootHash for version tracking.

Request body:
{
  "did": "string",
  "dataObjects": [...],
  "hashTree": {
    "algorithm": "SHA-256",
    "individualHashes": [...],
    "priorRootHash": "string",  // Must match current rootHash
    "rootHash": "string"
  }
}

Response 200: Updated document
Response 400: Hash mismatch
Response 404: DID not found

--------------------------------------------------------------------------------

## Deactivate DID
--------------------------------------------------------------------------------
POST /api/did/deactivate
Content-Type: application/json

Soft-delete a DID. Document preserved for audit trail.

Request body:
{
  "did": "string"
}

Response 200: { "success": true, "deactivatedAt": "ISO8601" }
Response 404: DID not found
Response 410: Already deactivated

--------------------------------------------------------------------------------

## List DIDs
--------------------------------------------------------------------------------
GET /api/did/list?limit=50&offset=0&active=true

Query parameters:
  limit     Number of results (default: 50, max: 100)
  offset    Pagination offset (default: 0)
  active    Filter by active status (true/false)

Response 200:
{
  "dids": [...],
  "total": number,
  "limit": number,
  "offset": number
}

--------------------------------------------------------------------------------

## Compute Hash Tree
--------------------------------------------------------------------------------
POST /api/compute-hash-tree
Content-Type: application/json

Utility endpoint to compute DID, USN, and hash tree from data objects.

Request body:
{
  "dataObjects": [
    {
      "objectType": "physicalIdentifiers",
      "data": {
        "manufacturer": "NVIDIA",
        "partNumber": "DGXA100",
        "serialNumber": "SN-001"
      }
    }
  ],
  "priorRootHash": null  // Optional, for updates
}

Response 200:
{
  "did": "string",
  "usn": "xxxx-xxxx-xxxx",
  "hashTree": {
    "algorithm": "SHA-256",
    "individualHashes": [...],
    "rootHash": "string"
  }
}

--------------------------------------------------------------------------------

## Verify Hash Tree
--------------------------------------------------------------------------------
POST /api/verify-hash-tree
Content-Type: application/json

Verify that a hash tree matches its data objects.

Request body:
{
  "dataObjects": [...],
  "hashTree": {...}
}

Response 200: { "valid": true }
Response 400: { "valid": false, "errors": [...] }

--------------------------------------------------------------------------------

## File Upload
--------------------------------------------------------------------------------
POST /api/storage/upload
Content-Type: multipart/form-data

Upload a file attachment for a DID.

Form fields:
  file    The file to upload
  did     Associated DID (64-char hex)

Response 200:
{
  "success": true,
  "url": "https://..."
}

================================================================================
HASH COMPUTATION (ISO 20435 Section 7)
================================================================================

1. Individual Hash:
   hash = SHA-256(JSON.stringify(dataObject))

2. Root Hash:
   sortedHashes = individualHashes.sort()
   concatenated = priorRootHash + sortedHashes.join('')
   rootHash = SHA-256(concatenated)

3. DID Generation:
   physicalIdentifiers = { manufacturer, partNumber, serialNumber }
   did = SHA-256(manufacturer + partNumber + serialNumber).toUpperCase()

4. USN Generation:
   bytes = hexToBytes(did)
   usn = base58(bytes).slice(0, 12)
   formatted = usn.slice(0,4) + '-' + usn.slice(4,8) + '-' + usn.slice(8,12)

================================================================================
ERROR RESPONSES
================================================================================

400 Bad Request     Invalid input, missing required fields, hash mismatch
404 Not Found       DID does not exist
410 Gone            DID has been deactivated
500 Server Error    Internal error

All errors return:
{
  "error": "string",
  "details": "string"  // Optional
}

================================================================================
LINKS
================================================================================

Swagger UI:          /swagger
OpenAPI JSON:        /api/swagger
Upload Interface:    /dpp/upload
View DPPs:           /dpp/list-2

================================================================================