Repository navigation
Conversation
Serve the Vite app (/ui) and the Incus API from one origin, modeled on the Hye Ararat devProxy.ts but running on Node with native PFX client certificate support and no extra dependencies. It mirrors the original DEV_PROXY_* settings (API target, upstream client PFX and passphrase, listener mode, cross-origin isolation) and adds DEV_PROXY_PORT, DEV_PROXY_HOST and DEV_PROXY_APP_TARGET. HTTP bodies are streamed, same-host redirects are rewritten onto the incoming origin, and WebSocket upgrades (Vite HMR and /1.0/events) are piped over raw sockets. Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Events layer: one shared, session-scoped connection to /1.0/events with lifecycle and operation events on a core socket and logging on its own socket, so a restricted session keeps core delivery. Reconnects use bounded backoff with jitter and report interruption and recovery, without implying that consumers have caught up. Payloads stay in memory. Project switching: a header project selector backed by a shared selection context. It defaults to All Projects, which is distinct from the "default" project, and builds project/all-projects query parameters per endpoint. Data layer core: one in-memory observation store per deployment and session, holding resource existence, field groups and collection membership with completeness, independently of the request that revealed them. Freshness follows event coverage: an interruption makes facts need validation and a restored connection alone does not make them fresh. Requirements raised in the same tick are planned together, equivalent requests are shared, and events received while a request is in flight are replayed on top of its response so older reads cannot undo them. Projects and instances resource definitions expose consumer hooks with typed field selection (useProjects, useProject, useInstances, useInstance) plus imperative APIs on the same machinery. Lifecycle events change the store directly: creation, deletion, rename and instance state changes need no refetch, and updates revalidate only the affected resource. Instance queries resolve the project from the shared selection unless one is given, filter by status on the server or evaluate it locally from complete broader results, and stay reactive as instances enter or leave a result. Also adds pop-up notifications for operations and resource changes, an events debug panel and an instance list on the instances page. Refs: lxc#6, lxc#10, lxc#11, lxc#13 Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Shorten multi-line doc comments to one line and drop long design notes. No code changes. Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Persistence: observations are written back to one IndexedDB database per deployment and session through a coalescing, bounded queue that never delays consumers. Resource definitions supply explicit allowlists; a group is persisted whole or not at all, so config with unclassified keys (e.g. cloud-init data) and sampled runtime state stay in memory. Restored facts are usable but never fresh, never overwrite newer in-memory observations, and a collection is restored as complete only if every member record was stored. Storage failures leave the in-memory layer untouched. Tabs of the same session share observations, deletions and invalidations over a BroadcastChannel. Merges compare observation times rather than arrival order, same-time conflicts require validation, nothing is echoed back, and remote facts are fresh only under continuous local coverage. Commands: the transport now supports methods, bodies, If-Match, ETags and async (202) responses, and maps 412 to a conflict. Instances and projects expose edit/save based on the writable baseline and its ETag, plus instance state actions and delete, and project create, delete and rename. Affected data is invalidated centrally; a connection failure after sending is reported as an unknown outcome and never replayed. Operations are registered in a shared registry before the handle is returned, merge events that arrive early, follow events or long-poll /wait without coverage, distinguish lost monitoring from failure, support wait and cancel, and revalidate affected data on completion. Capabilities (lxc#7) are read from api_extensions: without server filtering queries filter locally, without all-projects support the result is an explicit unsupported error, and without recursion=2 runtime state uses per-instance /state requests. Instances gain config, devices, expanded config and sampled runtime state. Profile changes invalidate the expanded config of dependent instances, including through default-project profile inheritance. Project used_by establishes instance existence and relationships. Logout wipes every Incus UI database and in-memory state in all tabs, guarded by a generation outside IndexedDB, and reports blocked deletion. It runs when the session stops being trusted. Also fixes isFetching consulting requests of other resource definitions. Refs: lxc#1, lxc#6, lxc#7, lxc#13 Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Consumers now recompute only when a store change touches a key they read: the store records record, collection, relation and type reads during each computation, and request, error and coverage changes still reach every consumer. Results are compared and shared structurally instead of serialised, so unchanged rows keep their identity and are not re-rendered. On 1,000 instances with 11 watched lists, applying 300 lifecycle events drops from about 3.4s to 1.2s. Prefetching activates a requirement ahead of its consumer and holds it for a while; a consumer that mounts meanwhile shares the request. The project selector prefetches a project's instance list on hover or focus. Request planning fixes from review: - Individual GETs keep the needs they were planned for, so resolving an undecided member reports fetching and records failures with backoff instead of retrying immediately. Equal requests already in flight adopt the new needs. Applies to instances and projects. - Explicit refreshes reach the planners, which revalidate even when the store looks fresh. - Events journaled during a request replay with the validation they had on arrival, so a reconnect cannot make pre-gap facts fresh. - Without event coverage, watched facts are re-checked periodically so expired ones are reported stale and revalidated. Loading states: collectionView and resourceView decide between skeleton, data, empty, error and absent, preferring any known data over a skeleton. Reusable table and list skeletons fade in after a short delay so quick loads never flash; the instance list and project selector use them. Also caches persistence policy lookups, clears retry timers on dispose, and falls back to getRandomValues for tab ids where crypto.randomUUID is unavailable (plain HTTP). Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
sonner is not recommended for shadcn's Base UI components. Event toasts now use a shared toast manager rendered through a Base UI toast viewport. Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
The proxy reads the Incus CLI configuration and proxies to its default remote, or to the one named by --remote or INCUS_REMOTE. TLS remotes use the CLI client certificate and pinned server certificate, local remotes use the unix socket. npm run dev now starts the proxy, which spawns Vite. Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Devtools now only render in development builds. Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Signed-off-by: Joseph Maldjian <joseph.maldjian@hyecompany.com>
Signed-off-by: Joseph Maldjian <joseph.maldjian@hyecompany.com>
Signed-off-by: Joseph Maldjian <joseph.maldjian@hyecompany.com>
Signed-off-by: Joseph Maldjian <joseph.maldjian@hyecompany.com>
Extend the Incus client with any HTTP method, JSON bodies and extra headers, a single retry on 305 (incus webui OIDC refresh), async envelopes, and listeners for 401/403 so the session is re-checked when a request is refused. Read the server's auth methods and user.ui.* settings from GET /1.0, which Incus exposes before authentication, and derive the sign-in screen options (offer_cli, auto_init_oidc and the legacy sso_only alias). Add certificate enrollment with a trust token, small persisted sign-in hints (no credentials), and OS/browser detection. Refs: lxc#1, lxc#8, lxc#9 Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Redirect signed-out users to a sign-in screen that offers the methods the server advertises, plus "Sign in with Incus CLI" (incus webui) on Linux and macOS. It honours user.ui.auth.offer_cli and auto_init_oidc (with the user.ui.sso_only alias) and skips itself when only one method remains. OIDC hands over to /oidc/login. TLS client certificates: generate a certificate and key in the browser (.crt, .key, and a 3DES/SHA-1 MAC .pfx that macOS Keychain imports), enroll it with a trust token or manually, or use one already in the browser. Then sign in through the CLI (incus remote add --tls-cert ..., incus webui) or follow import steps for the detected OS and browser, resuming after a browser restart. Client tokens: paste a certificate-signed JWT to sign in through /tls/login; /tls/logout signs out. When a token session ends, a dialog explains whether it expired and offers a new token or another method. Sign-out lives in a sidebar user menu and explains when a browser certificate or incus webui keeps the session trusted. node-forge is used under its BSD-3-Clause option and is loaded only on the generate screen. Refs: lxc#1, lxc#3, lxc#4 Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
The generated route tree was committed without the /auth/cli and /auth/tls/* routes, which broke type checking. Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
Keep only icons that carry meaning (loading, copy, back, disclosure, the sidebar user menu). Option lists, notices and the certificate downloads are now text-only. Signed-off-by: Luxxy-GF <68338577+Luxxy-GF@users.noreply.github.com>
✅ REUSE Specification compliance check passedDifferential licensesThe following non-Apache-2.0 licenses occur in files covered by this check:
License texts already present before this PR: |
Hye-Dev
marked this pull request as draft
November 5, 2026 19:40
Collaborator
|
Draft until #22 is finalized. This PR will change depending on what happens there. |
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 #1
Summary
Signed-out users are sent to a sign-in screen that offers the methods the server advertises, plus "Sign in with Incus CLI" (
incus webui) on Linux and macOS.user.ui.auth.offer_cliandauto_init_oidc(with theuser.ui.sso_onlyalias). OIDC hands over to/oidc/login./tls/login. When a token session ends, a dialog says whether it expired and offers a new token or another method.incus webuikeeps the session trusted.node-forge(BSD-3-Clause) is loaded only on the certificate generation screen.Notes for review
incusFetchgained the auth-failure hook, the 305 retry forincus webuitoken refresh, and aheadersoption.incusRequeststill rejects async responses.notify().Testing
npm run typecheck,npm run lint,npm run test:dev(58/58), andnpm run test:incus(292/292) pass.