Files
explorer-monorepo/backend/api/rest
Devin e0722b8e7e fix(auth): typed context keys and real sentinel errors
backend/api/middleware/context.go (new):
- Introduces an unexported ctxKey type and three constants
  (ctxKeyUserAddress, ctxKeyUserTrack, ctxKeyAuthenticated) that
  replace the bare string keys 'user_address', 'user_track', and
  'authenticated'. Bare strings trigger go vet's SA1029 and collide
  with keys from any other package that happens to share the name.
- Helpers: ContextWithAuth, UserAddress, UserTrack, IsAuthenticated.
- Sentinel: ErrMissingAuthorization replaces the misuse of
  http.ErrMissingFile as an auth-missing signal. (http.ErrMissingFile
  belongs to multipart form parsing and was semantically wrong.)

backend/api/middleware/auth.go:
- RequireAuth, OptionalAuth, RequireTrack now all read/write via the
  helpers; no more string literals for context keys in this file.
- extractAuth returns ErrMissingAuthorization instead of
  http.ErrMissingFile.
- Dropped now-unused 'context' import.

backend/api/track4/operator_scripts.go, backend/api/track4/endpoints.go,
backend/api/rest/features.go:
- Read user address / track via middleware.UserAddress() and
  middleware.UserTrack() instead of a raw context lookup with a bare
  string key.
- Import 'github.com/explorer/backend/api/middleware'.

backend/api/track4/operator_scripts_test.go:
- Four test fixtures updated to seed the request context through
  middleware.ContextWithAuth (track 4, authenticated) instead of
  context.WithValue with a bare 'user_address' string. This is the
  load-bearing change that proves typed keys are required: a bare
  string key no longer wakes up the middleware helpers.

backend/api/middleware/context_test.go (new):
- Round-trip test for ContextWithAuth + UserAddress + UserTrack +
  IsAuthenticated.
- Defaults: UserTrack=1, UserAddress="", IsAuthenticated=false on a
  bare context.
- TestContextKeyIsolation: an outside caller that inserts
  'user_address' as a bare string key must NOT be visible to
  UserAddress; proves the type discipline.
- ErrMissingAuthorization sentinel smoke test.

Verification:
- go build ./... clean.
- go vet ./... clean (removes SA1029 on the old bare keys).
- go test ./api/middleware/... ./api/track4/... ./api/rest/... PASS.

Advances completion criterion 3 (Auth correctness).
2026-04-18 19:05:24 +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.