Commit Graph
5566 Commits
Author SHA1 Message Date
zacharyandClaude Opus 5 29390a0cc8 docs: spec — back to a table, health bar as a column
L'utilisateur revient sur la forme liste et retient la proposition
initiale : tableau HomarrDataTable avec la bande de santé en colonne.

La bande reste dans la v1 (D4 inchangée) — c'est la forme qui change,
pas le périmètre. Le tableau rend le tri et la visibilité responsive,
absorbe la croissance du nombre de sites, et correspond à ce que fait
l'interface Ubiquiti.

Contrepartie consignée : dans une colonne la bande est étroite, ce qui
fait de l'infobulle par segment le moyen principal de lire une tranche
plutôt qu'un confort.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:24:05 +02:00
zacharyandClaude Opus 5 5736f9ac4e docs: spec — merge ISP metrics into the site health list
Proposition de l'utilisateur, retenue : fusionner les métriques ISP avec
la barre « Internet Health » pour une liste d'état rapide des sites.

Elle inverse la décision D4. La barre avait été écartée au motif que
`internetIssues` est un tableau creux dont il faudrait reconstituer les
périodes saines — vrai de cette source, mais `isp-metrics` fournit la
même information déjà dense, une entrée par site, vérifié. La barre
coûte alors une boucle de coloration, pas un moteur de graphe.

D3 change aussi : liste d'état plutôt que tableau, la bande au centre
plutôt qu'en colonne. HomarrDataTable n'a donc plus lieu d'être, et le
tri disparaît. Limite assumée et consignée : au-delà de cinq ou six
sites la forme tableau redeviendrait préférable.

Point de justesse ajouté au contrat : une tranche horaire sans mesure
vaut "unknown" et jamais "healthy". Un site enregistré depuis douze
heures n'a que douze tranches sur vingt-quatre ; les peindre en vert
affirmerait un bon fonctionnement jamais mesuré.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:24:05 +02:00
zacharyandClaude Opus 5 92c878befd docs: design for UniFi Site Manager integration
Nouvelle intégration cloud-only, distincte de unifiOs, remontant une vue
multi-sites. Premier des trois projets identifiés à partir des captures
du Site Manager ; il construit aussi le socle des deux suivants.

