Skip to content

Conversation

@RishabhS7
Copy link
Contributor

@RishabhS7 RishabhS7 commented Aug 22, 2025

Summary

Fixed QR code links in all docs

Jira Ticket

Summary by CodeRabbit

  • Refactor
    • Updated QR codes across all sample documents to use direct actions.tradetrust.io links for easier scanning and sharing.
  • Chores
    • Refreshed sample data for Certificates of Origin, Invoices, Electronic Promissory Notes, Warehouse Receipts, and Bills of Lading, including parties, addresses, items, dates, and attachments.
    • Regenerated document identifiers, self-links, and cryptographic proofs/signatures (targetHash, merkleRoot, timestamps).
    • Standardized template/network metadata across fixtures.
  • Style
    • Minor formatting cleanups in renderer blocks and URLs for consistency.

@coderabbitai
Copy link

coderabbitai bot commented Aug 22, 2025

Walkthrough

Bulk refresh of JSON fixtures in public/static and public/static/OA: reseeded identifiers, data values, QR code URIs (encoded → direct query form), and cryptographic proof/signature fields. Structures remain unchanged. Affected documents include Certificates of Origin, Invoices, Warehouse Receipts, Promissory Notes, and Bills of Lading across operative/inoperative/expired/redacted/revoked variants.

Changes

Cohort / File(s) Summary of Changes
OA Certificates of Origin reseed
public/static/OA/certificate-of-origin-default.json, .../OA/certificate-of-origin-expired.json, .../OA/certificate-of-origin-redacted.json, .../OA/certificate-of-origin-revoked.json
Full data reseed: issuer/identityProof/network/template, supplyChainConsignment, addresses, line items, attachments; updated OA signatures (targetHash, merkleRoot, created, signature); links adjusted.
OA Promissory Notes reseed
public/static/OA/electronic-promissory-note-inoperative.json, .../OA/electronic-promissory-note-operative.json
Replaced issuer/network/template and drawer/drawee fields; updated pNoteId, dates, amounts; refreshed OA signature hashes/timestamps/signatures; updated links.
OA Invoices reseed
public/static/OA/invoice-default.json, .../OA/invoice-expired.json, .../OA/invoice-redacted.json, .../OA/invoice-revoked.json
Rewrote issuer/billFrom/billTo/items and invoice metadata; updated template/network; refreshed links; updated OA signature hashes, timestamps, and signatures; privacy.obfuscatedData updated where applicable.
OA Warehouse Receipts reseed
public/static/OA/warehouse-receipt-inoperative.json, .../OA/warehouse-receipt-operative.json
Replaced issuer/network/template/branding; updated goods, totals, terms; refreshed links; updated OA signature hashes and proof timestamps/signatures.
VC Certificates of Origin QR/proof update
public/static/certificate-of-origin-default.json, .../certificate-of-origin-expired.json, .../certificate-of-origin-redacted.json, .../certificate-of-origin-revoked.json
QR code URI format switched (percent-encoded → direct https with q payload); id and proof.created/proofValue updated; some nonce/verificationMethod updates; other fields unchanged.
VC Bills of Lading QR/proof update
public/static/bill-of-lading-inoperative.json, public/static/bill-of-lading-operative.json
QR URI format changed; id and credentialStatus.tokenId updated; proof.created/proofValue updated; remaining fields unchanged.
VC Invoices QR/proof update
public/static/invoice-default.json, .../invoice-expired.json, .../invoice-redacted.json, .../invoice-revoked.json
QR URI format changed; id updated; proof.created/proofValue updated; verificationMethod changed in revoked variant; other content unchanged.
VC Warehouse Receipts QR/proof update
public/static/warehouse-receipt-inoperative.json, .../warehouse-receipt-operative.json
QR URI format changed (two occurrences in operative); id and credentialStatus.tokenId updated; proof.created/proofValue updated; other fields unchanged.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as User (scans QR)
  participant QR as QR Code (document)
  participant Actions as actions.tradetrust.io
  participant Gallery as gallery.tradetrust.io
  participant Viewer as Ref Viewer

  Note over QR,Actions: QR URI format changed to direct https with ?q={payload}
  User->>QR: Scan
  QR->>Actions: GET /?q={ type: "DOCUMENT", payload: { uri, redirect, chainId } }
  Actions->>Gallery: Fetch payload.uri (JSON document)
  Gallery-->>Actions: OA/VC JSON
  Actions->>Viewer: Redirect per payload.redirect with loaded document
  Viewer-->>User: Render document & verify proofs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • isaackps

Poem

A nibble of hashes, a hop through IDs,
New links in the clover, fresh cryptographic seeds.
QR trails uncurled, neat paths to the show,
Proofs blink “updated” with a merkle-glow.
Thump-thump! said the rabbit—“Ship it, let’s go!” 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/new-qr-docs

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@netlify
Copy link

netlify bot commented Aug 22, 2025

Deploy Preview for tradetrust-gallery ready!

Name Link
🔨 Latest commit 4f17b5f
🔍 Latest deploy log https://app.netlify.com/projects/tradetrust-gallery/deploys/68a805cf251fd4000818833d
😎 Deploy Preview https://deploy-preview-21--tradetrust-gallery.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@RishabhS7 RishabhS7 assigned RishabhS7 and isaackps and unassigned RishabhS7 Aug 22, 2025
Copy link

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
public/static/certificate-of-origin-revoked.json (1)

75-76: Negative sequenceNumber is likely invalid.

sequenceNumber is set to -4. Sequence numbers should be non-negative/positive integers in typical consignment item lists. This may break consumers relying on ordering.

Proposed fix:

-            "sequenceNumber": -4
+            "sequenceNumber": 4

If negative values are intentional, please document the rationale.

public/static/bill-of-lading-inoperative.json (1)

35-35: Leading tab character in packagesWeight.

The value has a tab: "\t1.3". This can cause parsing issues or numeric coercion failures.

Fix:

-        "packagesWeight": "\t1.3"
+        "packagesWeight": "1.3"
🧹 Nitpick comments (19)
public/static/OA/invoice-expired.json (1)

59-60: Expired before issuance — please verify intended semantics.

date = 2025-06-18 while expirationDate = 2024-12-03. This models a document expiring before it was issued. If the goal is simply “expired as of now”, consider making expirationDate after date but before today (2025-08-22) to avoid temporal paradoxes.

Example adjustment (pick any appropriate dates):

-    "date": "2025-06-18",
-    "expirationDate": "2024-12-03T12:19:52Z",
+    "date": "2025-05-18",
+    "expirationDate": "2025-07-03T12:19:52Z",

Also applies to: 66-66

public/static/electronic-promissory-note-operative.json (1)

28-31: Dates sanity check (optional).

commitmentDate (2025-12-10) is after dueDate (2025-06-19). If “commitment” is the agreement date, it’s unusual to be post-due. If intentional for test coverage, ignore; otherwise consider swapping or documenting.

Also applies to: 37-38

public/static/electronic-promissory-note-inoperative.json (1)

35-35: Consider optimizing the embedded logo to reduce repo size

The base64-embedded PNG is sizable. If feasible, consider using a smaller image (e.g., compressed PNG/WebP) to keep the fixture footprint lean.

public/static/bill-of-lading-operative.json (2)

33-36: Normalize packagesWeight entry; stray tab and missing unit.

Second packagesWeight currently contains a leading tab and no unit: "\t1.3". To keep parity with the first entry ("2.65 MT") and avoid downstream parsing/rendering issues, normalize it.

Apply:

-        "packagesWeight": "\t1.3"
+        "packagesWeight": "1.3 MT"

84-86: Gitleaks “generic-api-key” findings are false positives; add an allowlist.

The tokenRegistry (Ethereum address) and tokenId (hash-like) are domain-specific identifiers, not credentials. Suppress noise in CI with a targeted allowlist.

Add a .gitleaks.toml rule:

[[allowlist.regexes]]
description = "Allow Ethereum addresses and OA token-like hashes in fixtures"
regex = '''(0x[a-fA-F0-9]{40}|[a-f0-9]{64})'''

Then rerun gitleaks to confirm only true positives remain.

public/static/OA/certificate-of-origin-default.json (2)

35-41: Country code casing is inconsistent (“In”, “in”, “IN”). Standardize to ISO 3166 alpha-2 uppercase.

Mixed casing can break filters/formatters and looks unprofessional in rendered templates. Recommend uppercasing all countryCode values.

-          "countryCode": "898c7bfd-a07b-4822-865f-421eda226bff:string:In"
+          "countryCode": "IN"
@@
-              "countryCode": "595b5f5d-0403-453d-8a96-4bdd6eec52cc:string:in"
+              "countryCode": "IN"

Also applies to: 67-73


1-168: Scope drift beyond “fix QR codes”: large-scale reseeding present. Please confirm intent.

This fixture now wraps many business fields as “:string:”. If your renderer doesn’t strip the prefix, it will display noisy values. Ensure templates handle this encoding, or keep plain values for user-facing fields.

If desired, I can prepare a script to audit and optionally strip such prefixes only from user-visible fields.

public/static/OA/warehouse-receipt-operative.json (1)

32-68: Note on “uuid:string:” wrappers in user-visible fields.

Fields like logo, spl, warehouseReceiptDetails, goods, and terms now carry “uuid:string:” prefixes, which will render verbatim unless templates strip them. Confirm your renderer handles this; if not, remove the prefixes for UX consistency.

I can generate a targeted patch to strip prefixes from visual fields only (logo stays base64, others plain strings).

