LumeScope is a neutral, read-only API aggregator for the Lumera network. It decodes Action metadata (Cascade/Sense), provides Cascade previews (MIME types, file sizes), and aggregates SuperNode metrics, probes, version compatibility, and payment statistics—so Lumera clients stay lightweight and responsive.
- Actions API — List and detail endpoints for decoded Action metadata (Cascade/Sense types) with transaction lifecycle tracking (register, finalize, approve)
- SuperNode Metrics — Aggregated hardware stats, version matrix, payment info, and availability probes
- Background Scheduler — Automatic sync loops:
- Validators sync (default: 5m)
- SuperNodes sync (default: 2m)
- Actions sync (default: 30s)
- SuperNode port probes (default: 1m)
- Action transaction enricher (background)
- Embedded PostgreSQL 14 — Single-container deployment; no external database required
- Swagger UI — Interactive API docs at
/docs - OpenAPI 3.0 — Machine-readable spec at
/openapi.json - stdlib-only HTTP — No third-party web frameworks; uses Go's
net/http
LumeScope exposes 16 endpoints. All data is read-only.
| Endpoint | Method | Description | Key Params | Example |
|---|---|---|---|---|
/healthz |
GET | Liveness probe (always 200 if running) | — | curl http://localhost:18080/healthz |
/readyz |
GET | Readiness probe | — | curl http://localhost:18080/readyz |
/v1/actions |
GET | List actions with decoded metadata | type, creator, state, supernode, fromHeight, toHeight, limit, cursor, include_transactions |
curl 'http://localhost:18080/v1/actions?type=cascade&limit=5' |
/v1/actions/{id} |
GET | Action details with transactions | — | curl http://localhost:18080/v1/actions/action123 |
/v1/actions/stats |
GET | Aggregated action statistics | from, to (RFC3339), type |
curl 'http://localhost:18080/v1/actions/stats?type=cascade' |
/v1/supernodes/metrics |
GET | List supernode metrics | currentState, status, version, minFailedProbeCounter, limit, cursor |
curl 'http://localhost:18080/v1/supernodes/metrics?status=available&limit=10' |
/v1/supernodes/{id}/metrics |
GET | Single supernode metrics | — | curl http://localhost:18080/v1/supernodes/lumera1abc.../metrics |
/v1/supernodes/{id}/paymentInfo |
GET | Payment statistics by denomination | — | curl http://localhost:18080/v1/supernodes/lumera1abc.../paymentInfo |
/v1/supernodes/stats |
GET | Aggregated hardware statistics | — | curl http://localhost:18080/v1/supernodes/stats |
/v1/supernodes/action-stats |
GET | Action statistics per supernode | — | curl http://localhost:18080/v1/supernodes/action-stats |
/v1/supernodes/unavailable |
GET | Supernodes with unavailable status API | currentState |
curl http://localhost:18080/v1/supernodes/unavailable |
/v1/supernodes/sync |
POST | Trigger manual sync+probe (if enabled) | — | curl -X POST http://localhost:18080/v1/supernodes/sync |
/v1/version/matrix |
GET | Version compatibility matrix (partial LEP2) | — | curl http://localhost:18080/v1/version/matrix |
/openapi.json |
GET | OpenAPI 3.0 specification | — | curl http://localhost:18080/openapi.json |
/docs |
GET | Swagger UI documentation | — | Open in browser: http://localhost:18080/docs |
/metrics |
GET | Prometheus metrics (stub) | — | curl http://localhost:18080/metrics |
Note:
/metricscurrently returns stub data. Rate limiting is planned for future releases.
See also: docs/openapi.json and docs/context.json for implementation details.
docker build -t lumescope .Build output is ~358 MB.
Minimal (ephemeral, for testing):
docker run -d -p 18080:18080 -e LUMERA_API_BASE=https://lcd.lumera.io --name lumescope lumescopeWith custom environment file:
cp .env.example .env
# Edit .env with your settings (see Configuration below)
docker run -d -p 18080:18080 \
-v $(pwd)/.env:/app/.env \
--name lumescope lumescope# Health check
curl -i http://localhost:18080/healthz
# Readiness check
curl -i http://localhost:18080/readyz
# Fetch recent actions
curl -s 'http://localhost:18080/v1/actions?limit=3' | jq .
# Open Swagger UI in browser
open http://localhost:18080/docsdocker stop lumescope
docker rm lumescopeCopy .env.example to .env and customize as needed. The container reads environment variables at startup.
| Variable | Required | Default | Description |
|---|---|---|---|
LUMERA_API_BASE |
Yes | http://localhost:1317 |
Lumera REST (LCD) endpoint URL |
PORT |
No | 18080 |
HTTP server listen port |
CORS_ALLOW_ORIGINS |
No | * |
Comma-separated CORS origins |
DB_DSN |
No | postgres://postgres:postgres@localhost:5432/lumescope?sslmode=disable |
PostgreSQL connection string (for external DB) |
DB_MAX_CONNS |
No | 10 |
Max database connections |
HTTP_TIMEOUT |
No | 10s |
Outbound HTTP timeout for Lumera calls |
READ_HEADER_TIMEOUT |
No | 5s |
Server read header timeout |
READ_TIMEOUT |
No | 30s |
Server read timeout |
WRITE_TIMEOUT |
No | 30s |
Server write timeout |
IDLE_TIMEOUT |
No | 120s |
Server idle timeout |
REQUEST_TIMEOUT |
No | 10s |
Per-request server timeout |
VALIDATORS_SYNC_INTERVAL |
No | 5m |
Validators sync frequency |
SUPERNODES_SYNC_INTERVAL |
No | 2m |
SuperNodes sync frequency |
ACTIONS_SYNC_INTERVAL |
No | 30s |
Actions sync frequency |
PROBE_INTERVAL |
No | 1m |
SuperNode probe frequency |
DIAL_TIMEOUT |
No | 2s |
TCP dial timeout for probes |
| Variable | Default | Description |
|---|---|---|
POSTGRES_DB |
lumescope |
Database name |
POSTGRES_USER |
postgres |
Database user |
POSTGRES_PASSWORD |
postgres |
Database password (set for security) |
PGDATA |
/var/lib/postgresql/data |
Data directory |
Recommendation: Set POSTGRES_PASSWORD to a strong value in production:
docker run -d -p 18080:18080 \
-e LUMERA_API_BASE=https://lcd.lumera.io \
-e POSTGRES_PASSWORD=your-secure-password \
--name lumescope lumescopeMount a volume to retain PostgreSQL data across container restarts:
docker run -d -p 18080:18080 \
-e LUMERA_API_BASE=https://lcd.lumera.io \
-e POSTGRES_PASSWORD=your-secure-password \
-v lumescope_data:/var/lib/postgresql/data \
--name lumescope lumescopeThe Makefile provides convenience targets:
# Mainnet with persistent volume
make docker-run-mainnet
# Testnet with persistent volume
make docker-run-testnet
# Ephemeral local development
make docker-run-localTo use an external PostgreSQL 13+ database instead of the embedded one:
docker run -d -p 18080:18080 \
-e LUMERA_API_BASE=https://lcd.lumera.io \
-e DB_DSN="postgres://user:pass@your-pg-host:5432/lumescope?sslmode=require" \
--name lumescope lumescopeThe application auto-creates required tables and indexes on startup.
For high availability, run multiple LumeScope containers pointing to a shared external PostgreSQL:
# Instance 1
docker run -d -p 18081:18080 \
-e LUMERA_API_BASE=https://lcd.lumera.io \
-e DB_DSN="postgres://user:pass@pg-host:5432/lumescope?sslmode=require" \
--name lumescope-1 lumescope
# Instance 2
docker run -d -p 18082:18080 \
-e LUMERA_API_BASE=https://lcd.lumera.io \
-e DB_DSN="postgres://user:pass@pg-host:5432/lumescope?sslmode=require" \
--name lumescope-2 lumescopePlace a load balancer (nginx, HAProxy, cloud LB) in front of the instances.
- Health endpoint:
GET /healthz(liveness) - Readiness endpoint:
GET /readyz - Metrics endpoint:
GET /metrics(currently returns stub data; Prometheus integration planned)
The Docker image includes a built-in HEALTHCHECK that polls /healthz every 30 seconds.
- Full Prometheus metrics export
- Rate limiting per client
- Redis caching layer for sub-200ms p95 latency
Assumes you have already built a local lumescope image (see Quickstart).
# Login to Docker Hub
docker login
# Tag the local image
docker tag lumescope yourusername/lumescope:v1.0.0
# Push to Docker Hub
docker push yourusername/lumescope:v1.0.0
# (Optional) Also push a :latest tag
docker tag lumescope yourusername/lumescope:latest
docker push yourusername/lumescope:latestGHCR requires a classic Personal Access Token (PAT) with the correct scopes. If you see denied: permission_denied: The token provided does not match expected scopes, your token is missing required permissions.
1. Create a classic PAT:
- Go to github.com/settings/tokens → Generate new token (classic).
- Select scopes:
repo(full control) — required if the package repository is private.read:packages— pull images.write:packages— push images.
- Copy the token; you won't see it again.
2. (Org only) Ensure package write permissions:
If publishing under an organization, your user must have write access to packages:
- Navigate to Organization → Settings → Packages.
- Under Package creation, ensure members can publish packages.
- Verify you are a member with appropriate role (e.g., Maintainer or Admin).
3. Authenticate and push:
# Set environment variables (or substitute directly)
export GITHUB_PAT=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export GITHUB_USERNAME=yourusername
# Login to GHCR
echo $GITHUB_PAT | docker login ghcr.io -u $GITHUB_USERNAME --password-stdin
# Tag the local image (replace {owner} with your username or org)
docker tag lumescope ghcr.io/{owner}/lumescope:v1.0.0
# Push to GHCR
docker push ghcr.io/{owner}/lumescope:v1.0.0
# (Optional) Also push a :latest tag
docker tag lumescope ghcr.io/{owner}/lumescope:latest
docker push ghcr.io/{owner}/lumescope:latestFor ARM64 and AMD64 support using docker buildx:
docker buildx create --use
# Docker Hub
docker buildx build --platform linux/amd64,linux/arm64 \
-t yourusername/lumescope:v1.0.0 \
--push .
# GHCR
docker buildx build --platform linux/amd64,linux/arm64 \
-t ghcr.io/{owner}/lumescope:v1.0.0 \
--push .If Docker warns about storing credentials unencrypted, configure a credential helper:
# Example: use the native OS keychain (macOS/Windows) or pass (Linux)
# See: https://docs.docker.com/engine/reference/commandline/login/#credential-helpers
docker-credential-helper # varies by OSOn Linux, install pass and docker-credential-pass, then configure ~/.docker/config.json:
{
"credsStore": "pass"
}- Go 1.24+
- PostgreSQL 13+ (or use Docker)
# Build binary
make build
# or: go build -o bin/lumescope ./cmd/lumescope
# Run directly
./bin/lumescope
# Or run without building
go run ./cmd/lumescope| Target | Description |
|---|---|
make build |
Build the Go binary to bin/lumescope |
make docker-build |
Build the Docker image |
make docker-run |
Run ephemeral container (local dev) |
make docker-run-local |
Alias for docker-run |
make docker-run-mainnet |
Run with mainnet LCD + persistent volume |
make docker-run-testnet |
Run with testnet LCD + persistent volume |
make docker-stop |
Stop the lumescope container |
make docker-rm |
Remove the lumescope container |
make docker-rebuild |
Stop, remove, rebuild, and run |
├── cmd/lumescope/ # Application entrypoint
├── internal/
│ ├── background/ # Scheduler and sync loops
│ ├── config/ # Environment configuration
│ ├── db/ # PostgreSQL operations
│ ├── decoder/ # Protobuf metadata decoder
│ ├── handlers/ # HTTP route handlers
│ ├── lumera/ # Lumera LCD client
│ ├── server/ # HTTP router setup
│ └── util/ # JSON helpers
├── docs/
│ ├── context.json # Implementation status reference
│ ├── requirements.json # Project requirements
│ ├── openapi.json # OpenAPI 3.0 spec (JSON)
│ └── openapi.yaml # OpenAPI 3.0 spec (YAML)
├── Dockerfile # Multi-stage build with embedded Postgres
├── Makefile # Build and run targets
└── .env.example # Environment variable template
Symptom: Actions/supernodes not syncing; logs show connection errors.
Solution:
- Verify
LUMERA_API_BASEis set correctly:curl https://lcd.lumera.io/cosmos/base/tendermint/v1beta1/node_info
- Check network connectivity from the container:
docker exec lumescope wget -qO- https://lcd.lumera.io/healthz - If using a local node, ensure the LCD port (1317) is exposed.
Symptom: Startup fails or queries timeout.
Solution:
- For embedded Postgres, check container logs:
docker logs lumescope
- For external Postgres, verify
DB_DSN:psql "postgres://user:pass@host:5432/lumescope?sslmode=disable" -c "\dt"
- Ensure the database user has CREATE TABLE privileges.
Symptom: Supernodes show as unavailable; probe metrics missing.
Cause: SuperNode ports 4444, 4445, or 8002 may be firewalled or the status API is disabled by operators.
Solution:
- This is expected for some supernodes.
- Check
/v1/supernodes/unavailableto see affected nodes. - The
failedProbeCounterfield tracks consecutive failures.
Symptom: Browser console shows CORS policy errors.
Solution:
Set CORS_ALLOW_ORIGINS to your frontend origin:
docker run -d -p 18080:18080 \
-e LUMERA_API_BASE=https://lcd.lumera.io \
-e CORS_ALLOW_ORIGINS="https://your-app.com" \
--name lumescope lumescopeUse * only for development.
MIT License. See LICENSE for details.