Third URL shape for deep links, pointing at a specific version snapshot
rather than "latest of item". Stable link — useful for creators sharing
"review exactly this draft" references. Routes through the same
resolver component with a new byVersion flag on route data; reuses the
existing getVersionInfo API and the same warning-if-unpublished gate as
the preview flow.
Spec + plan updated to document the new shape and the expanded IoT Hub
backend contract.
Nine bite-sized tasks (i18n, utils, API methods, warning dialog, detail
dialog badge, resolver component, routing, type-page handoff, smoke
test) each verified by build + manual walkthrough. No frontend unit
tests because ui-ngx has no test runner configured.
Adds design for /iot-hub/{itemId} and /iot-hub/{itemId}/preview deep
links, covering router resolver component, warning dialog for
unpublished content, detail dialog preview badge, type-page handoff,
and the IoT Hub-side API endpoints required to support it.
- getFilterInfo and getWidgetCategories now append peOnly=false and tbVersion=<computed> to the URL, matching getPublishedVersions behavior
- add-item dialog content: scope max-height: 70vh to mat-gt-sm
Root pom.xml wired <skipAssembly>${pkg.skip.zip}</skipAssembly> at the
plugin-level <configuration> of maven-assembly-plugin inside the
always-active `packaging` profile's <pluginManagement>. Maven merges
plugin-level <configuration> into every execution of that plugin, so
-Dpkg.skip.zip=true (and the -Dpkg.skip=true alias that activates it)
suppressed any maven-assembly-plugin execution across the reactor -
not only the intended Windows ZIP execution.
In CE lts-4.2/4.3 this is latent (no CE module declares a non-ZIP
assembly execution), but it breaks downstream forks that do. PE's
rule-node-twilio-sms, for instance, declares a custom make-assembly
execution producing the classified -rule-node.jar consumed by
application's copy-pe-rule-nodes step; under -Dpkg.skip.zip=true that
assembly silently became a no-op and the downstream build failed to
resolve the classified artifact.
tools/pom.xml already sidesteps this via `combine.self="override"` on
its own <pluginManagement> - earlier evidence that the placement was
fragile.
Move <skipAssembly> into the `assembly` execution's own <configuration>
so it scopes only to the Windows ZIP execution.
Verified via mvn help:effective-pom on application/: with the fix,
<skipAssembly>true</skipAssembly> no longer appears at plugin-level
<configuration>, only inside the `assembly` <execution>.
Several testSaveProtoDeviceProfileWithInvalidRpcRequestSchema* tests
intermittently fail with:
org.thingsboard.server.dao.exception.TenantNotFoundException: Tenant
with id <fresh-tenant-uuid> not found
when the tenant created in @Before has not yet been populated in the
tenant profile cache by the time the request hits the partition-lookup
path (DefaultTenantRoutingInfoService -> TbTenantProfileCache ->
TenantService#findTenantById). The underlying request is idempotent
(the schema is invalid so it is rejected with 400 regardless of
retries), so wrap the doPost + status assertion in Awaitility with
Mockito.reset inside the retry block: only the last attempt's
invocations are visible to the subsequent verify* assertions.
Applies to all testSaveDeviceProfileWithInvalidRpcRequestProtoSchema
callers, including the currently-muted
testSaveProtoDeviceProfileWithInvalidRpcRequestSchemaRequestIdDateType.
The test asserts exactly 2 UserCredentialsUpdateMsg after creating a new
tenant-admin user, but the user activation flow can emit either 2 or 3
depending on timing:
- activateUserCredentials publishes CREDENTIALS_UPDATED (msg #1)
- setUserCredentialsEnabled publishes CREDENTIALS_UPDATED (msg #2)
- the initial USER ADDED edge event is processed asynchronously in
UserEdgeProcessor and bundles an extra UserCredentialsUpdateMsg when
it finds userCredentials.isEnabled() == true (i.e. activation
already raced past the ADDED event)
When the race goes the second way we end up with 1 UserUpdateMsg plus
3 UserCredentialsUpdateMsg, which currently fails the hard-coded
assertEquals(2, ...) assertion.
Accept both 2 and 3 UserCredentialsUpdateMsg instead of asserting an
exact count, matching the reality of the asynchronous edge event
pipeline.
Await cached resource data to become available after save eviction
before asserting, and await null after deletion. Prevents Mockito
verifyNoMoreInteractions(resourceService) failure caused by racing
background cache-load invocations.
Backport of 99334ba7fe from master.
- MpItemVersionQuery switched to options-object pattern (no more positional undefined params)
- Remove widgets-bundle-search and widget-types-panel components (inlined / merged into filter popover)
- Widget select empty state: shared #noData template with tb-no-data-bg illustration + 'Clear all filters' button (clears both search and filters); Installed->All widgets adds 'Browse IoT Hub' banner that navigates to IoT Hub->All widgets
- Filter popover: immediate-apply (no Apply/Cancel), Clear all + close in header, tbPopoverPlacement=bottomRight, tbPopoverShowCloseButton=false; installed mode uses same expansion-panel style as iot hub with widget type badge and Include Deprecated (shown for bundle and allWidgets)
- Sort mat-menu (Most installed / Newest / Name) with iconPositionEnd; client-side sort for installed widgets, scada items first when scadaFirst=true
- Replace all-widgets/installed-from-iot-hub placeholder SVGs with high-fidelity PNG@2x assets (incl. separate all-iot-hub-widgets.png for IoT Hub mode)
- IoT Hub browse: merge add-mode styles into embedded class, embedded always uses mobile filter drawer; compact grid 1 col default / 2 cols gt-md; regular 3 cols gt-sm; empty state uses tb-no-data-bg
- iot-hub-search: empty state uses tb-no-data-bg; add-item-dialog: tb-fullscreen-dialog-lt-md panel class, content 70vh with widths 80vw/1000px/1200px at gt-sm/gt-md/gt-xmd
Build hygiene for developers who rebuild lts-4.2 frequently: cleans the
pom.xml sources that generate noise without any code change.
- Pin maven-clean-plugin to 3.5.0 (latest stable) via a
<maven-clean-plugin.version> property, matching the convention already
used for surefire/install/deploy/jar plugins. Removes 55 "version is
missing" warnings plus the cascading "Some problems were encountered
while building the effective model" messages for every child module.
- Extend license-maven-plugin excludes for files that never carry a
license header: **/lombok.config, **/eslint.config.mjs,
**/config.monitoring, **/valkey-certs/**, **/data/certs/**, **/*.otf.
Directory-scoped patterns are used instead of broad extension globs
(**/*.crt, **/*.key, **/*.pem) so a stray cert dropped outside these
directories still raises a warning.
- Exclude sjk-jfr5 / sjk-jfr6 / sjk-nps transitive deps from cassandra-all
in tools/pom.xml. Their published POMs declare system-scope deps against
unresolved ${jmc5.path}, ${jmc6.path}, ${visualvm.path} properties,
producing 7 ERROR-level lines on every build. No ThingsBoard code imports
sjk, jmc, or netbeans profiler classes.
Net impact: 1040 -> 843 WARNING lines, 7 -> 0 ERROR lines. Build still
green. Full categorization of remaining warnings and Tier 2/3 migration
plan is tracked in issue #15481.
- postgres: 16.6 -> 18 (dao sql-test.properties / nosql-test.properties)
- timescaledb: latest-pg12 -> latest-pg18 (dao timescale-test.properties)
TimescaleDB pg15+ images crash on cgroup v2 CI hosts because
/docker-entrypoint-initdb.d/001_timescaledb_tune.sh evaluates
[ ${TS_TUNE_MEMORY} -gt ${FREE_BYTES} ] with an empty left operand
after the kernel reports the 64-bit max for /sys/fs/cgroup/memory.max.
Work around the upstream bug by setting NO_TS_TUNE=true.
The Testcontainers JDBC URL (jdbc:tc:timescaledb:...) does not support
docker env vars, so register a custom JdbcDatabaseContainerProvider
(TbTimescaleDBContainerProvider, activated via jdbc:tc:tbtimescaledb:...)
that starts a PostgreSQLContainer backed by timescale/timescaledb with
NO_TS_TUNE=true.
Production docker-compose files and tb-postgres image are untouched.
- New TbIotHubInstalledItemsDialogComponent opened from detail dialog Manage section
- Extract TbIotHubInstalledItemsTableComponent with itemVersion mode for single-item view
- Add installed item counts API (GET /installedItems/counts) and itemId filter to installed items list
- Wire installed counts into home, browse, search, and detail dialog (replaces installedDevices list)
- Propagate ChipOverflowDirective with minChips input; use on detail dialog meta chips
- openEntity opens in new tab; "View item details" swaps to "Review device instructions" for DEVICE items
Redesign item detail dialog: move install/add/update/open buttons to footer,
move creator to sticky meta bar with avatar and verified badge, add manage
section with solution instructions, remove, and installed items count buttons,
update subtitle with grouped icon+text pairs matching design.
Add getInstalledItemCounts API (backend + frontend) returning item counts
by itemId per type. Replace installedDevices list with count-based tracking
in home, browse, and search components. Add installedItemsCount to item card
and detail dialog data flow.
TbRestApiCallNodeTest ran concurrently with SsrfSafeAddressResolverGroupTest,
which toggles the static SsrfProtectionValidator.enabled flag in its
setUp/tearDown. When the flag leaked into the REST test's async HTTP calls,
'localhost' was rejected by SSRF and extra tellFailure invocations broke the
Mockito verify count.
TbHttpClientTest and SsrfSafeAddressResolverGroupTest already declare
@ResourceLock("SsrfProtectionValidator"); apply the same lock to
TbRestApiCallNodeTest so all three SSRF-sensitive tests serialize.
Fixes#15453
Prevents UnrecognizedPropertyException during rolling upgrades when a
newer node writes a cached entity with an added field and an older node
reads it back. The Redis-backed TbJsonRedisSerializer now uses
JacksonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER instead of the strict
OBJECT_MAPPER used by JacksonUtil.fromBytes.
Add verified field to CreatorView and creatorVerified to MpItemVersionView.
Show verified badge (32px teal icon + tooltip) on creator profile page.
Show 16px teal verified icon on item cards when creator is verified.
Make dlg-meta-bar always rendered and sticky in item detail dialog.