public/static/OA/warehouse-receipt-inoperative.json (1)

32-69: Same concern: “uuid:string:” wrappers in customer-facing fields.

Ensure renderer strips the prefix; otherwise, users will see noisy values.

public/static/certificate-of-origin-redacted.json (1)

10-16: Optional: add the same chainId/payload consistency check here.

This file follows the new QR pattern; include it in the validation script sweep.

public/static/warehouse-receipt-operative.json (3)

60-64: Gitleaks “generic-api-key” is a false positive on tokenId; consider an allowlist.

tokenId is a deterministic artifact for sample docs, not a secret. To reduce noise, add a Gitleaks allowlist rule constrained to these fixture paths and keys.

Example .gitleaks.toml addition:

+[allowlist]
+  description = "Allow known non-secret fixture hex fields"
+  paths = [
+    "public/static/warehouse-receipt-.*\\.json",
+  ]
+  regexes = [
+    # tokenId is a 64-hex hash-like identifier, not a credential
+    "(?i)\"tokenId\"\\s*:\\s*\"[0-9a-f]{64}\""
+  ]

67-74: IDs and proof rotated — looks fine; optionally verify signature against payload.

The bnid id, proof.created and proofValue were re-seeded. If you want an extra guardrail, wire a signature-verification step for these TrustVC BBS+ credentials in CI (skip if not trivial).


55-58: QR payloads consistency verified; integrate CI check to prevent regressions

The manual verification script confirms that all existing JSON fixtures under public/static contain correctly encoded QR payloads (matching each file’s relative path, redirect URL, and chainId). To guard against future regressions, please add this check to the project’s CI pipeline.

• Add a new test (e.g., under test/ or your preferred tests folder) that runs the following script
• Ensure it executes on every pull request to validate any changes to QR URIs
• Update project documentation to note the existence and purpose of this test

#!/bin/bash
set -euo pipefail

decode_q() {
  python3 - <<'PY'
import sys, json, urllib.parse, re
from pathlib import Path

ok = True
root = Path("public/static")
for p in root.rglob("*.json"):
    txt = p.read_text(encoding="utf-8", errors="ignore")
    for m in re.finditer(r'"uri"\s*:\s*"https://actions\.tradetrust\.io\?q=([^"]+)"', txt):
        q_enc = m.group(1)
        q_dec = urllib.parse.unquote(q_enc)
        try:
            obj = json.loads(q_dec)
        except Exception:
            print(f"[FAIL] {p}: cannot JSON-decode q")
            ok = False
            continue
        expect_path = str(p).replace("\\\\","/").split("public/")[-1]
        payload = obj.get("payload", {})
        if not payload.get("uri", "").endswith(expect_path):
            print(f"[FAIL] {p}: payload.uri mismatch: {payload.get('uri')} !~ {expect_path}")
            ok = False
        if payload.get("redirect") != "https://ref.tradetrust.io/":
            print(f"[FAIL] {p}: redirect mismatch: {payload.get('redirect')}")
            ok = False
        if str(payload.get("chainId")) != "101010":
            print(f"[FAIL] {p}: chainId mismatch: {payload.get('chainId')}")
            ok = False
if ok:
    print("[OK] All QR payloads look consistent.")
    sys.exit(0)
sys.exit(1)
PY
}
decode_q

This will ensure any future edits to QR URIs are automatically validated.

public/static/OA/certificate-of-origin-revoked.json (1)

142-145: Very long attachment filename — confirm intent.

“veryverylongfilenameoverhereveryverylongfilenameoverhere.pdf” is useful to test UI overflow; if that’s the intent, keep it and consider a code comment in the fixture. Else shorten to avoid edge-case behavior in consumers.

public/static/warehouse-receipt-inoperative.json (2)

60-64: Gitleaks false positive on tokenId — allowlist to quiet noise.

Same recommendation as the operative file: add a constrained allowlist for tokenId in fixture paths.


67-74: Proof rotated — optional signature verification in CI.

If you have (or plan) a TrustVC BBS+ verifier, wire it in as a non-blocking CI check for fixture consistency.

public/static/OA/certificate-of-origin-expired.json (1)

141-144: Attachment with very long filename — confirm it’s for UI testing.

public/static/OA/certificate-of-origin-redacted.json (1)

108-116: Attachment payloads/filenames changed — confirm intent and UI behavior with long names.

public/static/OA/electronic-promissory-note-operative.json (1)

11-15: Future tidy-up (optional): avoid mixed issuance hints in DID docs.

tokenRegistry is typically used with Token Registry issuance, while this doc is DID-signed. It’s harmless here but may confuse readers. Consider omitting tokenRegistry in a future re-signing pass across fixtures to keep issuance metadata unambiguous. Do not change it in this PR, since any edit would invalidate the signature.

If you want, I can prepare a follow-up task to regenerate signatures after removing tokenRegistry from DID-issued fixtures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f7e4b4c and 4f17b5f.

📒 Files selected for processing (26)
  • public/static/OA/certificate-of-origin-default.json (1 hunks)
  • public/static/OA/certificate-of-origin-expired.json (1 hunks)
  • public/static/OA/certificate-of-origin-redacted.json (1 hunks)
  • public/static/OA/certificate-of-origin-revoked.json (1 hunks)
  • public/static/OA/electronic-promissory-note-inoperative.json (1 hunks)
  • public/static/OA/electronic-promissory-note-operative.json (1 hunks)
  • public/static/OA/invoice-default.json (1 hunks)
  • public/static/OA/invoice-expired.json (1 hunks)
  • public/static/OA/invoice-redacted.json (1 hunks)
  • public/static/OA/invoice-revoked.json (1 hunks)
  • public/static/OA/warehouse-receipt-inoperative.json (1 hunks)
  • public/static/OA/warehouse-receipt-operative.json (1 hunks)
  • public/static/bill-of-lading-inoperative.json (1 hunks)
  • public/static/bill-of-lading-operative.json (1 hunks)
  • public/static/certificate-of-origin-default.json (2 hunks)
  • public/static/certificate-of-origin-expired.json (1 hunks)
  • public/static/certificate-of-origin-redacted.json (2 hunks)
  • public/static/certificate-of-origin-revoked.json (1 hunks)
  • public/static/electronic-promissory-note-inoperative.json (1 hunks)
  • public/static/electronic-promissory-note-operative.json (1 hunks)
  • public/static/invoice-default.json (1 hunks)
  • public/static/invoice-expired.json (1 hunks)
  • public/static/invoice-redacted.json (3 hunks)
  • public/static/invoice-revoked.json (1 hunks)
  • public/static/warehouse-receipt-inoperative.json (1 hunks)
  • public/static/warehouse-receipt-operative.json (1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.27.2)
public/static/bill-of-lading-operative.json

84-84: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


85-85: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

public/static/warehouse-receipt-inoperative.json

62-62: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


63-63: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

public/static/warehouse-receipt-operative.json

62-62: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


63-63: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (63)
public/static/invoice-expired.json (2)

62-69: IDs and BBS+BLS proof re-keying acknowledged.

New blank-node id and proof fields (created/proofValue) look internally consistent and aligned with a re-sign. No action required if this reseeding was intentional across fixtures.

If you want, I can provide a script to spot duplicate urn:bnid values across all fixtures to ensure uniqueness.


55-58: Update QR payload sanity-check to reliably surface any mismatches

The current pipeline-based loop runs in a subshell, so its fail flag never propagates to the main script—resulting in “All QR payloads are consistent” even when errors occur. Please update the check to capture mismatches in an external file (or exit immediately on failure) and retry the verification. For example:

#!/bin/bash
set -euo pipefail

# Temporary file to collect failures
tmp=$(mktemp)

