Skip to content

feat: normalize API error messaging across pages#3

Open
jaydenkalu wants to merge 44 commits into
mainfrom
issues/469-normalize-api-error-messaging
Open

feat: normalize API error messaging across pages#3
jaydenkalu wants to merge 44 commits into
mainfrom
issues/469-normalize-api-error-messaging

Conversation

@jaydenkalu

Copy link
Copy Markdown
Owner

Closes AnnabelJoe#469

Summary

Introduces a shared apiFetch / parseApiError utility 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() wraps fetch and throws on non-ok
  • meters/page.tsx: remove local error state, use useToast + apiFetch — register, revoke, and load errors all push a toast; inline error banners removed

Acceptance criteria

  • ✅ All API call failures surface a common toast pattern
  • ✅ Errors include retry guidance when applicable (retriable: true / STELLAR codes)
  • ✅ Console logging unchanged; UI stays clean

jessicanath and others added 30 commits June 27, 2026 17:28
- 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.
)

Give dashboard, live generation, and governance charts aria-labelledby descriptions, legend text for screen readers, and context summaries of the underlying data.
* 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>
…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
dependabot Bot and others added 14 commits July 1, 2026 10:33
…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>
…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
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.

Normalize API error messaging across pages