Skip to content

Staging - #284

Open
0xsemaj wants to merge 38 commits into
masterfrom
staging
Open

Staging#284
0xsemaj wants to merge 38 commits into
masterfrom
staging

Conversation

@0xsemaj

@0xsemaj 0xsemaj commented Jun 3, 2026

Copy link
Copy Markdown
Member

No description provided.

0xsemaj and others added 30 commits May 28, 2026 21:23
* fix: update webhook service taxonomy and guard against undefined service

- Rename service values from signals.vss/events.behavior/events.safety to signals/events
- Prefix condition field names with vss. namespace
- Merge event name options into single events key
- Change isEventService to use strict equality instead of startsWith (fixes crash when service is undefined)
- Add service default value to NewWebhookForm to prevent undefined on initial render

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Bump yaml from 2.8.2 to 2.8.3

Bumps [yaml](https://github.com/eemeli/yaml) from 2.8.2 to 2.8.3.
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](eemeli/yaml@v2.8.2...v2.8.3)

---
updated-dependencies:
- dependency-name: yaml
  dependency-version: 2.8.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update constants and vehicle details

* Update burn

* Enable Stale vehicle removal

* Add debug

* Add delete check

* Fix db anomaly

* Add SACD

* setPermissions fix

* powertraintype fix

* Remove powertrainType that's throwing off the mint

* fix SACD and add animation

* Show button to simulator

* Update to paymaster

* Revert "Update to paymaster"

This reverts commit 37f58c1.

* Update app creation modal

* Badge for simulated vehicles

* Remove Tesla replace with Chevy

* Configurator mis-disabling

* Avoid 0x mismatch

* Explorer init

* fix 404

* Explorer work

* compile issue fix

* Type fix

* init query

* token xchange

* query fix

* vehicle pages

* Remove double wrapping

* debug

* Avoid circular dep issue

* path fix

* move sdk to serverside

* Add query

* JSON update

* error handling + navbar

* new license card

* fix

* Sharing card

* hide right column

* fix transparent icon

* SDK update

* Bump lodash, @graphql-codegen/cli and @graphql-codegen/client-preset

Bumps [lodash](https://github.com/lodash/lodash), [@graphql-codegen/cli](https://github.com/dotansimha/graphql-code-generator/tree/HEAD/packages/graphql-codegen-cli) and [@graphql-codegen/client-preset](https://github.com/dotansimha/graphql-code-generator/tree/HEAD/packages/presets/client). These dependencies needed to be updated together.

Updates `lodash` from 4.17.21 to 4.18.1
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](lodash/lodash@4.17.21...4.18.1)