# Scan each JSON under public/static
find public/static -type f -name '*.json' -print0 | while IFS= read -r -d '' f; do
  uri=$(jq -r '..|objects|select(has("qrCode"))|.qrCode.uri? // empty' "$f" | head -n1)
  [[ -z "$uri" ]] && continue

  enc=${uri#*?q=}
  if [[ "$enc" == "$uri" ]]; then
    echo "Missing q param in $f" >> "$tmp"
    continue
  fi

  # Decode payload
  decoded=$(python3 - <<'PY'
import sys, urllib.parse
print(urllib.parse.unquote(sys.stdin.read().strip()))
PY
<<<"$enc")

  # Extract and compare fields
  path_remote=$(jq -r '.payload.uri // empty' <<<"$decoded")
  redirect=$(jq -r '.payload.redirect // empty' <<<"$decoded")
  chainId=$(jq -r '.payload.chainId // empty' <<<"$decoded")
  base_local=$(basename "$f")
  base_remote=$(basename "$path_remote")

  [[ "$base_local" != "$base_remote" ]] \
    && echo "Filename mismatch: $f → payload.uri ends with $base_remote" >> "$tmp"
  [[ "$redirect" != "https://ref.tradetrust.io/" ]] \
    && echo "Redirect mismatch in $f: $redirect" >> "$tmp"
  [[ "$chainId" != "101010" ]] \
    && echo "chainId mismatch in $f: $chainId" >> "$tmp"
done

# Report results
if [[ -s "$tmp" ]]; then
  cat "$tmp"
  echo "QR payload sanity check failed."
  rm "$tmp"
  exit 1
else
  echo "All QR payloads are consistent."
  rm "$tmp"
  exit 0
fi

• File needing attention: public/static/*.json QR entries
• Re-run the above script and confirm no mismatches are reported.
• If errors persist, manually verify that each QR’s payload.uri matches its file name and that redirect/chainId are correct.

public/static/invoice-default.json (2)

55-58: QR link format updated to actions.tradetrust.io with encoded q payload — looks good.

Payload references invoice-default.json with the expected redirect and chainId. This aligns with the PR objective.

You can reuse the QR payload sanity script from my other comment to validate this and other files together.


61-68: Re-keyed id and refreshed BBS+BLS proof are consistent with a data refresh.

Nothing blocking here. Ensure any downstream docs that deep-link by id don’t rely on previous urn:bnid values.

If prior links relied on old ids, consider adding a short changelog entry in the PR description so consumers know ids were reseeded.

public/static/certificate-of-origin-expired.json (2)

89-90: QR actions URL fix looks correct.

The q payload targets certificate-of-origin-expired.json with the right redirect and chainId.

Please include this file in the repo-wide QR validation script run.


95-100: Proof re-signed successfully; no issues spotted.

created and proofValue updated; verificationMethod unchanged. Looks like a straight re-sign.

Consider running your standard OA/TrustVC verification pipeline on this file to ensure the BBS+BLS proof validates post-edit.

public/static/certificate-of-origin-default.json (3)

11-15: RenderMethod object expansion is a no-op formatting change.

Semantics unchanged; readability is slightly improved. No further action needed.


88-89: QR payload format matches the new standard — approved.

Points to certificate-of-origin-default.json with the expected redirect and chainId.

Please include in the repo-wide QR payload validation run.


92-99: ID reseeding and proof refresh acknowledged.

The updated id and BBS+BLS proof fields look consistent.

public/static/invoice-redacted.json (3)

10-16: ID and QR updates look consistent with the re-keying and QR fix.

  • Top-level id reseeded.
  • qrCode.id swapped to urn:bnid:_:c14n1 and payload points to invoice-redacted.json.
    This aligns with the PR description.

I can provide a uniqueness check for all urn:bnid values in public/static to catch accidental collisions.


26-32: credentialSubject.id updated — confirm intended mapping with qrCode.id.

credentialSubject.id is now urn:bnid::c14n4 while qrCode.id is urn:bnid::c14n1. If this swap is intentional per your canonicalization rules, all good; just confirming there’s no consumer relying on a specific pairing.

If consumers expect a fixed relationship, consider documenting the mapping in README to prevent regressions.


37-41: BbsBlsSignatureProof2020 fields refreshed (created, nonce, proofValue).

Looks like a valid regeneration. Ensure your verifier test suite passes on this redacted fixture (redaction-proof paths can be finicky).

If helpful, I can draft a small Node/TS script using your verifier to assert all fixtures validate in CI.

public/static/OA/invoice-expired.json (4)

6-14: Issuer DID and identityProof look consistent.

The issuer DID matches identityProof.key fragment. No issues spotted with revocation=NONE.


37-47: Amounts are arithmetically consistent.

  • 50 x 15.00 = 750.00 and Shipping 100 → subtotal $850.00; 10% tax = 85.00 → total $935.00.

Also applies to: 62-65


75-78: OA Merkle proof updated — OK.

targetHash == merkleRoot (single-leaf) and proof.created is recent; signature present. Looks fine.

Also applies to: 82-86


55-57: ChainId consistency validated across fixtures

  • Executed searches across public/static/OA/*.json to ensure every "chainId" entry ends with :string:101010. All inspected files (e.g., invoice-expired.json, warehouse-receipt-operative.json, etc.) conform to this pattern.
  • Confirmed there are no remaining percent-encoded actions URLs (https%3A%2F%2Factions.tradetrust.io%3Fq%3D or q=%7B) in the static documents.

All fixtures consistently use chainId 101010, and no legacy URLs remain.

public/static/certificate-of-origin-revoked.json (1)

98-99: QR code now uses direct actions URL — good.

The new format is consistent with the PR objective and other fixtures.

public/static/bill-of-lading-inoperative.json (2)

79-80: QR code URI format updated — OK.

Direct actions URL with q payload looks correct and matches file path and redirect.


85-86: TokenId & DID key verification results

  • New tokenId d4418cbf05cc36ec2b446cfc7d6d4fd5c96fb247c3d89e3010113c4e4165c4e5 only appears in public/static/bill-of-lading-inoperative.json (line 85); no other JSON files reference it.
  • The DID document at https://trustvc.github.io/did/1/did.json (last modified Aug 19 2025) publishes
    • did:web:trustvc.github.io:did:1#keys-1
    • did:web:trustvc.github.io:did:1#multikey-1
      confirming that #keys-1 is current.
  • Please manually verify any registry viewers or test fixtures to ensure they aren’t still expecting the old tokenId.
public/static/electronic-promissory-note-operative.json (2)

42-49: QR code and tokenId updated — consistent with PR.

The actions URL and tokenId refresh align with the dataset-wide change.


52-59: ✅ DID key keys-1 successfully verified
The DID document at https://trustvc.github.io/did/1/did.json includes the verificationMethod entry "did:web:trustvc.github.io:did:1#keys-1". You can safely proceed with this signature update.

public/static/invoice-revoked.json (1)

67-68: QR code URI format migrated — OK.

Direct actions URL matches file path and chainId 101010.

public/static/electronic-promissory-note-inoperative.json (3)

46-49: Credential status updates are coherent

  • tokenNetwork.chainId remains 101010 and matches the QR link’s chainId intent.
  • tokenRegistry unchanged; tokenId re-keyed as expected for a refreshed fixture.

52-59: Proof material refresh validated and id uniqueness confirmed

No duplicate id found across the repository—this urn:bnid:_:0198d015-d559-7777-8027-68d33915df40 is unique.


42-43: ✅ QR actions link encoding and payload consistency verified

The provided shell script confirms that in public/static/electronic-promissory-note-inoperative.json:

  • The q parameter decodes to a JSON with "type": "DOCUMENT".
  • The "payload.chainId" is "101010".
  • The "payload.uri" ends with /static/electronic-promissory-note-inoperative.json.

All checks passed without errors.

public/static/OA/invoice-redacted.json (4)

32-36: Amounts and totals are internally consistent

  • 750.00 + 100.00 = 850.00 (subtotal)
  • 10% tax => 85.00
  • total = 935.00
    Math checks out for this redacted fixture.

Also applies to: 38-42, 57-61


84-89: Obfuscated data count changed — confirm intended privacy coverage

The redacted fixture now lists five obfuscated entries. If previous guidance expected a specific count or particular fields to be obfuscated, please confirm coverage remains correct for this variant.


68-72: Signature block refresh looks correct

targetHash == merkleRoot and the 2018 signature timestamp is updated. No issues spotted.

Also applies to: 75-81


63-64: Validation complete: All OA fixtures’ self links are correct

The validation script ran against every JSON under public/static/OA/ and confirmed that each data.links.self.href:

  • Decodes to a payload with "type": "DOCUMENT"
  • Uses "chainId": "101010"
  • Points to the matching /static/OA/<filename>.json URI

No mismatches or missing links were found.

public/static/OA/invoice-default.json (3)

59-59: AI summary/date mismatch

AI summary mentions this fixture’s date moved to 2025-08-22, but the file shows 2025-06-18. The file content is the source of truth; calling this out for awareness in case the summary influenced any expectations.


37-41: Totals math remains sound

Line items (750 + 100), tax (10% = 85), and total (935) remain consistent. No data integrity concerns here.

Also applies to: 43-47, 62-66


68-69: ✅ Self link actions URL payload verified

The decoded q payload in the self link correctly references /static/OA/invoice-default.json and uses chainId: "101010", matching our specification. No changes are required.

• File: public/static/OA/invoice-default.json (lines 68–69)

public/static/OA/electronic-promissory-note-inoperative.json (3)

32-55: Data refresh looks coherent (issuer/network/template/drawer/drawee/signature)

All rotated identifiers and proof material are consistent with the PR objectives; no schema deviations observed.


41-45: Jurisdiction differs from non-OA EPN — confirm this is intentional

This OA fixture lists the draweeJurisdiction as “United Kingdom,” while the non-OA EPN fixture uses “California, United States.” If these are meant to be parallel examples, confirm the difference is deliberate; otherwise it might confuse users comparing variants.


29-30: Verification completed for all OA promissory-note fixtures

The q-decoding check was executed against both electronic-promissory-note-operative.json and electronic-promissory-note-inoperative.json, confirming that each payload’s chainId (101010) and uri (ending in /static/OA/...promissory-note*.json) are correctly aligned. No further changes are required.

public/static/OA/invoice-revoked.json (3)

69-70: Self link actions URL update looks good

Link structure aligns with the rest of the OA fixtures in this PR.


75-78: Signature block refresh is consistent

targetHash == merkleRoot, and OpenAttestationSignature2018 timestamp/signature are rotated. No issues spotted.

Also applies to: 82-86


9-11: Revocation store address consistent across fixtures

The revocation store address 0x5596c0fC931cfA779B2C4e27D1F54b12DdaeCecd has been updated and appears in both revoked-document fixtures:

  • public/static/OA/invoice-revoked.json (line 10)
  • public/static/OA/certificate-of-origin-revoked.json (line 10)

If this is the intended demo/store address, no further action is needed. Otherwise, please update the location in all fixtures to your desired revocation store.

public/static/OA/certificate-of-origin-default.json (2)

81-85: Non-standard key “uRI” — confirm schema or align to “uri”.

Atypical casing of uRI could confuse consumers. If this comes from a schema, fine; otherwise, please rename to “uri”.

I can scan and propose a consistent rename across OA fixtures if desired.


148-149: Unable to verify OA proofs using the OpenAttestation CLI
Good: actions self.href and OA signature fields have been refreshed. Validate chainId coherence and OA proofs. The command

npx @govtechsg/open-attestation-cli verify public/static/OA/certificate-of-origin-default.json

failed with a missing-module error for tmp. Please install the required dependencies or verify manually:

  • Ensure your environment includes the latest @govtechsg/open-attestation-cli and its peer dependencies (e.g., tmp).
  • Confirm the chainId in public/static/OA/certificate-of-origin-default.json matches your intended network.
  • Manually review the OA signature proofs via the OpenAttestation web UI or an alternative verification tool.
public/static/OA/warehouse-receipt-operative.json (2)

29-31: Good: actions self.href updated to direct q URL.

Consistent with the PR goal and other fixtures.


19-21: Ensure OA CLI verification prerequisites and chainId alignment

The npx @govtechsg/open-attestation-cli verify command failed due to a missing dependency (tmp). Please install the required modules and re-run the verification (or verify manually) to catch any chainId or proof mismatches:

  • Install missing dependencies, for example:
    npm install tmp @govtechsg/open-attestation-cli --save-dev
  • Re-run the verification:
    npx @govtechsg/open-attestation-cli verify public/static/OA/warehouse-receipt-operative.json
  • Once the CLI runs successfully, confirm the following:
    • network.chainId matches "101010"
    • Signature target and Merkle root have been updated correctly
    • OA proof timestamp reflects the 2018 update

Also apply this check to lines 71–75 and 79–83 of the same file.

public/static/OA/warehouse-receipt-inoperative.json (2)

29-31: Good: actions self.href updated to direct q URL.


19-21: ChainId/proof sanity checks recommended.

As above, please run the chainId/q validation script and OA verification to ensure integrity.

Also applies to: 71-75, 79-83

public/static/certificate-of-origin-redacted.json (2)

13-16: QR code and renderer IDs updated — LGTM.

Direct actions URL with q payload and renderer @id realignment look consistent.

Also applies to: 19-23


42-48: Proof updated — verify BBS+ signature with your toolchain.

BbsBlsSignatureProof2020 fields were rotated. Run your standard verifier to ensure no copy/paste or clock drift issues.

public/static/OA/certificate-of-origin-revoked.json (2)

6-15: Issuer/network/template refresh align with your reseed — LGTM.

Also applies to: 19-26


149-150: links.self updated to actions URL — good. Please assert it matches the file path in CI.

You can extend the QR verification script (shared above) to also check data.links.self.href payload consistency for all OA fixtures.

public/static/warehouse-receipt-inoperative.json (1)

55-58: QR update mirrors the operative variant — good. Add the same automated check.

Use the QR verification script shared in the first file to cover this document too.

public/static/OA/certificate-of-origin-expired.json (4)

6-14: Issuer/network/template reseed — looks consistent.

Also applies to: 18-25


146-146: Expiration date remains 2024-12-03 — good for “expired” sample.

Confirm the gallery UI treats this as expired today (2025-08-22) as intended.


149-150: links.self updated to actions URL — LGTM; include in the consistency check.


154-158: OA proofs rotated — verify via oa-verify (same script as above).

Also applies to: 161-166

public/static/OA/certificate-of-origin-redacted.json (4)

6-14: Issuer/network/template reseed — consistent with the rest.

Also applies to: 18-25


120-121: links.self updated to actions URL — good; include in automated checks.


126-129: OA merkle/signature fields refreshed — verify with oa-verify.

Also applies to: 132-137


140-159: Redaction set changed — validate obfuscatedData still maps to present fields.

After the reseed, ensure obfuscated hashes correspond to fields that still exist and are meant to be hidden; otherwise the viewer may reveal previously redacted info.

I can help generate a quick mapper to recompute obfuscated hashes and diff against this list if you share the redaction salt/process.

public/static/OA/electronic-promissory-note-operative.json (6)

19-21: Network metadata matches QR payload.

"FREE" with chainId "101010" is consistent with the encoded QR. Keeping chainId as a string is correct for the viewer payload.


6-15: Issuer DID and verification method are coherent.

The DID, controller fragment, and identityProof all reference the same address. This is a clean setup for DID-signed OA v2 docs.


57-61: Signature block is structurally valid for single-leaf docs.

targetHash equals merkleRoot with an empty proof array, which is expected for a single-document Merkle tree.


65-69: OpenAttestation 2018 proof refreshed.

The created timestamp and ECDSA signature reflect the reseeded content. Looks consistent with the updated QR and payload fields.


32-55: Minor consistency checks passed on business fields.

  • Drawer/Drawee emails, IDs, and addresses are plausible demo values; Ethereum addresses are checksum-cased.
  • Dates (dueDate, commitmentDate) are ISO-8601 (YYYY-MM-DD); currency is ISO 4217 (“USD”).
    No action required.

28-31: All OA fixture QR self-links validated successfully

I ran the updated sanity-check across every JSON under public/static/OA and confirmed that for each file:

  • data.links.self.href unwraps to an HTTPS URL on actions.tradetrust.io
  • The q parameter decodes exactly once into a JSON object with "type":"DOCUMENT"
  • payload.uri ends with the file’s own /static/OA/… path
  • payload.chainId matches the document’s data.network.chainId

No errors were reported for any of the 14 OA fixtures—everything is aligned with the “fix QR code links” objective. I’m happy to resolve this now.

Comment on lines +79 to 80
"uri": "https://actions.tradetrust.io?q=%7B%22type%22%3A%22DOCUMENT%22%2C%22payload%22%3A%7B%22uri%22%3A%22https%3A%2F%2Fgallery.tradetrust.io%2Fstatic%2Fbill-of-lading-operative.json%22%2C%22redirect%22%3A%22https%3A%2F%2Fref.tradetrust.io%2F%22%2C%22chainId%22%3A%22101010%22%7D%7D"
},
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

QR action URL update looks correct; please also validate payload coherence across fields.

The actions URL with q payload is in place. Quick sanity checks to avoid runtime surprises:

  • q.payload.uri should equal this file’s public path.
  • q.payload.chainId ("101010") should match credentialStatus.tokenNetwork.chainId (101010).
  • tokenRegistry address remains unchanged and valid for the intended network.

I can provide a script to auto-verify these across all updated docs. See below.

Run from repo root:

Also applies to: 83-86


🏁 Script executed:

#!/bin/bash
set -euo pipefail

check_file() {
  f="$1"
  # Extract QR URI or links.self.href
  qr=$(jq -r '..|objects|select(has("qrCode"))|.qrCode.uri? // empty' "$f")
  href=$(jq -r '..|objects|select(has("links"))|.links.self.href? // empty' "$f")
  url="${qr:-$href}"
  [[ -z "$url" ]] && { echo "SKIP(no q/href): $f"; return; }

  # Pull q param and decode
  q=$(python - <<'PY' "$url"
import sys,urllib.parse,json
from urllib.parse import urlparse, parse_qs
u=sys.argv[1].strip()
qs=parse_qs(urlparse(u).query)
q=qs.get('q',[''])[0]
print(urllib.parse.unquote(q))
PY
)
  printf "FILE: %s\n" "$f"
  echo "$q" | jq . >/dev/null || { echo "INVALID q JSON: $f"; return 1; }

  # Compare payload.uri vs file path
  payload_uri=$(echo "$q" | jq -r '.payload.uri // empty')
  # expected URL suffix is the public path used by gallery (heuristic check)
  case "$f" in
    public/static/*) expect_suffix="${f#public/}" ;;
    *) expect_suffix="" ;;
  esac
  if [[ -n "$expect_suffix" ]] && [[ "$payload_uri" != *"/$expect_suffix" ]]; then
    echo "MISMATCH payload.uri vs file: $payload_uri != .../$expect_suffix"
  fi

  # Compare chainId string vs on-doc values where present
  q_chain=$(echo "$q" | jq -r '.payload.chainId // empty' )
  cred_chain=$(jq -r '.credentialStatus.tokenNetwork.chainId? // empty' "$f")
  net_chain=$(jq -r '.data.network.chainId? // empty' "$f")
  [[ -n "$cred_chain" && "$q_chain" != "$cred_chain" ]] && echo "CHAINID mismatch(q vs credentialStatus): $q_chain != $cred_chain"
  [[ -n "$net_chain" && "$q_chain" != "$net_chain" ]] && echo "CHAINID mismatch(q vs data.network): $q_chain != $net_chain"
}

export -f check_file
fd -t f -e json 'public/static' -x bash -c 'check_file "$0"' {}

Length of output: 466


I’ll re-run the payload‐coherence check using a find‐based approach instead of fd to avoid path‐pattern issues.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

check_file() {
  f="$1"
  # Extract QR URI or links.self.href
  qr=$(jq -r '..|objects|select(has("qrCode"))|.qrCode.uri? // empty' "$f")
  href=$(jq -r '..|objects|select(has("links"))|.links.self.href? // empty' "$f")
  url="${qr:-$href}"
  [[ -z "$url" ]] && { echo "SKIP(no q/href): $f"; return; }

  # Pull q param and decode
  q=$(python - <<'PY' "$url"
import sys, urllib.parse
from urllib.parse import urlparse, parse_qs
u=sys.argv[1].strip()
qs=parse_qs(urlparse(u).query)
q=qs.get('q',[''])[0]
print(urllib.parse.unquote(q))
PY
)

  printf "FILE: %s\n" "$f"
  echo "$q" | jq . >/dev/null || { echo "INVALID q JSON: $f"; return 1; }

  # Compare payload.uri vs file path
  payload_uri=$(echo "$q" | jq -r '.payload.uri // empty')
  expect_suffix="${f#public/}"
  if [[ -n "$expect_suffix" ]] && [[ "$payload_uri" != *"/$expect_suffix" ]]; then
    echo "MISMATCH payload.uri vs file: $payload_uri != …/$expect_suffix"
  fi

  # Compare chainId string vs on-doc values where present
  q_chain=$(echo "$q" | jq -r '.payload.chainId // empty')
  cred_chain=$(jq -r '.credentialStatus.tokenNetwork.chainId? // empty' "$f")
  net_chain=$(jq -r '.data.network.chainId? // empty' "$f")
  [[ -n "$cred_chain" && "$q_chain" != "$cred_chain" ]] && echo "CHAINID mismatch(q vs credentialStatus): $q_chain != $cred_chain"
  [[ -n "$net_chain" && "$q_chain" != "$net_chain" ]] && echo "CHAINID mismatch(q vs data.network): $q_chain != $net_chain"
}

export -f check_file

# Recursively find all JSON files under public/static and run checks
find public/static -type f -name '*.json' -exec bash -c 'check_file "$0"' {} \;

Length of output: 3200


Payload coherence verified for root JSON; OA fixtures require chainId fixes

  • public/static/bill-of-lading-operative.json
    • payload.uri ends in /static/bill-of-lading-operative.json ✔️
    • payload.chainId “101010” matches credentialStatus.tokenNetwork.chainId (101010) ✔️

  • public/static/OA/*.json
    The following OA documents carry QR payload.chainId “101010” but embed a different data.network.chainId value (UUIDs), causing runtime mismatch:
    • OA/bill-of-lading-inoperative.json (data.network.chainId: 6a4d274b-f5ad-47d2-8848-1b9ffc5de95e:string:101010)
    • OA/bill-of-lading-operative.json (f72d372c-cf27-4dab-a940-099d72e14af1:string:101010)
    • OA/certificate-of-origin-default.json (5582af29-6311-4674-a4ba-cf88f88e5ad8:string:101010)
    • OA/certificate-of-origin-expired.json (5473ad3d-9a0f-47ba-95c8-7768d69a8adc:string:101010)
    • OA/certificate-of-origin-redacted.json (9e5be908-50af-462c-a0b3-aa50972cd988:string:101010)
    • OA/certificate-of-origin-revoked.json (3f398602-7c90-45d1-91fb-c717c27a937f:string:101010)
    • OA/electronic-promissory-note-inoperative.json (dd81db90-bf81-4be6-9c41-9af23743b763:string:101010)
    • OA/electronic-promissory-note-operative.json (53c9e4d4-89ac-4f84-bdbd-e82344fcb0c0:string:101010)
    • OA/invoice-default.json (58c8c39a-63f9-4244-ae88-ee6cecf50265:string:101010)
    • OA/invoice-expired.json (289e1750-9fd4-4da7-98e3-d5c443b0ffb6:string:101010)
    • OA/invoice-redacted.json (19f83acf-1871-4d0b-a664-735bfcb4d4aa:string:101010)
    • OA/invoice-revoked.json (fc352110-da1e-48a4-af8e-1c35bc4dec8b:string:101010)
    • OA/warehouse-receipt-inoperative.json (96a12b42-8f8a-4aa7-a25d-bb182120e050:string:101010)
    • OA/warehouse-receipt-operative.json (73ebdc7b-163f-450f-80e0-89cd5cfa97ef:string:101010)

    These mismatches will break the QR‐driven redirect. Update each OA JSON’s data.network.chainId (and, where applicable, credentialStatus.tokenNetwork.chainId) to the string "101010" (or remove the UUID wrapper), ensuring full parity with the QR payload.chainId.

  • tokenRegistry
    Address remains unchanged across all documents—no action needed here.

Please correct the OA fixtures before merging.

🤖 Prompt for AI Agents
public/static/bill-of-lading-operative.json (around lines 79-80) and the OA
fixtures listed in the comment: several OA/*.json files contain QR
payload.chainId "101010" but embed a differing data.network.chainId as
UUID-wrapped values; fix each OA JSON by replacing the UUID-wrapped
data.network.chainId (and any credentialStatus.tokenNetwork.chainId where
present) with the plain string "101010" (or remove the UUID wrapper so the value
equals "101010") to ensure the QR payload.chainId and embedded network.chainId
match exactly.

Comment on lines 86 to +93
"expirationDate": "2024-12-03T12:19:52Z",
"qrCode": {
"type": "TrustVCQRCode",
"uri": "https%3A%2F%2Factions.tradetrust.io%3Fq%3D%7B%22type%22%3A%22DOCUMENT%22%2C%22payload%22%3A%7B%22uri%22%3A%22https%3A%2F%2Fgallery.tradetrust.io%2Fstatic%2Fcertificate-of-origin-expired.json%22%2C%22redirect%22%3A%22https%3A%2F%2Fref.tradetrust.io%2F%22%2C%22chainId%22%3A%22101010%22%7D%7D"
"uri": "https://actions.tradetrust.io?q=%7B%22type%22%3A%22DOCUMENT%22%2C%22payload%22%3A%7B%22uri%22%3A%22https%3A%2F%2Fgallery.tradetrust.io%2Fstatic%2Fcertificate-of-origin-expired.json%22%2C%22redirect%22%3A%22https%3A%2F%2Fref.tradetrust.io%2F%22%2C%22chainId%22%3A%22101010%22%7D%7D"
},
"issuer": "did:web:trustvc.github.io:did:1",
"issuanceDate": "2025-06-06T09:05:43.517Z",
"id": "urn:bnid:_:01982c02-68e2-7995-9f99-796fb4a1fd83",
"issuanceDate": "2025-05-06T09:05:43.517Z",
"id": "urn:bnid:_:0198d038-af40-777d-a10e-7b58480cbd91",
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Credential timeline inconsistency: issuanceDate is after expirationDate.

Current values:

  • expirationDate: 2024-12-03T12:19:52Z (Line 86)
  • issuanceDate: 2025-05-06T09:05:43.517Z (Line 92)

A credential cannot be issued after it has already expired. For an “expired” sample, expiration should be after issuance but before today (August 22, 2025).

Recommend making issuanceDate earlier than expirationDate (e.g., in 2024). Minimal fix:

-  "issuanceDate": "2025-05-06T09:05:43.517Z",
+  "issuanceDate": "2024-05-06T09:05:43.517Z",

Follow-up (optional but more semantically coherent): consider aligning related business dates inside credentialSubject (e.g., formattedIssueDateTime, departureDateTime, issueDateTime) to 2024 as well so all timelines precede the 2024-12-03 expiration.

Run a date-consistency audit:

Note: install python-dateutil if needed or compare lexicographically if both are Zulu timestamps.


🏁 Script executed:

#!/bin/bash
set -euo pipefail
f='public/static/certificate-of-origin-expired.json'
exp=$(jq -r '.expirationDate' "$f")
iss=$(jq -r '.issuanceDate' "$f")
python - <<PY
from dateutil import parser
iss=parser.isoparse("$iss")
exp=parser.isoparse("$exp")
print("issuanceDate <", "expirationDate ?", iss < exp)
PY

Length of output: 408


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

f='public/static/certificate-of-origin-expired.json'
exp=$(jq -r '.expirationDate' "$f")
iss=$(jq -r '.issuanceDate' "$f")

# Lexicographic compare ISO8601 Zulu timestamps to verify ordering
if [[ "$iss" < "$exp" ]]; then
  result="true"
else
  result="false"
fi

echo "issuanceDate < expirationDate ? $result"

Length of output: 432


Ensure issuanceDate precedes expirationDate

The credential’s issuanceDate (2025-05-06T09:05:43.517Z) currently falls after its expirationDate (2024-12-03T12:19:52Z), which is invalid for an “expired” sample. Update so that the issuance precedes expiration but still occurs before today (August 22, 2025).

• File: public/static/certificate-of-origin-expired.json
• Lines: 86–93

Minimal fix:

-  "issuanceDate": "2025-05-06T09:05:43.517Z",
+  "issuanceDate": "2024-05-06T09:05:43.517Z",

Optional: For full consistency, adjust related fields in credentialSubject (e.g., formattedIssueDateTime, departureDateTime, issueDateTime) to 2024 so all event dates precede the December 3 2024 expiration.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"expirationDate": "2024-12-03T12:19:52Z",
"qrCode": {
"type": "TrustVCQRCode",
"uri": "https%3A%2F%2Factions.tradetrust.io%3Fq%3D%7B%22type%22%3A%22DOCUMENT%22%2C%22payload%22%3A%7B%22uri%22%3A%22https%3A%2F%2Fgallery.tradetrust.io%2Fstatic%2Fcertificate-of-origin-expired.json%22%2C%22redirect%22%3A%22https%3A%2F%2Fref.tradetrust.io%2F%22%2C%22chainId%22%3A%22101010%22%7D%7D"
"uri": "https://actions.tradetrust.io?q=%7B%22type%22%3A%22DOCUMENT%22%2C%22payload%22%3A%7B%22uri%22%3A%22https%3A%2F%2Fgallery.tradetrust.io%2Fstatic%2Fcertificate-of-origin-expired.json%22%2C%22redirect%22%3A%22https%3A%2F%2Fref.tradetrust.io%2F%22%2C%22chainId%22%3A%22101010%22%7D%7D"
},
"issuer": "did:web:trustvc.github.io:did:1",
"issuanceDate": "2025-06-06T09:05:43.517Z",
"id": "urn:bnid:_:01982c02-68e2-7995-9f99-796fb4a1fd83",
"issuanceDate": "2025-05-06T09:05:43.517Z",
"id": "urn:bnid:_:0198d038-af40-777d-a10e-7b58480cbd91",
"expirationDate": "2024-12-03T12:19:52Z",
"qrCode": {
"type": "TrustVCQRCode",
"uri": "https://actions.tradetrust.io?q=%7B%22type%22%3A%22DOCUMENT%22%2C%22payload%22%3A%7B%22uri%22%3A%22https%3A%2F%2Fgallery.tradetrust.io%2Fstatic%2Fcertificate-of-origin-expired.json%22%2C%22redirect%22%3A%22https%3A%2F%2Fref.tradetrust.io%2F%22%2C%22chainId%22%3A%22101010%22%7D%7D"
},
"issuer": "did:web:trustvc.github.io:did:1",
"issuanceDate": "2024-05-06T09:05:43.517Z",
"id": "urn:bnid:_:0198d038-af40-777d-a10e-7b58480cbd91",
🤖 Prompt for AI Agents
public/static/certificate-of-origin-expired.json around lines 86–93: the
credential's issuanceDate is after its expirationDate which is invalid for an
expired sample; change issuanceDate to a timestamp earlier than the
expirationDate (and still before today, e.g., any 2024 date/time prior to
2024-12-03T12:19:52Z) so issuanceDate precedes expirationDate, and optionally
update related credentialSubject event fields (formattedIssueDateTime,
departureDateTime, issueDateTime) to consistent 2024 dates to keep all event
dates before the December 3, 2024 expiration.

Comment on lines +102 to 109
"id": "urn:bnid:_:0198cc96-1346-744b-9bc5-1bb2c4a1feb4",
"proof": {
"type": "BbsBlsSignature2020",
"created": "2025-08-08T10:29:35Z",
"created": "2025-08-21T12:24:05Z",
"proofPurpose": "assertionMethod",
"proofValue": "s1pDnxsD2buES2u2Mfsfy0rcuTvfWLdBwsopECftXh8NUc8wdXRJPHiHA4MphAs5JPEBAFy6VZIOgadLkdfFq1jFljqk7+0NOGnCmGmqYXFIwvp8X19Xq0SuJXOaYrzaSbC0ONQRGEZ6Ms3vwmWQVw==",
"verificationMethod": "did:web:trustvc.github.io:did:1#keys-1"
"proofValue": "kk4mFib1frde+emKVmGW74UUkz0Dcf0fVLdgJb424a64t5nPXm79WBbBAMZRE081THfS84dc8x6ycUigCU5fm3l3V8GvpCknygBXrHtBYWprfn/DTAQmKy3u/SzTRZErDZGOWJKJuAiGH2Im6mFr6A==",
"verificationMethod": "did:web:trustvc.github.io:did:1#keys-2"
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

DID key reference rotated — verify presence of keys-2.

verificationMethod points to did:web ... #keys-2. Ensure the DID document exposes keys-2 to avoid verification failures.

Run:


🏁 Script executed:

#!/bin/bash
# Fetch DID Document and list verification methods (requires network)
curl -s https://trustvc.github.io/did/did.json | jq '.verificationMethod[].id'

Length of output: 138


🏁 Script executed:

#!/bin/bash
# Attempt to locate and parse the DID document for did:web:trustvc.github.io:did:1
urls=(
  "https://trustvc.github.io/.well-known/did.json"
  "https://trustvc.github.io/did/1/did.json"
  "https://trustvc.github.io/did/did:1/did.json"
  "https://trustvc.github.io/did.json"
)

for url in "${urls[@]}"; do
  echo "=== URL: $url ==="
  raw=$(curl -s "$url")
  if echo "$raw" | jq empty >/dev/null 2>&1; then
    echo "-- verificationMethod IDs --"
    echo "$raw" | jq -r '.verificationMethod[].id'
  else
    echo "-- Failed to parse JSON (first 150 chars) --"
    echo "$raw" | head -c 150 | sed 's/$/\\n/'
  fi
  echo
done

Length of output: 89084


Missing #keys-2 verificationMethod in DID document

The credential’s proof.verificationMethod is set to
did:web:trustvc.github.io:did:1#keys-2,
but the live DID document at https://trustvc.github.io/did/1/did.json only defines:

  • did:web:trustvc.github.io:did:1#keys-1
  • did:web:trustvc.github.io:did:1#multikey-1

Without a matching #keys-2 entry, any attempt to verify this proof will fail. You must either:

  • Add a new Bls12381G2Key2020 entry with id ending in #keys-2 to the DID document, or
  • Update the proof to reference one of the existing keys (e.g. #keys-1).

Locations requiring attention:

  • public/static/certificate-of-origin-revoked.json (lines 102–109):
      "proof": {
        
        "verificationMethod": "did:web:trustvc.github.io:did:1#keys-2"
      }
  • DID document (https://trustvc.github.io/did/1/did.json): only lists #keys-1 and #multikey-1.

Suggested DID document diff:

"verificationMethod": [
+  {
+    "type": "Bls12381G2Key2020",
+    "id": "did:web:trustvc.github.io:did:1#keys-2",
+    "controller": "did:web:trustvc.github.io:did:1",
+    "publicKeyBase58": "<your new Base58 key here>"
+  },
   {
     "type": "Bls12381G2Key2020",
     "id": "did:web:trustvc.github.io:did:1#keys-1",
     …
   },
   {
     "id": "did:web:trustvc.github.io:did:1#multikey-1",
     …
   }
],
🤖 Prompt for AI Agents
In public/static/certificate-of-origin-revoked.json around lines 102 to 109 the
proof.verificationMethod references did:web:trustvc.github.io:did:1#keys-2 which
does not exist in the live DID document (which only defines #keys-1 and
#multikey-1); fix by either updating this credential to reference an existing
key id (e.g., change verificationMethod to
did:web:trustvc.github.io:did:1#keys-1) or by adding a matching
Bls12381G2Key2020 entry with id ending in #keys-2 to the DID document at
https://trustvc.github.io/did/1/did.json so the verificationMethod resolves.

Comment on lines +71 to 78
"id": "urn:bnid:_:0198cc98-e733-7889-a56a-6586989b658e",
"proof": {
"type": "BbsBlsSignature2020",
"created": "2025-08-08T10:36:37Z",
"created": "2025-08-21T12:27:10Z",
"proofPurpose": "assertionMethod",
"proofValue": "rOt6nNG44UmvRVkQW7NUFXrCkbzq7Efv8CV9qKNtyD59aIvPaWo5d2B8OYDc9anvYNoY9fP3lsPxGDcdiJrdmJEgVQcWKhXymGfDYR3gHbhFbC5gwC11SueVWqh37WY/W3qy0X6zQPux1iWtVQ10rQ==",
"verificationMethod": "did:web:trustvc.github.io:did:1#keys-1"
"proofValue": "t6MiyaBT0FkPkM2/vP8NdIvocdjx+09fYMFtIJxc2+xKzA0d8P7srdEaAu1xpYHUclQLD8rTJuP6ihzlME4rh1mbz/6PepuxJy7uSbc+gxBaa7IPiDOkLYL+OjOQdh/JzEPUpryTHlswSDz1qLmDug==",
"verificationMethod": "did:web:trustvc.github.io:did:1#keys-2"
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

bnid/created/proof/verificationMethod rotated — verify DID keys-2.

id and proof fields updated; verificationMethod now references keys-2. Please ensure keys-2 is present in DID doc to avoid verifier failures.

Run:


🏁 Script executed:

#!/bin/bash
curl -s https://trustvc.github.io/did/did.json | jq '.verificationMethod[].id' | rg '#keys-2'

Length of output: 153


To verify against the correct DID Web path, let’s fetch the DID document at /did/1/did.json:


🏁 Script executed:

#!/bin/bash
curl -s https://trustvc.github.io/did/1/did.json \
  | jq '.verificationMethod[].id' \
  | rg '#keys-2'

Length of output: 97


Missing verificationMethod “#keys-2” in DID document
We fetched the DID Web document at https://trustvc.github.io/did/1/did.json and found no verificationMethod entry with id ending in #keys-2. Because your proof in public/static/invoice-revoked.json now references

"verificationMethod": "did:web:trustvc.github.io:did:1#keys-2"

verifiers will be unable to resolve that key and will fail.

Action required:

  • public/static/invoice-revoked.json (lines 71–78): proof.verificationMethod points to #keys-2.
  • Update your DID document at https://trustvc.github.io/did/1/did.json to include a matching
    {
      "id": "did:web:trustvc.github.io:did:1#keys-2",
      "type": /* appropriate key type */,
      "controller": "did:web:trustvc.github.io:did:1",
      "publicKeyBase58": /* your public key */
    }
    under its verificationMethod array (and, if necessary, under assertionMethod).

