Skip to content

Add PP Dashboard API and event subscription#36

Merged
AquiGorka merged 5 commits intodevfrom
feat/86c8mw0jh-pp-dashboard
Mar 17, 2026
Merged

Add PP Dashboard API and event subscription#36
AquiGorka merged 5 commits intodevfrom
feat/86c8mw0jh-pp-dashboard

Conversation

@AquiGorka
Copy link

Summary

  • Event watcher service that polls Stellar RPC for Channel Auth contract events (provider_added, provider_removed, contract_initialized)
  • Channel registry tracks on-chain registration state (active/pending/inactive) with KV-persisted cursor for restart resilience
  • Ed25519 challenge/verify dashboard auth with multisig support via Horizon signers lookup
  • 7 dashboard API endpoints: auth (challenge + verify), channels, mempool, operations, treasury, audit-export
  • JWT expiry fix (pre-existing bug: tokens never expired due to double-counted epoch)
  • Hard crash if SERVICE_AUTH_SECRET missing in production mode
  • COUNT queries for operations stats, SQL date filtering for audit export
  • Composite index on (status, deleted_at, created_at) for new query patterns

Test plan

  • deno test --no-check --allow-all src/ — 25 tests pass
  • Manual: POST /dashboard/auth/challenge → sign nonce → POST /dashboard/auth/verify → use JWT for data endpoints
  • Manual: GET /dashboard/channels returns registry state
  • Manual: GET /dashboard/audit-export?status=COMPLETED downloads CSV

Polls Stellar RPC getEvents for provider_added, provider_removed, and
contract_initialized events on the Channel Auth contract.

- EventWatcher: self-scheduling poll loop, KV-persisted cursor for
  restart resilience, handler registration pattern
- ChannelRegistry: tracks channel state (active/pending/inactive) from
  on-chain events
- fetchChannelAuthEvents: parses RPC event responses into typed events
- 16 unit tests with mock RPC responses
Operator authentication via Ed25519 signed challenge. Multisig-aware
via Horizon signers lookup. Bounded challenge store (max 1000),
configurable TTL from env, one-time nonce consumption.

Dependencies injected for testability (provider key, Horizon URL,
JWT generator). 9 unit tests including 64-byte invalid signature test.
- POST /dashboard/auth/challenge — nonce for Ed25519 signing
- POST /dashboard/auth/verify — verify signature, issue JWT
- GET /dashboard/channels — channel registry state
- GET /dashboard/mempool — mempool stats and config
- GET /dashboard/operations — bundle/tx counts via COUNT queries
- GET /dashboard/treasury — OpEx balance from Horizon
- GET /dashboard/audit-export — CSV export with SQL date filtering

Auth endpoints use low rate limit (10/min). Data endpoints protected
by JWT middleware. Error responses don't leak internal details.
- Start/stop EventWatcher in main.ts bootstrap/shutdown
- Fix JWT expiry: getNumericDate(0)/getNumericDate(SESSION_TTL)
- Hash nonce for JWT sessionId instead of raw material
- Hard crash if SERVICE_AUTH_SECRET missing in production
- Add countByStatus and findByStatusAndDateRange to repositories
- Add composite index on (status, deleted_at, created_at)
The sessionId hashing broke the existing SEP-10 auth flow — bundle
endpoints look up sessions by the raw challenge hash stored in KV,
but the JWT now contained a hashed value that didn't match.

Move the nonce hashing to dashboard-auth.ts only, since dashboard
tokens don't use session lookups. The shared generate-jwt.ts passes
challengeHash through unchanged to preserve SEP-10 compatibility.
@AquiGorka AquiGorka merged commit b4d0a98 into dev Mar 17, 2026
2 checks passed
@AquiGorka AquiGorka deleted the feat/86c8mw0jh-pp-dashboard branch March 17, 2026 16:50
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.

1 participant