feat: normalize API error messaging across pages#3
Open
jaydenkalu wants to merge 44 commits into
Open
Conversation
- Add MeterMetadata type and computeMetadataHash() to crypto lib - Extend ReadingSchema to accept optional metadata + metadata_signature_hex - Verify Ed25519 metadata signature in POST /api/readings - Persist metadata, metadata_hash, metadata_signature_hex on readings row - Add migration 003 for new readings columns - Update send-reading.mjs to sign and send --firmware/--model/--manufacturer
- middleware.ts: detect locale from Accept-Language header, persist as cookie, forward as x-locale header to server components; fallback to 'en' - lib/i18n.ts: message catalogue (en/es/fr/de/pt) + getTranslations() with English fallback for missing keys - layout.tsx: reads x-locale header, sets <html lang> dynamically - api/locale/route.ts: POST endpoint to switch locale via cookie
…e#605) Documents technical and procedural requirements for bridging SolarProof certificates to I-REC(E) (Evident registry) and Energy Web Origin (ERC-1888). Covers data gaps, integration phases, open questions, and references.
Closes AnnabelJoe#613 Adds docs/BACKLOG.md with a detailed backlog entry for the hardware meter provisioning UX feature: user stories, acceptance criteria, and technical notes for the /dashboard/meters provisioning flow.
- Add src/lib/api-error.ts: parseApiError() normalises {error,code,retriable}
response shapes; apiFetch() wrapper throws human-readable error strings
- meters/page.tsx: replace inline error state with useToast pushToast()
- registerMeter/revokeMeter use apiFetch (consistent error extraction)
- onError/onSuccess push toast instead of setting local error state
- Remove redundant inline error <p> and <div role=alert> blocks
Closes AnnabelJoe#469
- Extract both clients into a single typed module (supabase.ts) - Add requireEnv() helper for early, descriptive validation of env vars - Browser anon client exported as singleton to prevent duplicate GoTrue auth instances and session-sync issues - Service-role client exported as factory (createServiceClient) — returns a new instance per call to avoid cross-request data leaks, with persistSession and autoRefreshToken disabled - Full JSDoc explaining which client to use and when - Both clients typed with generated Database interface Closes AnnabelJoe#544
Replace blank loading text with shared skeleton components on certificates, governance, admin, and verify pages, with accessible aria-busy states.
* feat: note to backlog for real-time certificate alerts * feat(audit_registry): add on-chain helper views for anchor status (AnnabelJoe#553) Expose AnchorStatus, anchor_status, anchored_at_ledger, and bucket_for_hash read-only helpers so integrators can query anchor state in a single call. --------- Co-authored-by: raizo07 <agadaraizo@gmail.com>
Co-authored-by: raizo07 <agadaraizo@gmail.com>
…belJoe#726) meters/page.tsx - RegisterForm: - Extract Field wrapper that emits aria-invalid, aria-describedby on the child input and shows an inline error paragraph with role=alert + aria-live - Client-side validate() on blur (per-field) and on submit (all fields) - Errors only shown after a field has been touched to avoid pre-emptive noise - Submit button disabled + aria-disabled when field errors are present - Duplicate generic error banner removed; per-field messages are the source governance/page.tsx - CreateProposalForm: - Replace inline <style> tag in Field with Tailwind border-color utilities - Add required prop and visible asterisk indicator to Field wrapper - Add submitError state so API errors surface via role=alert (no more alert()) - Add required prop to all four fields; error indicators use aria-live=polite - Vote mutation errors now shown in a role=alert banner (no more alert()) transfer-modal.tsx: - Validate Stellar address (starts with G, 56 chars) on blur and on submit - aria-invalid, aria-describedby wired to error / hint paragraphs - Submit button disabled while field is invalid after touch - Submit errors surface via role=alert inline banner - Close button disabled while submitting retire-modal.tsx: - Fix malformed file (two partial form fragments merged into one clean component) - Show success state with CheckCircle after confirmed retirement - Error surfaces via role=alert with id so submit button can aria-describedby it - Close button gets disabled + aria-label while submitting Closes AnnabelJoe#475
…belJoe#725) - Poll Freighter isAllowed() every 30s while wallet is connected - Immediately expire session if poll detects wallet is no longer authorised - Re-check session on tab visibility change (returning to tab) so stale state is never shown even between poll intervals - Update persisted address if user switches Freighter account mid-session - expireSession() clears both in-memory state and sessionStorage atomically, ensuring no stale user-specific data remains visible after expiry - Stop polling on component unmount to prevent memory leaks - Explicit clearPersistedSession() helper used in all expiry paths Closes AnnabelJoe#470
…#724) - Distinguish 'never connected' vs 'disconnected mid-session' states - Show reconnect prompt with WifiOff icon when wallet drops mid-session - Show connect prompt with Wallet icon when wallet was never connected - Display inline error message if connection attempt fails - Add 'inline' variant for compact banner embedding inside sections - Disable connect/reconnect button while connecting (aria-busy) - Add reconnect/disconnected translation keys to all four locales - All prompts use role=status + aria-live=polite for screen-reader support Closes AnnabelJoe#468
) Bumps the minor-updates group with 4 updates: [prettier](https://github.com/prettier/prettier), [turbo](https://github.com/vercel/turborepo), [@aws-sdk/client-secrets-manager](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-secrets-manager) and [@axe-core/playwright](https://github.com/dequelabs/axe-core-npm). Updates `prettier` from 3.8.3 to 3.9.3 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](prettier/prettier@3.8.3...3.9.3) Updates `turbo` from 2.9.16 to 2.10.0 - [Release notes](https://github.com/vercel/turborepo/releases) - [Changelog](https://github.com/vercel/turborepo/blob/main/RELEASE.md) - [Commits](vercel/turborepo@v2.9.16...v2.10.0) Updates `@aws-sdk/client-secrets-manager` from 3.1073.0 to 3.1075.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-secrets-manager/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.1075.0/clients/client-secrets-manager) Updates `@axe-core/playwright` from 4.11.3 to 4.12.1 - [Release notes](https://github.com/dequelabs/axe-core-npm/releases) - [Changelog](https://github.com/dequelabs/axe-core-npm/blob/develop/CHANGELOG.md) - [Commits](https://github.com/dequelabs/axe-core-npm/commits) --- updated-dependencies: - dependency-name: prettier dependency-version: 3.9.3 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor-updates - dependency-name: turbo dependency-version: 2.10.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor-updates - dependency-name: "@aws-sdk/client-secrets-manager" dependency-version: 3.1075.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minor-updates - dependency-name: "@axe-core/playwright" dependency-version: 4.12.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…belJoe#476) (AnnabelJoe#717) - copy-button.tsx: add writeToClipboard() with execCommand fallback for mobile browsers that lack navigator.clipboard; add aria-pressed state; add optional onCopied callback; export writeToClipboard for reuse - verify/page.tsx: replace bare navigator.clipboard.writeText with writeToClipboard; push success/error toast on copy; add aria-live region to Share button label for screen-reader feedback - Update snapshots for CopyButton/CopyableText (aria-pressed added) Closes AnnabelJoe#476
) (AnnabelJoe#715) - Configurable exponential backoff via env vars: STELLAR_RETRY_MAX (default: 3) STELLAR_RETRY_BASE_MS (default: 500ms) STELLAR_RETRY_MAX_MS (default: 8000ms) STELLAR_RPC_TIMEOUT_MS (default: 10000ms) - isTransient() identifies retryable errors (timeout, ECONNRESET, 503/429) - rpcCall() retries up to RETRY_MAX times with exponential delay - Permanent failures (non-transient) surfaced immediately without retrying - Circuit breaker unchanged: opens after 5 consecutive timeouts - Structured logging via logger.warn on retries and circuit events Closes AnnabelJoe#496
…oe#493) (AnnabelJoe#714) - Add AppError class with category, httpStatus, retriable properties - Add ErrorCategory enum: STELLAR_TIMEOUT, STELLAR_CIRCUIT, STELLAR_RPC, DB_QUERY, DB_CONSTRAINT, VALIDATION, UNAUTHORIZED, INTERNAL - Add errorBody() helper for consistent {error, code, retriable} API responses - Update stellar.ts: use AppError instead of raw errors, add structured logging - Update queue.ts: log error category on job failures for observability - Update readings route: use AppError/errorBody for DB errors Closes AnnabelJoe#493
…label, and hydration guard (AnnabelJoe#713) - Add mounted guard to prevent hydration mismatch on initial render - Add aria-pressed to convey toggle state to screen readers - Add aria-label describing the action (Switch to light/dark mode) - Theme preference already persists via ThemeProvider storageKey=solarproof-theme
…ders (AnnabelJoe#712) - Wrap StatCard in React.memo to prevent re-renders on unrelated state changes - Stabilize analytics query key with primitive values instead of object reference - Wrap each chart panel in ErrorBoundary (inline) to isolate render failures - Import ErrorBoundary and memo
…oe#710) - Add kwh upper bound (max 1,000,000) to reject unrealistic values - Add hex-only regex to signature_hex to reject non-hex characters - Add millisecond guard on timestamp (max 9_999_999_999 seconds) - Add float guard on timestamp (.int()) - Add descriptive error messages to all schema fields - Update tests: add new 400 cases for UUID, zero kwh, large kwh, string kwh, non-hex sig, millis timestamp, float timestamp, missing nonce - Fix 202 response expectation (async enqueue pattern) - Replace anchorReading test with enqueue payload assertion - Add mocks for queue, rate-limit, idempotency, auth, logger
…pdates (AnnabelJoe#738) Bumps the patch-updates group with 7 updates in the / directory: | Package | From | To | | --- | --- | --- | | [prettier](https://github.com/prettier/prettier) | `3.9.3` | `3.9.4` | | [turbo](https://github.com/vercel/turborepo) | `2.10.0` | `2.10.2` | | [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.101.0` | `5.101.2` | | [bullmq](https://github.com/taskforcesh/bullmq) | `5.79.1` | `5.79.2` | | [next-intl](https://github.com/amannn/next-intl) | `4.13.0` | `4.13.1` | | [@playwright/test](https://github.com/microsoft/playwright) | `1.61.0` | `1.61.1` | | [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) | `4.3.0` | `4.3.2` | Updates `prettier` from 3.9.3 to 3.9.4 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](prettier/prettier@3.9.3...3.9.4) Updates `turbo` from 2.10.0 to 2.10.2 - [Release notes](https://github.com/vercel/turborepo/releases) - [Changelog](https://github.com/vercel/turborepo/blob/main/RELEASE.md) - [Commits](vercel/turborepo@v2.10.0...v2.10.2) Updates `@tanstack/react-query` from 5.101.0 to 5.101.2 - [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.101.2/packages/react-query) Updates `bullmq` from 5.79.1 to 5.79.2 - [Release notes](https://github.com/taskforcesh/bullmq/releases) - [Commits](taskforcesh/bullmq@v5.79.1...v5.79.2) Updates `next-intl` from 4.13.0 to 4.13.1 - [Release notes](https://github.com/amannn/next-intl/releases) - [Changelog](https://github.com/amannn/next-intl/blob/main/CHANGELOG.md) - [Commits](amannn/next-intl@v4.13.0...v4.13.1) Updates `@playwright/test` from 1.61.0 to 1.61.1 - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](microsoft/playwright@v1.61.0...v1.61.1) Updates `tailwindcss` from 4.3.0 to 4.3.2 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.2/packages/tailwindcss) --- updated-dependencies: - dependency-name: prettier dependency-version: 3.9.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: turbo dependency-version: 2.10.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: "@tanstack/react-query" dependency-version: 5.101.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: bullmq dependency-version: 5.79.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: next-intl dependency-version: 4.13.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: "@playwright/test" dependency-version: 1.61.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: tailwindcss dependency-version: 4.3.2 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>
…base-544 All four issues
…er-provisioning-backlog docs: add hardware meter provisioning UX backlog item
…ersonas docs: add product persona docs for auditors, cooperatives, and meter operators
…ter-metadata feat: add signed meter metadata payloads
…dge-cases test(energy-token): validate SEP-41 metadata and trustline edge cases
…energyweb-interop research: I-REC / Energy Web interoperability requirements
…le-detection feat: add multilingual fallback and locale detection
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.
Closes AnnabelJoe#469
Summary
Introduces a shared
apiFetch/parseApiErrorutility so all pages surface API failures through the existing toast system rather than inconsistent inline state.Changes
src/lib/api-error.ts(new):parseApiError(body)normalises{error}and{error,code,retriable}shapes into a user-friendly string (adds retry guidance for transient codes);apiFetch()wrapsfetchand throws on non-okmeters/page.tsx: remove localerrorstate, useuseToast+apiFetch— register, revoke, and load errors all push a toast; inline error banners removedAcceptance criteria
retriable: true/ STELLAR codes)