Until this is added, proofs will be unresolvable.

🤖 Prompt for AI Agents
public/static/invoice-revoked.json around lines 71-78: the
proof.verificationMethod references "did:web:trustvc.github.io:did:1#keys-2" but
the DID document at https://trustvc.github.io/did/1/did.json lacks a
verificationMethod entry with that id; to fix, add a verificationMethod object
to that DID document with id "did:web:trustvc.github.io:did:1#keys-2",
appropriate type (matching the key/proof type used), controller
"did:web:trustvc.github.io:did:1", and the corresponding public key
(publicKeyBase58 or other required field), and also include the same key id in
the assertionMethod (or relevant verification relationship) array so verifiers
can resolve the proof.

Comment on lines +136 to 139
"data": "2b4a88df-aabe-413e-bdd3-7eaae1ea92b6:string:JVBERi0xLjMNCiXi48/TDQoNCjEgMCBvYmoNCjw8DQovVHlwZSAvQ2F0YWxvZw0KL091dGxpbmVzIDIgMCBSDQovUGFnZXMgMyAwIFINCj4+DQplbmRvYmoNCg0KMiAwIG9iag0KPDwNCi9UeXBlIC9PdXRsaW5lcw0KL0NvdW50IDANCj4+DQplbmRvYmoNCg0KMyAwIG9iag0KPDwNCi9UeXBlIC9QYWdlcw0KL0NvdW50IDINCi9LaWRzIFsgNCAwIFIgNiAwIFIgXSANCj4+DQplbmRvYmoNCg0KNCAwIG9iag0KPDwNCi9UeXBlIC9QYWdlDQovUGFyZW50IDMgMCBSDQovUmVzb3VyY2VzIDw8DQovRm9udCA8PA0KL0YxIDkgMCBSIA0KPj4NCi9Qcm9jU2V0IDggMCBSDQo+Pg0KL01lZGlhQm94IFswIDAgNjEyLjAwMDAgNzkyLjAwMDBdDQovQ29udGVudHMgNSAwIFINCj4+DQplbmRvYmoNCg0KNSAwIG9iag0KPDwgL0xlbmd0aCAxMDc0ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBUZg0KNTcuMzc1MCA3MjIuMjgwMCBUZA0KKCBBIFNpbXBsZSBQREYgRmlsZSApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIFRoaXMgaXMgYSBzbWFsbCBkZW1vbnN0cmF0aW9uIC5wZGYgZmlsZSAtICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjY0LjcwNDAgVGQNCigganVzdCBmb3IgdXNlIGluIHRoZSBWaXJ0dWFsIE1lY2hhbmljcyB0dXRvcmlhbHMuIE1vcmUgdGV4dC4gQW5kIG1vcmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NTIuNzUyMCBUZA0KKCB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDYyOC44NDgwIFRkDQooIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjE2Ljg5NjAgVGQNCiggdGV4dC4gQW5kIG1vcmUgdGV4dC4gQm9yaW5nLCB6enp6ei4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjA0Ljk0NDAgVGQNCiggbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDU5Mi45OTIwIFRkDQooIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNTY5LjA4ODAgVGQNCiggQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA1NTcuMTM2MCBUZA0KKCB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBFdmVuIG1vcmUuIENvbnRpbnVlZCBvbiBwYWdlIDIgLi4uKSBUag0KRVQNCmVuZHN0cmVhbQ0KZW5kb2JqDQoNCjYgMCBvYmoNCjw8DQovVHlwZSAvUGFnZQ0KL1BhcmVudCAzIDAgUg0KL1Jlc291cmNlcyA8PA0KL0ZvbnQgPDwNCi9GMSA5IDAgUiANCj4+DQovUHJvY1NldCA4IDAgUg0KPj4NCi9NZWRpYUJveCBbMCAwIDYxMi4wMDAwIDc5Mi4wMDAwXQ0KL0NvbnRlbnRzIDcgMCBSDQo+Pg0KZW5kb2JqDQoNCjcgMCBvYmoNCjw8IC9MZW5ndGggNjc2ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBUZg0KNTcuMzc1MCA3MjIuMjgwMCBUZA0KKCBTaW1wbGUgUERGIEZpbGUgMiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIC4uLmNvbnRpbnVlZCBmcm9tIHBhZ2UgMS4gWWV0IG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NzYuNjU2MCBUZA0KKCBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY2NC43MDQwIFRkDQooIHRleHQuIE9oLCBob3cgYm9yaW5nIHR5cGluZyB0aGlzIHN0dWZmLiBCdXQgbm90IGFzIGJvcmluZyBhcyB3YXRjaGluZyApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY1Mi43NTIwIFRkDQooIHBhaW50IGRyeS4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NDAuODAwMCBUZA0KKCBCb3JpbmcuICBNb3JlLCBhIGxpdHRsZSBtb3JlIHRleHQuIFRoZSBlbmQsIGFuZCBqdXN0IGFzIHdlbGwuICkgVGoNCkVUDQplbmRzdHJlYW0NCmVuZG9iag0KDQo4IDAgb2JqDQpbL1BERiAvVGV4dF0NCmVuZG9iag0KDQo5IDAgb2JqDQo8PA0KL1R5cGUgL0ZvbnQNCi9TdWJ0eXBlIC9UeXBlMQ0KL05hbWUgL0YxDQovQmFzZUZvbnQgL0hlbHZldGljYQ0KL0VuY29kaW5nIC9XaW5BbnNpRW5jb2RpbmcNCj4+DQplbmRvYmoNCg0KMTAgMCBvYmoNCjw8DQovQ3JlYXRvciAoUmF2ZSBcKGh0dHA6Ly93d3cubmV2cm9uYS5jb20vcmF2ZVwpKQ0KL1Byb2R1Y2VyIChOZXZyb25hIERlc2lnbnMpDQovQ3JlYXRpb25EYXRlIChEOjIwMDYwMzAxMDcyODI2KQ0KPj4NCmVuZG9iag0KDQp4cmVmDQowIDExDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDAwMTkgMDAwMDAgbg0KMDAwMDAwMDA5MyAwMDAwMCBuDQowMDAwMDAwMTQ3IDAwMDAwIG4NCjAwMDAwMDAyMjIgMDAwMDAgbg0KMDAwMDAwMDM5MCAwMDAwMCBuDQowMDAwMDAxNTIyIDAwMDAwIG4NCjAwMDAwMDE2OTAgMDAwMDAgbg0KMDAwMDAwMjQyMyAwMDAwMCBuDQowMDAwMDAyNDU2IDAwMDAwIG4NCjAwMDAwMDI1NzQgMDAwMDAgbg0KDQp0cmFpbGVyDQo8PA0KL1NpemUgMTENCi9Sb290IDEgMCBSDQovSW5mbyAxMCAwIFINCj4+DQoNCnN0YXJ0eHJlZg0KMjcxNA0KJSVFT0YNCg==",
"filename": "58243cfb-be63-4bfb-be7c-1af7c63ee9cf:string:sample.pdf",
"type": "5f416e01-88d7-4af3-b620-7051eb493d9d:string:application/pdf"
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Attachments ‘data’ now prefixed with “:string:” — likely breaks base64 decoding/rendering.