Updates `@graphql-codegen/cli` from 5.0.7 to 6.2.1
- [Release notes](https://github.com/dotansimha/graphql-code-generator/releases)
- [Changelog](https://github.com/dotansimha/graphql-code-generator/blob/master/packages/graphql-codegen-cli/CHANGELOG.md)
- [Commits](https://github.com/dotansimha/graphql-code-generator/commits/@graphql-codegen/cli@6.2.1/packages/graphql-codegen-cli)

Updates `@graphql-codegen/client-preset` from 4.8.3 to 5.2.4
- [Release notes](https://github.com/dotansimha/graphql-code-generator/releases)
- [Changelog](https://github.com/dotansimha/graphql-code-generator/blob/master/packages/presets/client/CHANGELOG.md)
- [Commits](https://github.com/dotansimha/graphql-code-generator/commits/HEAD/packages/presets/client)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.18.1
  dependency-type: direct:production
- dependency-name: "@graphql-codegen/cli"
  dependency-version: 6.2.1
  dependency-type: direct:development
- dependency-name: "@graphql-codegen/client-preset"
  dependency-version: 5.2.4
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Improve API key gen exp

* modal fix

* Perf improvements on web3 transactions

* More exp improvements

* Add FleetOS tenant registration flow from API Keys section

- New "Generate FleetOS Tenant" button: ensures fleets.dimo.co is an
  authorized redirect URI, generates an API key, obtains a DevJWT, and
  registers the tenant via POST to the FleetOS API in one guided flow
- FleetOS signer address persisted to localStorage so the matching row
  is tagged with a "FleetOS" badge across page refreshes
- Signer is rolled back on-chain if anything after enablement fails,
  since the private key is unknown to FleetOS at that point
- Loading modal is now non-dismissable (backdrop + Escape blocked) while
  status is 'loading', preventing mid-flow exits across all operations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Regenerate GraphQL types for updated SignerFragment

Added clientId and redirectURIs fields to SignerFragment require
codegen output to be updated so the typed gql document resolves
correctly at compile time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix TDZ crash: move useFragment before useState that depends on it

In production builds, minification causes a ReferenceError when
fragment.clientId is accessed inside a useState initializer that
appears before the fragment const declaration. Moving useFragment
to the top of the component resolves the temporal dead zone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Register FleetOS: rename, new icon, confirmation modal

- Rename button to "Register FleetOS" with TruckIcon
- Button now opens a confirmation modal explaining the multi-step flow
  before any transactions are initiated
- Confirmation lists what will happen (redirect URI, API key, tenant
  registration) and warns not to close the window once started

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix FleetOS button layout, modal centering, and copy

- Wrap buttons in flex div so they render side by side
- Remove className from Modal to preserve fixed overlay centering
- Shorten confirmation modal copy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* FleetOS: all-or-none rollback on failure

- Track addedRedirectUri to distinguish newly-added from pre-existing
- On failure: roll back signer and redirect URI only if created in this
  flow, leaving pre-existing redirect URIs untouched
- Show "Rolling back changes..." status so the user knows cleanup is
  happening before the error is surfaced

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* RentalOS: update /tenant/register request shape with user profile data

Rename FLEETS_REGISTER_ENDPOINT → RENTAL_OS_REGISTER_ENDPOINT and
update the POST body to match the new API contract: adds wallet
(smartContractAddress), email, first_name, last_name, and business_name
fetched from the DB via getUserByToken.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix: use server action getUser instead of server-only service

getUserByToken imports next/headers which can't run in a client
component. Switch to the existing getUser server action wrapper.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Allow fleets.dimo.co in CSP connect-src

Required for the RentalOS /tenant/register fetch from the browser.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* RentalOS: wait for on-chain propagation, retry JWT + registration

After enabling the signer and redirect URI, wait 8 s for auth servers
to index the on-chain state before requesting a JWT. Then retry JWT
generation up to 3x (5 s apart) and the registration call up to 3x
(5 s apart) before giving up. Rollback only happens after all retries
are exhausted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix RentalOS tag not showing after wizard completes

GraphQL returns addresses in lowercase; account.address is checksummed.
Normalize to lowercase on save and comparison so the tag matches
regardless of which source the signer row comes from.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* RentalOS: use Developer JWT signed by API key, not Global Account key

getGlobalAccountDeveloperJwt signs with the Turnkey embedded key (User
JWT). Instead, call getDeveloperJwt directly with the newly generated
signer private key so the Authorization header carries a proper
Developer JWT tied to the developer license.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* RentalOS: add console logging to diagnose 403 failures

Logs getDeveloperJwt result/errors per attempt, the registration
request body (API key redacted), and the full status + response body
from each /tenant/register attempt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix: strip 0x prefix from private key before getDeveloperJwt

web3 returns privateKey with 0x prefix; the DIMO SDK expects raw hex.
Matches how APIKeyModal displays the key and how Turnkey exports it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix: strip 0x prefix from apiKey in /tenant/register body

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Trim whitespace from business_name before /tenant/register

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add multi-configuration design spec

One-to-many configurations per license — backend API changes,
new list page at /configurator, create moves to /configurator/new.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add multi-configuration implementation plan

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: rename getConfigurationsByClientId to return array, add deleteConfiguration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: consolidate [id] configurator form components to shared location

Add configuration_id to shared SharedProps type, update [id] ConfigurationForm
imports to reference shared components path, and delete the now-redundant
duplicate files from the [id]-specific directory.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add ConfigurationList component with edit/delete per row

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add /configurator list page and /configurator/new create route

Moves DEVELOPER_LICENSE_INFO to ListView, replaces the root configurator
page with a list view, and adds a /new route for creating configurations
(redirects to list on save instead of the edit page).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add /configurator list page and /configurator/new create route

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: simplify Vehicles entry point — always route to configurator list

* fix: update stale import path after [id] types consolidation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: update LicenseCard to use renamed getConfigurationsByClientId

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: normalize getConfigurationsByClientId response to always return array

Backend currently returns a single object; wrap it until API is updated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: show configurator link with count when multiple configurations exist

Single config still shows copy button; 2+ configs links to configurator list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add Copy Link action to configurator list

Copies the login.dimo.org sharing URL directly from the list without entering each configuration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: auto-open Register RentalOS modal via ?focus=rentals_os_signup

Visitors arriving at console.dimo.org?focus=rentals_os_signup are now
routed (post-login) to their first developer license details page, with
the Register RentalOS confirmation modal opened automatically. The focus
value is preserved across the unauthenticated /sign-in redirect, the
OAuth round-trip, and the post-login /app redirect via sessionStorage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: wrap home pages in Suspense for useSearchParams CSR bailout

Adding useSearchParams to the home View triggered a Next.js
"missing-suspense-with-csr-bailout" prerender error on /app and /.
Wrap the View in <Suspense> on both routes (matches the existing
sign-in page pattern).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: import focus constants from server-safe module in middleware

Middleware was importing FOCUS_QUERY_PARAM from src/utils/focus.ts,
which is marked 'use client'. In production the Edge-Runtime middleware
bundle treated the import as a client reference instead of inlining the
string, so request.nextUrl.searchParams.get(undefined) returned null and
?focus=rentals_os_signup was dropped on the / -> /sign-in redirect.

Split the shared constants into src/utils/focusConstants.ts (no
'use client') and have middleware import from there. The client helpers
(saveFocus / getFocus / clearFocus) stay in focus.ts and re-export the
constants so existing client call sites are unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* link updates

* Add Japan

* Connection License Msg update

* feat(brand): Brand panel on license details (uploads + name) (#274)

* feat(brand): Brand panel on license details (uploads + name)

Adds a CollapsibleSection to /license/[tokenId]/details/ where dev
license owners can set their OEM brand:

  - name      (string, <= 100 chars)
  - logo      (any aspect, used on the auth button + redirect pages)
  - icon      (square, cropped on upload via react-easy-crop; used in
               the popup chrome + tab favicon)

These persist via dev-console-api's new endpoints
(DIMO-Network/dimo-developer-console-api#68). The login-with-dimo SDK
will fetch them at initializeDimoSDK time so the button auto-themes.

How it composes

  src/services/brand.ts          axios wrappers for the three new
                                 endpoints — matches app.ts pattern.
  src/actions/brand.ts           'use server' thin wrappers, matches
                                 actions/workspace.ts.
  components/Brand/Brand.tsx     CollapsibleSection. Loads workspace via
                                 getWorkspace() then existing brand via
                                 fetchMyBrand. Gates edits with
                                 useIsLicenseOwner.
  components/Brand/components/
    ImagePicker.tsx              File picker + drag-and-drop + preview.
                                 For square icon w/ non-SVG, wraps
                                 react-easy-crop to produce a 1:1
                                 cropped File via canvas. SVGs pass
                                 through unchanged.
  components/View/View.tsx       Mounts <Brand> next to RedirectUris;
                                 adds BrandFragment to the GQL query.

Deps

  + react-easy-crop ^5.5.0

Auth

  No new pattern — reads and writes ride the existing
  AuthenticationMiddleware on dev-console-api. Ownership verified
  server-side as workspace.owner === request.user.user.address.
  Non-owners see the panel in read-only mode.

* feat(brand): primary color picker in Brand panel

Adds a hex color input + native <input type=color> picker to the
Brand panel on /license/[tokenId]/details/. Validates #RRGGBB
format client-side and on the API. A small swatch shows the
resolved color next to the input.

Color flows through saveMyBrand → console-api → workspace_brands
.primary_color. SDK + popup pick it up via their respective
brand fetches.

* fix(build): install react-easy-crop + regen gql + null-safe tokenId access

- Adds react-easy-crop to package-lock.json (Vercel build was missing
  the dep)
- Regenerates src/gql after adding BrandFragment
- One pre-existing null-safety hop in layout.tsx surfaced by the
  codegen rerun: data?.developerLicense.tokenId -> data?.developerLicense?.tokenId

* fix(brand): require display name in panel

SDK and popup both gate brand load on body.name — an empty name causes
the entire brand (logo, icon, color) to be silently dropped on the
consumer side. Make the form refuse to submit without a name so users
aren't surprised when their uploaded logo never appears.

* fix(brand): allow IPFS gateway + blob/data URIs in img-src CSP

Brand panel renders the uploaded logo/icon via <img src=https://assets.dimo.org/...>
and the live preview via URL.createObjectURL (blob: URLs). Default CSP
only allowed 'self' + walletconnect — both would have been silently
blocked, so the user would upload a logo and see nothing on the next
render.

* fix(brand): strip dead WalletConnect entries from CSP

Console uses Turnkey + ZeroDev for auth; wagmi is only used for HTTP
transports + chain defs, no WC connector is configured. Verified
runtime: Vercel preview sign-in page settles with zero requests to
explorer-api.walletconnect.com or pulse.walletconnect.org. CSP was
allowlisting endpoints we never call — removed both from connect-src
and img-src to shrink the attack surface and stop signalling that
the codebase uses WC.

* chore: revert unrelated .gitignore change

CLAUDE.md gitignore entry slipped into this PR but is not related to
the brand work. Belongs in a separate housekeeping change.

* fix(brand): address code review issues before merge

- Color picker: replace reset() with setValue(..., { shouldDirty: true })
  so the form isDirty flag stays correct and other fields aren't re-validated
- CSP img-src: remove `data:` — image previews use blob: URLs (URL.createObjectURL),
  not data URIs
- Add setValue to useForm destructure (required by the above fix)
- services/brand: handle 404 from API (API now returns 404 when no brand exists,
  previously returned {}); import isAxiosError for the guard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(brand): handle 404 in getMyBrand (API now returns 404 not {})

API endpoint GET /my/workspace/:id/brand was updated to return 404
when no brand exists instead of {}. Update the service to catch 404
and return null instead of trying to distinguish {} from a valid response.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: James Li <james.li.upenn@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(brand): surface workspace-load failures instead of silent no-op (#275)

When getWorkspace() returns no id (expired session, no company workspace
yet) the load effect was returning silently — setLoading(false) still
ran via finally, so the form rendered, but workspaceId stayed null and
every Save click hit the early-return guard with zero user feedback.

Notify on both code paths:
  - load(): if !ws?.id, show 'Workspace not found' toast + Sentry message
  - onSubmit(): if !workspaceId, show 'Cannot save' toast instead of return
  - load() catch: surface a generic 'Brand load error' toast

Diagnostic for users currently seeing 'Save Brand does nothing' on
console.dimo.org — the toast will name which step failed.

* fix(brand): stop toast loop on workspace-load failure (#276)

dae756c added setNotification to the load effect's deps to surface the
silent no-op. But NotificationContext's setNotification reference is
not stable across renders — each toast caused a re-render that flipped
the dep, which re-ran the effect, which fetched + failed + toasted
again. Infinite loop of "Could not load your workspace" toasts on any
account whose getWorkspace() returns empty.

Two changes:
  - load effect runs once (empty deps) via a ref-pinned setNotification
  - error message goes into a loadError state slot, toasted by a second
    effect keyed only on loadError so re-renders can't refire the fetch

setNotification used in onSubmit is unchanged — that path runs on user
click, not in a render cycle.

* fix(brand): resolve workspace by license tokenId (#277)

Companion to DIMO-Network/dimo-developer-console-api#69. The Brand panel
is per-license, so the URL already pins the right workspace — switch
the load effect to use the new /api/my/workspace/by-token/:tokenId
endpoint and keep the company-scoped lookup only as a fallback.

Fixes the silent 'Save Brand does nothing' bug on accounts whose
workspace.company_id has drifted from the user's current company.

* content type fix

* NextJs config

* docs: add multi-brand per developer license design spec

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(brand): extend service + action layers for multi-brand collection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(brand): add BrandRow component with default badge and owner-gated actions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(brand): add BrandForm component for create/edit with rename warning and set-default

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(brand): refactor Brand panel into multi-brand list manager with SDK hint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update InputMaybe type to include undefined

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(brand): disable delete button when only one brand or brand is default

canDelete was inverted - was allowing delete of the only brand (which the
API rejects anyway with 409). Now correctly disabled unless there are
multiple brands AND this one is not the default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(configurator): add brandName selector to Login with DIMO config

When a workspace has multiple brands, the Login with DIMO configuration
form now shows a brand dropdown populated from the configured brands.
Selecting a brand emits brandName in the generated code snippet and URL.
Leaving it as 'Default' omits the prop, matching existing single-brand
behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(configurator): add brandName selector to Share Vehicles with DIMO section

Mirrors the Login with DIMO brand dropdown — shows when workspace has
multiple named brands, omitted for single-brand workspaces.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(connections): grant SACD permissions to generated connection keys (#279)

* feat(connections): grant SACD permissions to generated connection keys

The connection-create flow generated a Connection License key and a Device
Issuance key but never granted them any on-chain permissions, so neither
could actually be used to generate certificates or mint synthetic devices.
After the mint, the flow now reads connectionId from the ConnectionMinted
event and calls setPermissions on the SACD contract for each grantee:
permission 1 (MintSD, bitmask 12) for the device-issuance key, permission
2 (GenerateCertificate, bitmask 48) for the license key. The unused Kernel
AA wrapping is dropped — the grantee is the raw EOA derived from each
generated private key. The loading modal now describes what each signature
is for instead of a single generic label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(connections): show device issuance address on connection details

Derive and display the EOA address for the Device Issuance Key so users
can reference it without unmasking the private key.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: update codegen'd GraphQL types

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Correct more connection mint prices 100 to 1

* docs: add design spec for renounce vehicle permissions feature

Captures architecture, data flow, component design, error handling,
and testing plan for the per-vehicle renounce action on the vehicle
list table. Also removes unused axios import from brand.ts that was
blocking the pre-commit lint hook.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(vehicles): add renounce vehicle access action

- useRenounceVehiclePermissions hook: calls SACD setPermissions with
  permissions=0 and expiration=0 to zero out developer's access
- RenounceVehicleModal: confirmation modal with vehicle MMY, consequence
  copy, inline error on failure, loading state during tx
- VehicleDetailsTable: inline kebab menu per row opens modal; optimistic
  removal from list on success + background refetch; success/error toasts
  via NotificationContext; Sentry capture on error
- Tests: 14 passing across hook unit and modal unit test suites

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(vehicles): restore exact gql query string for TypedDocumentNode inference

Trailing whitespace in the query must match the codegen-registered string
exactly or gql() returns unknown instead of TypedDocumentNode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(vehicles): use renouncePermissions instead of setPermissions

The SACD contract only allows the grantor to call setPermissions — grantees
get Unauthorized(address). The contract exposes a dedicated
renouncePermissions(asset, tokenId) function (0x290a7e7e) where msg.sender
is treated as the grantee, allowing developers to self-revoke access.

Added renouncePermissions to Sacd.json ABI and updated hook accordingly.
Removed unused currentUser dependency from the hook.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(vehicles): throw on success:false receipt from processTransactions

processTransactions only throws on HttpRequestError or a non-empty
receipt.reason — a failed transaction with success:false and no reason
string was silently returning, causing the UI to show success while the
on-chain renounce never executed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* debug(vehicles): log clientId vs smartContractAddress in renounce

Surfaces whether the SACD grantee (clientId) matches msg.sender
(smartContractAddress) — a mismatch would explain silent no-ops.
Also logs the full processTransactions result including tx hash.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(test): pass clientId arg to renounce calls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add frontend redesign design spec

DIMO Teal direction, dark/light mode via next-themes + class strategy,
collapsible grouped sidebar, shadcn/ui component migration plan.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add frontend redesign implementation plan

10-task foundation-first plan: token layer, theme toggle, sidebar
collapse, shadcn/ui migration, Sonner, AppCard simplification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add DIMO Teal token layer and shadcn/ui foundation

Installs next-themes, lucide-react, clsx, tailwind-merge, and shadcn/ui.
Sets up DIMO Teal HSL CSS variables for light/dark modes, updates Tailwind
config with darkMode class + token colors, and adds src/lib/utils.ts with cn().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add dark/light mode toggle via next-themes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: make ThemeToggle keyboard accessible, fix hydration fallback size

Replace div[role=switch] with a native <button> so the toggle is
focusable and activatable via Space/Enter without custom JS.

Also correct the hydration placeholder dimensions from 52×26px to
54×22px to match the real rendered size (p-0.5 + two w-6 h-[18px]
spans + gap-0.5).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add sidebar collapse state to LayoutContext

Extends LayoutContext with isSidebarCollapsed/setSidebarCollapsed, persisting
the value to localStorage via withLayout HOC. TDD: tests written first.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: redesign sidebar with grouped sections and collapse toggle

Replaces flat nav list with workspace/resources sections, adds a collapse
button that toggles icon-only mode, and migrates all hardcoded dark colors
to design-token Tailwind classes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove Wrapper-in-render, add type=button, stable keys, type bottomMenu

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: redesign header credits as teal pill, show balance in USD

Switch Header.css to semantic tokens (bg-sidebar, border-border, text-foreground).
Redesign CreditsWidget small variant as a compact teal pill with $-prefixed USD
balance — no wallet icon, no "DCX" text. Large variant updated to "Buy Credits"
and semantic token classes. Initial balance now shows "$0.00" instead of "0".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: migrate Button to shadcn/ui foundation

Replace @base-ui/react/button with standard HTML button via React.forwardRef
in src/components/ui/button.tsx. Wrap it in the app Button component using
cn() + variant="default", and replace all hardcoded dark colors in Button.css
with semantic token classes while preserving all variant selectors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: migrate form primitives to shadcn/ui (Input, Textarea, Switch, Checkbox)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: import ChangeEvent type directly in CheckboxField

* feat: migrate Modal to shadcn Dialog

Replace Headless UI Dialog+Transition with shadcn/Radix Dialog primitive.
Keeps identical prop API (isOpen, setIsOpen, className, showClose, children)
and preserves role="close-modal" on the close button. Removes shadcn's
auto-generated close button from DialogContent to avoid duplication.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* wip: frontend-redesign paused at 8/10 tasks

* feat: replace withNotifications HOC and Toast with Sonner

Migrates all 44 setNotification callsites to toast.success/error/info
from sonner. Removes withNotifications HOC from AuthorizedLayout,
GuestLayout, sign-in/View, and sign-up/View. Adds <Toaster /> to
RootLayout inside ThemeProvider.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: AppCard simplification + LicenseCard token cleanup (Task 10)

Removes environment display from AppCard (scope/ENVIRONMENTS_LABELS),
updates AppCard CSS to use card/border/foreground tokens. Updates
LicenseCard CSS to use card/border tokens instead of surface-raised.
Updates test to remove environment label assertion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: migrate useErrorHandler to sonner, clean up VehicleSimulator test mock

Removes the last non-infrastructure usages of NotificationContext:
- useErrorHandler now calls toast.error() directly via sonner
- VehicleSimulator test no longer wraps with NotificationContext.Provider
  since the component already uses toast directly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: remove dead notification infrastructure (Toast, NotificationPanel, withNotifications, useNotification)

These were superseded by Sonner during the frontend redesign. No remaining imports in src/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: replace remaining bg-surface-* and hardcoded text-white with semantic tokens

Completes the DIMO Teal shadcn/ui semantic token migration across all
high-priority components and pages. bg-surface-default→bg-card,
bg-surface-raised→bg-accent, bg-surface-sunken→bg-background,
text-white (standalone)→text-foreground, text-white/50→text-muted-foreground,
border-[#322D2F]→border-border. bg-black in connection cards also replaced
with bg-card. Intentional colored-bg text-white pairings (cta-default,
blue-600, red-900, indigo-600) left untouched.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: replace invalid text-text-primary token, clean up remaining text-white misses

text-text-primary generates no CSS in this project — replaced all occurrences
with text-foreground. Also removes dead onClick prop from AppCard interface and
fixes standalone text-white/text-white/50 on plain backgrounds in EmptyList,
modal CSS files, CSVUpload, and _not-found.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: replace inert bg-surface-overlay with bg-accent token

* fix: add sr-only DialogTitle to Modal, remove stale handoff files

* chore: remove .superpowers from tracking, add to .gitignore

* tailwind update

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: James Reategui <JamesReate@users.noreply.github.com>
Co-authored-by: zer0stars <74260741+zer0stars@users.noreply.github.com>
Co-authored-by: Dylan Moreland <79415431+elffjs@users.noreply.github.com>
Co-authored-by: Dylan Moreland <dylan@dimo.zone>
…mode

- GuestLayout always uses dark mode to avoid background image issues
- SelectField uses semantic color tokens instead of hardcoded dark values
  so dropdown text and menus render correctly in light mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The dark class on <main> overrides CSS vars for children but the body
background still leaks through without an explicit bg-background on the
guest-layout container.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaced hardcoded bg-cta-default/text-white with semantic tokens
(bg-background, border-input, text-foreground) to match ui/input.tsx
so selects render correctly in both light and dark mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- SelectWithChevron rewritten as a custom div-based dropdown using the
  same select-field/custom-menu CSS as SelectField — native <select>
  popups use OS styling and can't be themed
- CEL builder components (DataAttributeSelector, OperatorSelector,
  EventNameSelector, ValueInput) switched from SelectWithChevron +
  register() to SelectField + control, matching the Service.tsx pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New /licenses page shows license list and onboarding banner
  (content previously on the home page)
- Home page redesigned with shortcut cards: Licenses, Connections,
  Webhooks, Vehicle Explorer — for quick navigation
- Licenses added to sidebar Workspace section just below Home
- /licenses added to page titles for header rendering

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaced bg-cta-default/text-white with bg-background/border-input/
text-foreground to match ui/input.tsx and render correctly in both themes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Top section: always-dark cluster with radial gradient, 3-column grid
  (Usage gauge | License identity | Vehicles gauge)
- Gauge rings: circular border with primary glow, large count + label
- Usage and Vehicles get cluster prop for compact gauge rendering
- Bottom sections: 2-column grid (Signers, Redirect URIs, JWTs, Brand)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LicenseCard: whole card is now clickable → navigates directly to details,
  removing the redundant "License Details" button
- License details: widen center cluster column (1fr 2fr 1fr) so Client ID
  doesn't wrap; stack expandable panels in a single column to prevent the
  expand-neighbors visual glitch; add border to CollapsibleSection for
  light mode contrast
- Icons: replace DeveloperBoardIcon (white fill, chip-like) with an ID-card
  outline; ChipIcon (Data Explorer) with a magnifying glass; ConnectionsIcon
  (wide graph network, similar to Webhooks) with a link-chain icon — all now
  use currentColor so they adapt to light/dark themes
- Navigation: clean up hardcoded fill-white/stroke-white classes on Webhooks
  menu item

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Nav "Licenses" now goes directly to /license/[tokenId]/details when
the user has a license. With no licenses, shows a prompt and the
"Create a license" button instead of the old license list page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Matches the DeveloperJwts pattern: action button sits in the
CollapsibleSection title row (right side), not buried in the content.
Removed the verbose description from the Brand header.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents the tab-based layout replacing the instrument cluster UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ader

Replace the instrument-cluster layout with a persistent header (name, token ID, client ID, rename button) and a 4-tab layout (Overview, Config, Vehicles, Brand). Overview tab shows Usage stat, vehicle count, and quick-action shortcuts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
0xsemaj and others added 7 commits May 31, 2026 19:26
…e fixes

All conflicts resolved by keeping staging (HEAD) versions, which include:
- Light-mode color fixes (bg-primary, border-border, fill-foreground)
- Settings page redesign
- License details page redesign
- CSS semantic token migration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Save brandName to configuration JSON for LoginWithDimo and
  ShareVehiclesWithDimo (was silently dropped on submit)
- Fix Cancel/Resend buttons in email recovery using hardcoded
  border-white + CSS invert filter — replace with primary-outline
- Remove hardcoded bg-grey-400 disabled override in email recovery
  CSS, letting Button's disabled:opacity-50 handle it properly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign-in and email-recovery forms use bg-card inside a hardcoded .dark
container, but text color was inherited from body (light mode = dark
text) rather than resolved from the .dark context. Adding
text-card-foreground forces the correct light text within the dark
card regardless of the app-level theme.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OTP boxes were nearly invisible (bg-background ≈ black on dark theme)
and cramped (outer padding left no room for the digit). Switch to
bg-muted, strip padding, and center content so digits are legible.

Resend Code button had same border invert border-white anti-pattern
as the email recovery buttons — replace with primary-outline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TextField wraps shadcn Input which hardcodes bg-background, h-10,
w-full, px-3/py-2 — impossible to override via className. Switch to
bare <input> elements styled directly with bg-muted, w-12 h-12,
text-center, and proper focus ring.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dimo-developer-console Ready Ready Preview, Comment Jun 3, 2026 12:46am

Request Review

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