feat(observability): add OpenTelemetry APM instrumentation (#291)#3
Open
devSoniia wants to merge 65 commits into
Open
feat(observability): add OpenTelemetry APM instrumentation (#291)#3devSoniia wants to merge 65 commits into
devSoniia wants to merge 65 commits into
Conversation
AnnabelJoe#37) - Add rollback .down.sql for every existing migration (001-006) - Add migration 007: operator_sessions table for JWT refresh token rotation - Update CI to verify rollback scripts exist for every migration file Closes AnnabelJoe#37
…lJoe#40) - Add src/lib/auth.ts: requireAuth() validates Bearer JWT via Supabase getUser() - Add POST /api/auth/login: email+password → access_token + refresh_token - Add POST /api/auth/logout: invalidates current session - Add POST /api/auth/refresh: rotates refresh token - Protect GET /api/meters, POST /api/meters, GET /api/readings with requireAuth() - Add v1 re-exports for all auth routes - Add unit tests for requireAuth() (missing header, invalid token, valid token) Closes AnnabelJoe#40
…h, queries (AnnabelJoe#57) New tests added: - test_anchor_records_ledger_sequence: verifies anchored_at_ledger is set - test_duplicate_anchor_does_not_increment_total: dedup leaves count unchanged - test_different_hashes_are_independent: two distinct hashes both anchor cleanly - test_old_signer_rejected_after_rotation: rotated-out signer gets Unauthorized - test_total_anchors_starts_at_zero: count is 0 before any anchor - test_admin_query / test_api_signer_query: query functions return correct values - test_large_number_of_anchors: 50 anchors stored and retrievable (large payload) - test_boundary_hash_values: all-zeros and all-ones hashes are valid - test_migrate_updates_version: migrate() stores new version string Closes AnnabelJoe#57
…PC checks (AnnabelJoe#45) - Check DB connectivity via a lightweight SELECT on cooperatives - Check Stellar RPC reachability via getHealth JSON-RPC call - Return degraded status if any check exceeds 300 ms threshold - Return 503 if any check errors, 200 for ok/degraded - Hard 450 ms timeout per check keeps total response < 500 ms - Response shape: { status, ts, checks: { database, stellar_rpc } } - 5 unit tests: ok, DB error, Stellar error, degraded (slow), latency_ms present Closes AnnabelJoe#45
feat(health): comprehensive health check endpoint GET /api/health (AnnabelJoe#45)
…try-tests test(audit_registry): comprehensive unit tests (AnnabelJoe#57)
feat(auth): JWT + Supabase Auth for operator API routes (AnnabelJoe#40)
feat(migrations): versioned SQL migrations with rollback scripts (AnnabelJoe#37)
- Add loading spinner to all form submit buttons - Disable cancel buttons during submission to prevent interruption - Add cursor-not-allowed class for better UX - Prevent duplicate form submissions Closes AnnabelJoe#21
- Create useRealtimeReadings hook for WebSocket connection management - Add connection status indicator (Live/Offline/Connecting) - Implement automatic reconnection with 5s delay - Add graceful fallback to 30s polling when WebSocket unavailable - Animate new readings into the table with fade-in effect - Update readings cache in real-time without manual refresh - Add placeholder WebSocket API endpoint with implementation notes Closes AnnabelJoe#9
- Create reusable CopyButton and CopyableText components - Add copy buttons to all certificate IDs across the app - Add copy functionality for meter public keys - Add copy button for wallet addresses in navbar - Add copy buttons for transaction hashes in certificate chain - Add copy buttons for reading hashes and signatures in verify page - Show visual confirmation (checkmark) for 2 seconds after copy - Works in all modern browsers using Clipboard API Closes AnnabelJoe#23
Closes AnnabelJoe#27, AnnabelJoe#30, AnnabelJoe#32, AnnabelJoe#35 - AnnabelJoe#27: Add sliding-window rate limit (60 req/min per meter pubkey) to POST /api/readings using Upstash Redis pipeline. Returns 429 with Retry-After header on breach. Falls back to allow-all when Redis is unavailable. - AnnabelJoe#30: Add required 'name' field to POST /api/meters registration. Duplicate pubkey now returns 409 before attempting insert. - AnnabelJoe#32: Add tracer-sim integration for failed mint diagnosis. On mint failure: replays via TRACER_SIM_URL, stores diagnosis JSON on the reading record (mint_diagnosis column), fires mint_failed webhook, and returns diagnosis in the 500 error response. - AnnabelJoe#35: Add GET /api/verify/[id] dynamic route returning full chain of custody (reading, Ed25519 proof, anchor tx, mint tx, retirement tx). No auth required. Response cached 60 s via Redis. Re-exported at /api/v1/verify/[id]. DB: migration 20260427000008 adds meters.name and readings.mint_diagnosis.
…lJoe#17 — i18n, governance form, voting UI, verify stepper
…belJoe#25 AnnabelJoe#20 - Fix hydration mismatch: add mounted guard in Navbar so wallet UI and theme toggle only render client-side, eliminating SSR/CSR mismatch. AnnabelJoe#25 - Add Stellar network indicator badge to Navbar. Reads NEXT_PUBLIC_STELLAR_NETWORK env var; yellow for testnet, green for mainnet, links to Stellar Expert explorer. AnnabelJoe#24 - Add WalletGate component for protected routes. Dashboard, Meters, and Certificates pages now show a connect-wallet prompt instead of empty state when no wallet is connected. Removed redundant inline connect banner from Certificates page. AnnabelJoe#19 - Add search and filter to Certificates page. Supports search by certificate ID or meter ID (via readings join), status filter (active/retired), and date range filter. All filters reflected in URL params. API updated with q, status, date_from, date_to query params. Also fix pre-existing orphaned </ErrorBoundary> tags in dashboard page.
Bumps the minor-updates group with 7 updates: | Package | From | To | | --- | --- | --- | | [@noble/ed25519](https://github.com/paulmillr/noble-ed25519) | `2.1.0` | `2.3.0` | | [@supabase/supabase-js](https://github.com/supabase/supabase-js/tree/HEAD/packages/core/supabase-js) | `2.104.1` | `2.105.0` | | [@t3-oss/env-nextjs](https://github.com/t3-oss/t3-env/tree/HEAD/packages/nextjs) | `0.11.1` | `0.13.11` | | [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `0.468.0` | `0.577.0` | | [next](https://github.com/vercel/next.js) | `15.1.3` | `15.5.15` | | [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `15.1.3` | `15.5.15` | | [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) | `0.6.14` | `0.8.0` | Updates `@noble/ed25519` from 2.1.0 to 2.3.0 - [Release notes](https://github.com/paulmillr/noble-ed25519/releases) - [Commits](paulmillr/noble-ed25519@2.1.0...2.3.0) Updates `@supabase/supabase-js` from 2.104.1 to 2.105.0 - [Release notes](https://github.com/supabase/supabase-js/releases) - [Changelog](https://github.com/supabase/supabase-js/blob/develop/packages/core/supabase-js/CHANGELOG.md) - [Commits](https://github.com/supabase/supabase-js/commits/v2.105.0/packages/core/supabase-js) Updates `@t3-oss/env-nextjs` from 0.11.1 to 0.13.11 - [Release notes](https://github.com/t3-oss/t3-env/releases) - [Changelog](https://github.com/t3-oss/t3-env/blob/main/packages/nextjs/CHANGELOG.md) - [Commits](https://github.com/t3-oss/t3-env/commits/@t3-oss/env-nextjs@0.13.11/packages/nextjs) Updates `lucide-react` from 0.468.0 to 0.577.0 - [Release notes](https://github.com/lucide-icons/lucide/releases) - [Commits](https://github.com/lucide-icons/lucide/commits/0.577.0/packages/lucide-react) Updates `next` from 15.1.3 to 15.5.15 - [Release notes](https://github.com/vercel/next.js/releases) - [Changelog](https://github.com/vercel/next.js/blob/canary/release.js) - [Commits](vercel/next.js@v15.1.3...v15.5.15) Updates `eslint-config-next` from 15.1.3 to 15.5.15 - [Release notes](https://github.com/vercel/next.js/releases) - [Changelog](https://github.com/vercel/next.js/blob/canary/release.js) - [Commits](https://github.com/vercel/next.js/commits/v15.5.15/packages/eslint-config-next) Updates `prettier-plugin-tailwindcss` from 0.6.14 to 0.8.0 - [Release notes](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/blob/main/CHANGELOG.md) - [Commits](tailwindlabs/prettier-plugin-tailwindcss@v0.6.14...v0.8.0) --- updated-dependencies: - dependency-name: "@noble/ed25519" dependency-version: 2.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minor-updates - dependency-name: "@supabase/supabase-js" dependency-version: 2.105.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minor-updates - dependency-name: "@t3-oss/env-nextjs" dependency-version: 0.13.11 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minor-updates - dependency-name: lucide-react dependency-version: 0.577.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minor-updates - dependency-name: next dependency-version: 15.5.15 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minor-updates - dependency-name: eslint-config-next dependency-version: 15.5.15 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor-updates - dependency-name: prettier-plugin-tailwindcss dependency-version: 0.8.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor-updates ... Signed-off-by: dependabot[bot] <support@github.com>
…yarn/minor-updates-90e75f2a75 build(deps): bump the minor-updates group with 7 updates
…4-25 fix: resolve issues AnnabelJoe#19, AnnabelJoe#20, AnnabelJoe#24, AnnabelJoe#25 — search/filter, hydration, wallet gate, network badge
…-ids-issue-23 feat: add copy-to-clipboard functionality for IDs and hashes
feat: verify stepper, governance form + voting, i18n (AnnabelJoe#17 AnnabelJoe#15 AnnabelJoe#16 AnnabelJoe#10)
…ard-websocket-issue-9 feat: add real-time dashboard updates with WebSocket support
…0-32-35 feat: rate limiting, meter name, tracer-sim, verify chain-of-custody (AnnabelJoe#27 AnnabelJoe#30 AnnabelJoe#32 AnnabelJoe#35)
…es-issue-21 fix: add spinner and disable buttons during form submission
- Add getCorsHeaders() helper in src/lib/cors.ts - Restrict allowed origins to CORS_ALLOWED_ORIGINS env var + localhost in dev - Handle OPTIONS preflight with 204 / 403 in middleware - Attach CORS headers to all API responses including versioning redirects - Enable credentials mode (Access-Control-Allow-Credentials: true) - Add CORS_ALLOWED_ORIGINS to env.ts schema and .env.example Closes AnnabelJoe#46
Adds regression tests for four closed bug issues so they cannot be silently reintroduced: - AnnabelJoe#29 input validation: 11 tests covering missing/invalid fields on POST /api/readings and POST /api/meters, and that validation runs before any DB access - AnnabelJoe#49 Stellar account existence check: 4 tests verifying mint failures (non-existent account, missing trustline, missing cooperative address) are surfaced as structured 500 errors - AnnabelJoe#73 reading deduplication: 4 tests verifying that AlreadyAnchored / duplicate errors from the anchor step return 409 with reading_id, while unique readings still return 201 All 19 regression tests pass. Documents the process in CONTRIBUTING.md. Closes AnnabelJoe#125
- AC1: create → vote to pass → execute succeeds - AC2: create → vote to reject → execution blocked - AC3: quorum not met (50% yes < 51% threshold) → execution blocked - AC4: expired proposal (no votes) → cannot execute Closes AnnabelJoe#122
…belJoe#123) - Factory functions for: cooperative, meter, reading, certificate, operator - emptyCleanupIds() + cleanup() for afterEach teardown in dependency order - factories.test.ts verifies each factory shape and cleanup behaviour - All factories accept overrides and auto-create parent rows Closes AnnabelJoe#123
- New crate: apps/contracts/proptest/ (stable Rust, no nightly needed) - P1: mint amount always positive — non-positive amounts rejected - P2: balance never negative after mint/burn sequences - P3: vote count monotonically non-decreasing - Failures produce minimal reproducible examples via proptest shrinking - CI: new 'proptest' job in ci.yml runs cargo test Closes AnnabelJoe#121
…nnabelJoe#124) - Add @axe-core/playwright devDependency - e2e/helpers/a11y.ts: checkA11y() helper — runs axe on WCAG 2.0/2.1 A/AA - e2e/a11y.spec.ts: tests for /verify and / pages - Critical and serious violations fail the test with selector + fix URL - Baseline violations section documented in a11y.spec.ts Closes AnnabelJoe#124
) Bumps the patch-updates group with 3 updates: [@supabase/supabase-js](https://github.com/supabase/supabase-js/tree/HEAD/packages/core/supabase-js), [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react). Updates `@supabase/supabase-js` from 2.106.0 to 2.106.2 - [Release notes](https://github.com/supabase/supabase-js/releases) - [Changelog](https://github.com/supabase/supabase-js/blob/master/packages/core/supabase-js/CHANGELOG.md) - [Commits](https://github.com/supabase/supabase-js/commits/v2.106.2/packages/core/supabase-js) Updates `@tanstack/react-query` from 5.100.11 to 5.100.14 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.100.14/packages/react-query) Updates `@types/react` from 19.2.14 to 19.2.15 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: "@supabase/supabase-js" dependency-version: 2.106.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: "@tanstack/react-query" dependency-version: 5.100.14 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: "@types/react" dependency-version: 19.2.15 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: patch-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Fix security vulnerabilities and implement I-REC bridge (AnnabelJoe#126, AnnabelJoe#132, AnnabelJoe#135, AnnabelJoe#136)
…ons, and accessibility improvements
…-responsive-accessibility Responsive dashboard, certificate detail page, toast notifications, and accessibility improvements
## [1.1.0](AnnabelJoe/solarproof@v1.0.0...v1.1.0) (2026-05-28) ### Features * responsive dashboard, certificate detail page, toast notifications, and accessibility improvements ([704c0a5](AnnabelJoe@704c0a5))
- GET /api/health returns 200 with uptime and version - GET /api/ready checks DB connectivity, returns 503 if unhealthy - Both endpoints unauthenticated (no middleware) - docker-compose.yml with healthcheck configured Closes AnnabelJoe#275
CI already enforces pnpm install --frozen-lockfile. Update CONTRIBUTING.md to match: use --frozen-lockfile for normal installs, and explain when to commit an updated lockfile. Closes AnnabelJoe#302
- List active/past proposals with vote counts and status badges - Vote For / Against / Abstain buttons (wallet signature stub) - Voted state persisted in component state and shown to user - Voting deadline countdown from ledger difference - Visual vote bar (green/red/gray proportional breakdown) Closes AnnabelJoe#265
…ting-ui-265 feat: implement voting UI for community governance proposals
## [1.2.0](AnnabelJoe/solarproof@v1.1.0...v1.2.0) (2026-05-28) ### Features * add governance voting UI ([AnnabelJoe#265](AnnabelJoe#265)) ([b59d23a](AnnabelJoe@b59d23a))
…kfile-302 ci: enforce pnpm lockfile integrity and update developer docs
…endpoints-275 feat: add /api/health and /api/ready endpoints
## [1.3.0](AnnabelJoe/solarproof@v1.2.0...v1.3.0) (2026-05-28) ### Features * add /api/health and /api/ready endpoints ([AnnabelJoe#275](AnnabelJoe#275)) ([4f761a4](AnnabelJoe@4f761a4)) ### Documentation * document pnpm --frozen-lockfile requirement ([AnnabelJoe#302](AnnabelJoe#302)) ([4072e11](AnnabelJoe@4072e11))
Closes AnnabelJoe#291 - Add src/instrumentation.ts: Next.js instrumentation hook that initialises the OpenTelemetry Node SDK with OTLP HTTP exporter - Instruments HTTP requests and fetch calls (covers Stellar + Supabase) - Service name/version set from env vars with sensible defaults - Enable experimental.instrumentationHook in next.config.ts - Add @opentelemetry/* dependencies (pinned versions) Configure via env vars: OTEL_EXPORTER_OTLP_ENDPOINT — OTLP collector URL (Grafana Cloud, Honeycomb) OTEL_EXPORTER_OTLP_HEADERS — auth headers OTEL_SERVICE_NAME — defaults to solarproof-api
🔍 Vercel Preview DeploymentURL: Learn More: https://err.sh/vercel/no-credentials-found
|
Closes AnnabelJoe#308 - Add architecture overview diagram with data flow and key files table - Add Docker Compose setup instructions (Option A) - Expand env vars section with Redis and observability vars - Add test commands for all packages (web unit, e2e, contracts, stellar) - Add troubleshooting entries for idempotency, OpenTelemetry, Docker, inactive meter, and missing env vars - Expand project structure with src/ subdirectory breakdown
✅ cargo audit |
…onboarding docs: enhance developer onboarding guide (AnnabelJoe#308)
✅ pnpm audit |
🔍 Vercel Preview DeploymentURL: Learn More: https://err.sh/vercel/no-credentials-found
|
✅ cargo audit |
| * violations are found. Baseline violations (if any) are documented below. | ||
| */ | ||
|
|
||
| import { test, expect } from '@playwright/test' |
Comment on lines
+3
to
+12
| import { | ||
| Zap, | ||
| ShieldCheck, | ||
| Link2, | ||
| Award, | ||
| FlameKindling, | ||
| ExternalLink, | ||
| CheckCircle2, | ||
| Clock, | ||
| } from 'lucide-react' |
| const inMock = vi.fn().mockReturnValue({ error: null }) | ||
| deleteMock.mockReturnValue({ in: inMock }) | ||
|
|
||
| function makeInsertMock(row: Record<string, unknown>) { |
|
|
||
| #[test] | ||
| fn test_api_signer_query() { | ||
| let (env, api_signer, client) = setup(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes AnnabelJoe#291
Integrates OpenTelemetry SDK into the Next.js API to provide traces, metrics, and logs for Stellar interactions and API requests.
Changes
src/instrumentation.ts(new)Next.js instrumentation hook that initialises the OpenTelemetry Node SDK:
stellar.anchor,stellar.mint)next.config.tsexperimental.instrumentationHook: truepackage.json@opentelemetry/*dependenciesConfiguration
OTEL_EXPORTER_OTLP_ENDPOINTOTEL_EXPORTER_OTLP_HEADERSAuthorization=Basic ...)OTEL_SERVICE_NAMEsolarproof-api)