Skip to main content

Developer Field Mapping

Complete mapping of Admin Dashboard UI fields to backend storage locations, node modules, and API endpoints.

Overview​

This document maps every field in the Admin Dashboard UI to:

  • Backend storage locations (Google Cloud Storage files)
  • Node modules and functions that handle the data
  • API endpoints that read/write the data
  • Frontend JavaScript files that display/edit the data

Merchant Creation Form​

Company Name​

UI Location: Add Merchant Modal → Company Name field
Frontend File: admin/js/merchants.js → submitAddMerchant()
Frontend Element: #merchantName

Backend Storage:

  • File: gs://finmatch-secrets/merchants.json
  • Path: profiles[merchantId].merchantName
  • Also Saved As: profiles[merchantId].companyName

Backend Processing:

  • File: cloud-run/merchant-api/index.js
  • Function: POST /api/merchants
  • Validation: cloud-run/merchant-api/lib/validation.js → validateMerchantData()
  • Node Module: @google-cloud/storage (via atomicWrite())

API Endpoint: POST https://merchant-api-238644427841.europe-west2.run.app/api/merchants

Domain​

UI Location: Add Merchant Modal → Domain field
Frontend File: admin/js/merchants.js → submitAddMerchant()
Frontend Element: #domain

Backend Storage:

  • File: gs://finmatch-secrets/merchants.json
  • Path: profiles[merchantId].domain
  • Also Saved To: gs://finmatch-secrets/merchant-router.json → [merchantId].domain