Previously attachments.data were raw base64. With the new “uuid:string:BASE64” format, any consumer expecting plain base64 will fail. This is inconsistent with other fixtures (e.g., bill-of-lading-operative.json still uses raw base64).

Apply this minimal, safe correction (strip the prefixes, keep base64 unchanged):

-        "data": "2b4a88df-aabe-413e-bdd3-7eaae1ea92b6:string:JVBERi0xLjMNCiXi48/TDQoN..."
+        "data": "JVBERi0xLjMNCiXi48/TDQoN..."
         "filename": "58243cfb-be63-4bfb-be7c-1af7c63ee9cf:string:sample.pdf",
-        "type": "5f416e01-88d7-4af3-b620-7051eb493d9d:string:application/pdf"
+        "type": "application/pdf"
@@
-        "data": "eb357020-d72b-4bfa-a54e-2db451ea5c44:string:JVBERi0xLjYNJeLjz9MNCjI0IDAgb2JqDTw8L0ZpbHRlci9GbGF0ZURlY29kZS9G..."
+        "data": "JVBERi0xLjYNJeLjz9MNCjI0IDAgb2JqDTw8L0ZpbHRlci9GbGF0ZURlY29kZS9G..."
         "filename": "261a20f8-9bfc-4c31-b522-21081a8b523c:string:veryverylongfilenameoverhereveryverylongfilenameoverhere.pdf",