Constat notable : il n'existe pas d'API cachée. /ea/* est un alias
complet de /v1/*, et une trentaine d'autres chemins plausibles
renvoient 404. La surface documentée est toute la surface.

La séparation types / parse est imposée dès la conception par le défaut
rencontré sur l'intégration précédente, où un import serveur dans un
module réexporté côté client empêchait l'application de démarrer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:24:05 +02:00
zacharyandClaude Opus 5 950a925fd6 feat(widgets): 5s refresh, download first, chart from the first reading
Trois demandes utilisateur, plus une adaptation rendue nécessaire par la
première.

- Ordre inversé : descendant avant montant.
- Rafraîchissement porté de 60 s à 5 s. Il fallait le faire sur les DEUX
  couches locales : l'intervalle client seul aurait relu la même entrée
  de cache serveur douze fois. Le cache cloud reste à 5 min, ses
  métriques n'évoluant que par tranches de 5 min.
- Le graphe est rendu dès la première mesure : vide plutôt qu'absent,
  ce qui évite un saut de mise en page et n'affirme rien de faux.

Adaptation : la console ne rafraîchit ses statistiques que toutes les
30 s (mesuré — `lastHeartbeatAt` avance par pas de 30 s exacts, valeurs
identiques entre deux battements). Interroger toutes les 5 s renvoie
donc six fois la même mesure. Sans filtrage, le graphe deviendrait un
escalier et 60 points ne couvriraient plus que 5 minutes. Une lecture
identique à la précédente n'est donc pas enregistrée.

Seuil de péremption locale recalibré de 150 s à 30 s : l'ancien était
dimensionné pour 60 s + 60 s et ne signalait plus rien d'utile.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:24:05 +02:00
zacharyandClaude Opus 5 0a623b7434 feat(widgets): chart WAN throughput instead of static figures
L'API UniFi ne fournit que l'instantané et Homarr ne stocke aucun
historique : la série est accumulée côté client, comme le fait déjà le
widget systemResources. Elle repart donc vide à chaque rechargement.

Deux décisions d'honnêteté, dans la ligne du reste du widget :
- une lecture en échec est ignorée, jamais enregistrée comme un zéro,
  qui dessinerait une chute à la ligne de base n'ayant pas eu lieu ;
- sous deux points, on affiche les chiffres seuls : une ligne plate
  tracée sur un point unique se lit comme un réseau au repos alors
  qu'on n'a rien mesuré.

Couleurs validées par le validateur de palette (bande de luminosité,
chroma, séparation daltonisme et vision normale, contraste) en thème
clair ET sombre. La paire orange.5/yellow.5 du widget systemResources
n'a délibérément pas été reprise : son ΔE en vision normale est de
12,1, sous le plancher de lisibilité de 15.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:23:55 +02:00
zacharyandClaude Opus 5 0e950ce5e3 fix(nextjs): register the unifiOs category translation key
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:23:55 +02:00
zacharyandClaude Opus 5 3125bcf400 fix(integrations): keep unifi-os-types client-safe
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:23:44 +02:00
zacharyandClaude Opus 5 277fbb841e fix: address final review — cloud TLS, MAC guard, honest ISP metrics
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:23:44 +02:00
zacharyandClaude Opus 5 1b312b3103 docs: spec — make ISP metrics nullable, they are absent during a WAN outage
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:23:44 +02:00
zacharyandClaude Opus 5 a793e3c325 fix(widgets): stop asserting a gateway that does not exist, label the ISP gap
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:23:44 +02:00
zacharyandClaude Opus 5 5958c6df65 feat(widgets): add UniFi OS widget
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:23:44 +02:00
zacharyandClaude Opus 5 e8c8343b9f fix(widgets): remove out-of-scope UniFi OS widget stub from task 6
The widget stub (packages/widgets/src/unifi-os/) was incorrectly added in
Task 6 and belongs to Task 7. Its removal confirms the type system does not
require it, and prevents inconsistencies: the stub declares IconWifi while
Task 7 specifies IconRouter, and it is not registered in manifest.ts,
catalog.ts or refetch-intervals.ts.

- Delete packages/widgets/src/unifi-os/ directory entirely
- Revert packages/widgets/src/index.tsx to commit 57286d83d

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:22:24 +02:00
zacharyandClaude Opus 5 604c6d0855 feat(api): expose unifiOs widget summary query through tRPC router and request handler
Create unifiOs request handler with 60s cache and stale-on-error fallback, and tRPC router exposing clientApi.widget.unifiOs.summary query. Include minimal widget stub for type system.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:22:19 +02:00
zacharyandClaude Opus 5 11dd6f44ea fix(integrations): make client/device counts nullable and test real degradation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:22:04 +02:00
zachary 7758e6537b docs: spec — drop unused VPN servers call, make client/device counts nullable 2026-10-08 00:22:04 +02:00
zacharyandClaude Opus 5 0abde13101 feat(integrations): add UnifiOsIntegration with optional cloud enrichment
Introduces UnifiOsIntegration, orchestrating UnifiOsApi (local) and
UnifiSmApi (optional cloud) to build the UnifiOsSummary. Local endpoint
calls degrade independently via Promise.allSettled; the cloud client is
never instantiated without a configured siteManagerApiKey secret.
Registers the unifiOs kind in the integration creator, index, and types
barrels, resolving the previously-failing typecheck.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:22:04 +02:00
zacharyandClaude Opus 5 2de3063dc1 fix(integrations): select newest ISP metric period explicitly
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:21:50 +02:00
zacharyandClaude Opus 5 2d601279e3 fix(integrations): type unifi-os test fetch mocks for tsc
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:21:50 +02:00
zacharyandClaude Opus 5 ca1cc54623 feat(integrations): add optional UniFi Site Manager client with 5min cache
Task 4 of the UniFi OS integration: an optional cloud client for
Ubiquiti's Site Manager API that enriches the local console with ISP
latency data. Instantiated only when a cloud API key is configured
(Task 5). Every failure path (bad key, non-ok status, parse error,
unmatched gateway MAC) returns null rather than throwing, since the
cloud is a pure enrichment. Metrics are cached 5 minutes, keyed by
gateway MAC, to respect the ~27 min publication lag and avoid rate
limiting; the query window is 3 hours because a 15-minute window
returns an empty array on the real API.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:21:50 +02:00
zacharyandClaude Opus 5 c17b863e3f feat(integrations): add UniFi OS local API client
Implements HTTP client for UniFi OS console integration API with support for
fetching site information, client counts, device statistics, and VPN server
configs. Includes pagination handling with filter-based fallback when client
count exceeds API limit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:21:50 +02:00
zacharyandClaude Opus 5 65d1266e63 fix(integrations): make unifi-os test invocation-independent with vi.hoisted()
Guarded environment validation with SKIP_ENV_VALIDATION and SECRET_ENCRYPTION_KEY
set in vi.hoisted() so that tests pass both with 'pnpm test' (NODE_ENV=development)
and bare 'pnpm vitest run' (no env override).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:21:50 +02:00
zachary 2692b6ea17 docs: fix test command in plan (pnpm test, not pnpm vitest run) 2026-10-08 00:21:50 +02:00
zacharyandClaude Opus 5 9339e6308b feat(integrations): add UniFi OS schemas and pure mappers
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:21:50 +02:00
zacharyandClaude Opus 5 13d27fb308 feat(definitions): declare unifiOs integration kind, category and widget kind
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:21:50 +02:00
zacharyandClaude Opus 5 f3d0c2f527 docs: implementation plan for UniFi OS integration
Plan en 9 tâches avec cycle TDD par étape, du vocabulaire dans
@homarr/definitions jusqu'au déploiement sur le LXC.

Corrige aussi la spec sur deux points relevés en écrivant le plan :
- catalog.ts (widgetCatalogIcons) est un cinquième point d'enregistrement,
  vérifié par manifest.spec.ts et absent du §5.2
- le §9 décrivait un test d'agrégation multi-site devenu sans objet depuis
  la décision de ne pas agréger

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:21:14 +02:00
zacharyandClaude Opus 5 ac9a0b0f42 docs: design for UniFi OS integration
Conception validée pour une intégration UniFi OS en complément de
unifiController, basée sur l'API d'intégration officielle (clé X-API-KEY)
plutôt que sur l'ancienne API du Network Controller.

Toutes les capacités et limites de l'API ont été mesurées sur une console
réelle en 10.6.102, pas déduites de la documentation publiée (qui s'arrête
à 10.4.57 et est déjà en retard sur les consoles).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-08 00:21:14 +02:00
Releases Homarr e8d67b9b02 chore(release): 2.3.0 [skip ci] 2026-10-07 18:21:46 +00:00
homarr-releases[bot] 95d10d32c2 chore(release): automatic release v2.3.0 2026-10-07 18:21:01 +00:00
ajnart 01d142455b fix(release): invoke Bun explicitly for lockfile updates 2026-10-07 19:40:53 +02:00
ajnart d31f8568dc fix(rss-feed): update description length test fixture 2026-10-07 18:01:22 +02:00
homarr-releases[bot] 6c355897d2 chore(release): automatic release v2.3.0 2026-10-07 15:45:15 +00:00
Ben Zikriandajnart 68238fa69b feat(rss-feed): add configurable description max length (#7051)
Co-authored-by: ajnart <thomas@ajnart.dev>
2026-10-07 17:42:59 +02:00
Thomas a7fac57d62 fix(docs): simplify integration secrets styling (#7076) 2026-10-07 17:03:12 +02:00
Thomas 2ea05f50cc fix(widgets): restore readable summary text and icons (#7068)
* fix(widgets): restore readable summary text and icons

* fix: size Bazarr columns using displayed dimensions

* Revert "fix: size Bazarr columns using displayed dimensions"

This reverts commit 02e28a964faa191a91f840b7b45d79ea937dac5d.
2026-10-07 17:02:38 +02:00
Thomas 8d78d0ae54 fix(board): separate nested container headers (#7060)
* fix(board): separate nested container headers

* fix(board): bound nested header inset
2026-10-07 16:39:37 +02:00
Thomas 229bd4b3ed chore: use Bun package management and Turbo remote caching (#6978)
* feat: migrate tooling and runtimes to bun

* fix: serialize act installs and adapt backup checks

* fix: finish bun scripts and rootless act setup

* fix: support bun images in runtime benchmarks

* fix: keep a single bun toolchain configuration

* fix: include docs mascot sources in workshop build

* docs: use bun in remaining tool commands

* fix: complete bun sqlite development tooling

* docs: explain sqlite development adapter

* fix: align remaining commands and local ci validation

* fix: use renovate regex fallback with bun

* fix: finalize bun sqlite connections during cleanup

* fix: preserve sqlite foreign key enforcement

* fix: align docker build frontends

* fix: prepare release versions with bun

* Add Bun benchmarks and preserve SQLite connection defaults

* Benchmark Bun installs, conflicts and production workloads

* Force Bun workspace tools and HTTP/1.1 upstream streaming

* Exclude benchmark evidence from Docker contexts

* Expose branch benchmarks through CI

* Verify hydrated widget data in production benchmarks

* Measure image archives and document benchmark protocol

* Audit dependency sharing across every workspace

* Pin pnpm for nested baseline benchmark scripts

* Preserve nested manager pinning on benchmark resume

* Include application and runtime image footprints

* Fail benchmark gates on candidate command errors

* Report complete build overhead and sampled memory bounds

* Validate migration comparisons across pinned revisions

* Record configurable runtime memory budgets

* Retain out-of-memory kills in runtime budget probes

* Reject OOM events consistently across runtime metrics

* Record complete Bun migration benchmarks

* Record memory diagnosis and correct Turbo caching

* Use Bun package management while preserving Node runtimes

* Keep native build fallbacks and exclude development artifacts

* Fix Node ESM metadata and isolate local CI configuration

* Measure development performance and isolate act environment

* Support isolated environment files in rootless act

* Validate the full migration range with act

* Preserve native SQLite binding for bundled migrations

* Use documented dev defaults and report benchmark scope

* Validate dev defaults and isolate restart measurements

* Record package-manager and development benchmarks

* Keep benchmark measurements and link full command artifacts

* Clean up temporary act environment files

* Validate Node runtimes in package-manager comparisons

* Validate every workspace in manual CI runs

* Retain patched nested brace expansion versions

* Complete package-manager and Node performance report

* Normalize archived benchmark logs

* Record final hosted validation

* Cache both Next builds with platform isolation

* Prime cache with write-only mode

* Split Next artifacts below Cloudflare upload limit

* Assemble coherent standalone cache outputs

* Preserve traced middleware entrypoints

* Assemble traced directory links before files

* Separate cached dependencies from assembled output

* Record signed Turbo cache benchmarks

* Remove archived benchmark captures

Full benchmark evidence is preserved at 8f7d3bcd14109bfb13fa664d31710b88d820ad66.

* Remove migration benchmark harness

* fix: correct migration launch and local Act prerequisites

* Consolidate Turbo caches and production artifacts

* Exclude generated files from Docker cache inputs

* fix: address Bun migration review findings

* fix: check restored compiler bundle manifests
2026-10-07 16:38:14 +02:00
Thomas dc5f382875 fix: avoid stretching Beszel charts while rows overflow (#7074) 2026-10-07 15:39:44 +02:00
1bc614b367 feat(api): expose existing dashboard controls (#6546)
* feat(api): expand REST coverage for full dashboard automation

Closes #6435.

Boards could only be created empty through the API. The single endpoint for
adding a widget took no geometry, so the size came from the widget default and
the position was always the next free cell. Everything else a setup needs was
reachable from the interface only.

Board composition
- POST /api/boards/items accepts an optional placement: width, height, xOffset,
  yOffset and sectionId, or a layouts array for per breakpoint control. Without
  it the previous automatic placement is unchanged.
- Adds read, update and delete for items, CRUD for sections, read and replace
  for layouts, and GET /api/boards/{id} for the whole board.
- GET /api/boards/{id}/export and POST /api/boards/import make a board
  reproducible from version control. onConflict decides what happens when the
  name is taken, so a pipeline can be re-run.
- Board access is manageable through GET/PUT /api/boards/{id}/permissions.

Remaining services
- Search engines, integrations, groups, api keys and server settings are
  exposed over OpenAPI and registered as MCP tools.
- GET /api/config/export and POST /api/config/import cover the configuration of
  a whole instance. Ids are kept so references inside opaque widget options stay
  intact, and entities are matched by natural key when the id is unknown, which
  is what makes a document from another instance applicable.
- The backup endpoints accept an ApiKey header, so a recovery job no longer
  needs a browser session.

Headless bootstrap
- homarr api-keys create prints a key without opening the web interface, which
  together with the existing recreate-admin removes the last manual step.

Notes
- No database migration, the schema already stores position and size.
- Grid coordinates and sizes in a document are bounded, and the placement scan
  no longer walks every column, so a large grid cannot occupy the server.
- Imports collect their statements first and apply them in one transaction, so a
  rejected document never leaves a board half written.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix: harden dashboard automation APIs

* fix: validate global home board settings

* fix: validate merged import settings

* docs(api): describe the bounded placement scan accurately

The comment still described the earlier version that walked every row up to the
last occupied one. Both axes now iterate the edges of the occupied areas, so the
cost follows the amount of content rather than the dimensions of the grid.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(api): keep the search engine type narrow and record the new MCP tools

The `.output()` added to `searchEngine.getPaginated` widened `type` back to a
string through the plain select schema, which broke the management page that
switches on it. It now reuses the narrowed union the detail endpoint already has.

`mcp.spec` pins the reviewed tool inventory; the 33 tools this branch exposes are
added to it. The configuration round trip asserted the first layout of an item,
which is the mobile one half of the time and holds the same item clamped, so it
addresses the base layout by id instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(api): complete Homarr automation endpoints

* refactor(api): consolidate preferences and task docs

* refactor(api): narrow REST to dashboard automation

* refactor(api): expose existing dashboard controls only

* fix(docs): drop removed API key CLI path

---------

Co-authored-by: rfdrew <20803599+rfdrew@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Thomas Camlong <thomas@ajnart.fr>
Co-authored-by: ajnart <thomas@ajnart.dev>
2026-10-07 15:02:59 +02:00
homarr-renovate[bot] 6b1a956ce3 chore(deps): update dependency shell-quote@<1.8.5 to v1.11.0 [security] (#7071)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2026-10-07 11:54:42 +00:00
Thomas a932cb85a7 fix(boards): reduce phone outer gutters (#7070)
Related to #7069. Remove duplicated shell gutters on phone boards while retaining widget insets and wider layout spacing.
2026-10-07 13:22:11 +02:00
Thomas eb1d449dca fix(widgets): allow narrow Docker and downloads tables to scroll (#7067)
Related to #7058. Preserve readable table column widths and enable horizontal scrolling in narrow Docker and Downloads widgets.
2026-10-07 12:16:44 +02:00
Thomas 29a422e4d8 fix: collapse Beszel controls on touch screens (#7065)
Related to #7022. Keep Beszel touch controls accessible through a compact dismissible menu.
2026-10-07 12:12:58 +02:00
Thomas ff22c577ac fix: keep dashboard CSS out of board settings (#7066)
Related to #7062. Keep dashboard custom CSS out of dashboard settings.
2026-10-07 12:12:43 +02:00
Thomas fb435eff41 fix(db): explain unsupported MySQL upgrade options (#7063) 2026-10-07 11:14:45 +02:00
Thomas 3f02da7b59 fix(dns-hole-summary): restore colors and fit compact cards (#7045)
Related to #7020 and #7018. Restore DNS summary colors, fit compact cards, and match preview text scaling.
2026-10-07 10:00:24 +02:00
Thomas d1c88b6821 fix: return board header to current dashboard (#7059)
Related to #7056. Keep the current board destination when returning from dashboard settings.
2026-10-07 09:59:43 +02:00
homarr-releases[bot] 8c977dfd1f chore: update bug report template (#7044)
Add Homarr 2.2.0 to the bug report version list.
2026-10-07 09:58:42 +02:00
Thomas 8ae66b2c5b fix: allow unlimited sidebar content while editing (#7061) 2026-10-07 09:56:31 +02:00
Thomas f420df5d03 Merge pull request #7046 from homarr-labs/docs/update-helm-docs
docs(helm): update chart installation page
2026-10-07 07:46:19 +02:00
homarr-crowdin[bot] 892015065c chore(lang): updated translations from crowdin (#7049) 2026-10-07 07:45:55 +02:00