Backend Processing:

  • File: cloud-run/merchant-api/index.js
  • Function: POST /api/merchants
  • Normalization: Adds https:// prefix if missing
  • Validation: Regex pattern /^https?:\/\/[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/
  • CORS Update: updateCorsPolicy() adds domain to CORS whitelist

Node Modules:

  • @google-cloud/storage - GCS read/write
  • express - API endpoint handling

API Endpoint: POST https://merchant-api-238644427841.europe-west2.run.app/api/merchants

Company Number​

UI Location: Add Merchant Modal → Company Number field
Frontend File: admin/js/merchants.js → submitAddMerchant()
Frontend Element: #companyNo

Backend Storage:

  • File: gs://finmatch-secrets/merchants.json
  • Path: profiles[merchantId].companyNo
  • Optional: Can be undefined if not provided

Backend Processing:

  • File: cloud-run/merchant-api/index.js
  • Function: POST /api/merchants
  • No Validation: Optional field, no validation required

API Endpoint: POST https://merchant-api-238644427841.europe-west2.run.app/api/merchants

Environment​

UI Location: Add Merchant Modal → Environment dropdown
Frontend File: admin/js/merchants.js → submitAddMerchant()
Frontend Element: #environment

Backend Storage:

  • File: gs://finmatch-secrets/merchants.json
  • Path: profiles[merchantId].environment
  • Also Saved To: gs://finmatch-secrets/merchant-router.json → [merchantId].environment

Backend Processing:

  • File: cloud-run/merchant-api/index.js
  • Function: POST /api/merchants
  • Default: 'p' (Production) if not specified
  • Derivation: deriveEnvironment() can override based on domain
  • Values: 'p' (Production), 's' (Staging), 't' (Test)

Node Modules:

  • @google-cloud/storage - GCS read/write

API Endpoint: POST https://merchant-api-238644427841.europe-west2.run.app/api/merchants

Merchant Edit Form​

FinMatch ID​

UI Location: Merchant page → Edit Merchant (inline) → FinMatch ID field
Frontend File: admin/js/merchants.js → editMerchant(), submitEditMerchant()
Frontend Element: #editFinmatchId

Backend Storage:

  • File: gs://finmatch-secrets/merchants.json
  • Path: profiles[merchantId].finmatchId
  • Also Used As: Key in profiles object

Backend Processing:

  • File: cloud-run/merchant-api/index.js
  • Function: PUT /api/merchants/:id
  • Validation: Format check (M\d{6} or FM-\d{4}-\d{4}-\d{4})
  • Uniqueness: Checked to prevent overwriting existing IDs

Node Modules:

  • @google-cloud/storage - GCS read/write
  • express - API endpoint handling

API Endpoint: PUT https://merchant-api-238644427841.europe-west2.run.app/api/merchants/:id

Validation:

  • Frontend: admin/js/merchants.js → Pattern /^(M\d{6}|FM-[0-9]{4}-[0-9]{4}-[0-9]{4})$/
  • Backend: cloud-run/partner-api/lib/validation.js → validateMerchantId()

Merchant Details Page​

Stale client state and URL alignment (critical)​

Symptoms: The URL shows one merchant (?id=…) and the title/header match, but another merchant’s contacts, lenders, snippet merchantID, features matrix, or Merchant History / Merchant JSON targets appear. Saves may surface “Merchant with ID … already exists” when the change-ID path used a stale global ID.

Cause: showMerchantDetails() is async; overlapping navigations could previously leave window.currentMerchantDetails or parts of the DOM inconsistent with the visible deep link.

Frontend mitigations (admin/js/merchants.js): sequence guard (_showMerchantDetailsSeq + stillActive()); header snippet rendered synchronously before any await; lender line and features use the source config loaded for the current merchant.id; Admin tab actions (History, JSON, Quote) and Finance Assistant settings use getMerchantIdFromLocation() and resolveMerchantForPageActions() so they follow the address bar when globals lag; snippet-status getCurrentMerchant uses the same resolver.

Frontend mitigations (admin/js/merchant-crud.js): exitMerchantEditMode({ skipReshow: true }) when switching merchant (no redundant async re-show of the previous merchant); on exit from edit, prefer originalMerchantData over window.currentMerchantDetails when re-rendering.

Operator workaround: Hard refresh if anything looks mixed. If data is still wrong after refresh, validate GET /api/merchants/{id} and contactIds (wrong contact pointers are data issues, not this UI bug).

User docs: Merchant Page Editing — Troubleshooting.

Merchant ID Display​

UI Location: Merchant Details → Merchant Information → ID
Frontend File: admin/js/merchants.js → showMerchantDetails()
Frontend Element: #detailMerchantId

Backend Source:

  • File: gs://finmatch-secrets/merchants.json
  • Path: profiles[merchantId].finmatchId or merchantId (key)

API Endpoint: GET https://merchant-api-238644427841.europe-west2.run.app/api/merchants/:id

Snippet Code Display​

UI Location: Merchant page → App card → Header snippet
Frontend File: admin/js/merchants.js → showMerchantDetails(), generateSnippetCode()
Frontend Element: #detailSnippet

Generation:

  • Function: generateSnippetCode(merchantId, environment)
  • Location: admin/js/merchants.js
  • Format: <script src="https://storage.googleapis.com/finmatch-finance-marketing-assets/{env}/scripts/finmatch-sdk.js?merchantID={id}&v=1.0" type="module" async></script>

Backend Source:

  • Merchant ID: From profiles[merchantId].finmatchId
  • Environment: From profiles[merchantId].environment

Storage Location:

  • SDK Files: gs://finmatch-finance-marketing-assets/{environment}/scripts/finmatch-sdk.js
  • CORS Config: gs://finmatch-secrets/cors.json (CORS_JSON_BUCKET; no Git copy)

Backend File Structure​

merchants.json​

Location: gs://finmatch-secrets/merchants.json

Structure:

{
"profiles": {
"M000101": {
"finmatchId": "M000101",
"merchantName": "Company Name",
"companyName": "Company Name",
"domain": "https://example.com",
"companyNo": "12345678",
"environment": "p",
"merchantStatus": "suspended",
"createdAt": "2025-01-09T12:00:00.000Z",
"lastUpdated": "2025-01-09T12:00:00.000Z"
}
},
"versionStamp": "Updated: 2025-01-09T12:00:00.000Z - Added merchant M000101"
}

Node Module: @google-cloud/storage
Access Function: cloud-run/merchant-api/lib/jsonStore.js → atomicWrite()

merchant-router.json​

Location: gs://finmatch-secrets/merchant-router.json

Structure:

{
"M000101": {
"environment": "p",
"domain": "https://example.com"
}
}

Node Module: @google-cloud/storage
Access Function: cloud-run/merchant-api/lib/jsonStore.js → atomicWrite()

Updated When:

  • Merchant is created
  • Merchant environment is changed
  • Merchant domain is changed

cors.json​

Location: gs://finmatch-secrets/cors.json (CORS_JSON_BUCKET; no Git copy)
Applied To: gs://finmatch-finance-marketing-assets bucket

Structure:

[
{
"maxAgeSeconds": 3600,
"method": ["GET", "HEAD"],
"origin": [
"https://example.com",
"https://www.example.com"
],
"responseHeader": ["Content-Type"]
}
]

Node Module: @google-cloud/storage
Access Function: cloud-run/merchant-api/index.js → updateCorsPolicy()

Updated When: Merchant is created (automatic)

Node Modules Reference​

Merchant API (cloud-run/merchant-api/)​

Location: cloud-run/merchant-api/node_modules/

Key Modules:

  • express (^4.18.2) - Web framework

    • Used for: API endpoints, request handling
    • Files: index.js (all endpoints)
  • cors (^2.8.5) - CORS middleware

    • Used for: API CORS configuration
    • Files: index.js (top-level CORS setup)
  • @google-cloud/storage (^7.7.0) - GCS client

    • Used for: Reading/writing JSON files in GCS
    • Files: index.js, lib/jsonStore.js

Package File: cloud-run/merchant-api/package.json

Partner API (cloud-run/partner-api/)​

Location: cloud-run/partner-api/node_modules/

Key Modules:

  • express - Web framework
  • @google-cloud/storage - GCS client
  • Validation modules - Merchant ID format validation

Package File: cloud-run/partner-api/package.json

API Endpoints​

Create Merchant​

Endpoint: POST /api/merchants
File: cloud-run/merchant-api/index.js
Function: app.post('/api/merchants', ...)

Writes To:

  • merchants.json (via atomicWrite())
  • merchant-router.json (via atomicWrite())
  • cors.json (via updateCorsPolicy())

Node Modules Used:

  • express - Request handling
  • @google-cloud/storage - GCS operations

Get Merchant​

Endpoint: GET /api/merchants/:id
File: cloud-run/merchant-api/index.js
Function: app.get('/api/merchants/:id', ...)

Reads From:

  • merchants.json (via GCS download)

Node Modules Used:

  • express - Request handling
  • @google-cloud/storage - GCS read

Update Merchant​

Endpoint: PUT /api/merchants/:id
File: cloud-run/merchant-api/index.js
Function: app.put('/api/merchants/:id', ...)

Writes To:

  • merchants.json (via atomicWrite())
  • merchant-router.json (if environment changed, via atomicWrite())

Node Modules Used:

  • express - Request handling
  • @google-cloud/storage - GCS operations

Frontend Files​

merchants.js​

Location: admin/js/merchants.js

Key Functions:

  • submitAddMerchant() - Creates new merchant
  • editMerchant() - Loads merchant for editing
  • submitEditMerchant() - Updates merchant
  • showMerchantDetails() - Displays merchant details
  • generateSnippetCode() - Generates snippet code
  • loadMerchantProfiles() - Loads all merchants from API

API Calls:

  • POST /api/merchants - Create merchant
  • GET /api/merchants/:id - Get merchant
  • PUT /api/merchants/:id - Update merchant
  • GET /api/merchants - Get all merchants

merchants/index.html​

Location: admin/merchants/index.html

Key Elements:

  • #addMerchantModal - Add merchant form
  • #editMerchantModal - Edit merchant form
  • #merchantPage - Merchant details view
  • #detailSnippet - Snippet code display
  • #editSnippetDisplay - Snippet code in edit form

Data Flow Summary​

UI Form Field
↓
Frontend JavaScript (merchants.js)
↓
API Request (fetch)
↓
Merchant API (index.js)
↓
Validation (validation.js)
↓
Atomic Write (jsonStore.js)
↓
Google Cloud Storage
↓
JSON File (merchants.json / merchant-router.json / cors.json)