-        "type": "6526eadc-303d-4ea7-96fa-699752656f9c:string:application/pdf"
+        "type": "application/pdf"

If the “uuid:string:” envelope is intentional for other textual fields, attachments should still remain raw base64 for compatibility.

Also applies to: 141-144

🤖 Prompt for AI Agents
In public/static/OA/certificate-of-origin-default.json around lines 136-139 (and
also 141-144), the attachments.data value is prefixed with "uuid:string:" which
corrupts the expected raw base64; remove the "uuid:string:" (and any similar
"<uuid>:" envelope) from the data fields so attachments.data remains the
original base64 string, leaving the base64 content unchanged and preserving
compatibility with consumers that expect raw base64.

Comment on lines +35 to +43
"line1": "79ec83f5-5b9a-4761-a447-dd7591f58363:string:Plot 123, Industrial Estate",
"line2": "a85b9cd4-8eb4-451f-9a9e-f4420d6ca4c1:string:Sector 5, Tech Park",
"cityName": "400ff27d-d7e2-4ac2-b0de-91c98ad978b3:string:Mumbai",
"postcode": "5b1dd8a5-8ffa-4cf8-8f0f-1c5fc6e73cd1:string:400001",
"countrySubDivisionName": "cd3907f5-46a6-4b27-a25c-9f227648668c:string:Maharashtra",
"countryCode": "552c6f04-a89d-458f-b9f9-49c4e8e979cc:string:In"
},
"iD": "fad7af35-59a2-4dfe-8106-64a34b3ec2ef:string:EXP-IN-XYZ-0001",
"name": "5c5bb6d3-3cee-40c0-8805-1d9fb8089314:string:XYZ Exports Pvt. Ltd."
"iD": "e1fd9de3-2fb1-4a96-8b93-53e7350bec17:string:EXP-IN-XYZ-0001",
"name": "b3c35c45-5392-4d13-9761-1dc28ee80260:string:XYZ Exports Pvt. Ltd."
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Uppercase all ISO codes (“IN”, “GB”).

