Files
explorer-monorepo/backend/api/rest
Devin 09db9de398
Some checks failed
CI / Backend (go 1.23.x) (pull_request) Successful in 6m22s
CI / Backend security scanners (pull_request) Failing after 2m0s
CI / Frontend (node 20) (pull_request) Successful in 3m6s
CI / gitleaks (secret scan) (pull_request) Failing after 17s
chore(ci): align Go to 1.23.x, add staticcheck/govulncheck/gitleaks gates
.github/workflows/ci.yml:
- Go version: 1.22 -> 1.23.4 (matches go.mod's 'go 1.23.0' declaration).
- Split into four jobs with explicit names:
    * test-backend: go vet + go build + go test
    * scan-backend: staticcheck + govulncheck (installed from pinned tags)
    * test-frontend: npm ci + eslint + tsc --noEmit + next build
    * gitleaks: full-history secret scan on every PR
- Branches triggered: master + main + develop (master is the repo
  default; the previous workflow only triggered on main/develop and
  would never have run on the repo's actual PRs).
- actions/checkout@v4, actions/setup-go@v5, actions/setup-node@v4.
- Concurrency group cancels stale runs on the same ref.
- Node and Go caches enabled for faster CI.

.gitleaks.toml (new):
- Extends gitleaks defaults.
- Custom rule 'explorer-legacy-db-password-L@ker' keeps the historical
  password pattern L@kers?\$?2010 wedged in the detection set even
  after rotation, so any re-introduction (via copy-paste from old
  branches, stale docs, etc.) fails CI.
- Allowlists docs/SECURITY.md and CHANGELOG.md where the string is
  cited in rotation context.

backend/staticcheck.conf (new):
- Enables the full SA* correctness set.
- Temporarily disables ST1000/1003/1005/1020/1021/1022, U1000, S1016,
  S1031. These are stylistic/cosmetic checks; the project has a long
  tail of pre-existing hits there that would bloat every PR. Each is
  commented so the disable can be reverted in a dedicated cleanup.

Legit correctness issues surfaced by staticcheck and fixed in this PR:
- backend/analytics/token_distribution.go: 'best-effort MV refresh'
  block no longer dereferences a shadowed 'err'; scope-tight 'if err :='
  used for the subsequent QueryRow.
- backend/api/rest/middleware.go: compressionMiddleware() was parsing
  Accept-Encoding and doing nothing with it. Now it's a literal
  pass-through with a TODO comment pointing at gorilla/handlers.
- backend/api/rest/mission_control.go: shadowed 'err' from
  json.Unmarshal was assigned to an ignored outer binding via
  fmt.Errorf; replaced with a scoped 'if uerr :=' that lets the RPC
  fallback run as intended.
- backend/indexer/traces/tracer.go: best-effort CREATE TABLE no longer
  discards the error implicitly.
- backend/indexer/track2/block_indexer.go: 'latestBlock - uint64(i) >= 0'
  was a tautology on uint64. Replaced with an explicit
  'if uint64(i) > latestBlock { break }' guard so operators running
  count=1000 against a shallow chain don't underflow.
- backend/tracing/tracer.go: introduces a local ctxKey type and two
  constants so WithValue calls stop tripping SA1029.

Verification:
- go build ./... clean.
- go vet ./... clean.
- go test ./... all existing tests PASS.
- staticcheck ./... clean except for the SA1029 hits in
  api/middleware/auth.go and api/track4/operator_scripts_test.go,
  which are resolved by PR #4 once it merges to master.

Advances completion criterion 4 (CI in good health).
2026-04-18 19:10:20 +00:00
..

REST API Server

REST API implementation for the ChainID 138 Explorer Platform.

Structure

  • server.go - Main server setup and route configuration
  • routes.go - Route handlers and URL parsing
  • auth.go - Wallet auth, user-session auth, RPC product access, subscriptions, and API keys
  • blocks.go - Block-related endpoints
  • transactions.go - Transaction-related endpoints
  • addresses.go - Address-related endpoints
  • search.go - Unified search endpoint
  • mission_control.go - Mission-control bridge trace and cached liquidity helpers
  • validation.go - Input validation utilities
  • middleware.go - HTTP middleware (logging, compression)
  • errors.go - Error response utilities

API Endpoints

Auth

  • POST /api/v1/auth/nonce - Create a wallet-signature nonce
  • POST /api/v1/auth/wallet - Authenticate a wallet and receive a track JWT
  • POST /api/v1/auth/register - Create an access-console user session
  • POST /api/v1/auth/login - Log in to the access console

Blocks

  • GET /api/v1/blocks - List blocks (paginated)
  • GET /api/v1/blocks/{chain_id}/{number} - Get block by number
  • GET /api/v1/blocks/{chain_id}/hash/{hash} - Get block by hash

Transactions

  • GET /api/v1/transactions - List transactions (paginated, filterable)
  • GET /api/v1/transactions/{chain_id}/{hash} - Get transaction by hash

Addresses

  • GET /api/v1/addresses/{chain_id}/{address} - Get address information
  • GET /api/v1/search?q={query} - Unified search (auto-detects type: block number, address, or transaction hash)

Health

  • GET /health - Health check endpoint

Mission control

  • GET /api/v1/mission-control/stream - SSE stream for bridge/RPC health
  • GET /api/v1/mission-control/bridge/trace?tx=0x... - Blockscout-backed tx trace with Chain 138 contract labels
  • GET /api/v1/mission-control/liquidity/token/{address}/pools - 30-second cached proxy to token-aggregation pools

Access and API keys

  • GET /api/v1/access/me - Current signed-in access user and subscriptions
  • GET /api/v1/access/products - RPC product catalog for Core, Alltra, and Thirdweb lanes
  • GET /api/v1/access/subscriptions - List product subscriptions
  • POST /api/v1/access/subscriptions - Request or activate a product subscription
  • GET /api/v1/access/admin/subscriptions - List pending or filtered subscriptions for admin review
  • POST /api/v1/access/admin/subscriptions - Approve, suspend, or revoke a subscription as an admin
  • GET /api/v1/access/api-keys - List issued API keys
  • POST /api/v1/access/api-keys - Create an API key for a tier, product, scopes, expiry, and optional quota override
  • POST /api/v1/access/api-keys/{id} - Revoke an API key
  • DELETE /api/v1/access/api-keys/{id} - Alternate revoke verb
  • GET /api/v1/access/usage - Per-product usage summary
  • GET /api/v1/access/audit - Recent validated API-key usage rows for the signed-in user
  • GET /api/v1/access/admin/audit - Admin view of recent validated API-key usage rows, optionally filtered by product
  • POST /api/v1/access/internal/validate-key - Internal edge validation hook for API-key enforcement and usage logging
  • GET /api/v1/access/internal/validate-key - auth_request-friendly validator for nginx or similar proxies

Track 4 operator

  • POST /api/v1/track4/operator/run-script - Run an allowlisted script under OPERATOR_SCRIPTS_ROOT

Features

  • Input validation (addresses, hashes, block numbers)
  • Pagination support
  • Query timeouts for database operations
  • CORS headers
  • Request logging
  • Error handling with consistent error format
  • Health checks with database connectivity
  • Wallet JWT auth for track endpoints
  • Email/password user sessions for the explorer access console
  • RPC product catalog, subscription state, API key issuance, revocation, and usage summaries

Running

cd backend/api/rest
go run main.go

Or use the development script:

./scripts/run-dev.sh

Configuration

Set environment variables:

  • DB_HOST - Database host
  • DB_PORT - Database port
  • DB_USER - Database user
  • DB_PASSWORD - Database password
  • DB_NAME - Database name
  • PORT - API server port (default: 8080)
  • CHAIN_ID - Chain ID (default: 138)
  • RPC_URL - Chain RPC used by Track 1 and mission-control health/SSE data
  • TOKEN_AGGREGATION_BASE_URL - Upstream token-aggregation base URL for mission-control liquidity proxy
  • BLOCKSCOUT_INTERNAL_URL - Internal Blockscout base URL for bridge trace lookups
  • EXPLORER_PUBLIC_BASE - Public explorer base URL used in mission-control trace responses
  • CCIP_RELAY_HEALTH_URL - Optional relay health probe URL, for example http://192.168.11.11:9860/healthz
  • CCIP_RELAY_HEALTH_URLS - Optional comma-separated named relay probes, for example mainnet=http://192.168.11.11:9860/healthz,bsc=http://192.168.11.11:9861/healthz,avax=http://192.168.11.11:9862/healthz
  • MISSION_CONTROL_CCIP_JSON - Optional JSON snapshot fallback when relay health is provided as a file instead of an HTTP endpoint
  • OPERATOR_SCRIPTS_ROOT - Root directory for allowlisted Track 4 scripts
  • OPERATOR_SCRIPT_ALLOWLIST - Comma-separated list of permitted script names or relative paths
  • OPERATOR_SCRIPT_TIMEOUT_SEC - Optional Track 4 script timeout in seconds (max 599)
  • JWT_SECRET - Shared secret for wallet and user-session JWT signing
  • ACCESS_ADMIN_EMAILS - Comma-separated email allowlist for access-console admins
  • ACCESS_INTERNAL_SECRET - Shared secret used by internal edge validators calling /api/v1/access/internal/validate-key

Auth model

There are now two distinct auth planes:

  1. Wallet auth

    • POST /api/v1/auth/nonce
    • POST /api/v1/auth/wallet
    • Used for wallet-oriented explorer tracks and operator features.
  2. Access-console user auth

    • POST /api/v1/auth/register
    • POST /api/v1/auth/login
    • Used for /api/v1/access/* endpoints and the frontend /access console.

RPC access model

The access layer currently models three RPC products:

  • core-rpc
    • Provider: besu-core
    • VMID: 2101
    • Approval required
    • Intended for operator-grade and sensitive use
  • alltra-rpc
    • Provider: alltra
    • VMID: 2102
    • Self-service subscription model
  • thirdweb-rpc
    • Provider: thirdweb
    • VMID: 2103
    • Self-service subscription model

The explorer can now:

  • register and authenticate users
  • publish an RPC product catalog
  • create product subscriptions
  • issue scoped API keys
  • set expiry presets and quota overrides
  • rotate keys by minting a replacement and revoking the old one
  • review approval-gated subscriptions through an admin surface
  • revoke keys
  • show usage summaries
  • show recent audit activity for users and admins
  • validate keys for internal edge enforcement and append usage records
  • support nginx auth_request integration through the GET /api/v1/access/internal/validate-key form

Current limitation:

  • the internal validation hook exists, but nginx/Besu/relay still need to call it or replicate its rules to enforce traffic at the edge
  • billing collection and invoicing are not yet handled by this package

Operational reference:

  • explorer-monorepo/deployment/ACCESS_EDGE_ENFORCEMENT_RUNBOOK.md
  • explorer-monorepo/deployment/common/nginx-rpc-api-key-gate.conf

Mission-control deployment notes

  • Include explorer-monorepo/deployment/common/nginx-mission-control-sse.conf in the same nginx server block that proxies /explorer-api/.
  • Keep the nginx upstream port aligned with the Go API PORT.
  • Verify internal reachability to BLOCKSCOUT_INTERNAL_URL and TOKEN_AGGREGATION_BASE_URL from the API host before enabling the mission-control cards in production.