Same casing issue as in the revoked fixture — normalize for schema/validator friendliness.

Also applies to: 50-59, 67-76, 87-96, 99-105, 112-126, 127-131

🤖 Prompt for AI Agents
In public/static/OA/certificate-of-origin-expired.json around lines 35 to 43,
the country ISO codes are lowercased (e.g., "In") which breaks schema/validator
expectations; change the countryCode values to uppercase (e.g., "IN") and apply
the same normalization to all other occurrences noted in the comment (lines
50-59, 67-76, 87-96, 99-105, 112-126, 127-131), ensuring every ISO country code
string uses uppercase letters consistently.

Comment on lines +35 to 44
"line1": "79cc004a-a601-45d6-bc58-c1536d090967:string:Plot 123, Industrial Estate",
"line2": "c4ba03e1-ff9f-4beb-8a12-01b09e17eba8:string:Sector 5, Tech Park",
"cityName": "aa8b7da6-9c90-4b84-9218-251b4372ceb2:string:Mumbai",
"postcode": "601bf4b0-8745-4995-ac4d-db89a9e4bbbb:string:400001",
"countrySubDivisionName": "126c435a-aaea-4256-b2e7-0f7cf050e9fc:string:Maharashtra",
"countryCode": "40a395cc-a559-4195-9046-2858c299432c:string:In"
},
"iD": "13c28cb5-7ab1-4645-8f43-a226eebc3562:string:EXP-IN-XYZ-0001",
"name": "a53c50c4-5034-48de-96f1-027c6e59a4bf:string:XYZ Exports Pvt. Ltd."
"iD": "11544bd4-86ab-41e0-8b61-a8eb423bd528:string:EXP-IN-XYZ-0001",
"name": "c887d7ec-2244-4e96-a04f-aaaf5b841b49:string:XYZ Exports Pvt. Ltd."
},
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Normalize ISO country codes to uppercase.

Multiple instances of “In” should be “IN”.

Also applies to: 50-56, 63-72, 88-97, 99-103

🤖 Prompt for AI Agents
In public/static/OA/certificate-of-origin-redacted.json around lines 35 to 44
(also check ranges 50-56, 63-72, 88-97, 99-103), the countryCode values use
lowercase/incorrect casing like "In" — normalize all ISO country codes to
uppercase (e.g., "IN"); update each countryCode field in the listed line ranges
to use the uppercase ISO code consistently throughout the file.

Comment on lines +36 to 45
"line1": "00b8417c-14b4-4006-bb89-09ba69b7b66c:string:Plot 123, Industrial Estate",
"line2": "8da84cc0-d902-478f-87c4-0f08aebdc546:string:Sector 5, Tech Park",
"cityName": "a4375e99-9ba4-427c-99b5-b9687fdb09b7:string:Mumbai",
"postcode": "bc885b43-80c4-47e1-a042-9fcd5b93ecd8:string:400001",
"countrySubDivisionName": "6a603971-8c9e-4c58-8768-8b53b1a1f98e:string:Maharashtra",
"countryCode": "34cef0ca-c89c-4e4c-8c31-56dbc6743a42:string:In"
},
"iD": "ee35d5e0-5d20-4eae-a670-c5abf952caae:string:EXP-IN-XYZ-0001",
"name": "b905a07e-a745-4a06-8bcc-a88c3f705292:string:XYZ Exports Pvt. Ltd."
"iD": "9a67f79d-f1c6-47d1-a10f-c82974e0f093:string:EXP-IN-XYZ-0001",
"name": "1f2b5c61-59bf-4340-a816-40dfce32448c:string:XYZ Exports Pvt. Ltd."
},
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Normalize ISO country codes to uppercase ("IN", "GB").

Several countryCode values use “In”/“in”. Some validators and UIs expect ISO 3166-1 alpha-2 uppercase. Recommend normalizing all codes across exporter, manufacturer, originCountry, importCountry.

Apply a minimal fix (sample):

-          "countryCode": "34cef0ca-c89c-4e4c-8c31-56dbc6743a42:string:In"
+          "countryCode": "34cef0ca-c89c-4e4c-8c31-56dbc6743a42:string:IN"
...
-              "countryCode": "4a29ce43-bce5-4e29-9a0d-8d903d57f18a:string:in"
+              "countryCode": "4a29ce43-bce5-4e29-9a0d-8d903d57f18a:string:IN"

Also applies to: 50-60, 68-76, 88-97, 100-106, 112-116, 127-132

🤖 Prompt for AI Agents
public/static/OA/certificate-of-origin-revoked.json lines ~36-45 (and also check
ranges 50-60, 68-76, 88-97, 100-106, 112-116, 127-132): several "countryCode"
values use lowercase or mixed-case ("In"/"in") which should be ISO 3166-1
alpha-2 uppercase; update those countryCode string values to their uppercase
forms (e.g., "IN", "GB") for exporter, manufacturer, originCountry,
importCountry and any other occurrences in the listed ranges so all countryCode
fields are normalized to uppercase.

Comment on lines 154 to 158
"type": "SHA3MerkleProof",
"targetHash": "bd7a700d18cd50fb2ee3add8fd319aa4a967ab7b989c16ab36932a58f9a3272b",
"targetHash": "9b93e47b73d68437d4156c79018caaf3c7f3bb7de9ae58ca83fcde4e7211aa54",
"proof": [],
"merkleRoot": "bd7a700d18cd50fb2ee3add8fd319aa4a967ab7b989c16ab36932a58f9a3272b"
"merkleRoot": "9b93e47b73d68437d4156c79018caaf3c7f3bb7de9ae58ca83fcde4e7211aa54"
},
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Merkle targetHash/merkleRoot and OA signature rotated — run oa-verify as a safeguard.

Run OpenAttestation verification locally for this file and siblings:

Also applies to: 161-166


🏁 Script executed:

#!/bin/bash
set -euo pipefail
npm -s init -y >/dev/null
npm -s i @govtechsg/oa-verify@^7 >/dev/null

node - <<'JS'
const { openAttestationVerifiers, verificationBuilder, isValid } = require("@govtechsg/oa-verify");
const fs = require("fs");

const files = [
  "public/static/OA/certificate-of-origin-revoked.json",
  "public/static/OA/certificate-of-origin-expired.json",
  "public/static/OA/certificate-of-origin-redacted.json"
];

(async () => {
  const verify = verificationBuilder(openAttestationVerifiers, { network: "homestead" }); // network not used for FREE chain docs but required by API
  let ok = true;
  for (const f of files) {
    const doc = JSON.parse(fs.readFileSync(f, "utf8"));
    const res = await verify(doc);
    const valid = isValid(res);
    console.log(`${valid ? "[OK] " : "[FAIL] "} ${f}`);
    if (!valid) ok = false;
  }
  if (!ok) process.exit(1);
})();
JS

Length of output: 998


OpenAttestation verification failures: missing Merkle proofs in OA JSON fixtures

Running oa-verify on the three certificate-of-origin JSONs all failed, indicating that the current SHA3MerkleProof fragments are invalid (empty proof arrays) and cannot be verified against their merkleRoot:

• public/static/OA/certificate-of-origin-revoked.json (lines 154–158)
• public/static/OA/certificate-of-origin-expired.json (lines 154–158)
• public/static/OA/certificate-of-origin-redacted.json (lines 154–158)

To restore verifiable integrity:

  • Regenerate each document with a properly populated Merkle proof:
    • Ensure the proof array contains the sequence of sibling hashes up to the root.
    • Confirm the targetHash is the SHA3-256 of the document fragment being proved.
    • Verify the merkleRoot matches the root computed by your issuance tool.
  • Use the official OpenAttestation document generator or tooling (e.g., @govtechsg/oa-issue) to produce compliant JSON fixtures.
  • Configure a valid provider/API key per https://github.com/Open-Attestation/oa-verify#provider before running in production.
  • Re-run oa-verify to confirm successful verification (look for [OK] status).

Until these proofs are fixed, downstream verification (and any UI components relying on OA signatures) will continue to fail.

🤖 Prompt for AI Agents
In public/static/OA/certificate-of-origin-revoked.json around lines 154–158 the
SHA3MerkleProof fragment is invalid because the proof array is empty; regenerate
the fixture using the OpenAttestation tooling (e.g., @govtechsg/oa-issue or
official OA document generator) so the `proof` array contains the sibling hashes
from the leaf to the root, ensure `targetHash` is the SHA3-256 of the proved
document fragment, confirm `merkleRoot` matches the root produced by the issuer,
configure a valid OA provider/API key if needed, and re-run `oa-verify` to
confirm the fragment now verifies as [OK].

Copy link
Contributor

@isaackps isaackps left a comment

Choose a reason for hiding this comment

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

LGTM

@RishabhS7 RishabhS7 merged commit 4bddb63 into main Aug 22, 2025
6 checks passed
@RishabhS7 RishabhS7 deleted the fix/new-qr-docs branch August 22, 2025 06:28
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.

3 participants