diff --git a/CHANGELOG.md b/CHANGELOG.md
index daffb1584..d193d3aac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [1.6.0-rc.12] — 2026-08-04
+
+### Changed
+
+- **Routine dependency maintenance across the root tooling, demo, UI, and website workspaces** ([#653](https://github.com/CodesWhat/drydock/pull/653), [#654](https://github.com/CodesWhat/drydock/pull/654), [#655](https://github.com/CodesWhat/drydock/pull/655), [#656](https://github.com/CodesWhat/drydock/pull/656)). The dependency-version guard's Next.js check became a 16.x floor instead of an exact pin so routine patch bumps stop tripping it ([#664](https://github.com/CodesWhat/drydock/pull/664)).
+- **Crowdin translation sync** ([#665](https://github.com/CodesWhat/drydock/pull/665)): one French container-component string corrected.
+
+### Fixed
+
+- **"Agent Mismatch" no longer appears in the container list/SSE display during the brief window an agent's docker/dockercompose trigger is still (re)registering** ([#605](https://github.com/CodesWhat/drydock/issues/605)). Eligibility is recomputed live on every read, and `AgentClient._doHandshake()` deregisters the agent's components before awaiting the `/api/triggers` fetch and re-register. A read in that window found zero triggers for the agent and `computeUpdateEligibility` raised a hard `agent-mismatch` blocker, disabling the Update button, even though nothing was actually misconfigured — the condition self-corrected once registration finished. `agent-mismatch` now downgrades to a soft blocker (button stays enabled) on display surfaces whenever the container's own agent is mid-registration, per the new `AgentClient.isRegisteringComponents` flag (true only for the deregister→re-register span, not the whole reconnect backoff). Update **admission** (`app/updates/request-update.ts`) is unaffected and stays hard/fail-closed throughout, so an update can never be enqueued through a wrong-agent trigger during that window.
+- **WebSocket log streams no longer reject anonymous-auth sessions** ([#636](https://github.com/CodesWhat/drydock/issues/636)). Both WS upgrade paths — the system log stream and the container log stream — gated on `isAuthenticatedSession()` requiring `session.passport.user`, which `passport-anonymous` never sets, so under `DD_ANONYMOUS_AUTH_CONFIRM=true` the log stream WebSocket always rejected the upgrade even though every REST endpoint worked. `isAuthenticatedSession` now also accepts the session when anonymous authentication is the registered mode.
+- **Maturity clock: swallowed auth errors surfaced, per-container threshold respected** ([#604](https://github.com/CodesWhat/drydock/issues/604)). `getImagePublishedAt` failures — including GHCR/LSCR 401/403 auth errors — now log at `warn` instead of `debug`, so the maturity gate's silent fallback from the registry `publishedAt` to `updateDetectedAt` is no longer invisible. `getRawUpdateMaturityLevel` (`app/model/container.ts`) and `getContainerMaturityLevel` (`app/api/container/maturity-filter.ts`) now resolve each container's own `updatePolicy.maturityMinAgeDays` before falling back to the global `DD_UI_MATURITY_THRESHOLD_DAYS`, matching the gate's own `isUpdateSuppressed`/`isMaturityGatePending` logic so the hot/mature badge can no longer disagree with the gate in the same API response.
+- **Container start/stop/restart/rollback return an explicit 501 instead of an ambiguous 404 for agent containers without lifecycle transport** ([#637](https://github.com/CodesWhat/drydock/issues/637)). `POST /:id/start|stop|restart` and `POST /:id/rollback` returned a bare 404 `No docker trigger found for this container` whenever the lookup missed, indistinguishable from "container not found" — for agent-owned containers this was the only signal the UI got. That lookup miss now returns 501 naming the likely cause (the agent's connection typically hasn't advertised `usesControllerDockerTransport`) when `container.agent` is set; non-agent containers still get the existing 404. This complements the native-transport support that shipped in rc.11 via [#651](https://github.com/CodesWhat/drydock/pull/651), which closed #637's core gap — this is the remaining explicit-error half.
+
+### Security
+
+- **`brace-expansion`, `ip-address`, and `fast-uri` overrides advanced to patched releases.** `brace-expansion` moved to 5.0.9 in `app/`, `ui/`, and `e2e/` (CVE-2026-69152, [GHSA-rgw5-rvv9-x895](https://github.com/advisories/GHSA-rgw5-rvv9-x895)); `ip-address` moved to 10.3.1 in `app/` (CVE-2026-54272, CVE-2026-69192, CVE-2026-69198), pulled in transitively via `express-rate-limit` and `mqtt` → `socks`; `fast-uri` advanced from 4.1.1 to 4.1.2 in `app/` and `ui/` (host confusion via backslash authority introducer, CVE-2026-18446, [GHSA-7p8r-x3mc-p8w7](https://github.com/advisories/GHSA-7p8r-x3mc-p8w7), superseding [#658](https://github.com/CodesWhat/drydock/pull/658)).
+
## [1.6.0-rc.11] — 2026-08-01
### Added
@@ -2308,7 +2326,8 @@ Remaining upstream-only changes (not ported — not applicable to drydock):
| Fix codeberg tests | Covered by drydock's own tests |
| Update changelog | Upstream-specific |
-[Unreleased]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.11...HEAD
+[Unreleased]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.12...HEAD
+[1.6.0-rc.12]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.11...v1.6.0-rc.12
[1.6.0-rc.11]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.10...v1.6.0-rc.11
[1.6.0-rc.10]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.9...v1.6.0-rc.10
[1.6.0-rc.9]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.8...v1.6.0-rc.9
diff --git a/README.md b/README.md
index b4ba72192..30153d62e 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
-
+
@@ -178,6 +178,17 @@ See the [Quick Start guide](https://getdrydock.com/docs/quickstart) for Docker C
🆕 Recent Updates
+v1.6.0-rc.12 highlights
+
+- **Security dependency refresh** — `brace-expansion` 5.0.9 (app/UI/e2e, CVE-2026-69152), `ip-address` 10.3.1 (app runtime, CVE-2026-54272/-69192/-69198), and `fast-uri` 4.1.2 (app/UI, CVE-2026-18446). ([#659](https://github.com/CodesWhat/drydock/pull/659))
+- **Maturity clock** — the hot/mature badge resolves per-container `updatePolicy.maturityMinAgeDays` before the global threshold, matching the gate, and registry publish-date failures log at `warn` instead of disappearing at `debug`. ([#604](https://github.com/CodesWhat/drydock/issues/604))
+- **Agent registration grace** — transient `agent-mismatch`/`no-update-trigger-configured` blockers soften on display surfaces while an agent's components re-register; admission stays fail-closed. ([#605](https://github.com/CodesWhat/drydock/issues/605))
+- **WS log streams + anonymous auth** — log-stream WebSocket upgrades accept sessions when anonymous authentication is the registered mode. ([#636](https://github.com/CodesWhat/drydock/issues/636))
+- **Explicit 501s** — lifecycle actions on agent containers without controller Docker transport return 501 naming the cause instead of an ambiguous 404. ([#637](https://github.com/CodesWhat/drydock/issues/637))
+
+
+
+
v1.6.0-rc.11 highlights
- **Portwing transport** — Portwing 0.9.0's exact `transport=docker-api`, `execution=controller`, `events=portwing` marker now routes native registry checks, single/batch updates, start/stop/restart, update previews, and backup rollbacks through authenticated Standard HTTP or Edge request/response/stream transport. Portwing remains the lifecycle-event source, and raw inventory cannot erase controller-enriched update results. ([#632](https://github.com/CodesWhat/drydock/issues/632), [#637](https://github.com/CodesWhat/drydock/issues/637), [Portwing #76](https://github.com/CodesWhat/portwing/issues/76))
diff --git a/app/agent/AgentClient.test.ts b/app/agent/AgentClient.test.ts
index 31f80086b..9a43e436a 100644
--- a/app/agent/AgentClient.test.ts
+++ b/app/agent/AgentClient.test.ts
@@ -743,6 +743,50 @@ describe('AgentClient', () => {
expect(client.isConnected).toBe(true);
});
+ test('sets isRegisteringComponents for the deregister -> re-register span and resets after completion (#605)', async () => {
+ const observedDuringDeregister: boolean[] = [];
+ const observedDuringWatcherFetch: boolean[] = [];
+ const observedDuringTriggerFetch: boolean[] = [];
+
+ vi.mocked(registry.deregisterAgentComponents).mockImplementationOnce(async () => {
+ observedDuringDeregister.push(client.isRegisteringComponents);
+ });
+
+ axios.get
+ .mockResolvedValueOnce({ data: [] }) // containers
+ .mockImplementationOnce(async () => {
+ observedDuringWatcherFetch.push(client.isRegisteringComponents);
+ return { data: [] };
+ })
+ .mockImplementationOnce(async () => {
+ observedDuringTriggerFetch.push(client.isRegisteringComponents);
+ return { data: [] };
+ });
+
+ storeContainer.getContainers.mockReturnValue([]);
+
+ expect(client.isRegisteringComponents).toBe(false);
+ await client.handshake();
+
+ expect(observedDuringDeregister).toEqual([true]);
+ expect(observedDuringWatcherFetch).toEqual([true]);
+ expect(observedDuringTriggerFetch).toEqual([true]);
+ expect(client.isRegisteringComponents).toBe(false);
+ });
+
+ test('resets isRegisteringComponents to false when a mid-handshake step throws (#605)', async () => {
+ axios.get.mockResolvedValueOnce({ data: [] }); // containers succeeds
+ vi.mocked(registry.deregisterAgentComponents).mockRejectedValueOnce(
+ new Error('deregister failed'),
+ );
+ storeContainer.getContainers.mockReturnValue([]);
+
+ await expect(client.handshake()).rejects.toThrow('deregister failed');
+
+ expect(client.isRegisteringComponents).toBe(false);
+ expect(client.isConnected).toBe(false);
+ });
+
test('should emit agent-connected when transitioning to connected state', async () => {
axios.get
.mockResolvedValueOnce({ data: [] })
@@ -1120,6 +1164,13 @@ describe('AgentClient', () => {
expect(spy).toHaveBeenCalled();
});
+ test('should reset isRegisteringComponents to false on disconnect (#605)', () => {
+ client.isConnected = true;
+ client.isRegisteringComponents = true;
+ client.scheduleReconnect(1000);
+ expect(client.isRegisteringComponents).toBe(false);
+ });
+
test('should not schedule duplicate reconnects', () => {
const spy = vi.spyOn(client, 'startSse').mockImplementation(() => {});
client.scheduleReconnect(1000);
@@ -7575,10 +7626,23 @@ describe('AgentClient', () => {
});
describe('handleComponentSync (edge agent public shim)', () => {
- test('deregisters agent components and re-registers watchers and triggers', async () => {
+ test('keeps isRegisteringComponents true through edge component replacement and resets it after success (#605)', async () => {
const watchers = [{ type: 'docker', name: 'local', configuration: {} }];
const triggers = [{ type: 'mock', name: 'update', configuration: {} }];
+ const observedSteps: string[] = [];
+ vi.mocked(registry.deregisterAgentComponents).mockImplementationOnce(async () => {
+ observedSteps.push(`deregister:${client.isRegisteringComponents}`);
+ });
+ vi.mocked(registry.registerComponent)
+ .mockImplementationOnce(async (component) => {
+ observedSteps.push(`${component.kind}:${client.isRegisteringComponents}`);
+ })
+ .mockImplementationOnce(async (component) => {
+ observedSteps.push(`${component.kind}:${client.isRegisteringComponents}`);
+ });
+
+ expect(client.isRegisteringComponents).toBe(false);
await client.handleComponentSync(watchers, triggers);
expect(registry.deregisterAgentComponents).toHaveBeenCalledWith('test-agent');
@@ -7588,6 +7652,38 @@ describe('AgentClient', () => {
expect(registry.registerComponent).toHaveBeenCalledWith(
expect.objectContaining({ kind: 'trigger', provider: 'mock', name: 'update' }),
);
+ expect(observedSteps).toEqual(['deregister:true', 'watcher:true', 'trigger:true']);
+ expect(client.isRegisteringComponents).toBe(false);
+ });
+
+ test('resets isRegisteringComponents when edge watcher registration throws (#605)', async () => {
+ const observedDuringDeregister: boolean[] = [];
+ let observedDuringWatcherRegistration = false;
+
+ vi.mocked(registry.deregisterAgentComponents)
+ .mockImplementationOnce(async () => {
+ observedDuringDeregister.push(client.isRegisteringComponents);
+ })
+ .mockImplementationOnce(async () => {
+ observedDuringDeregister.push(client.isRegisteringComponents);
+ });
+ vi.mocked(registry.registerComponent).mockImplementationOnce(async () => {
+ observedDuringWatcherRegistration = client.isRegisteringComponents;
+ throw new Error('watcher registration failed');
+ });
+
+ await expect(
+ client.handleComponentSync(
+ [{ type: 'docker', name: 'local', configuration: {} }],
+ [{ type: 'mock', name: 'update', configuration: {} }],
+ ),
+ ).rejects.toThrow('watcher registration failed');
+
+ expect(observedDuringDeregister).toEqual([true, true]);
+ expect(observedDuringWatcherRegistration).toBe(true);
+ expect(registry.deregisterAgentComponents).toHaveBeenCalledTimes(2);
+ expect(registry.registerComponent).toHaveBeenCalledTimes(1);
+ expect(client.isRegisteringComponents).toBe(false);
});
test('works with empty watchers and triggers (no-op)', async () => {
@@ -7869,6 +7965,26 @@ describe('AgentClient', () => {
});
describe('Portwing Docker API transport', () => {
+ test('reports whether a watcher uses controller Docker transport', async () => {
+ await client.handleComponentSync(
+ [
+ {
+ type: 'docker',
+ name: 'docker',
+ configuration: {
+ transport: 'docker-api',
+ execution: 'controller',
+ events: 'portwing',
+ },
+ },
+ ],
+ [],
+ );
+
+ expect(client.hasControllerDockerTransport('docker')).toBe(true);
+ expect(client.hasControllerDockerTransport('missing')).toBe(false);
+ });
+
test('component sync synthesizes docker/update only for a controller Docker transport watcher', async () => {
const watcher = {
type: 'docker',
diff --git a/app/agent/AgentClient.ts b/app/agent/AgentClient.ts
index e3f0ff995..082397988 100644
--- a/app/agent/AgentClient.ts
+++ b/app/agent/AgentClient.ts
@@ -276,6 +276,20 @@ export class AgentClient {
// Parsed once at construction when authmode is 'ed25519'; undefined in token mode.
private readonly ed25519PrivateKey?: KeyObject;
public isConnected: boolean;
+ /**
+ * True only while this agent's components are being replaced — the span
+ * inside `_doHandshake()` (and the equivalent edge-path
+ * `handleComponentSync()`) between deregistering and finishing the
+ * re-registration (watchers, then triggers).
+ * Eligibility display surfaces (container list, SSE enrichment)
+ * read this to soften `agent-mismatch` / `no-update-trigger-configured` to a
+ * soft blocker during that transient window — see issue #605. Always reset
+ * in a `finally` so a handshake failure, or a disconnect via
+ * `scheduleReconnect()`, reverts to the hard-blocker default. Admission
+ * (`app/updates/request-update.ts`) never reads this field and stays
+ * fail-closed throughout.
+ */
+ public isRegisteringComponents: boolean;
public info: AgentClientRuntimeInfo;
private reconnectTimer: NodeJS.Timeout | null;
private reconnectAttempts: number;
@@ -310,6 +324,7 @@ export class AgentClient {
}
this.isConnected = false;
+ this.isRegisteringComponents = false;
this.info = {};
this.reconnectTimer = null;
this.reconnectAttempts = 0;
@@ -331,6 +346,15 @@ export class AgentClient {
return this.watcherSnapshotCache.get(watcherSnapshotCacheKey(watcherType, watcherName));
}
+ /**
+ * Whether the given watcher on this agent advertises controller Docker
+ * transport, i.e. lifecycle actions (start/stop/restart/rollback) execute
+ * locally on the controller instead of being proxied to the agent.
+ */
+ hasControllerDockerTransport(watcherName: string): boolean {
+ return this.controllerDockerTransportWatchers.has(watcherName);
+ }
+
private parseBaseUrl(): URL {
// Validate the URL to prevent request forgery (CodeQL js/request-forgery)
const parsed = new URL(this.getCandidateUrl());
@@ -936,53 +960,62 @@ export class AgentClient {
const containers = response.data;
this.log.info(`Handshake successful. Received ${containers.length} containers.`);
- // Unregister existing components for this agent
- await registry.deregisterAgentComponents(this.name);
-
- // Fetch and register watchers
+ // isRegisteringComponents is true for the entire deregister → re-register
+ // span below, including the container-inventory apply that happens
+ // between watcher and trigger registration. The `finally` guarantees it
+ // reverts to false whether registration succeeds or this method throws.
+ this.isRegisteringComponents = true;
try {
- const responseWatchers = await axios.get(
- `${this.baseUrl}/api/watchers`,
- this.buildRequestConfig('GET', '/api/watchers'),
- );
- await this.registerAgentWatchersTransactional(responseWatchers.data);
- // Only transfer update-enrichment ownership after every controller-side
- // watcher/delegate has registered successfully.
- this.setControllerDockerTransportWatchers(responseWatchers.data);
- this.seedWatcherSnapshotCacheFromHandshake(responseWatchers.data);
- } catch (error: unknown) {
- this.log.warn(`Failed to fetch/register watchers: ${getErrorMessage(error)}`);
- }
-
- // Apply inventory only after watcher registration. Controller-transport
- // descriptors change which fields are authoritative: Portwing owns live
- // runtime state, while Drydock's native watcher owns update enrichment.
- await this.processAuthoritativeContainers(containers);
- // A zero-container handshake is ambiguous: it could mean the agent has
- // no running containers, or its in-memory store is fresh-empty after a
- // restart while docker still has running containers. Defer the prune
- // until the first authoritative watcher snapshot arrives — that path is
- // unambiguous because the snapshot is only emitted after a successful
- // enumeration with no enrichment errors (#362, #386 / d02080ae).
- // Pruning here would wipe last-known state for an agent that's about to
- // re-populate it in seconds via its first watch cycle.
- if (containers.length > 0) {
- this.pruneOldContainers(containers);
- } else if (this.hasConnectedOnce) {
- this.log.warn(
- 'Handshake returned 0 containers; preserving last-known state until the first watch cycle completes',
- );
- }
+ // Unregister existing components for this agent
+ await registry.deregisterAgentComponents(this.name);
- // Fetch and register triggers
- try {
- const responseTriggers = await axios.get(
- `${this.baseUrl}/api/triggers`,
- this.buildRequestConfig('GET', '/api/triggers'),
- );
- await this.registerAgentComponents('trigger', responseTriggers.data);
- } catch (error: unknown) {
- this.log.warn(`Failed to fetch/register triggers: ${getErrorMessage(error)}`);
+ // Fetch and register watchers
+ try {
+ const responseWatchers = await axios.get(
+ `${this.baseUrl}/api/watchers`,
+ this.buildRequestConfig('GET', '/api/watchers'),
+ );
+ await this.registerAgentWatchersTransactional(responseWatchers.data);
+ // Only transfer update-enrichment ownership after every controller-side
+ // watcher/delegate has registered successfully.
+ this.setControllerDockerTransportWatchers(responseWatchers.data);
+ this.seedWatcherSnapshotCacheFromHandshake(responseWatchers.data);
+ } catch (error: unknown) {
+ this.log.warn(`Failed to fetch/register watchers: ${getErrorMessage(error)}`);
+ }
+
+ // Apply inventory only after watcher registration. Controller-transport
+ // descriptors change which fields are authoritative: Portwing owns live
+ // runtime state, while Drydock's native watcher owns update enrichment.
+ await this.processAuthoritativeContainers(containers);
+ // A zero-container handshake is ambiguous: it could mean the agent has
+ // no running containers, or its in-memory store is fresh-empty after a
+ // restart while docker still has running containers. Defer the prune
+ // until the first authoritative watcher snapshot arrives — that path is
+ // unambiguous because the snapshot is only emitted after a successful
+ // enumeration with no enrichment errors (#362, #386 / d02080ae).
+ // Pruning here would wipe last-known state for an agent that's about to
+ // re-populate it in seconds via its first watch cycle.
+ if (containers.length > 0) {
+ this.pruneOldContainers(containers);
+ } else if (this.hasConnectedOnce) {
+ this.log.warn(
+ 'Handshake returned 0 containers; preserving last-known state until the first watch cycle completes',
+ );
+ }
+
+ // Fetch and register triggers
+ try {
+ const responseTriggers = await axios.get(
+ `${this.baseUrl}/api/triggers`,
+ this.buildRequestConfig('GET', '/api/triggers'),
+ );
+ await this.registerAgentComponents('trigger', responseTriggers.data);
+ } catch (error: unknown) {
+ this.log.warn(`Failed to fetch/register triggers: ${getErrorMessage(error)}`);
+ }
+ } finally {
+ this.isRegisteringComponents = false;
}
this.isConnected = true;
@@ -1061,6 +1094,10 @@ export class AgentClient {
const reconnectDelay = delay ?? this.getNextReconnectDelayMs();
const wasConnected = this.isConnected;
this.isConnected = false;
+ // A disconnect is never a "still registering" state — it's a hard loss of
+ // the agent. Reset unconditionally so a disconnect that races a still-running
+ // _doHandshake() cannot leave eligibility softened after the connection drops.
+ this.isRegisteringComponents = false;
if (wasConnected) {
void emitAgentDisconnected({
agentName: this.name,
@@ -2148,12 +2185,19 @@ export class AgentClient {
watchers: AgentComponentDescriptor[],
triggers: AgentComponentDescriptor[],
): Promise {
- this.setControllerDockerTransportWatchers([]);
- await registry.deregisterAgentComponents(this.name);
- await this.registerAgentWatchersTransactional(watchers);
- this.setControllerDockerTransportWatchers(watchers);
- this.seedWatcherSnapshotCacheFromHandshake(watchers);
- await this.registerAgentComponents('trigger', triggers);
+ // Same deregister → re-register window as _doHandshake(): keep transient
+ // eligibility blockers soft while components are being replaced.
+ this.isRegisteringComponents = true;
+ try {
+ this.setControllerDockerTransportWatchers([]);
+ await registry.deregisterAgentComponents(this.name);
+ await this.registerAgentWatchersTransactional(watchers);
+ this.setControllerDockerTransportWatchers(watchers);
+ this.seedWatcherSnapshotCacheFromHandshake(watchers);
+ await this.registerAgentComponents('trigger', triggers);
+ } finally {
+ this.isRegisteringComponents = false;
+ }
}
/**
diff --git a/app/api/backup.test.ts b/app/api/backup.test.ts
index 66f8d42b0..e1f5d952d 100644
--- a/app/api/backup.test.ts
+++ b/app/api/backup.test.ts
@@ -10,6 +10,7 @@ const {
mockGetAllBackups,
mockGetBackup,
mockGetState,
+ mockGetAgent,
} = vi.hoisted(() => ({
mockRouter: { use: vi.fn(), get: vi.fn(), post: vi.fn() },
mockGetContainer: vi.fn(),
@@ -17,6 +18,7 @@ const {
mockGetAllBackups: vi.fn(),
mockGetBackup: vi.fn(),
mockGetState: vi.fn(),
+ mockGetAgent: vi.fn(),
}));
vi.mock('express', () => ({
@@ -40,6 +42,10 @@ vi.mock('../registry', () => ({
getState: mockGetState,
}));
+vi.mock('../agent/manager', () => ({
+ getAgent: mockGetAgent,
+}));
+
const { mockBackupLog } = vi.hoisted(() => ({
mockBackupLog: { info: vi.fn(), warn: vi.fn(), debug: vi.fn() },
}));
@@ -263,6 +269,183 @@ describe('Backup Router', () => {
});
});
+ test('should return 404 when a capable agent has no docker trigger registered yet', async () => {
+ const handler = getHandler('post', '/:id/rollback');
+ mockGetContainer.mockReturnValue({
+ id: 'c1',
+ name: 'nginx',
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ });
+ mockGetBackupsByName.mockReturnValue([
+ {
+ id: 'b1',
+ containerId: 'c1',
+ imageName: 'library/nginx',
+ imageTag: '1.24',
+ },
+ ]);
+ mockGetState.mockReturnValue({ trigger: {} });
+ mockGetAgent.mockReturnValue({ hasControllerDockerTransport: vi.fn(() => true) });
+
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(404);
+ expect(res.json).toHaveBeenCalledWith({
+ error: expect.stringContaining('No docker trigger found'),
+ });
+ });
+
+ test('should return 404, not 501, when the agent is unknown or disconnected', async () => {
+ const handler = getHandler('post', '/:id/rollback');
+ mockGetContainer.mockReturnValue({
+ id: 'c1',
+ name: 'nginx',
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ });
+ mockGetBackupsByName.mockReturnValue([
+ {
+ id: 'b1',
+ containerId: 'c1',
+ imageName: 'library/nginx',
+ imageTag: '1.24',
+ },
+ ]);
+ mockGetState.mockReturnValue({ trigger: {} });
+ mockGetAgent.mockReturnValue(undefined);
+
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(404);
+ expect(res.json).toHaveBeenCalledWith({
+ error: expect.stringContaining('No docker trigger found'),
+ });
+ });
+
+ test('should return 501 when the agent-owned container agent lacks controller docker transport', async () => {
+ const handler = getHandler('post', '/:id/rollback');
+ mockGetContainer.mockReturnValue({
+ id: 'c1',
+ name: 'nginx',
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ });
+ mockGetBackupsByName.mockReturnValue([
+ {
+ id: 'b1',
+ containerId: 'c1',
+ imageName: 'library/nginx',
+ imageTag: '1.24',
+ },
+ ]);
+ mockGetState.mockReturnValue({ trigger: {} });
+ mockGetAgent.mockReturnValue({ hasControllerDockerTransport: vi.fn(() => false) });
+
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(501);
+ expect(res.json).toHaveBeenCalledWith({
+ error: expect.stringContaining("container's agent connection"),
+ });
+ });
+
+ test('should return 501, not 500, when a legacy incapable AgentTrigger is registered for the container', async () => {
+ const handler = getHandler('post', '/:id/rollback');
+ const legacyAgentTrigger = {
+ type: 'docker',
+ agent: 'edge-1',
+ getWatcher: vi.fn(() => {
+ throw new Error(
+ 'AgentTrigger docker.edge-1 cannot provide local Docker capability getWatcher; the agent does not advertise controller Docker transport',
+ );
+ }),
+ };
+ mockGetContainer.mockReturnValue({
+ id: 'c1',
+ name: 'nginx',
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ });
+ mockGetBackupsByName.mockReturnValue([
+ {
+ id: 'b1',
+ containerId: 'c1',
+ imageName: 'library/nginx',
+ imageTag: '1.24',
+ },
+ ]);
+ mockGetState.mockReturnValue({ trigger: { 'docker.edge-1': legacyAgentTrigger } });
+ mockGetAgent.mockReturnValue({ hasControllerDockerTransport: vi.fn(() => false) });
+
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(legacyAgentTrigger.getWatcher).not.toHaveBeenCalled();
+ expect(res.status).toHaveBeenCalledWith(501);
+ expect(res.json).toHaveBeenCalledWith({
+ error: expect.stringContaining("container's agent connection"),
+ });
+ });
+
+ test('should roll back an agent-owned container whose agent advertises controller docker transport', async () => {
+ const handler = getHandler('post', '/:id/rollback');
+ const container = {
+ id: 'c1',
+ name: 'nginx',
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ image: { registry: { name: 'hub' } },
+ };
+ const latestBackup = {
+ id: 'b1',
+ containerId: 'c1',
+ imageName: 'library/nginx',
+ imageTag: '1.24',
+ };
+
+ mockGetContainer.mockReturnValue(container);
+ mockGetBackupsByName.mockReturnValue([latestBackup]);
+ mockGetAgent.mockReturnValue({ hasControllerDockerTransport: vi.fn(() => true) });
+
+ const mockCurrentContainer = {};
+ const mockContainerSpec = { State: { Running: true } };
+ const mockTrigger = {
+ type: 'docker',
+ agent: 'edge-1',
+ getWatcher: vi.fn(() => ({ dockerApi: {} })),
+ pullImage: vi.fn().mockResolvedValue(undefined),
+ getCurrentContainer: vi.fn().mockResolvedValue(mockCurrentContainer),
+ inspectContainer: vi.fn().mockResolvedValue(mockContainerSpec),
+ stopAndRemoveContainer: vi.fn().mockResolvedValue(undefined),
+ recreateContainer: vi.fn().mockResolvedValue(undefined),
+ };
+ mockGetState.mockReturnValue({
+ trigger: { 'docker.edge-1': mockTrigger },
+ registry: { hub: { getAuthPull: vi.fn().mockResolvedValue({}) } },
+ });
+
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(mockTrigger.pullImage).toHaveBeenCalled();
+ expect(mockTrigger.stopAndRemoveContainer).toHaveBeenCalled();
+ expect(mockTrigger.recreateContainer).toHaveBeenCalled();
+ expect(res.status).toHaveBeenCalledWith(200);
+ expect(res.json).toHaveBeenCalledWith({
+ message: 'Container rolled back successfully',
+ backup: latestBackup,
+ });
+ });
+
test('should rollback successfully', async () => {
const handler = getHandler('post', '/:id/rollback');
const container = {
diff --git a/app/api/backup.ts b/app/api/backup.ts
index 05fbf6dbd..d4de711fa 100644
--- a/app/api/backup.ts
+++ b/app/api/backup.ts
@@ -10,7 +10,12 @@ import {
} from '../triggers/providers/docker/created-container-candidate.js';
import { recordAuditEvent } from './audit-events.js';
import { requireDestructiveActionConfirmation } from './destructive-confirmation.js';
-import { findDockerTriggerForContainer, NO_DOCKER_TRIGGER_FOUND_ERROR } from './docker-trigger.js';
+import {
+ AGENT_LIFECYCLE_UNSUPPORTED_ERROR,
+ findDockerTriggerForContainer,
+ isAgentLifecycleUnsupported,
+ NO_DOCKER_TRIGGER_FOUND_ERROR,
+} from './docker-trigger.js';
import { sendErrorResponse } from './error-response.js';
import { handleContainerActionError } from './helpers.js';
@@ -82,6 +87,11 @@ async function rollbackContainer(req: Request, res: Response) {
backup = backups[0];
}
+ if (isAgentLifecycleUnsupported(container)) {
+ sendErrorResponse(res, 501, AGENT_LIFECYCLE_UNSUPPORTED_ERROR);
+ return;
+ }
+
const trigger = findDockerTriggerForContainer(registry.getState().trigger, container);
if (!trigger) {
sendErrorResponse(res, 404, NO_DOCKER_TRIGGER_FOUND_ERROR);
diff --git a/app/api/container-actions.test.ts b/app/api/container-actions.test.ts
index 2e4ff03fd..a5aa07bce 100644
--- a/app/api/container-actions.test.ts
+++ b/app/api/container-actions.test.ts
@@ -8,6 +8,7 @@ const {
mockUpdateContainer,
mockMarkPendingFreshStateAfterManualUpdate,
mockGetState,
+ mockGetAgent,
mockInsertAudit,
mockGetAuditCounter,
mockGetContainerActionsCounter,
@@ -19,6 +20,7 @@ const {
mockUpdateContainer: vi.fn((c) => c),
mockMarkPendingFreshStateAfterManualUpdate: vi.fn(),
mockGetState: vi.fn(),
+ mockGetAgent: vi.fn(),
mockInsertAudit: vi.fn(),
mockGetAuditCounter: vi.fn(),
mockGetContainerActionsCounter: vi.fn(),
@@ -42,6 +44,10 @@ vi.mock('../registry', () => ({
getState: mockGetState,
}));
+vi.mock('../agent/manager', () => ({
+ getAgent: mockGetAgent,
+}));
+
vi.mock('../store/audit', () => ({
insertAudit: mockInsertAudit,
}));
@@ -189,6 +195,126 @@ describe('Container Actions Router', () => {
});
});
+ test('should start an agent-owned container whose agent advertises controller docker transport', async () => {
+ const container = {
+ id: 'c1',
+ name: 'nginx',
+ image: { name: 'nginx' },
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ };
+ mockGetContainer.mockReturnValue(container);
+ const { trigger, dockerContainer } = createDockerTrigger({ agent: 'edge-1' });
+ mockGetState.mockReturnValue({ trigger: { 'docker.edge-1': trigger } });
+ mockGetAgent.mockReturnValue({ hasControllerDockerTransport: vi.fn(() => true) });
+
+ const handler = getHandler('post', '/:id/start');
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(dockerContainer.start).toHaveBeenCalled();
+ expect(res.status).toHaveBeenCalledWith(200);
+ expect(res.json).toHaveBeenCalledWith({
+ message: 'Container started successfully',
+ result: expect.any(Object),
+ });
+ });
+
+ test('should return 404 when a capable agent has no docker trigger registered yet', async () => {
+ mockGetContainer.mockReturnValue({
+ id: 'c1',
+ name: 'nginx',
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ });
+ mockGetState.mockReturnValue({ trigger: {} });
+ mockGetAgent.mockReturnValue({ hasControllerDockerTransport: vi.fn(() => true) });
+
+ const handler = getHandler('post', '/:id/start');
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(404);
+ expect(res.json).toHaveBeenCalledWith({
+ error: expect.stringContaining('No docker trigger found'),
+ });
+ });
+
+ test('should return 404, not 501, when the agent is unknown or disconnected', async () => {
+ mockGetContainer.mockReturnValue({
+ id: 'c1',
+ name: 'nginx',
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ });
+ mockGetState.mockReturnValue({ trigger: {} });
+ mockGetAgent.mockReturnValue(undefined);
+
+ const handler = getHandler('post', '/:id/start');
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(404);
+ expect(res.json).toHaveBeenCalledWith({
+ error: expect.stringContaining('No docker trigger found'),
+ });
+ });
+
+ test('should return 501 when the agent-owned container agent lacks controller docker transport', async () => {
+ mockGetContainer.mockReturnValue({
+ id: 'c1',
+ name: 'nginx',
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ });
+ mockGetState.mockReturnValue({ trigger: {} });
+ mockGetAgent.mockReturnValue({ hasControllerDockerTransport: vi.fn(() => false) });
+
+ const handler = getHandler('post', '/:id/start');
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(res.status).toHaveBeenCalledWith(501);
+ expect(res.json).toHaveBeenCalledWith({
+ error: expect.stringContaining("container's agent connection"),
+ });
+ });
+
+ test('should return 501, not 500, when a legacy incapable AgentTrigger is registered for the container', async () => {
+ const legacyAgentTrigger = {
+ type: 'docker',
+ agent: 'edge-1',
+ getWatcher: vi.fn(() => {
+ throw new Error(
+ 'AgentTrigger docker.edge-1 cannot provide local Docker capability getWatcher; the agent does not advertise controller Docker transport',
+ );
+ }),
+ };
+ mockGetContainer.mockReturnValue({
+ id: 'c1',
+ name: 'nginx',
+ agent: 'edge-1',
+ watcher: 'edge-1',
+ });
+ mockGetState.mockReturnValue({ trigger: { 'docker.edge-1': legacyAgentTrigger } });
+ mockGetAgent.mockReturnValue({ hasControllerDockerTransport: vi.fn(() => false) });
+
+ const handler = getHandler('post', '/:id/start');
+ const req = createMockRequest({ params: { id: 'c1' } });
+ const res = createMockResponse();
+ await handler(req, res);
+
+ expect(legacyAgentTrigger.getWatcher).not.toHaveBeenCalled();
+ expect(res.status).toHaveBeenCalledWith(501);
+ expect(res.json).toHaveBeenCalledWith({
+ error: expect.stringContaining("container's agent connection"),
+ });
+ });
+
test('should return 403 when feature flag is disabled', async () => {
mockGetServerConfiguration.mockReturnValue({ feature: { containeractions: false } });
diff --git a/app/api/container-actions.ts b/app/api/container-actions.ts
index 9ce0197e4..d0e83d7bb 100644
--- a/app/api/container-actions.ts
+++ b/app/api/container-actions.ts
@@ -15,7 +15,12 @@ import {
UpdateRequestError,
} from '../updates/request-update.js';
import { recordAuditEvent } from './audit-events.js';
-import { findDockerTriggerForContainer, NO_DOCKER_TRIGGER_FOUND_ERROR } from './docker-trigger.js';
+import {
+ AGENT_LIFECYCLE_UNSUPPORTED_ERROR,
+ findDockerTriggerForContainer,
+ isAgentLifecycleUnsupported,
+ NO_DOCKER_TRIGGER_FOUND_ERROR,
+} from './docker-trigger.js';
import { sendErrorResponse } from './error-response.js';
import { handleContainerActionError } from './helpers.js';
@@ -118,6 +123,11 @@ async function executeAction(
return;
}
+ if (isAgentLifecycleUnsupported(container)) {
+ sendErrorResponse(res, 501, AGENT_LIFECYCLE_UNSUPPORTED_ERROR);
+ return;
+ }
+
const trigger = findDockerTriggerForContainer(registry.getState().trigger, container);
if (!trigger) {
sendErrorResponse(res, 404, NO_DOCKER_TRIGGER_FOUND_ERROR);
diff --git a/app/api/container/handlers/list.test.ts b/app/api/container/handlers/list.test.ts
index e47cd1109..151645a90 100644
--- a/app/api/container/handlers/list.test.ts
+++ b/app/api/container/handlers/list.test.ts
@@ -1587,6 +1587,79 @@ describe('buildEligibilityContext cross-agent scoping (issue #411)', () => {
(result as any).updateEligibility.blockers.find((b: any) => b.reason === 'active-operation'),
).toBeDefined();
});
+
+ describe('agent-mismatch severity during registration window (#605)', () => {
+ function mismatchedDockerTrigger() {
+ return {
+ type: 'docker',
+ agent: 'agent-a',
+ configuration: { threshold: 'all' },
+ getId: () => 'docker.update',
+ isTriggerIncluded: () => true,
+ isTriggerExcluded: () => false,
+ };
+ }
+
+ test('downgrades to soft when the container agent is still completing registration', () => {
+ const container = createContainerWithUpdate({ agent: 'agent-b' });
+ const getAgent = vi.fn().mockReturnValue({ isRegisteringComponents: true });
+ const context: CrudHandlerContext = {
+ ...createMockContext(),
+ getTriggers: vi
+ .fn()
+ .mockReturnValue({ 'docker.update': mismatchedDockerTrigger() } as never),
+ getAgent,
+ };
+
+ const result = attachUpdateEligibility(context, container);
+
+ const blocker = (result as any).updateEligibility.blockers.find(
+ (b: any) => b.reason === 'agent-mismatch',
+ );
+ expect(blocker).toBeDefined();
+ expect(blocker.severity).toBe('soft');
+ expect(getAgent).toHaveBeenCalledWith('agent-b');
+ });
+
+ test('stays hard when the agent is not pending registration', () => {
+ const container = createContainerWithUpdate({ agent: 'agent-b' });
+ const context: CrudHandlerContext = {
+ ...createMockContext(),
+ getTriggers: vi
+ .fn()
+ .mockReturnValue({ 'docker.update': mismatchedDockerTrigger() } as never),
+ getAgent: vi.fn().mockReturnValue(undefined),
+ };
+
+ const result = attachUpdateEligibility(context, container);
+
+ const blocker = (result as any).updateEligibility.blockers.find(
+ (b: any) => b.reason === 'agent-mismatch',
+ );
+ expect(blocker).toBeDefined();
+ expect(blocker.severity).toBe('hard');
+ });
+
+ test('falls back to an empty agent name when the container has no agent', () => {
+ const container = createContainerWithUpdate();
+ const getAgent = vi.fn().mockReturnValue(undefined);
+ const context: CrudHandlerContext = {
+ ...createMockContext(),
+ getTriggers: vi
+ .fn()
+ .mockReturnValue({ 'docker.update': mismatchedDockerTrigger() } as never),
+ getAgent,
+ };
+
+ const result = attachUpdateEligibility(context, container);
+
+ const blocker = (result as any).updateEligibility.blockers.find(
+ (b: any) => b.reason === 'agent-mismatch',
+ );
+ expect(blocker).toBeDefined();
+ expect(getAgent).toHaveBeenCalledWith('');
+ });
+ });
});
describe('createGetContainersHandler', () => {
diff --git a/app/api/container/handlers/list.ts b/app/api/container/handlers/list.ts
index b7f5dc3b5..278a9cc46 100644
--- a/app/api/container/handlers/list.ts
+++ b/app/api/container/handlers/list.ts
@@ -208,6 +208,8 @@ export function attachInProgressUpdateOperation(
function buildEligibilityContext(context: CrudHandlerContext): UpdateEligibilityContext {
return {
triggers: context.getTriggers ? context.getTriggers() : undefined,
+ isAgentPendingRegistration: (agentName) =>
+ context.getAgent(agentName ?? '')?.isRegisteringComponents === true,
getActiveOperation: (container: Container) => {
const byId = context.updateOperationStore.getActiveOperationByContainerId(container.id);
// Scoped by agent+watcher so cross-agent same-named ops don't affect eligibility (issue #411).
diff --git a/app/api/container/log-stream.test.ts b/app/api/container/log-stream.test.ts
index 34840175d..aa3dba28f 100644
--- a/app/api/container/log-stream.test.ts
+++ b/app/api/container/log-stream.test.ts
@@ -4,6 +4,7 @@ import * as configuration from '../../configuration/index.js';
import * as registry from '../../registry/index.js';
import * as storeContainer from '../../store/container.js';
import * as rateLimitKey from '../rate-limit-key.js';
+import { createIdentityAwareUpgradeRateLimitKeyResolver } from '../ws-upgrade-utils.js';
import {
attachContainerLogStreamWebSocketServer,
createContainerLogStreamGateway,
@@ -651,6 +652,159 @@ describe('api/container/log-stream', () => {
expect(mockWebSocketServer.handleUpgrade).not.toHaveBeenCalled();
});
+ test('accepts passport-less upgrades when anonymous authentication is active', async () => {
+ const isAnonymousAuthenticationActiveSpy = vi
+ .spyOn(registry, 'isAnonymousAuthenticationActive')
+ .mockReturnValue(true);
+ const ws = new EventEmitter() as EventEmitter & {
+ send: ReturnType;
+ close: ReturnType;
+ };
+ ws.send = vi.fn();
+ ws.close = vi.fn(() => {
+ ws.emit('close');
+ });
+
+ const mockWebSocketServer = {
+ handleUpgrade: vi.fn((_req, _socket, _head, callback: (socket: unknown) => void) =>
+ callback(ws),
+ ),
+ };
+
+ const gateway = createContainerLogStreamGateway({
+ getContainer: vi.fn(() => undefined),
+ getWatchers: vi.fn(() => ({})),
+ sessionMiddleware: (_req: unknown, _res: unknown, next: (error?: unknown) => void) =>
+ next(),
+ webSocketServer: mockWebSocketServer,
+ isRateLimited: vi.fn(() => false),
+ });
+
+ const socket = createUpgradeSocket();
+ await gateway.handleUpgrade(
+ createUpgradeRequest('/api/v1/containers/c1/logs/stream') as any,
+ socket as any,
+ Buffer.alloc(0),
+ );
+
+ expect(socket.write).not.toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
+ expect(mockWebSocketServer.handleUpgrade).toHaveBeenCalled();
+ expect(ws.close).toHaveBeenCalledWith(4004, 'Container not found');
+
+ isAnonymousAuthenticationActiveSpy.mockRestore();
+ });
+
+ test('rejects unauthenticated upgrades when anonymous authentication is not active', async () => {
+ const isAnonymousAuthenticationActiveSpy = vi
+ .spyOn(registry, 'isAnonymousAuthenticationActive')
+ .mockReturnValue(false);
+ const mockWebSocketServer = {
+ handleUpgrade: vi.fn(),
+ };
+
+ const gateway = createContainerLogStreamGateway({
+ getContainer: vi.fn(),
+ getWatchers: vi.fn(() => ({})),
+ sessionMiddleware: (_req: unknown, _res: unknown, next: (error?: unknown) => void) =>
+ next(),
+ webSocketServer: mockWebSocketServer,
+ isRateLimited: vi.fn(() => false),
+ });
+
+ const socket = createUpgradeSocket();
+ await gateway.handleUpgrade(
+ createUpgradeRequest('/api/v1/containers/c1/logs/stream') as any,
+ socket as any,
+ Buffer.alloc(0),
+ );
+
+ expect(socket.write).toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
+ expect(mockWebSocketServer.handleUpgrade).not.toHaveBeenCalled();
+
+ isAnonymousAuthenticationActiveSpy.mockRestore();
+ });
+
+ test('keys rate limiting by IP for anonymous-authenticated upgrades, not by session', async () => {
+ const isAnonymousAuthenticationActiveSpy = vi
+ .spyOn(registry, 'isAnonymousAuthenticationActive')
+ .mockReturnValue(true);
+ const capturedRateLimitKeys: string[] = [];
+ const mockWebSocketServer = {
+ handleUpgrade: vi.fn((_req, _socket, _head, callback: (socket: unknown) => void) =>
+ callback({ on: vi.fn(), off: vi.fn(), send: vi.fn(), close: vi.fn() }),
+ ),
+ };
+
+ const gateway = createContainerLogStreamGateway({
+ getContainer: vi.fn(() => undefined),
+ getWatchers: vi.fn(() => ({})),
+ sessionMiddleware: (_req: unknown, _res: unknown, next: (error?: unknown) => void) =>
+ next(),
+ webSocketServer: mockWebSocketServer,
+ isRateLimited: (key: string) => {
+ capturedRateLimitKeys.push(key);
+ return false;
+ },
+ getRateLimitKey: createIdentityAwareUpgradeRateLimitKeyResolver({
+ ratelimit: { identitykeying: true },
+ }),
+ });
+
+ const socket = createUpgradeSocket();
+ await gateway.handleUpgrade(
+ createUpgradeRequest('/api/v1/containers/c1/logs/stream') as any,
+ socket as any,
+ Buffer.alloc(0),
+ );
+
+ expect(socket.write).not.toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
+ expect(capturedRateLimitKeys).toEqual(['ip:127.0.0.1']);
+
+ isAnonymousAuthenticationActiveSpy.mockRestore();
+ });
+
+ test('keeps session-keyed rate limiting for passport-authenticated upgrades', async () => {
+ const authenticatingMiddleware = (
+ req: any,
+ _res: unknown,
+ next: (error?: unknown) => void,
+ ) => {
+ req.session = { passport: { user: '{"username":"alice"}' } };
+ req.sessionID = 'session-1';
+ next();
+ };
+ const capturedRateLimitKeys: string[] = [];
+ const mockWebSocketServer = {
+ handleUpgrade: vi.fn((_req, _socket, _head, callback: (socket: unknown) => void) =>
+ callback({ on: vi.fn(), off: vi.fn(), send: vi.fn(), close: vi.fn() }),
+ ),
+ };
+
+ const gateway = createContainerLogStreamGateway({
+ getContainer: vi.fn(() => undefined),
+ getWatchers: vi.fn(() => ({})),
+ sessionMiddleware: authenticatingMiddleware,
+ webSocketServer: mockWebSocketServer,
+ isRateLimited: (key: string) => {
+ capturedRateLimitKeys.push(key);
+ return false;
+ },
+ getRateLimitKey: createIdentityAwareUpgradeRateLimitKeyResolver({
+ ratelimit: { identitykeying: true },
+ }),
+ });
+
+ const socket = createUpgradeSocket();
+ await gateway.handleUpgrade(
+ createUpgradeRequest('/api/v1/containers/c1/logs/stream') as any,
+ socket as any,
+ Buffer.alloc(0),
+ );
+
+ expect(socket.write).not.toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
+ expect(capturedRateLimitKeys).toEqual(['session:session-1']);
+ });
+
test('closes websocket with 4004 when container is missing', async () => {
const ws = new EventEmitter() as EventEmitter & {
send: ReturnType;
diff --git a/app/api/container/log-stream.ts b/app/api/container/log-stream.ts
index 168d08fa7..c51a0754a 100644
--- a/app/api/container/log-stream.ts
+++ b/app/api/container/log-stream.ts
@@ -599,13 +599,19 @@ export function createContainerLogStreamGateway(
}
const upgradeRequest = request as UpgradeRequest;
- const authenticated = isAuthenticatedSession(upgradeRequest);
- const rateLimitKey = getRateLimitKey(upgradeRequest, authenticated);
+ // Rate-limit keying must stay based on genuine passport authentication only —
+ // anonymous auth being active shouldn't let anonymous clients earn session-keyed
+ // (rotatable) rate limits instead of IP-keyed ones.
+ const passportAuthenticated = isAuthenticatedSession(upgradeRequest);
+ const gateAuthenticated = isAuthenticatedSession(upgradeRequest, {
+ anonymousAuthActive: registry.isAnonymousAuthenticationActive(),
+ });
+ const rateLimitKey = getRateLimitKey(upgradeRequest, passportAuthenticated);
if (isRateLimited(rateLimitKey)) {
writeUpgradeError(socket, 429, 'Too Many Requests');
return;
}
- if (!authenticated) {
+ if (!gateAuthenticated) {
writeUpgradeError(socket, 401, 'Unauthorized');
return;
}
diff --git a/app/api/container/maturity-filter.test.ts b/app/api/container/maturity-filter.test.ts
index cb2d9bbb0..115e77dda 100644
--- a/app/api/container/maturity-filter.test.ts
+++ b/app/api/container/maturity-filter.test.ts
@@ -33,4 +33,41 @@ describe('api/container/maturity-filter', () => {
expect(applyContainerMaturityFilter(containers, undefined)).toBe(containers);
});
+
+ test('applyContainerMaturityFilter uses per-container updatePolicy.maturityMinAgeDays over the global threshold on the uncached fallback path', () => {
+ const previousThreshold = process.env.DD_UI_MATURITY_THRESHOLD_DAYS;
+ process.env.DD_UI_MATURITY_THRESHOLD_DAYS = '7';
+
+ try {
+ const tenDaysMs = 10 * 24 * 60 * 60 * 1000;
+ const containers = [
+ {
+ id: 'c1',
+ updateAvailable: true,
+ updateAge: tenDaysMs,
+ updatePolicy: { maturityMinAgeDays: 30 },
+ } as unknown as Container,
+ {
+ id: 'c2',
+ updateAvailable: true,
+ updateAge: tenDaysMs,
+ } as unknown as Container,
+ ];
+
+ // Global threshold is pinned to 7 days: c2 has no override so it's 'mature'.
+ // c1 overrides to 30 days, so the same 10-day-old update is still 'hot'.
+ expect(
+ applyContainerMaturityFilter(containers, 'hot').map((container) => container.id),
+ ).toEqual(['c1']);
+ expect(
+ applyContainerMaturityFilter(containers, 'mature').map((container) => container.id),
+ ).toEqual(['c2']);
+ } finally {
+ if (previousThreshold === undefined) {
+ delete process.env.DD_UI_MATURITY_THRESHOLD_DAYS;
+ } else {
+ process.env.DD_UI_MATURITY_THRESHOLD_DAYS = previousThreshold;
+ }
+ }
+ });
});
diff --git a/app/api/container/maturity-filter.ts b/app/api/container/maturity-filter.ts
index 59bdb3103..4cb9ceffc 100644
--- a/app/api/container/maturity-filter.ts
+++ b/app/api/container/maturity-filter.ts
@@ -28,13 +28,9 @@ function resolveUiMaturityThresholdDays(): number {
);
}
-function resolveUiMaturityThresholdMs(): number {
- return maturityMinAgeDaysToMilliseconds(resolveUiMaturityThresholdDays());
-}
-
function getContainerMaturityLevel(
container: Container,
- uiMaturityThresholdMs: number,
+ uiMaturityThresholdDays: number,
): ContainerMaturityFilter | undefined {
const cachedLevel = container.updateMaturityLevel;
if (cachedLevel === 'hot' || cachedLevel === 'mature' || cachedLevel === 'established') {
@@ -48,7 +44,11 @@ function getContainerMaturityLevel(
if (updateAge >= maturityMinAgeDaysToMilliseconds(ESTABLISHED_UPDATE_AGE_DAYS)) {
return 'established';
}
- return updateAge >= uiMaturityThresholdMs ? 'mature' : 'hot';
+ const maturityThresholdDays = resolveMaturityMinAgeDays(
+ container.updatePolicy?.maturityMinAgeDays,
+ uiMaturityThresholdDays,
+ );
+ return updateAge >= maturityMinAgeDaysToMilliseconds(maturityThresholdDays) ? 'mature' : 'hot';
}
export function applyContainerMaturityFilter(
@@ -59,8 +59,8 @@ export function applyContainerMaturityFilter(
return containers;
}
- const uiMaturityThresholdMs = resolveUiMaturityThresholdMs();
+ const uiMaturityThresholdDays = resolveUiMaturityThresholdDays();
return containers.filter(
- (container) => getContainerMaturityLevel(container, uiMaturityThresholdMs) === maturityFilter,
+ (container) => getContainerMaturityLevel(container, uiMaturityThresholdDays) === maturityFilter,
);
}
diff --git a/app/api/docker-trigger.ts b/app/api/docker-trigger.ts
index d509bdc83..930379199 100644
--- a/app/api/docker-trigger.ts
+++ b/app/api/docker-trigger.ts
@@ -1,9 +1,12 @@
import path from 'node:path';
+import { getAgent } from '../agent/manager.js';
import type { Container } from '../model/container.js';
import type Docker from '../triggers/providers/docker/Docker.js';
import type Trigger from '../triggers/providers/Trigger.js';
export const NO_DOCKER_TRIGGER_FOUND_ERROR = 'No docker trigger found for this container';
+export const AGENT_LIFECYCLE_UNSUPPORTED_ERROR =
+ "Lifecycle actions (start/stop/restart) are not supported over this container's agent connection, typically because the agent has not advertised the usesControllerDockerTransport capability.";
const DEFAULT_TRIGGER_TYPES = ['docker', 'dockercompose'];
const COMPOSE_DIRECTORY_FILE_CANDIDATES = new Set([
'compose.yaml',
@@ -255,6 +258,33 @@ export function isTriggerCompatibleWithContainer(
return true;
}
+/**
+ * Whether lifecycle actions (start/stop/restart/rollback) are unsupported for
+ * an agent-owned container, decided from the agent's actual advertised
+ * capability rather than trigger presence/absence:
+ *
+ * - No agent on the container: never unsupported (non-agent containers are
+ * handled by the plain docker-trigger lookup).
+ * - Agent not currently connected/registered: not decided here; the caller's
+ * docker-trigger lookup will report the honest transient 404 instead.
+ * - Agent connected but its watcher hasn't advertised controller Docker
+ * transport: unsupported, regardless of whether a legacy AgentTrigger is
+ * still registered for it (that trigger's getWatcher()/rollback methods
+ * throw rather than working).
+ */
+export function isAgentLifecycleUnsupported(
+ container: Pick,
+): boolean {
+ if (!container.agent) {
+ return false;
+ }
+ const agentClient = getAgent(container.agent);
+ if (!agentClient) {
+ return false;
+ }
+ return !agentClient.hasControllerDockerTransport(container.watcher);
+}
+
/**
* Find a docker trigger compatible with a container's agent context.
*/
diff --git a/app/api/log-stream.test.ts b/app/api/log-stream.test.ts
index 11ac5d138..ca900587b 100644
--- a/app/api/log-stream.test.ts
+++ b/app/api/log-stream.test.ts
@@ -1,12 +1,14 @@
import { EventEmitter } from 'node:events';
import { WebSocketServer } from 'ws';
import * as configuration from '../configuration/index.js';
+import * as registry from '../registry/index.js';
import {
attachSystemLogStreamWebSocketServer,
createSystemLogStreamGateway,
parseSystemLogStreamQuery,
} from './log-stream.js';
import * as rateLimitKey from './rate-limit-key.js';
+import { createIdentityAwareUpgradeRateLimitKeyResolver } from './ws-upgrade-utils.js';
function createUpgradeSocket() {
return {
@@ -403,6 +405,148 @@ describe('api/log-stream', () => {
expect(socket.write).toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
});
+ test('accepts passport-less upgrades when anonymous authentication is active', async () => {
+ const isAnonymousAuthenticationActiveSpy = vi
+ .spyOn(registry, 'isAnonymousAuthenticationActive')
+ .mockReturnValue(true);
+ const mockHandleUpgrade = vi.fn(
+ (_req: unknown, _socket: unknown, _head: unknown, callback: (ws: unknown) => void) => {
+ const ws = {
+ on: vi.fn((event: string, listener: () => void) => {
+ if (event === 'close') listener();
+ }),
+ off: vi.fn(),
+ send: vi.fn(),
+ close: vi.fn(),
+ };
+ callback(ws);
+ },
+ );
+ const gateway = createSystemLogStreamGateway({
+ sessionMiddleware: (_req: unknown, _res: unknown, next: (error?: unknown) => void) =>
+ next(),
+ webSocketServer: { handleUpgrade: mockHandleUpgrade },
+ isRateLimited: vi.fn(() => false),
+ });
+ const socket = createUpgradeSocket();
+
+ await gateway.handleUpgrade(
+ createUpgradeRequest('/api/v1/log/stream') as any,
+ socket as any,
+ Buffer.alloc(0),
+ );
+
+ expect(socket.write).not.toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
+ expect(mockHandleUpgrade).toHaveBeenCalledTimes(1);
+
+ isAnonymousAuthenticationActiveSpy.mockRestore();
+ });
+
+ test('rejects unauthenticated upgrades when anonymous authentication is not active', async () => {
+ const isAnonymousAuthenticationActiveSpy = vi
+ .spyOn(registry, 'isAnonymousAuthenticationActive')
+ .mockReturnValue(false);
+ const gateway = createSystemLogStreamGateway({
+ sessionMiddleware: (_req: unknown, _res: unknown, next: (error?: unknown) => void) =>
+ next(),
+ webSocketServer: { handleUpgrade: vi.fn() },
+ isRateLimited: vi.fn(() => false),
+ });
+ const socket = createUpgradeSocket();
+
+ await gateway.handleUpgrade(
+ createUpgradeRequest('/api/v1/log/stream') as any,
+ socket as any,
+ Buffer.alloc(0),
+ );
+
+ expect(socket.write).toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
+
+ isAnonymousAuthenticationActiveSpy.mockRestore();
+ });
+
+ test('keys rate limiting by IP for anonymous-authenticated upgrades, not by session', async () => {
+ const isAnonymousAuthenticationActiveSpy = vi
+ .spyOn(registry, 'isAnonymousAuthenticationActive')
+ .mockReturnValue(true);
+ const capturedRateLimitKeys: string[] = [];
+ const mockHandleUpgrade = vi.fn(
+ (_req: unknown, _socket: unknown, _head: unknown, callback: (ws: unknown) => void) => {
+ const ws = {
+ on: vi.fn((event: string, listener: () => void) => {
+ if (event === 'close') listener();
+ }),
+ off: vi.fn(),
+ send: vi.fn(),
+ close: vi.fn(),
+ };
+ callback(ws);
+ },
+ );
+ const gateway = createSystemLogStreamGateway({
+ sessionMiddleware: (_req: unknown, _res: unknown, next: (error?: unknown) => void) =>
+ next(),
+ webSocketServer: { handleUpgrade: mockHandleUpgrade },
+ isRateLimited: (key: string) => {
+ capturedRateLimitKeys.push(key);
+ return false;
+ },
+ getRateLimitKey: createIdentityAwareUpgradeRateLimitKeyResolver({
+ ratelimit: { identitykeying: true },
+ }),
+ });
+ const socket = createUpgradeSocket();
+
+ await gateway.handleUpgrade(
+ createUpgradeRequest('/api/v1/log/stream') as any,
+ socket as any,
+ Buffer.alloc(0),
+ );
+
+ expect(socket.write).not.toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
+ expect(capturedRateLimitKeys).toEqual(['ip:127.0.0.1']);
+
+ isAnonymousAuthenticationActiveSpy.mockRestore();
+ });
+
+ test('keeps session-keyed rate limiting for passport-authenticated upgrades', async () => {
+ const capturedRateLimitKeys: string[] = [];
+ const mockHandleUpgrade = vi.fn(
+ (_req: unknown, _socket: unknown, _head: unknown, callback: (ws: unknown) => void) => {
+ const ws = {
+ on: vi.fn((event: string, listener: () => void) => {
+ if (event === 'close') listener();
+ }),
+ off: vi.fn(),
+ send: vi.fn(),
+ close: vi.fn(),
+ };
+ callback(ws);
+ },
+ );
+ const gateway = createSystemLogStreamGateway({
+ sessionMiddleware: authenticatingSessionMiddleware,
+ webSocketServer: { handleUpgrade: mockHandleUpgrade },
+ isRateLimited: (key: string) => {
+ capturedRateLimitKeys.push(key);
+ return false;
+ },
+ getRateLimitKey: createIdentityAwareUpgradeRateLimitKeyResolver({
+ ratelimit: { identitykeying: true },
+ }),
+ });
+ const socket = createUpgradeSocket();
+
+ await gateway.handleUpgrade(
+ createUpgradeRequest('/api/v1/log/stream') as any,
+ socket as any,
+ Buffer.alloc(0),
+ );
+
+ expect(socket.write).not.toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
+ expect(capturedRateLimitKeys).toEqual(['session:session-1']);
+ });
+
test('does not write error when socket is already destroyed', async () => {
const gateway = createSystemLogStreamGateway({
sessionMiddleware: authenticatingSessionMiddleware,
diff --git a/app/api/log-stream.ts b/app/api/log-stream.ts
index 3226cd566..6f63c08e1 100644
--- a/app/api/log-stream.ts
+++ b/app/api/log-stream.ts
@@ -11,6 +11,7 @@ import {
onEntry,
} from '../log/buffer.js';
import { toDisplayLogEntry } from '../log/display-timestamp.js';
+import * as registry from '../registry/index.js';
import {
applySessionMiddleware,
createFixedWindowRateLimiter,
@@ -255,13 +256,19 @@ export function createSystemLogStreamGateway(dependencies: SystemLogStreamGatewa
}
const upgradeRequest = request as UpgradeRequest;
- const authenticated = isAuthenticatedSession(upgradeRequest);
- const rateLimitKey = getRateLimitKey(upgradeRequest, authenticated);
+ // Rate-limit keying must stay based on genuine passport authentication only —
+ // anonymous auth being active shouldn't let anonymous clients earn session-keyed
+ // (rotatable) rate limits instead of IP-keyed ones.
+ const passportAuthenticated = isAuthenticatedSession(upgradeRequest);
+ const gateAuthenticated = isAuthenticatedSession(upgradeRequest, {
+ anonymousAuthActive: registry.isAnonymousAuthenticationActive(),
+ });
+ const rateLimitKey = getRateLimitKey(upgradeRequest, passportAuthenticated);
if (isRateLimited(rateLimitKey)) {
writeUpgradeError(socket, 429, 'Too Many Requests');
return;
}
- if (!authenticated) {
+ if (!gateAuthenticated) {
writeUpgradeError(socket, 401, 'Unauthorized');
return;
}
diff --git a/app/api/openapi/paths/containers.test.ts b/app/api/openapi/paths/containers.test.ts
index 4d4c3302f..4b9701d33 100644
--- a/app/api/openapi/paths/containers.test.ts
+++ b/app/api/openapi/paths/containers.test.ts
@@ -73,6 +73,7 @@ describe('containerPaths', () => {
200: jsonResponse('Container started', {
$ref: '#/components/schemas/ContainerActionResponse',
}),
+ 501: errorResponse("Lifecycle actions unsupported by this container's agent connection"),
401: errorResponse('Authentication required'),
403: errorResponse('Container actions feature disabled'),
404: errorResponse('Container or docker trigger not found'),
@@ -94,6 +95,7 @@ describe('containerPaths', () => {
200: jsonResponse('Container stopped', {
$ref: '#/components/schemas/ContainerActionResponse',
}),
+ 501: errorResponse("Lifecycle actions unsupported by this container's agent connection"),
401: errorResponse('Authentication required'),
403: errorResponse('Container actions feature disabled'),
404: errorResponse('Container or docker trigger not found'),
@@ -115,6 +117,7 @@ describe('containerPaths', () => {
200: jsonResponse('Container restarted', {
$ref: '#/components/schemas/ContainerActionResponse',
}),
+ 501: errorResponse("Lifecycle actions unsupported by this container's agent connection"),
401: errorResponse('Authentication required'),
403: errorResponse('Container actions feature disabled'),
404: errorResponse('Container or docker trigger not found'),
diff --git a/app/api/openapi/paths/containers.ts b/app/api/openapi/paths/containers.ts
index cfedcc5b6..70790b2f7 100644
--- a/app/api/openapi/paths/containers.ts
+++ b/app/api/openapi/paths/containers.ts
@@ -818,6 +818,7 @@ export const containerPaths = {
200: jsonResponse('Rollback successful', {
$ref: '#/components/schemas/ContainerRollbackResponse',
}),
+ 501: errorResponse("Lifecycle actions unsupported by this container's agent connection"),
401: errorResponse('Authentication required'),
428: errorResponse('Destructive confirmation header is required'),
404: errorResponse('Container, backup, or trigger not found'),
@@ -830,18 +831,27 @@ export const containerPaths = {
operationId: 'startContainer',
successDescription: 'Container started',
failureDescription: 'Container start failed',
+ additionalErrorResponses: {
+ 501: errorResponse("Lifecycle actions unsupported by this container's agent connection"),
+ },
}),
'/api/v1/containers/{id}/stop': createRuntimeContainerActionPath({
summary: 'Stop container',
operationId: 'stopContainer',
successDescription: 'Container stopped',
failureDescription: 'Container stop failed',
+ additionalErrorResponses: {
+ 501: errorResponse("Lifecycle actions unsupported by this container's agent connection"),
+ },
}),
'/api/v1/containers/{id}/restart': createRuntimeContainerActionPath({
summary: 'Restart container',
operationId: 'restartContainer',
successDescription: 'Container restarted',
failureDescription: 'Container restart failed',
+ additionalErrorResponses: {
+ 501: errorResponse("Lifecycle actions unsupported by this container's agent connection"),
+ },
}),
'/api/v1/containers/{id}/update': createRuntimeContainerActionPath({
summary: 'Update container to latest available image',
diff --git a/app/api/sse-container-enrichment.test.ts b/app/api/sse-container-enrichment.test.ts
index 4a3bf8778..1478e3ee2 100644
--- a/app/api/sse-container-enrichment.test.ts
+++ b/app/api/sse-container-enrichment.test.ts
@@ -1,16 +1,25 @@
-var { mockGetState, mockGetActiveOperationByContainerId, mockGetActiveOperationByContainerName } =
- vi.hoisted(() => {
- return {
- mockGetState: vi.fn(() => ({ trigger: {}, watcher: {} })),
- mockGetActiveOperationByContainerId: vi.fn(() => undefined),
- mockGetActiveOperationByContainerName: vi.fn(() => undefined),
- };
- });
+var {
+ mockGetState,
+ mockGetActiveOperationByContainerId,
+ mockGetActiveOperationByContainerName,
+ mockGetAgent,
+} = vi.hoisted(() => {
+ return {
+ mockGetState: vi.fn(() => ({ trigger: {}, watcher: {} })),
+ mockGetActiveOperationByContainerId: vi.fn(() => undefined),
+ mockGetActiveOperationByContainerName: vi.fn(() => undefined),
+ mockGetAgent: vi.fn(() => undefined),
+ };
+});
vi.mock('../registry/index.js', () => ({
getState: mockGetState,
}));
+vi.mock('../agent/manager.js', () => ({
+ getAgent: mockGetAgent,
+}));
+
vi.mock('../store/update-operation.js', () => ({
getActiveOperationByContainerId: mockGetActiveOperationByContainerId,
getActiveOperationByContainerName: mockGetActiveOperationByContainerName,
@@ -23,9 +32,11 @@ describe('enrichContainerLifecyclePayloadWithEligibility', () => {
mockGetState.mockClear();
mockGetActiveOperationByContainerId.mockClear();
mockGetActiveOperationByContainerName.mockClear();
+ mockGetAgent.mockClear();
mockGetState.mockReturnValue({ trigger: {}, watcher: {} });
mockGetActiveOperationByContainerId.mockReturnValue(undefined);
mockGetActiveOperationByContainerName.mockReturnValue(undefined);
+ mockGetAgent.mockReturnValue(undefined);
});
describe('malformed payload guard', () => {
@@ -336,4 +347,82 @@ describe('enrichContainerLifecyclePayloadWithEligibility', () => {
).toBe(true);
});
});
+
+ describe('agent-mismatch severity during registration window (#605)', () => {
+ function mismatchedDockerTrigger() {
+ return {
+ type: 'docker',
+ agent: 'agent-a',
+ configuration: { threshold: 'all' },
+ getId: () => 'docker.update',
+ isTriggerIncluded: () => true,
+ isTriggerExcluded: () => false,
+ };
+ }
+
+ const updatePayload = (): any => ({
+ id: 'c1',
+ name: 'mysql',
+ image: { tag: { value: '9.6.0' } },
+ result: { tag: '9.7.0' },
+ });
+
+ test('downgrades to soft when the container agent is still completing registration', () => {
+ mockGetState.mockReturnValueOnce({
+ trigger: { 'docker.update': mismatchedDockerTrigger() },
+ watcher: {},
+ });
+ mockGetAgent.mockReturnValueOnce({ isRegisteringComponents: true });
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const result = enrichContainerLifecyclePayloadWithEligibility({
+ ...updatePayload(),
+ agent: 'agent-b',
+ }) as any;
+
+ const blocker = result.updateEligibility.blockers.find(
+ (b: { reason: string }) => b.reason === 'agent-mismatch',
+ );
+ expect(blocker).toBeDefined();
+ expect(blocker.severity).toBe('soft');
+ expect(mockGetAgent).toHaveBeenCalledWith('agent-b');
+ });
+
+ test('stays hard when the agent is not pending registration', () => {
+ mockGetState.mockReturnValueOnce({
+ trigger: { 'docker.update': mismatchedDockerTrigger() },
+ watcher: {},
+ });
+ mockGetAgent.mockReturnValueOnce(undefined);
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const result = enrichContainerLifecyclePayloadWithEligibility({
+ ...updatePayload(),
+ agent: 'agent-b',
+ }) as any;
+
+ const blocker = result.updateEligibility.blockers.find(
+ (b: { reason: string }) => b.reason === 'agent-mismatch',
+ );
+ expect(blocker).toBeDefined();
+ expect(blocker.severity).toBe('hard');
+ });
+
+ test('falls back to an empty agent name when the container has no agent', () => {
+ mockGetState.mockReturnValueOnce({
+ trigger: { 'docker.update': mismatchedDockerTrigger() },
+ watcher: {},
+ });
+ mockGetAgent.mockReturnValueOnce(undefined);
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const result = enrichContainerLifecyclePayloadWithEligibility(updatePayload()) as any;
+
+ const blocker = result.updateEligibility.blockers.find(
+ (b: { reason: string }) => b.reason === 'agent-mismatch',
+ );
+ expect(blocker).toBeDefined();
+ expect(mockGetAgent).toHaveBeenCalledWith('');
+ });
+ });
});
diff --git a/app/api/sse-container-enrichment.ts b/app/api/sse-container-enrichment.ts
index 0af942311..d8f44fc10 100644
--- a/app/api/sse-container-enrichment.ts
+++ b/app/api/sse-container-enrichment.ts
@@ -1,3 +1,4 @@
+import { getAgent } from '../agent/manager.js';
import type { ContainerLifecycleEventPayload } from '../event/index.js';
import type { Container } from '../model/container.js';
import {
@@ -18,6 +19,8 @@ function buildEligibilityContext(container: Container): UpdateEligibilityContext
triggers: registryState.trigger,
isSelfUpdateAvailable: isSelfUpdateAvailable(container),
maintenanceWindowOpen: getContainerMaintenanceWindowOpen(container, registryState.watcher),
+ isAgentPendingRegistration: (agentName) =>
+ getAgent(agentName ?? '')?.isRegisteringComponents === true,
getActiveOperation: (c: Container) => {
const byId = getActiveOperationByContainerId(c.id);
// Scoped by agent+watcher so cross-agent same-named ops don't pollute enrichment (issue #411).
diff --git a/app/api/ws-upgrade-utils.test.ts b/app/api/ws-upgrade-utils.test.ts
index f70199fa4..966b1f314 100644
--- a/app/api/ws-upgrade-utils.test.ts
+++ b/app/api/ws-upgrade-utils.test.ts
@@ -336,6 +336,16 @@ describe('ws-upgrade-utils', () => {
const request = {} as any;
expect(isAuthenticatedSession(request)).toBe(false);
});
+
+ test('returns true when anonymousAuthActive is true even without a passport user', () => {
+ const request = { session: { passport: {} } } as any;
+ expect(isAuthenticatedSession(request, { anonymousAuthActive: true })).toBe(true);
+ });
+
+ test('returns false when anonymousAuthActive is false and passport user is missing', () => {
+ const request = { session: { passport: {} } } as any;
+ expect(isAuthenticatedSession(request, { anonymousAuthActive: false })).toBe(false);
+ });
});
describe('getDefaultRateLimitKey', () => {
diff --git a/app/api/ws-upgrade-utils.ts b/app/api/ws-upgrade-utils.ts
index d463eb6fa..fc91fe343 100644
--- a/app/api/ws-upgrade-utils.ts
+++ b/app/api/ws-upgrade-utils.ts
@@ -152,9 +152,17 @@ export async function applySessionMiddleware(
});
}
-export function isAuthenticatedSession(request: UpgradeRequest): boolean {
+export interface IsAuthenticatedSessionOptions {
+ anonymousAuthActive?: boolean;
+}
+
+export function isAuthenticatedSession(
+ request: UpgradeRequest,
+ options: IsAuthenticatedSessionOptions = {},
+): boolean {
+ const { anonymousAuthActive = false } = options;
const passportSession = request.session?.passport;
- return passportSession?.user !== undefined;
+ return passportSession?.user !== undefined || anonymousAuthActive;
}
export function getDefaultRateLimitKey(request: UpgradeRequest): string {
diff --git a/app/model/container.test.ts b/app/model/container.test.ts
index 40710d04a..9c7417a66 100644
--- a/app/model/container.test.ts
+++ b/app/model/container.test.ts
@@ -1878,6 +1878,57 @@ test('model should use DD_UI_MATURITY_THRESHOLD_DAYS for hot/mature cutoff', asy
}
});
+test('model should use per-container updatePolicy.maturityMinAgeDays over DD_UI_MATURITY_THRESHOLD_DAYS for hot/mature cutoff', async () => {
+ const previousThreshold = process.env.DD_UI_MATURITY_THRESHOLD_DAYS;
+ vi.useFakeTimers();
+ try {
+ process.env.DD_UI_MATURITY_THRESHOLD_DAYS = '3';
+ const now = new Date('2026-03-15T12:00:00.000Z');
+ vi.setSystemTime(now);
+ const firstSeenAt = new Date(now.getTime() - daysToMs(10)).toISOString();
+
+ const containerValidated = container.validate({
+ id: 'container-123456789',
+ name: 'test',
+ watcher: 'test',
+ firstSeenAt,
+ updatePolicy: { maturityMinAgeDays: 30 },
+ image: {
+ id: 'image-123456789',
+ registry: {
+ name: 'hub',
+ url: 'https://hub',
+ },
+ name: 'organization/image',
+ tag: {
+ value: '1.0.0',
+ semver: true,
+ },
+ digest: {
+ watch: false,
+ repo: undefined,
+ },
+ architecture: 'arch',
+ os: 'os',
+ created: '2021-06-12T05:33:38.440Z',
+ },
+ result: {
+ tag: '1.0.1',
+ },
+ });
+
+ expect(containerValidated.updateAge).toBe(daysToMs(10));
+ expect(containerValidated.updateMaturityLevel).toBe('hot');
+ } finally {
+ vi.useRealTimers();
+ if (previousThreshold === undefined) {
+ delete process.env.DD_UI_MATURITY_THRESHOLD_DAYS;
+ } else {
+ process.env.DD_UI_MATURITY_THRESHOLD_DAYS = previousThreshold;
+ }
+ }
+});
+
test('model should keep updateAvailable when remote tag changes past skipped value', async () => {
const containerValidated = container.validate({
id: 'container-123456789',
diff --git a/app/model/container.ts b/app/model/container.ts
index cfb6e3ed4..0c8586371 100644
--- a/app/model/container.ts
+++ b/app/model/container.ts
@@ -749,7 +749,10 @@ function getRawUpdateMaturityLevel(
return 'established';
}
- const maturityThresholdDays = resolveUiMaturityThresholdDays();
+ const maturityThresholdDays = resolveMaturityMinAgeDays(
+ container.updatePolicy?.maturityMinAgeDays,
+ resolveUiMaturityThresholdDays(),
+ );
const maturityThresholdMs = maturityMinAgeDaysToMilliseconds(maturityThresholdDays);
return updateAge >= maturityThresholdMs ? 'mature' : 'hot';
}
diff --git a/app/model/update-eligibility.test.ts b/app/model/update-eligibility.test.ts
index 0206c11f4..f25196b05 100644
--- a/app/model/update-eligibility.test.ts
+++ b/app/model/update-eligibility.test.ts
@@ -1006,6 +1006,72 @@ describe('computeUpdateEligibility', () => {
const blocker = result.blockers.find((b) => b.reason === 'no-update-trigger-configured');
expect(blocker).toBeDefined();
});
+
+ describe('severity during the trigger registration window (#605)', () => {
+ test('downgrades to soft when container is agent-owned and its agent is pending registration', () => {
+ const container = makeContainerWithTagUpdate({ agent: 'agent-b' });
+ const isAgentPendingRegistration = vi.fn().mockReturnValue(true);
+ const result = computeUpdateEligibility(
+ container,
+ makeContext({
+ triggers: undefined,
+ now: FIXED_NOW,
+ isAgentPendingRegistration,
+ }),
+ );
+ const blocker = result.blockers.find((b) => b.reason === 'no-update-trigger-configured');
+ expect(blocker).toBeDefined();
+ expect(blocker?.severity).toBe('soft');
+ expect(isAgentPendingRegistration).toHaveBeenCalledWith('agent-b');
+ });
+
+ test('stays hard when container is agent-owned but its agent is not pending registration', () => {
+ const container = makeContainerWithTagUpdate({ agent: 'agent-b' });
+ const isAgentPendingRegistration = vi.fn().mockReturnValue(false);
+ const result = computeUpdateEligibility(
+ container,
+ makeContext({
+ triggers: undefined,
+ now: FIXED_NOW,
+ isAgentPendingRegistration,
+ }),
+ );
+ const blocker = result.blockers.find((b) => b.reason === 'no-update-trigger-configured');
+ expect(blocker).toBeDefined();
+ expect(blocker?.severity).toBe('hard');
+ });
+
+ test('stays hard for non-agent containers even when isAgentPendingRegistration would return true', () => {
+ const container = makeContainerWithTagUpdate(); // no agent property
+ const isAgentPendingRegistration = vi.fn().mockReturnValue(true);
+ const result = computeUpdateEligibility(
+ container,
+ makeContext({
+ triggers: undefined,
+ now: FIXED_NOW,
+ isAgentPendingRegistration,
+ }),
+ );
+ const blocker = result.blockers.find((b) => b.reason === 'no-update-trigger-configured');
+ expect(blocker).toBeDefined();
+ expect(blocker?.severity).toBe('hard');
+ expect(isAgentPendingRegistration).not.toHaveBeenCalled();
+ });
+
+ test('stays hard for agent-owned containers when no isAgentPendingRegistration callback is supplied', () => {
+ const container = makeContainerWithTagUpdate({ agent: 'agent-b' });
+ const result = computeUpdateEligibility(
+ container,
+ makeContext({
+ triggers: undefined,
+ now: FIXED_NOW,
+ }),
+ );
+ const blocker = result.blockers.find((b) => b.reason === 'no-update-trigger-configured');
+ expect(blocker).toBeDefined();
+ expect(blocker?.severity).toBe('hard');
+ });
+ });
});
describe('threshold-not-reached', () => {
@@ -1381,6 +1447,58 @@ describe('computeUpdateEligibility', () => {
);
expect(result.blockers.find((b) => b.reason === 'agent-mismatch')).toBeUndefined();
});
+
+ describe('severity during the trigger registration window (#605)', () => {
+ test('downgrades to soft when isAgentPendingRegistration returns true for the container agent', () => {
+ const trigger = makeTrigger({ agent: 'agent-a' });
+ const container = makeContainerWithTagUpdate({ agent: 'agent-b' });
+ const isAgentPendingRegistration = vi.fn().mockReturnValue(true);
+ const result = computeUpdateEligibility(
+ container,
+ makeContext({
+ triggers: { 'docker.update': trigger as never },
+ now: FIXED_NOW,
+ isAgentPendingRegistration,
+ }),
+ );
+ const blocker = result.blockers.find((b) => b.reason === 'agent-mismatch');
+ expect(blocker).toBeDefined();
+ expect(blocker?.severity).toBe('soft');
+ expect(isAgentPendingRegistration).toHaveBeenCalledWith('agent-b');
+ });
+
+ test('stays hard when isAgentPendingRegistration returns false for the container agent', () => {
+ const trigger = makeTrigger({ agent: 'agent-a' });
+ const container = makeContainerWithTagUpdate({ agent: 'agent-b' });
+ const isAgentPendingRegistration = vi.fn().mockReturnValue(false);
+ const result = computeUpdateEligibility(
+ container,
+ makeContext({
+ triggers: { 'docker.update': trigger as never },
+ now: FIXED_NOW,
+ isAgentPendingRegistration,
+ }),
+ );
+ const blocker = result.blockers.find((b) => b.reason === 'agent-mismatch');
+ expect(blocker).toBeDefined();
+ expect(blocker?.severity).toBe('hard');
+ });
+
+ test('stays hard when no isAgentPendingRegistration callback is supplied on the context', () => {
+ const trigger = makeTrigger({ agent: 'agent-a' });
+ const container = makeContainerWithTagUpdate({ agent: 'agent-b' });
+ const result = computeUpdateEligibility(
+ container,
+ makeContext({
+ triggers: { 'docker.update': trigger as never },
+ now: FIXED_NOW,
+ }),
+ );
+ const blocker = result.blockers.find((b) => b.reason === 'agent-mismatch');
+ expect(blocker).toBeDefined();
+ expect(blocker?.severity).toBe('hard');
+ });
+ });
});
describe('active-operation', () => {
diff --git a/app/model/update-eligibility.ts b/app/model/update-eligibility.ts
index 697ba850a..7aeebc6fd 100644
--- a/app/model/update-eligibility.ts
+++ b/app/model/update-eligibility.ts
@@ -106,8 +106,11 @@ function updateScanMatchesCandidate(container: Container, updateScan: UpdateSecu
);
}
-function makeBlocker(blocker: Omit): UpdateBlocker {
- return { ...blocker, severity: BLOCKER_SEVERITY[blocker.reason] };
+function makeBlocker(
+ blocker: Omit,
+ severityOverride?: UpdateBlockerSeverity,
+): UpdateBlocker {
+ return { ...blocker, severity: severityOverride ?? BLOCKER_SEVERITY[blocker.reason] };
}
export interface UpdateEligibility {
@@ -134,6 +137,20 @@ export interface UpdateEligibilityContext {
* eligibility model. Manual UI/API update requests leave it undefined and are never gated by it.
*/
maintenanceWindowOpen?: boolean;
+ /**
+ * Optional. Called with the container's own agent name when the `agent-mismatch` or
+ * `no-update-trigger-configured` branch is about to fire. Returning `true` (e.g. because
+ * the agent's client is mid-registration, per `AgentClient.isRegisteringComponents`)
+ * downgrades that blocker to `soft` instead of the reason's default `hard` severity, so the
+ * transient window between `AgentClient._doHandshake()` deregistering an agent's components
+ * and finishing their re-registration doesn't disable manual updates on display surfaces.
+ *
+ * This only softens *display* eligibility (container list, SSE enrichment). Admission
+ * (`app/updates/request-update.ts`) never wires this callback in, so a hard agent-mismatch
+ * always blocks the actual update request — an update can never be enqueued through a
+ * wrong-agent trigger during the registration window. See issue #605.
+ */
+ isAgentPendingRegistration?: (agentName: string | undefined) => boolean;
}
/**
@@ -442,32 +459,45 @@ export function computeUpdateEligibility(
);
if (!typeOnlyTrigger) {
- // 11. no-update-trigger-configured — no docker/dockercompose trigger exists at all
+ // 11. no-update-trigger-configured — no docker/dockercompose trigger exists at all.
+ // AgentClient._doHandshake() deregisters an agent's components before re-registering,
+ // so an agent-owned container can transiently see zero triggers of any kind during that
+ // window too. Apply the same #605 downgrade as agent-mismatch below.
+ const isPendingRegistration = container.agent
+ ? (context.isAgentPendingRegistration?.(container.agent) ?? false)
+ : false;
blockers.push(
- makeBlocker({
- reason: 'no-update-trigger-configured',
- message: 'No docker or dockercompose action trigger is configured for this container.',
- actionable: true,
- actionHint: 'Configure `DD_ACTION_DOCKER_*` or `DD_ACTION_DOCKERCOMPOSE_*`.',
- }),
+ makeBlocker(
+ {
+ reason: 'no-update-trigger-configured',
+ message: 'No docker or dockercompose action trigger is configured for this container.',
+ actionable: true,
+ actionHint: 'Configure `DD_ACTION_DOCKER_*` or `DD_ACTION_DOCKERCOMPOSE_*`.',
+ },
+ isPendingRegistration ? 'soft' : undefined,
+ ),
);
} else if (!candidateTrigger) {
// A docker trigger exists but it's not compatible with this container's agent.
// 10. agent-mismatch (detected here because full lookup failed but type-only succeeded)
const t = typeOnlyTrigger;
const triggerAgent = t.agent;
+ const isPendingRegistration = context.isAgentPendingRegistration?.(container.agent) ?? false;
blockers.push(
- makeBlocker({
- reason: 'agent-mismatch',
- message: `Update trigger runs on agent '${triggerAgent ?? ''}'; container is on agent '${container.agent ?? ''}'.`,
- actionable: true,
- actionHint: 'Configure an update trigger for the target agent.',
- details: {
- triggerAgent,
- containerAgent: container.agent,
- triggerId: t.getId?.(),
+ makeBlocker(
+ {
+ reason: 'agent-mismatch',
+ message: `Update trigger runs on agent '${triggerAgent ?? ''}'; container is on agent '${container.agent ?? ''}'.`,
+ actionable: true,
+ actionHint: 'Configure an update trigger for the target agent.',
+ details: {
+ triggerAgent,
+ containerAgent: container.agent,
+ triggerId: t.getId?.(),
+ },
},
- }),
+ isPendingRegistration ? 'soft' : undefined,
+ ),
);
} else {
const t = candidateTrigger;
diff --git a/app/package-lock.json b/app/package-lock.json
index a937f6aae..4f2261c23 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -3737,9 +3737,9 @@
"license": "MIT"
},
"node_modules/brace-expansion": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
- "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4798,9 +4798,9 @@
}
},
"node_modules/fast-uri": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-4.1.1.tgz",
- "integrity": "sha512-YPOs1zD5TG2+EZt+r88LwF6mclA7TPkpwMP7ZN3TO2HiHS8TXvq7QA/17iJsV9dubcLo/f8eEYqMBruyQV21hQ==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-4.1.2.tgz",
+ "integrity": "sha512-TyGmBcbDTZXcb2cj5MV89DrF42DKvb3y5DDUNh95iO+IMeAzMkVSxK1PZRrRIpc9yg8U2GhGdbofNa0LS/a4Bw==",
"funding": [
{
"type": "github",
@@ -5396,9 +5396,9 @@
"license": "ISC"
},
"node_modules/ip-address": {
- "version": "10.2.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
- "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
+ "version": "10.3.1",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.3.1.tgz",
+ "integrity": "sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==",
"license": "MIT",
"engines": {
"node": ">= 12"
diff --git a/app/package.json b/app/package.json
index b51c1c5d0..fb5cee5e8 100644
--- a/app/package.json
+++ b/app/package.json
@@ -74,8 +74,10 @@
"overrides": {
"axios": "1.18.1",
"body-parser": "2.3.0",
- "fast-uri": "4.1.1",
+ "brace-expansion": "5.0.9",
+ "fast-uri": "4.1.2",
"fast-xml-parser": "5.10.1",
+ "ip-address": "10.3.1",
"picomatch": "4.0.5",
"postcss": "8.5.24",
"qs": "6.15.3",
diff --git a/app/registry/index.test.ts b/app/registry/index.test.ts
index d18064910..868720fea 100644
--- a/app/registry/index.test.ts
+++ b/app/registry/index.test.ts
@@ -765,6 +765,7 @@ test('registerAuthentications should register anonymous auth when confirmation i
mockIsUpgrade.mockReturnValue(false);
await registry.testable_registerAuthentications();
expect(Object.keys(registry.getState().authentication)).toEqual(['anonymous.anonymous']);
+ expect(registry.isAnonymousAuthenticationActive()).toBe(true);
} finally {
if (previousAnonymousConfirmation === undefined) {
delete process.env.DD_ANONYMOUS_AUTH_CONFIRM;
@@ -774,6 +775,19 @@ test('registerAuthentications should register anonymous auth when confirmation i
}
});
+test('isAnonymousAuthenticationActive should return false when no anonymous strategy is registered', async () => {
+ authentications = {
+ basic: {
+ john: {
+ user: 'john',
+ hash: TEST_BASIC_HASH,
+ },
+ },
+ };
+ await registry.testable_registerAuthentications();
+ expect(registry.isAnonymousAuthenticationActive()).toBe(false);
+});
+
test('registerAuthentications should fallback to anonymous when all configured providers fail and confirmation is enabled', async () => {
const previousAnonymousConfirmation = process.env.DD_ANONYMOUS_AUTH_CONFIRM;
process.env.DD_ANONYMOUS_AUTH_CONFIRM = 'true';
diff --git a/app/registry/index.ts b/app/registry/index.ts
index b04d92823..29cf8ed3a 100644
--- a/app/registry/index.ts
+++ b/app/registry/index.ts
@@ -112,6 +112,17 @@ export function getAuthenticationRegistrationErrors(): AuthenticationRegistratio
return [...authenticationRegistrationErrors];
}
+/**
+ * Returns true when the registered authentication state contains a strategy
+ * whose description type is 'anonymous', i.e. anonymous authentication is
+ * the configured (and confirmed) auth mode.
+ */
+export function isAnonymousAuthenticationActive(): boolean {
+ return Object.values(state.authentication).some(
+ (authentication) => authentication.getStrategyDescription().type === 'anonymous',
+ );
+}
+
function addComponentToState(kind: ComponentKind, component: Component) {
const components = state[kind] as Record;
components[component.getId()] = component;
diff --git a/app/updates/request-update.test.ts b/app/updates/request-update.test.ts
index 2eb9a9c26..09ea0b33b 100644
--- a/app/updates/request-update.test.ts
+++ b/app/updates/request-update.test.ts
@@ -12,18 +12,29 @@ const {
mockLogWarn,
mockStatSync,
mockGetUpdateMode,
-} = vi.hoisted(() => ({
- mockGetOperationById: vi.fn(),
- mockGetActiveOperationByContainerId: vi.fn(),
- mockGetActiveOperationByContainerName: vi.fn(),
- mockGetRecentTerminalSucceededOperationByContainerName: vi.fn(() => undefined),
- mockHasOtherActiveOperationByContainerName: vi.fn(() => false),
- mockInsertOperation: vi.fn(),
- mockMarkOperationTerminal: vi.fn(),
- mockGetState: vi.fn(() => ({ trigger: {}, watcher: {} })),
- mockLogWarn: vi.fn(),
- mockStatSync: vi.fn(() => ({ isSocket: () => false })),
- mockGetUpdateMode: vi.fn(() => 'auto' as const),
+ mockGetAgent,
+ agentFixture,
+} = vi.hoisted(() => {
+ const agentFixture = { name: 'edge-2', isRegisteringComponents: false };
+ return {
+ mockGetOperationById: vi.fn(),
+ mockGetActiveOperationByContainerId: vi.fn(),
+ mockGetActiveOperationByContainerName: vi.fn(),
+ mockGetRecentTerminalSucceededOperationByContainerName: vi.fn(() => undefined),
+ mockHasOtherActiveOperationByContainerName: vi.fn(() => false),
+ mockInsertOperation: vi.fn(),
+ mockMarkOperationTerminal: vi.fn(),
+ mockGetState: vi.fn(() => ({ trigger: {}, watcher: {} })),
+ mockLogWarn: vi.fn(),
+ mockStatSync: vi.fn(() => ({ isSocket: () => false })),
+ mockGetUpdateMode: vi.fn(() => 'auto' as const),
+ mockGetAgent: vi.fn(),
+ agentFixture,
+ };
+});
+
+vi.mock('../agent/manager.js', () => ({
+ getAgent: mockGetAgent,
}));
vi.mock('../store/settings.js', () => ({
@@ -106,6 +117,8 @@ describe('request-update', () => {
mockGetState.mockReturnValue({ trigger: {}, watcher: {} });
mockStatSync.mockReturnValue({ isSocket: () => false });
mockGetUpdateMode.mockReturnValue('auto');
+ agentFixture.isRegisteringComponents = false;
+ mockGetAgent.mockReturnValue(undefined);
mockInsertOperation.mockImplementation((operation) => ({
id: operation.id || 'op-1',
...operation,
@@ -877,6 +890,31 @@ describe('request-update', () => {
});
});
+ test('stays a hard agent-mismatch rejection even when the agent is still completing registration (#605)', async () => {
+ agentFixture.isRegisteringComponents = true;
+ mockGetAgent.mockImplementation((name) =>
+ name === agentFixture.name ? agentFixture : undefined,
+ );
+ const trigger = {
+ type: 'docker',
+ trigger: vi.fn(),
+ agent: 'edge-1',
+ configuration: { threshold: 'all' },
+ getId: () => 'docker.update',
+ isTriggerIncluded: () => true,
+ isTriggerExcluded: () => false,
+ };
+ mockGetState.mockReturnValue({ trigger: { 'docker.update': trigger } });
+
+ await expect(
+ enqueueContainerUpdate(createContainerWithRawUpdate({ agent: 'edge-2' })),
+ ).rejects.toMatchObject>({
+ statusCode: 404,
+ message: expect.stringContaining("Update trigger runs on agent 'edge-1'"),
+ });
+ expect(mockGetAgent).not.toHaveBeenCalled();
+ });
+
test('rejects with 409 when self-update-unavailable blocker fires (drydock self-container, socket absent)', async () => {
const trigger = {
type: 'docker',
diff --git a/app/updates/request-update.ts b/app/updates/request-update.ts
index a6c9b4f56..69b1f8910 100644
--- a/app/updates/request-update.ts
+++ b/app/updates/request-update.ts
@@ -292,6 +292,12 @@ function prepareContainerUpdateRequest(
//
// The raw-candidate check above is the source of truth for "an update exists"
// when a soft gate deliberately makes updateAvailable false.
+ //
+ // isAgentPendingRegistration is deliberately NOT wired in here. That softening
+ // exists only for display surfaces (container list, SSE enrichment) — admission
+ // stays hard/fail-closed so a hard agent-mismatch can never be bypassed to enqueue
+ // an update through a wrong-agent trigger during the component re-registration
+ // window. See issue #605.
const eligibility = computeUpdateEligibility(container, {
triggers: registry.getState().trigger,
getActiveOperation: () => undefined,
diff --git a/app/watchers/providers/docker/Docker.containers.labels-version-finding.test.ts b/app/watchers/providers/docker/Docker.containers.labels-version-finding.test.ts
index 01a631b76..f1533dc92 100644
--- a/app/watchers/providers/docker/Docker.containers.labels-version-finding.test.ts
+++ b/app/watchers/providers/docker/Docker.containers.labels-version-finding.test.ts
@@ -257,7 +257,7 @@ describe('Docker Watcher', () => {
const result = await docker.findNewVersion(container, mockLogChild);
expect(result).toEqual({ tag: '1.0.0' });
- expect(mockLogChild.debug).toHaveBeenCalledWith(
+ expect(mockLogChild.warn).toHaveBeenCalledWith(
expect.stringContaining('publish date lookup failed'),
);
});
diff --git a/app/watchers/providers/docker/Docker.containers.test.ts b/app/watchers/providers/docker/Docker.containers.test.ts
index 525f65836..1f83839b9 100644
--- a/app/watchers/providers/docker/Docker.containers.test.ts
+++ b/app/watchers/providers/docker/Docker.containers.test.ts
@@ -1085,7 +1085,7 @@ describe('Docker Watcher', () => {
const result = await docker.findNewVersion(container, mockLogChild);
expect(result).toEqual({ tag: '1.0.0' });
- expect(mockLogChild.debug).toHaveBeenCalledWith(
+ expect(mockLogChild.warn).toHaveBeenCalledWith(
expect.stringContaining('publish date lookup failed'),
);
});
diff --git a/app/watchers/providers/docker/image-comparison.test.ts b/app/watchers/providers/docker/image-comparison.test.ts
index 429ccf6bb..90edf9c50 100644
--- a/app/watchers/providers/docker/image-comparison.test.ts
+++ b/app/watchers/providers/docker/image-comparison.test.ts
@@ -419,7 +419,28 @@ describe('image-comparison', () => {
expect(result.publishedAt).toBeUndefined();
expect(result.publishedAtTrusted).toBeUndefined();
expect(result.digest).toBe('sha256:def456');
- expect(log.debug).toHaveBeenCalledWith(expect.stringContaining('registry timeout'));
+ expect(log.warn).toHaveBeenCalledWith(expect.stringContaining('registry timeout'));
+ });
+
+ test('digest-only with comparisonTag continues when getImagePublishedAt throws and logContainer.warn is absent', async () => {
+ mockGetState.mockReturnValue({
+ registry: {
+ hub: {
+ getTags: vi.fn().mockResolvedValue(['latest']),
+ getImageManifestDigest: createManifestLookup(),
+ normalizeImage: identityNormalizeImage,
+ getImagePublishedAt: vi.fn().mockRejectedValue(new Error('timeout')),
+ },
+ },
+ });
+ const log = { error: vi.fn(), debug: vi.fn() } as unknown as Parameters<
+ typeof findNewVersion
+ >[1];
+
+ const result = await findNewVersion(createDigestOnlyContainer() as never, log);
+
+ expect(result.publishedAt).toBeUndefined();
+ expect(result.digest).toBe('sha256:def456');
});
test('digest-only with comparisonTag does not set publishedAt when getImagePublishedAt returns non-string', async () => {
@@ -808,7 +829,7 @@ describe('image-comparison', () => {
expect(result.publishedAtTrusted).toBeUndefined();
});
- test('logs debug and continues when getImagePublishedAt throws', async () => {
+ test('logs warn and continues when getImagePublishedAt throws', async () => {
mockGetState.mockReturnValue({
registry: {
hub: {
@@ -819,8 +840,35 @@ describe('image-comparison', () => {
},
},
});
- const debugFn = vi.fn();
- const log = { error: vi.fn(), warn: vi.fn(), debug: debugFn };
+ const warnFn = vi.fn();
+ const log = { error: vi.fn(), warn: warnFn, debug: vi.fn() };
+ const container = {
+ image: {
+ id: 'image-1',
+ registry: { name: 'hub' },
+ name: 'library/nginx',
+ tag: { value: '1.0.0', semver: false },
+ digest: { watch: false },
+ },
+ };
+ const result = await findNewVersion(container as never, log);
+ expect(result.publishedAt).toBeUndefined();
+ expect(warnFn).toHaveBeenCalledWith(expect.stringContaining('API error'));
+ });
+
+ test('logs warn on registry auth failure so it is not silently swallowed', async () => {
+ mockGetState.mockReturnValue({
+ registry: {
+ hub: {
+ getTags: vi.fn().mockResolvedValue(['1.1.0']),
+ getImageManifestDigest: createManifestLookup(),
+ normalizeImage: identityNormalizeImage,
+ getImagePublishedAt: vi.fn().mockRejectedValue(new Error('401 Unauthorized')),
+ },
+ },
+ });
+ const warnFn = vi.fn();
+ const log = { error: vi.fn(), warn: warnFn, debug: vi.fn() };
const container = {
image: {
id: 'image-1',
@@ -832,10 +880,10 @@ describe('image-comparison', () => {
};
const result = await findNewVersion(container as never, log);
expect(result.publishedAt).toBeUndefined();
- expect(debugFn).toHaveBeenCalledWith(expect.stringContaining('API error'));
+ expect(warnFn).toHaveBeenCalledWith(expect.stringContaining('401 Unauthorized'));
});
- test('continues silently when getImagePublishedAt throws and logContainer.debug is absent', async () => {
+ test('continues silently when getImagePublishedAt throws and logContainer.warn is absent', async () => {
mockGetState.mockReturnValue({
registry: {
hub: {
@@ -846,8 +894,8 @@ describe('image-comparison', () => {
},
},
});
- // Intentionally omit debug from log to exercise the false branch of typeof logContainer.debug
- const log = { error: vi.fn(), warn: vi.fn() } as unknown as Parameters<
+ // Intentionally omit warn from log to exercise the false branch of typeof logContainer.warn
+ const log = { error: vi.fn(), debug: vi.fn() } as unknown as Parameters<
typeof findNewVersion
>[1];
const container = {
diff --git a/app/watchers/providers/docker/image-comparison.ts b/app/watchers/providers/docker/image-comparison.ts
index 4d5131431..7db9f23c8 100644
--- a/app/watchers/providers/docker/image-comparison.ts
+++ b/app/watchers/providers/docker/image-comparison.ts
@@ -339,7 +339,9 @@ export async function findNewVersion(
}
}
} catch (error: unknown) {
- logContainer.debug(`Remote publish date lookup failed (${getErrorMessage(error)})`);
+ if (typeof logContainer.warn === 'function') {
+ logContainer.warn(`Remote publish date lookup failed (${getErrorMessage(error)})`);
+ }
}
} else {
logContainer.debug('Digest-only image — no registry tag candidate available');
@@ -423,8 +425,8 @@ export async function findNewVersion(
}
}
} catch (error: unknown) {
- if (typeof logContainer.debug === 'function') {
- logContainer.debug(`Remote publish date lookup failed (${getErrorMessage(error)})`);
+ if (typeof logContainer.warn === 'function') {
+ logContainer.warn(`Remote publish date lookup failed (${getErrorMessage(error)})`);
}
}
diff --git a/apps/demo/package-lock.json b/apps/demo/package-lock.json
index cd082a001..510e47273 100644
--- a/apps/demo/package-lock.json
+++ b/apps/demo/package-lock.json
@@ -24,9 +24,9 @@
"@iconify-json/fa6-solid": "1.2.4",
"@iconify-json/heroicons": "1.2.3",
"@iconify-json/iconoir": "1.2.11",
- "@iconify-json/lucide": "1.2.119",
+ "@iconify-json/lucide": "1.2.121",
"@iconify-json/ph": "1.2.2",
- "@iconify-json/tabler": "1.2.37",
+ "@iconify-json/tabler": "1.2.38",
"@tailwindcss/vite": "4.3.3",
"@types/node": "25.9.5",
"@vitejs/plugin-vue": "6.0.8",
@@ -650,9 +650,9 @@
}
},
"node_modules/@iconify-json/lucide": {
- "version": "1.2.119",
- "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.119.tgz",
- "integrity": "sha512-KbrC7fT5wPshV1KLRM0k91poP0OH4eKEVywEOH0FCczKb+qth8Pcq1Hy9kS2tXeF52s23qzLnG8AJsExPSupeA==",
+ "version": "1.2.121",
+ "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.121.tgz",
+ "integrity": "sha512-zSoQQSmsyFaeTpSwURHJ9PIrsDcGFpDNhGlpiTrs+Ua4uFeH5UsE26L4OEBLrgLWoSK0UO+JhsO8yehSw0403g==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -670,9 +670,9 @@
}
},
"node_modules/@iconify-json/tabler": {
- "version": "1.2.37",
- "resolved": "https://registry.npmjs.org/@iconify-json/tabler/-/tabler-1.2.37.tgz",
- "integrity": "sha512-tXc0jGhrxec6eTKxMI9We/r3cEItyU5dG8ngDOEKsL36a6+/xwk4sR7PIZROVajzxmvyUBsn659adDIfcswiUw==",
+ "version": "1.2.38",
+ "resolved": "https://registry.npmjs.org/@iconify-json/tabler/-/tabler-1.2.38.tgz",
+ "integrity": "sha512-9v6ooRU/bKOK/Whv4w2aiK5gBnfCV9Ei+uD1iDDeLu2b+EnF3G3ZKkRKWEOOLG8bJyfKn6XEia6gUQ9oO7cF+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2846,9 +2846,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.23",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz",
- "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==",
+ "version": "8.5.25",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
+ "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
"funding": [
{
"type": "opencollective",
diff --git a/apps/demo/package.json b/apps/demo/package.json
index 1e2834a31..9cc4040f3 100644
--- a/apps/demo/package.json
+++ b/apps/demo/package.json
@@ -27,9 +27,9 @@
"@iconify-json/fa6-solid": "1.2.4",
"@iconify-json/heroicons": "1.2.3",
"@iconify-json/iconoir": "1.2.11",
- "@iconify-json/lucide": "1.2.119",
+ "@iconify-json/lucide": "1.2.121",
"@iconify-json/ph": "1.2.2",
- "@iconify-json/tabler": "1.2.37",
+ "@iconify-json/tabler": "1.2.38",
"@tailwindcss/vite": "4.3.3",
"@types/node": "25.9.5",
"@vitejs/plugin-vue": "6.0.8",
@@ -38,7 +38,7 @@
"vitest": "4.1.10"
},
"overrides": {
- "postcss": "8.5.23",
+ "postcss": "8.5.25",
"yaml": "2.9.0",
"esbuild": "0.28.1"
},
diff --git a/apps/demo/src/mocks/data/agents.ts b/apps/demo/src/mocks/data/agents.ts
index 3c70dc8a5..5e30b6425 100644
--- a/apps/demo/src/mocks/data/agents.ts
+++ b/apps/demo/src/mocks/data/agents.ts
@@ -4,7 +4,7 @@ export const agents = [
host: '192.168.1.50',
port: 3001,
connected: true,
- version: '1.6.0-rc.11',
+ version: '1.6.0-rc.12',
os: 'linux',
arch: 'amd64',
cpus: 4,
diff --git a/apps/demo/src/mocks/data/audit.ts b/apps/demo/src/mocks/data/audit.ts
index b4935a92f..dc58412f4 100644
--- a/apps/demo/src/mocks/data/audit.ts
+++ b/apps/demo/src/mocks/data/audit.ts
@@ -3,7 +3,7 @@ export const auditEntries = [
id: 'aud-001',
timestamp: '2026-03-10T08:00:00.000Z',
action: 'system:start',
- details: 'Drydock v1.6.0-rc.11 started',
+ details: 'Drydock v1.6.0-rc.12 started',
},
{
id: 'aud-002',
@@ -207,6 +207,6 @@ export const auditEntries = [
timestamp: '2026-03-03T18:00:00.000Z',
action: 'container:watch',
container: 'drydock',
- details: 'Started watching ghcr.io/codeswhat/drydock:1.6.0-rc.11',
+ details: 'Started watching ghcr.io/codeswhat/drydock:1.6.0-rc.12',
},
];
diff --git a/apps/demo/src/mocks/data/containers.ts b/apps/demo/src/mocks/data/containers.ts
index 312a64bf2..500f3ff39 100644
--- a/apps/demo/src/mocks/data/containers.ts
+++ b/apps/demo/src/mocks/data/containers.ts
@@ -330,7 +330,7 @@ export const containers = [
displayName: 'Drydock',
displayIcon: 'sh-drydock',
image: 'codeswhat/drydock',
- tag: '1.6.0-rc.11',
+ tag: '1.6.0-rc.12',
registryType: 'ghcr',
registryUrl: 'https://ghcr.io',
scanStatus: 'scanned',
diff --git a/apps/demo/src/mocks/data/server.ts b/apps/demo/src/mocks/data/server.ts
index 2ef6c05c4..c0154f8ae 100644
--- a/apps/demo/src/mocks/data/server.ts
+++ b/apps/demo/src/mocks/data/server.ts
@@ -1,5 +1,5 @@
export const serverInfo = {
- version: '1.6.0-rc.11',
+ version: '1.6.0-rc.12',
uptime: 864000,
hostname: 'drydock-demo',
platform: 'linux',
diff --git a/apps/demo/src/mocks/handlers/app.ts b/apps/demo/src/mocks/handlers/app.ts
index dc86a04c1..1d6f781ff 100644
--- a/apps/demo/src/mocks/handlers/app.ts
+++ b/apps/demo/src/mocks/handlers/app.ts
@@ -4,7 +4,7 @@ export const appHandlers = [
http.get('/api/v1/app', () =>
HttpResponse.json({
name: 'Drydock',
- version: '1.6.0-rc.11',
+ version: '1.6.0-rc.12',
description: 'Docker container update manager',
repository: 'https://github.com/CodesWhat/drydock',
documentation: 'https://getdrydock.com/docs',
@@ -16,7 +16,7 @@ export const appHandlers = [
return HttpResponse.json(
{
generatedAt: new Date().toISOString(),
- server: { version: '1.6.0-rc.11', mode: 'demo' },
+ server: { version: '1.6.0-rc.12', mode: 'demo' },
summary: {
containers: 25,
watchers: 2,
diff --git a/apps/web/package-lock.json b/apps/web/package-lock.json
index 61fb4e424..3abde9a11 100644
--- a/apps/web/package-lock.json
+++ b/apps/web/package-lock.json
@@ -19,18 +19,18 @@
"fumadocs-mdx": "^15.0.12",
"fumadocs-ui": "^16.10.5",
"lucide-react": "^1.14.0",
- "next": "16.2.11",
+ "next": "16.2.12",
"react": "19.2.8",
"react-dom": "19.2.8",
"remark-custom-heading-id": "^2.0.0",
"tailwind-merge": "^3.6.0"
},
"devDependencies": {
- "@biomejs/biome": "2.5.5",
+ "@biomejs/biome": "2.5.6",
"@tailwindcss/postcss": "4.3.3",
"@types/node": "25.9.5",
- "@types/react": "19.2.17",
- "@types/react-dom": "19.2.3",
+ "@types/react": "19.2.18",
+ "@types/react-dom": "19.2.4",
"lefthook": "2.1.10",
"tailwindcss": "4.3.3",
"typescript": "6.0.3"
@@ -53,9 +53,9 @@
}
},
"node_modules/@biomejs/biome": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.5.tgz",
- "integrity": "sha512-r1S8nFsAG1MY+vJFZALzIvwXAJv6ejDQ0mxP21Tgr9YK3ZFtjrvbBwDdNhx1rUqvccEIeNg20cYCNzl6Cr69pQ==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.6.tgz",
+ "integrity": "sha512-lxVNjv7UF6KfhMJfL9gaUHbWdJdHbsAj6OSmwSYNdhRuG67NxNQ4Xdvh3TUxsSK9sBzJBQhEJj3AopmmNJ5pSA==",
"dev": true,
"license": "MIT OR Apache-2.0",
"bin": {
@@ -69,20 +69,20 @@
"url": "https://opencollective.com/biome"
},
"optionalDependencies": {
- "@biomejs/cli-darwin-arm64": "2.5.5",
- "@biomejs/cli-darwin-x64": "2.5.5",
- "@biomejs/cli-linux-arm64": "2.5.5",
- "@biomejs/cli-linux-arm64-musl": "2.5.5",
- "@biomejs/cli-linux-x64": "2.5.5",
- "@biomejs/cli-linux-x64-musl": "2.5.5",
- "@biomejs/cli-win32-arm64": "2.5.5",
- "@biomejs/cli-win32-x64": "2.5.5"
+ "@biomejs/cli-darwin-arm64": "2.5.6",
+ "@biomejs/cli-darwin-x64": "2.5.6",
+ "@biomejs/cli-linux-arm64": "2.5.6",
+ "@biomejs/cli-linux-arm64-musl": "2.5.6",
+ "@biomejs/cli-linux-x64": "2.5.6",
+ "@biomejs/cli-linux-x64-musl": "2.5.6",
+ "@biomejs/cli-win32-arm64": "2.5.6",
+ "@biomejs/cli-win32-x64": "2.5.6"
}
},
"node_modules/@biomejs/cli-darwin-arm64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.5.tgz",
- "integrity": "sha512-kUrAhXVWUrwmAUnV2iXSK7umxKFysTwvqK+Ty6ptUcLY/7T3SnCAjUowE4uvwaEej6nXZ7hu/dTtbokKdsPeag==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.6.tgz",
+ "integrity": "sha512-zMOLZP4oMrjh6m1zcSj1ud2awUPgTuMVbmQhYYWL7J8HwCnbHHBvTm7VBTRuY7epT5bez76IpKYQ11ZAqHFlnw==",
"cpu": [
"arm64"
],
@@ -97,9 +97,9 @@
}
},
"node_modules/@biomejs/cli-darwin-x64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.5.tgz",
- "integrity": "sha512-DamiYc5bUYZ2uxlfc+RLEPtz1Abb6PO5eTbOkufLpSGwd/7AMQAdxhFYiXmwwkJL8IsT8S7GvdgwDHqaMFAvKw==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.6.tgz",
+ "integrity": "sha512-JAC1VqzvO7Th5ZplU0G2uGfkZbxEe9uDDektPAhF0JLusoz1w+T4okp2bkykI0bbaO2vslKiRfj4gU43JaGreA==",
"cpu": [
"x64"
],
@@ -114,9 +114,9 @@
}
},
"node_modules/@biomejs/cli-linux-arm64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.5.tgz",
- "integrity": "sha512-lRKF/pH/1RiYiBKExi3TCZVAtvzEm77aifrvcNiDFrR9WxeAnDUjDnseb6y2XV85mjitLs6SILGm2XG77cHtSQ==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.6.tgz",
+ "integrity": "sha512-6XsYwCFkp5sMxl85ffhgeGpGgs6A7dRYFnkceZ7WVxvycuTnGdD5xa534Z3xfrBQ0JCMK/mujT6ZNPJoghedwg==",
"cpu": [
"arm64"
],
@@ -134,9 +134,9 @@
}
},
"node_modules/@biomejs/cli-linux-arm64-musl": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.5.tgz",
- "integrity": "sha512-U4WMl/sy/E/Q73vf15VspakLRRs2LDFcCeBxJnQfXzssb88zpV6PJPaQ3ezhQ7H6Ht2/8bvuZeHgJWzmoxllZg==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.6.tgz",
+ "integrity": "sha512-eUa3jeeYvfMt19LBeh6E5PUZpxnTC4JqNWo+EDjTtQjAr2xLGnWaxACtVU1DQqmHYbvThlJzLX+ZsYgrqh2qVw==",
"cpu": [
"arm64"
],
@@ -154,9 +154,9 @@
}
},
"node_modules/@biomejs/cli-linux-x64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.5.tgz",
- "integrity": "sha512-H/O39nJEw/2Zm/fm7hrmxxoF8kK/aU1uCoPp70ruXVbomaAdLpJJnCmL11Q2JotT8QVHH06So04Oq53lCSwSwQ==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.6.tgz",
+ "integrity": "sha512-Pop9VXCFUhFTMfFefZ39S+u2rOPyNp5iHlxbZRwXGACHLy2r0jjiRgJHmaEKJzL3SyxlVeGShXhvvElvWowonA==",
"cpu": [
"x64"
],
@@ -174,9 +174,9 @@
}
},
"node_modules/@biomejs/cli-linux-x64-musl": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.5.tgz",
- "integrity": "sha512-m7wC7tjX5Lrmo69dc4md8FeKpPU1NTCY1v7xUoQQ2vadWwNnBS0KZOG8471otFPHrTHihQJAjQPgMObpLvDe6A==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.6.tgz",
+ "integrity": "sha512-2Vp13QdKysH3HIWLaYLhUUwbK+jbZonJD1K+Lr0d0RO4wH7mkYd43vJixEDm8cUWrowoRz4UUHF1nm9Ae7ym8A==",
"cpu": [
"x64"
],
@@ -194,9 +194,9 @@
}
},
"node_modules/@biomejs/cli-win32-arm64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.5.tgz",
- "integrity": "sha512-7BryINPuYypLUAH3o/o5ZdgomJ4zn3EDR0ChZJst7n32S6ZhKbgHXuYydLu+YAnx59ehGFR0z/MG6qnzQi3Yyw==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.6.tgz",
+ "integrity": "sha512-tDGshcm6BdkZOCGnTDX0Y8/U4IfBSlnUU7T56nNDuPEfed+aHg+u8G36NB43fJVl0Os6+QURXIE1yuD7AaEofA==",
"cpu": [
"arm64"
],
@@ -211,9 +211,9 @@
}
},
"node_modules/@biomejs/cli-win32-x64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.5.tgz",
- "integrity": "sha512-bIBFo+n6MIxdNcVFy5CrurbKiZQiUciK3bt8+O9I4wjFZNTfXLpi+giq47522eXqW5NBc9ulx7dR1SlZKi2J5g==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.6.tgz",
+ "integrity": "sha512-WN05KwXnTO/2J45RQPvzZMXf7tZUIofHoR35xIPfCo7pQ2RFidxI8sfb5mGsaTxdMmEOzHzOPRCdA5/fCpc7xQ==",
"cpu": [
"x64"
],
@@ -1357,15 +1357,15 @@
}
},
"node_modules/@next/env": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.11.tgz",
- "integrity": "sha512-0do5A3BJ2gxWr0ZCMcD6BhW+e595jyxdTl3rXTS6lOtD8ektMiW6CO+EPwt1Eca1DBnm90r/7GdiKWBKxH++DA==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.12.tgz",
+ "integrity": "sha512-d0Z5Bc13Fa4nR8pFAKx2jay2yhJM16vlfHbTzYnUQAxlNb6B6lmn4hjt69lYNt4kRtyYP6gEM49lPRHNbIyneg==",
"license": "MIT"
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.11.tgz",
- "integrity": "sha512-wryL4pjKmDwGv2ox6+GZDFxvmtSRLqApBR8kL1j4+vhB7Z5vJC/zAnXpiR9Xkfzl0AS8WLMnsuGV/UKI67/rrw==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.12.tgz",
+ "integrity": "sha512-0W1R0teHWJrqKX0FH20IzzIWAOuGtBxPGuObrxy1lE8hQvCFj49KE8a3WUg0D7sq6rn6zkM4c7YGUnhudBS6oA==",
"cpu": [
"arm64"
],
@@ -1379,9 +1379,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.11.tgz",
- "integrity": "sha512-aZl2j4f/fLyjQvOhv0Oe9UaMAQHolYpKhctsoYzplSumKJKPUmgjcf6545aBtysLTcu994TREd0+pSgNE4ohmg==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.12.tgz",
+ "integrity": "sha512-Hy5Ls099+aFUmOLmIgPfLqNi6iCwhL3uQCssz5rWk+5Nkc6TUKCE83DY5BbNylfm3+mfwcSFnLRfrZDJhVxdtw==",
"cpu": [
"x64"
],
@@ -1395,9 +1395,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.11.tgz",
- "integrity": "sha512-5jEriyEnH/LWFy27L2ZG0XaLlyEJIjhsImEsiS9P563PKEVp2BVups/xfOucIrsvVntp11oNcZwjHvaDPYVB5g==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.12.tgz",
+ "integrity": "sha512-+YqU2h1cQkHsGfvjAsrSmst8UIFBibBGm5x3Xgel8NLMiDQtNOM4sM2GOEMvG5YiOBNeN/Ykk8cQC2S0Xrqljg==",
"cpu": [
"arm64"
],
@@ -1414,9 +1414,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.11.tgz",
- "integrity": "sha512-eIjcpx2fnnFSSkZDbTxy74KnokUXDjfoLClpWelfgHLf621aTqswhwXQ7GkD5K5rplrS6LZ/Bj+mVuvzluBOEg==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.12.tgz",
+ "integrity": "sha512-0qjhiYBaKAqF63LA1ZWAAnKTzFUguAaZiRa5etMLGGPj/B6uEVjtIZldIzFEp3wHlB0koK6aTzqPtSdplTCjoA==",
"cpu": [
"arm64"
],
@@ -1433,9 +1433,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.11.tgz",
- "integrity": "sha512-8WgzpaWMs46qJT9kiV47cje86L0x/Mu9t8/Gwj+pnbgW3rETVfCnaScPjlYUwNScpOozdcIMHWmAvuZJUonR2w==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.12.tgz",
+ "integrity": "sha512-7A3q26W+h7gnA15uqBToNuDqBEFZZcqh0mW2mn4AJh/G5pdg2RVE3n4slzLEliASZFG3NmsbEzng/x2Sh09mBg==",
"cpu": [
"x64"
],
@@ -1452,9 +1452,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.11.tgz",
- "integrity": "sha512-I3UgPds7G4ZYnTb/H+5GBGuUT2DhAk6j0mL6A4s63RjFs74wB2hOWP0vaxsK+3NJraExt3eYEPQ/UtT0x/64Nw==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.12.tgz",
+ "integrity": "sha512-qSjL/uppm+cbh21s72Ss8gkiOhQ4dExWHNGOWy6eZV7STj5WsKehgxT61beSsOj+YYQuTplL376lOCdMQU5T8w==",
"cpu": [
"x64"
],
@@ -1471,9 +1471,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.11.tgz",
- "integrity": "sha512-n89CjtcThnjrwgJMAiI5xbqwLY51zvwC9tSlArmVndAJLYVl9T9UAdlkXTmZvE++idoXe8KdglQlhNRdUp1c6g==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.12.tgz",
+ "integrity": "sha512-X6hzsOUJac/e7AWSbn9gQ9nzHld1xWP5iyjHpYWvud8pufB679O1xg4JDyKr8Xd69Jvd+kM2Der6uftiZCmjYA==",
"cpu": [
"arm64"
],
@@ -1487,9 +1487,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.11.tgz",
- "integrity": "sha512-md8CLNggS1Dx9pUgApzps5uAf+N8GN9xywzmNx9vHAWo94HtBwCCqkSnhIrdfQe83Dhz8Lfo/20Nb1Zxal092w==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.12.tgz",
+ "integrity": "sha512-F6fakeHuFTLOPt0bslQJdf+xtT+WIP9DVn/m4y1w1mRnVPyh3D/cNvzlRkxM444xfm+IvvYNSOrKiA2CDJ0Uxw==",
"cpu": [
"x64"
],
@@ -1502,15 +1502,6 @@
"node": ">= 10"
}
},
- "node_modules/@orama/orama": {
- "version": "3.1.18",
- "resolved": "https://registry.npmjs.org/@orama/orama/-/orama-3.1.18.tgz",
- "integrity": "sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">= 20.0.0"
- }
- },
"node_modules/@radix-ui/number": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.3.tgz",
@@ -1524,20 +1515,20 @@
"license": "MIT"
},
"node_modules/@radix-ui/react-accordion": {
- "version": "1.2.19",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.19.tgz",
- "integrity": "sha512-ir4jA6TYdFonIC6n6ngyvaNQ6ReOMTqDg7MK/+D7U9KfWJtRoyoGLYwD1umh6LXGxc7QkKH1nwTOy7mewQz42w==",
+ "version": "1.2.20",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.20.tgz",
+ "integrity": "sha512-jDhG9FvAEnlhnjrsINbNXcUa4G+L1KqSkJSunkbKEzFRcAb52jvM0PjPxPRvhe1HNc5F5yc0yzzWeeqlH4yBIg==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-collapsible": "1.1.19",
- "@radix-ui/react-collection": "1.1.14",
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-direction": "1.1.3",
- "@radix-ui/react-id": "1.1.3",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-use-controllable-state": "1.2.5"
+ "@radix-ui/react-collapsible": "1.1.20",
+ "@radix-ui/react-collection": "1.1.15",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-direction": "1.1.4",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-use-controllable-state": "1.2.6"
},
"peerDependencies": {
"@types/react": "*",
@@ -1555,12 +1546,12 @@
}
},
"node_modules/@radix-ui/react-arrow": {
- "version": "1.1.14",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.14.tgz",
- "integrity": "sha512-5GcTjiRmUKHDdGz2Fwm+SbVfGDVg1DBCoxUsc1fUL5k84ZYpfwIOjmTLKwCjOw2ZcH3w47rWkkx/vY/VxKuslw==",
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.15.tgz",
+ "integrity": "sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.1.9"
+ "@radix-ui/react-primitive": "2.1.10"
},
"peerDependencies": {
"@types/react": "*",
@@ -1578,19 +1569,19 @@
}
},
"node_modules/@radix-ui/react-collapsible": {
- "version": "1.1.19",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.19.tgz",
- "integrity": "sha512-TbvE0YFHJDRQXk6UpczD72Jr0UCGkJtAz3IVHE6W5N10sfJ0ZYAfVbR3+GR0/2BLZWAjHnOAFNSpzLFjdpYJdQ==",
+ "version": "1.1.20",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.20.tgz",
+ "integrity": "sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-id": "1.1.3",
- "@radix-ui/react-presence": "1.1.9",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-use-controllable-state": "1.2.5",
- "@radix-ui/react-use-layout-effect": "1.1.3"
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-presence": "1.1.10",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-use-controllable-state": "1.2.6",
+ "@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -1608,15 +1599,15 @@
}
},
"node_modules/@radix-ui/react-collection": {
- "version": "1.1.14",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.14.tgz",
- "integrity": "sha512-+n2VZftI+uAtyvmgn9mM33Gdc1gdvc9Fz6pjYm4qtQIXhvDR5oBQDYJCL/z053Q9nTIErpGEbt5H9K83W+mK1Q==",
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.15.tgz",
+ "integrity": "sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-slot": "1.3.2"
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-slot": "1.3.3"
},
"peerDependencies": {
"@types/react": "*",
@@ -1634,9 +1625,9 @@
}
},
"node_modules/@radix-ui/react-compose-refs": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.4.tgz",
- "integrity": "sha512-pWJo6lQAfR6uy1n7ii7PaCc9dLPwTXDYbQpORZU5B548Aqvl2pP1SM1vJGKyxIFqZMHRopRO4CQYX2iXAIB5jA==",
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz",
+ "integrity": "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -1649,9 +1640,9 @@
}
},
"node_modules/@radix-ui/react-context": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.1.tgz",
- "integrity": "sha512-EraVbFjiIjibpLr6EjvEDmSCYJU2SlKDMiO+qEK/D9GOWnQoAQlpQo2occGYC1UM9MBeEx5Bek3UtW/Qi57vAg==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.2.tgz",
+ "integrity": "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -1664,24 +1655,24 @@
}
},
"node_modules/@radix-ui/react-dialog": {
- "version": "1.1.22",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.22.tgz",
- "integrity": "sha512-ZvXpCrhEH2OrVa1l8caiuWzrk6Qleq6PeZQ824lXxUxFu6mE4/XzRz1DliOvS18WuBl3A3clg2gHPNiPqz8BjA==",
+ "version": "1.1.23",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.23.tgz",
+ "integrity": "sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-dismissable-layer": "1.1.18",
- "@radix-ui/react-focus-guards": "1.1.5",
- "@radix-ui/react-focus-scope": "1.1.15",
- "@radix-ui/react-id": "1.1.3",
- "@radix-ui/react-portal": "1.1.16",
- "@radix-ui/react-presence": "1.1.9",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-slot": "1.3.2",
- "@radix-ui/react-use-controllable-state": "1.2.5",
- "@radix-ui/react-use-layout-effect": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-dismissable-layer": "1.1.19",
+ "@radix-ui/react-focus-guards": "1.1.6",
+ "@radix-ui/react-focus-scope": "1.1.16",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-portal": "1.1.17",
+ "@radix-ui/react-presence": "1.1.10",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-slot": "1.3.3",
+ "@radix-ui/react-use-controllable-state": "1.2.6",
+ "@radix-ui/react-use-layout-effect": "1.1.4",
"aria-hidden": "^1.2.4",
"react-remove-scroll": "^2.7.2"
},
@@ -1701,9 +1692,9 @@
}
},
"node_modules/@radix-ui/react-direction": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.3.tgz",
- "integrity": "sha512-OdgAA/xb6WOQMKNn0mtbYoruMG6YMaBOnq+evWxSpMmiEMBdeFZawnIWRfPPeVXCRm+0lnN8jpJLjhD7/UIxWw==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.4.tgz",
+ "integrity": "sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -1716,16 +1707,16 @@
}
},
"node_modules/@radix-ui/react-dismissable-layer": {
- "version": "1.1.18",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.18.tgz",
- "integrity": "sha512-4tuTRonWG1Etcbc597++jlROMx7r34Otb0fATJhaK16Uq7XRotUS1aGyDX+yOBh668HQzhcpUpTLXFqMRVuFeA==",
+ "version": "1.1.19",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.19.tgz",
+ "integrity": "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-use-callback-ref": "1.1.3",
- "@radix-ui/react-use-effect-event": "0.0.4"
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-use-callback-ref": "1.1.4",
+ "@radix-ui/react-use-effect-event": "0.0.5"
},
"peerDependencies": {
"@types/react": "*",
@@ -1743,9 +1734,9 @@
}
},
"node_modules/@radix-ui/react-focus-guards": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.5.tgz",
- "integrity": "sha512-UQvlB7L/BYh3P8MLvwZnQkH521EDos40Rwnbt5+Qpg4Vbk0z3xJjRUmR6+aka4aT1IQQXFdO5bNPoE7cvFl5xQ==",
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.6.tgz",
+ "integrity": "sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -1758,14 +1749,14 @@
}
},
"node_modules/@radix-ui/react-focus-scope": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.15.tgz",
- "integrity": "sha512-rKjyFmJRsUhrCg39GJ0DOMfrOxHbw8WaS/KMOUPhLLm80LfDffRQGzF8RdulfDP3QfOJPJj4Sma+EU3E/90ykw==",
+ "version": "1.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.16.tgz",
+ "integrity": "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-use-callback-ref": "1.1.3"
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-use-callback-ref": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -1783,12 +1774,12 @@
}
},
"node_modules/@radix-ui/react-id": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.3.tgz",
- "integrity": "sha512-f/Wxm0ctyMymUJK0fqTSQlm85rbzdAkoNbPXJQ5+6caowVO8Yx+NWGjGz/oGhs/D+WIbbQpOrU0hU2Li2/42xQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz",
+ "integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.3"
+ "@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -1801,25 +1792,25 @@
}
},
"node_modules/@radix-ui/react-navigation-menu": {
- "version": "1.2.21",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.21.tgz",
- "integrity": "sha512-Y5SmS1Qd0SSG724Siw7ie5i+XL8+h3UgWLJcC/HaPKhuOnZz9sWP11gu5I7ZAvJL+rYu7X/FRZujRdf+s1QXTg==",
+ "version": "1.2.22",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.22.tgz",
+ "integrity": "sha512-ou7iLEJ+yrhQndkkA4U21XIdS/CS45F4iXIkTZcb6/Ne9EMsOuDudVmCwmDnfFZZ+y1FZqXRNSIgBy+YMvZVZg==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-collection": "1.1.14",
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-direction": "1.1.3",
- "@radix-ui/react-dismissable-layer": "1.1.18",
- "@radix-ui/react-id": "1.1.3",
- "@radix-ui/react-presence": "1.1.9",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-use-callback-ref": "1.1.3",
- "@radix-ui/react-use-controllable-state": "1.2.5",
- "@radix-ui/react-use-layout-effect": "1.1.3",
- "@radix-ui/react-use-previous": "1.1.3",
- "@radix-ui/react-visually-hidden": "1.2.10"
+ "@radix-ui/react-collection": "1.1.15",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-direction": "1.1.4",
+ "@radix-ui/react-dismissable-layer": "1.1.19",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-presence": "1.1.10",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-use-callback-ref": "1.1.4",
+ "@radix-ui/react-use-controllable-state": "1.2.6",
+ "@radix-ui/react-use-layout-effect": "1.1.4",
+ "@radix-ui/react-use-previous": "1.1.4",
+ "@radix-ui/react-visually-hidden": "1.2.11"
},
"peerDependencies": {
"@types/react": "*",
@@ -1837,25 +1828,24 @@
}
},
"node_modules/@radix-ui/react-popover": {
- "version": "1.1.22",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.22.tgz",
- "integrity": "sha512-w5DCbDSP6TiQKmmfFPsZ+gNK/CN1OWx/vkTFFSH70aUPso6RbPNO+Rv08X4SYOblnLoN/x6N6jGsdEWfbeGLig==",
+ "version": "1.1.23",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.23.tgz",
+ "integrity": "sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-dismissable-layer": "1.1.18",
- "@radix-ui/react-focus-guards": "1.1.5",
- "@radix-ui/react-focus-scope": "1.1.15",
- "@radix-ui/react-id": "1.1.3",
- "@radix-ui/react-popper": "1.3.6",
- "@radix-ui/react-portal": "1.1.16",
- "@radix-ui/react-presence": "1.1.9",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-slot": "1.3.2",
- "@radix-ui/react-use-controllable-state": "1.2.5",
- "@radix-ui/react-use-layout-effect": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-dismissable-layer": "1.1.19",
+ "@radix-ui/react-focus-guards": "1.1.6",
+ "@radix-ui/react-focus-scope": "1.1.16",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-popper": "1.3.7",
+ "@radix-ui/react-portal": "1.1.17",
+ "@radix-ui/react-presence": "1.1.10",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-slot": "1.3.3",
+ "@radix-ui/react-use-controllable-state": "1.2.6",
"aria-hidden": "^1.2.4",
"react-remove-scroll": "^2.7.2"
},
@@ -1875,20 +1865,20 @@
}
},
"node_modules/@radix-ui/react-popper": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.6.tgz",
- "integrity": "sha512-hMA05k4dWrsMLWey2njJmGOvBoRirwlilS1EaGF8zufJJUZiJ7dW96p48xVsIj1oJXPdtlcK7yG8W+JcDhFP7A==",
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.7.tgz",
+ "integrity": "sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg==",
"license": "MIT",
"dependencies": {
"@floating-ui/react-dom": "^2.0.0",
- "@radix-ui/react-arrow": "1.1.14",
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-use-callback-ref": "1.1.3",
- "@radix-ui/react-use-layout-effect": "1.1.3",
- "@radix-ui/react-use-rect": "1.1.3",
- "@radix-ui/react-use-size": "1.1.3",
+ "@radix-ui/react-arrow": "1.1.15",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-use-callback-ref": "1.1.4",
+ "@radix-ui/react-use-layout-effect": "1.1.4",
+ "@radix-ui/react-use-rect": "1.1.4",
+ "@radix-ui/react-use-size": "1.1.4",
"@radix-ui/rect": "1.1.3"
},
"peerDependencies": {
@@ -1907,13 +1897,13 @@
}
},
"node_modules/@radix-ui/react-portal": {
- "version": "1.1.16",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.16.tgz",
- "integrity": "sha512-Lml0Z1vVXni7Sk29TTltPF2+SYTUrTJONrlrfQMTDGNKzEkXHIdHqYDQ/TkHEqsKT9Igy2jDWP7AmFeDeimd2w==",
+ "version": "1.1.17",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.17.tgz",
+ "integrity": "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-use-layout-effect": "1.1.3"
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -1931,12 +1921,12 @@
}
},
"node_modules/@radix-ui/react-presence": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.9.tgz",
- "integrity": "sha512-LTi1v05bprIb8/GSY/GWusI0jfsYjQ3CD3Nin8o7jVxnpHzVQfzjOQJoJTQkE9bdmOnsS7SFdhkXiBv8PrYnxw==",
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.10.tgz",
+ "integrity": "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.3"
+ "@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -1954,12 +1944,12 @@
}
},
"node_modules/@radix-ui/react-primitive": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.9.tgz",
- "integrity": "sha512-aX5c84AYUD0EIodbQfpujB5XI0CbEaQ5U9du/wntNQK451i5iCJlE2JN6IN1LgQ3SnoBbnW/Jv1Z4rUowZV+hg==",
+ "version": "2.1.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.10.tgz",
+ "integrity": "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-slot": "1.3.2"
+ "@radix-ui/react-slot": "1.3.3"
},
"peerDependencies": {
"@types/react": "*",
@@ -1977,22 +1967,22 @@
}
},
"node_modules/@radix-ui/react-roving-focus": {
- "version": "1.1.18",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.18.tgz",
- "integrity": "sha512-TLnxyyaccLuJV5p9PnApzswNNL5Zn9YEvYeDKKbO0dsvqq6Pg1vnExNzp4HnQ5MjhN8jwAOkq7HsDBZ9q66V0A==",
+ "version": "1.1.19",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.19.tgz",
+ "integrity": "sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-collection": "1.1.14",
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-direction": "1.1.3",
- "@radix-ui/react-id": "1.1.3",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-use-callback-ref": "1.1.3",
- "@radix-ui/react-use-controllable-state": "1.2.5",
- "@radix-ui/react-use-is-hydrated": "0.1.2",
- "@radix-ui/react-use-layout-effect": "1.1.3"
+ "@radix-ui/react-collection": "1.1.15",
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-direction": "1.1.4",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-use-callback-ref": "1.1.4",
+ "@radix-ui/react-use-controllable-state": "1.2.6",
+ "@radix-ui/react-use-is-hydrated": "0.1.3",
+ "@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -2010,20 +2000,20 @@
}
},
"node_modules/@radix-ui/react-scroll-area": {
- "version": "1.2.17",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.17.tgz",
- "integrity": "sha512-LTyRyEyxDV8mMx8ef/N+AaigP/XuHggt59um/AgQdjO113VzCXOGzsBb6Jvh7el/Mz4XwZ/+UilkXFDSD/LGiw==",
+ "version": "1.2.18",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.18.tgz",
+ "integrity": "sha512-Zn5Cd171wxsO3Dfg8HaW6RifTb9CYTKQJHs/G4+LN1GfmJpaQMZQyQxMprVPHpaz7QY4l9BxK2JwQuzHsXC8nA==",
"license": "MIT",
"dependencies": {
"@radix-ui/number": "1.1.3",
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.4",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-direction": "1.1.3",
- "@radix-ui/react-presence": "1.1.9",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-use-callback-ref": "1.1.3",
- "@radix-ui/react-use-layout-effect": "1.1.3"
+ "@radix-ui/react-compose-refs": "1.1.5",
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-direction": "1.1.4",
+ "@radix-ui/react-presence": "1.1.10",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-use-callback-ref": "1.1.4",
+ "@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -2041,13 +2031,12 @@
}
},
"node_modules/@radix-ui/react-slot": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.2.tgz",
- "integrity": "sha512-nLBh0hpzgQA16ioKAWTSQvGjRj7QcI3pTpngtYZ12b4RP9N8eGSj7ziceHyHe04zrd0bAcLyMijO0ws0DLmDWw==",
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.3.tgz",
+ "integrity": "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==",
"license": "MIT",
"dependencies": {
- "@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.4"
+ "@radix-ui/react-compose-refs": "1.1.5"
},
"peerDependencies": {
"@types/react": "*",
@@ -2060,19 +2049,19 @@
}
},
"node_modules/@radix-ui/react-tabs": {
- "version": "1.1.20",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.20.tgz",
- "integrity": "sha512-/isB6Z/sIgMtnpGTig99pgMU0F8C4AmP7Dk36WN0PZ49H2mNjTpiCqmzIOOOZLez5F26DiZlQDFtPfQNMYb6Mg==",
+ "version": "1.1.21",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.21.tgz",
+ "integrity": "sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-context": "1.2.1",
- "@radix-ui/react-direction": "1.1.3",
- "@radix-ui/react-id": "1.1.3",
- "@radix-ui/react-presence": "1.1.9",
- "@radix-ui/react-primitive": "2.1.9",
- "@radix-ui/react-roving-focus": "1.1.18",
- "@radix-ui/react-use-controllable-state": "1.2.5"
+ "@radix-ui/react-context": "1.2.2",
+ "@radix-ui/react-direction": "1.1.4",
+ "@radix-ui/react-id": "1.1.4",
+ "@radix-ui/react-presence": "1.1.10",
+ "@radix-ui/react-primitive": "2.1.10",
+ "@radix-ui/react-roving-focus": "1.1.19",
+ "@radix-ui/react-use-controllable-state": "1.2.6"
},
"peerDependencies": {
"@types/react": "*",
@@ -2090,9 +2079,9 @@
}
},
"node_modules/@radix-ui/react-use-callback-ref": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.3.tgz",
- "integrity": "sha512-AUS7HoBBAncIsGMLNG+CcpLuJ+JIBbZzmyM8Qdb1eIThX0AlhSSC6wn40xfBlPE+ypx/vSSiRWnklUAjy3U3UA==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.4.tgz",
+ "integrity": "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -2105,14 +2094,14 @@
}
},
"node_modules/@radix-ui/react-use-controllable-state": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.5.tgz",
- "integrity": "sha512-UB1dXpxvHjR48poyKdKdTm7jT0kp3elkUKdKQiOkirlbYumqXinSJtrjDsr9maXNPvL12bKI4CDSmydms/9Aeg==",
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.6.tgz",
+ "integrity": "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.7",
- "@radix-ui/react-use-effect-event": "0.0.4",
- "@radix-ui/react-use-layout-effect": "1.1.3"
+ "@radix-ui/react-use-effect-event": "0.0.5",
+ "@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -2125,12 +2114,12 @@
}
},
"node_modules/@radix-ui/react-use-effect-event": {
- "version": "0.0.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.4.tgz",
- "integrity": "sha512-XYcfa6wlXDCwQtePuEiPmXLSAhGL4DWtedSyRgGbG3y10mw+OnrLp6SyeY1gJFMiYF0Dx0nMAX9InylKbLEFQQ==",
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.5.tgz",
+ "integrity": "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.3"
+ "@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -2143,9 +2132,9 @@
}
},
"node_modules/@radix-ui/react-use-is-hydrated": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.2.tgz",
- "integrity": "sha512-2+gAVu9uaSLbopCTvvuWX9MIgEOlyqXC1Ok+KLCO7cZPSHLENs7dL0KbFQUGFIcFKmDW/bmaQRJtd8E3cnMRUw==",
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.3.tgz",
+ "integrity": "sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -2158,9 +2147,9 @@
}
},
"node_modules/@radix-ui/react-use-layout-effect": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.3.tgz",
- "integrity": "sha512-rDiah9wvtqihWtWz02XreeRKIxt2EJF8y5D9rtY9l5A2zxePAtcPiOMpDugNRw5bFHz+1/8viVoc7ZVKiJknCw==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.4.tgz",
+ "integrity": "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -2173,9 +2162,9 @@
}
},
"node_modules/@radix-ui/react-use-previous": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.3.tgz",
- "integrity": "sha512-kbefNKla5AGhgvMqrg/qS7mYVLXTEHQLqoFIS03nKN2dAfQQ5PK5Tp+2LxS7BV6a6l4HHv4jTg6rtV2Uajwe2w==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.4.tgz",
+ "integrity": "sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -2188,9 +2177,9 @@
}
},
"node_modules/@radix-ui/react-use-rect": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.3.tgz",
- "integrity": "sha512-W0GSYZFKEfi6raMiMEfJSngvVbFDIyxtW5JuVg5NoQBY59l0dVQVGLbhog/tOdwq0qtZ+TXuX1ikSNan4/IZXA==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.4.tgz",
+ "integrity": "sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/rect": "1.1.3"
@@ -2206,12 +2195,12 @@
}
},
"node_modules/@radix-ui/react-use-size": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.3.tgz",
- "integrity": "sha512-jJq6tQQLvO/z4uWbztjwPV+1a/+H4rCaWypasLB/ac8DEdd6+p7dIm7o3F6P2KZPGkPMqD4s5424EdAdoU+GLA==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.4.tgz",
+ "integrity": "sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.3"
+ "@radix-ui/react-use-layout-effect": "1.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -2224,12 +2213,12 @@
}
},
"node_modules/@radix-ui/react-visually-hidden": {
- "version": "1.2.10",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.10.tgz",
- "integrity": "sha512-j1q1Aw5zpNp/mlNSkXeQNsF4RhRd0g2KYgR/BeN20D+PGncx4NmWQ5sMriucY9hlYG3jVRW5jH9PCQShL+ZiDA==",
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.11.tgz",
+ "integrity": "sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.1.9"
+ "@radix-ui/react-primitive": "2.1.10"
},
"peerDependencies": {
"@types/react": "*",
@@ -2781,9 +2770,9 @@
}
},
"node_modules/@types/react": {
- "version": "19.2.17",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz",
- "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==",
+ "version": "19.2.18",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz",
+ "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==",
"devOptional": true,
"license": "MIT",
"dependencies": {
@@ -2791,9 +2780,9 @@
}
},
"node_modules/@types/react-dom": {
- "version": "19.2.3",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
- "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.4.tgz",
+ "integrity": "sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==",
"devOptional": true,
"license": "MIT",
"peerDependencies": {
@@ -2893,159 +2882,170 @@
}
},
"node_modules/@yuku-analyzer/binding-darwin-arm64": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-darwin-arm64/-/binding-darwin-arm64-0.6.12.tgz",
- "integrity": "sha512-9rpIP7IeybjyvWUf6WnU24h1qo+JdxIHr1o3yb06HoE8tM3S/Jh5RrUw9aw5P9BKSIvSPbLyVlItX7PcD3o5bQ==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-darwin-arm64/-/binding-darwin-arm64-0.8.1.tgz",
+ "integrity": "sha512-p1LROfS/Fcz+10UFf+uSlVrawlJNdWKHLSH1jOnVdcaa82oaWbehoEdocS6DkYJxcARzG2QpkAGLBrIiMKCRBg==",
"cpu": [
"arm64"
],
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@yuku-analyzer/binding-darwin-x64": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-darwin-x64/-/binding-darwin-x64-0.6.12.tgz",
- "integrity": "sha512-ELLhNT4FGnqY8yh0W3cSs9rGMSeUyhib1aYD84RupjlfsrDTrQRoDhWu01Dv6xCfYgASYaj1Abntk91A7njNag==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-darwin-x64/-/binding-darwin-x64-0.8.1.tgz",
+ "integrity": "sha512-do28aZr3eQ0R61f3RiVOF+vvCw6oq7y/FcOU0KVCZOozH8Tr9ervprgAy7KbfWBezRODu5oa/XMdzP26vnstaA==",
"cpu": [
"x64"
],
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@yuku-analyzer/binding-freebsd-x64": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-freebsd-x64/-/binding-freebsd-x64-0.6.12.tgz",
- "integrity": "sha512-s76XocUMlK9liTyipALFb2K64ku35u/wg238A0NW8U5CUDsuIe/8tu5TzdLjJAGxnd0IV+gBneDt9cJJzLeFRQ==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-freebsd-x64/-/binding-freebsd-x64-0.8.1.tgz",
+ "integrity": "sha512-9pZxagkj2SOVWs7EF/XArW+1OiY4DHJCxoT/nybYrqNPxrDqk8KmSw3vdkE1GAOp00eaZ256230omoGTm8JdWA==",
"cpu": [
"x64"
],
+ "license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@yuku-analyzer/binding-linux-arm-gnu": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.6.12.tgz",
- "integrity": "sha512-hm8Tq0umop3RGu6dOMF61q69tYn1bDp1CeYD5ZjuGFQJclp0moVtjzY4z0bzusicKeZ9+k5LRroR0p5HWC2hDw==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.8.1.tgz",
+ "integrity": "sha512-uvXjAUndqZQIdqOHdWZMj/rwMVYGr44zLIULkfW/7FhIqMWAoC4PxTp94NsX2X3jj4B6RYF0GGO2ChOW8Ge3+Q==",
"cpu": [
"arm"
],
"libc": [
"glibc"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@yuku-analyzer/binding-linux-arm-musl": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm-musl/-/binding-linux-arm-musl-0.6.12.tgz",
- "integrity": "sha512-CxtPKLddogHAB3ZHVWaUl+U8jx0pdriTSbQ1K/orlDqU0GDhg8LuIRyUscP7r2/62fGGMzkc119fE71I4Nl1Fg==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm-musl/-/binding-linux-arm-musl-0.8.1.tgz",
+ "integrity": "sha512-f1dPM/0KCwv02dynHF0dmbW4iL7KfXIypWOCO4lh/VSLwPQYjd6RcI+LmKN6oaVhtELzBFguordipnIWbjpsKg==",
"cpu": [
"arm"
],
"libc": [
"musl"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@yuku-analyzer/binding-linux-arm64-gnu": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.6.12.tgz",
- "integrity": "sha512-EOyLcpAmF5qAVDKmKvV7xt8oBGeWQ92CqFI4s7h7TRlrF6TfGRrh8PwawGn92gFploNLAYj/1Z9Q1gVvwGgG9g==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.8.1.tgz",
+ "integrity": "sha512-NmtkwKscALPIZNlvHAdGMYQ0J9Ss7skKGdlom8ikWPF6L/5dH/TibqLhW7w8BwACCNYTAgKQN6B4uYfomL4fZw==",
"cpu": [
"arm64"
],
"libc": [
"glibc"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@yuku-analyzer/binding-linux-arm64-musl": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.6.12.tgz",
- "integrity": "sha512-T3eCYy6bMnVRMQEYAbDcpj08/XM93dBTtnn/DDocJN21RARe+KCzWKeL26J3yd3bOW3WVjVLq09BfdpAGB0buQ==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.8.1.tgz",
+ "integrity": "sha512-RGU5VLGYzHqIH0lbHv5qWGEeaDo5Cy5AG4Y3bIO/79nvS4fR2MamHzgRzTYmlgYLZVeK9RfL52hVv5sSfvp4Xg==",
"cpu": [
"arm64"
],
"libc": [
"musl"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@yuku-analyzer/binding-linux-x64-gnu": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.6.12.tgz",
- "integrity": "sha512-1Y+noIuvnDugIVsoIr5NduZqX7KuFTzICSkvG8RW3OKK9URVeTOicKK217i44ABZSSZJ7A0E7vzifapx0c9VDw==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.8.1.tgz",
+ "integrity": "sha512-274/hhQaj0WV8E88jSWvQFpqllRTtov41uLVwPJvpa4PAfD39VDb61No21v49+jjPwv7xrDOiheVDp9GvIOslg==",
"cpu": [
"x64"
],
"libc": [
"glibc"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@yuku-analyzer/binding-linux-x64-musl": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-x64-musl/-/binding-linux-x64-musl-0.6.12.tgz",
- "integrity": "sha512-woN/GuG95Fd6bp+ZQfmiFrZnoA2hdu3vfVSc89A8LElnYpzFaJM81sOZp8f3tVOVUJxbt7KAUiCLwSy34MJKqA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-x64-musl/-/binding-linux-x64-musl-0.8.1.tgz",
+ "integrity": "sha512-ZkYH/op9ykMsJMGuHRGcyHlYvLvhQsTbiCClqzyu847mFukJvFP6COG8Lfq3929oBrcPwoulwuYqMUO5Jubpkw==",
"cpu": [
"x64"
],
"libc": [
"musl"
],
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@yuku-analyzer/binding-win32-arm64": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-win32-arm64/-/binding-win32-arm64-0.6.12.tgz",
- "integrity": "sha512-8OVFnKbK+lgsL6MqILPLpzlsa00K4KiKsdbHH94hpGcrqaz1jv+k0Y7ujSaoYTWw5Bb7Lr9GJ3L1n1hT2sXoYA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-win32-arm64/-/binding-win32-arm64-0.8.1.tgz",
+ "integrity": "sha512-jXlKxJdrX9lsNSIoLgxZ9m0wqqPUWc+KoPxltbZKXhJNCj5hQBQCBgwOkn+QXNDPxFbEi3tlMOpiOvKXQ0S1DQ==",
"cpu": [
"arm64"
],
+ "license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@yuku-analyzer/binding-win32-x64": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-win32-x64/-/binding-win32-x64-0.6.12.tgz",
- "integrity": "sha512-3w8w1Xc5njwgbGTcn3JfDxWuQnFvtSll1D8gBlk4U8CI5v7ibKOMIdABucCXH8WtsRREG0ME5Vn0i422eX3zLQ==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-win32-x64/-/binding-win32-x64-0.8.1.tgz",
+ "integrity": "sha512-IyyYuVmFRYB/w5iTQ3QurgjQPLh3jUNMeWnE4o3Y4FKAUDWiQAEs9J5iNpBeM1f8SrX8Dy4vJwV7E/5enkL84A==",
"cpu": [
"x64"
],
+ "license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@yuku-toolchain/types": {
- "version": "0.6.11",
- "resolved": "https://registry.npmjs.org/@yuku-toolchain/types/-/types-0.6.11.tgz",
- "integrity": "sha512-i1JYFNJaKNCgyJ/nVoR8GK7wvlXF+ShYzFHBauWcvg8IoiXInK7pVziHcgNz/MWLPNr/Mb/CtmXccrJMkKqSHQ==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@yuku-toolchain/types/-/types-0.8.1.tgz",
+ "integrity": "sha512-HcGEV3kOn9evBTm2ARYOFNKAI7sY9twQozCVd9EVdlsBlnKi0a2iv8xXxYVHFCBQpX3SvvPXBhk8lcK6NUTdNg==",
"license": "MIT"
},
"node_modules/acorn": {
@@ -3225,9 +3225,9 @@
}
},
"node_modules/cnfast": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/cnfast/-/cnfast-0.0.8.tgz",
- "integrity": "sha512-EjXKMfGfdwtV4AcNSQ6AwQaVzpC1B7IxeiwA3FlhTXz+YFlMKVi4c1JX9tgD2QOlahQXjB8KUXrBaYG+3v871Q==",
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/cnfast/-/cnfast-0.1.0.tgz",
+ "integrity": "sha512-rH0jBKeLkVrK7NsZ5Ba2l7WdMBmm1k0FMpABeXUU1PgTUxbz3261gEuCSsrYuXo4BwAe3yCcIbQ93YyS52lOGQ==",
"license": "MIT",
"bin": {
"cnfast": "bin/cli.js"
@@ -3572,12 +3572,12 @@
}
},
"node_modules/framer-motion": {
- "version": "12.42.2",
- "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.42.2.tgz",
- "integrity": "sha512-5XY9luDiu0oHfHBjpDthFMh0ES+122w6p/papSJBweMkO8Sn+PW2QaEgRblQBpWFnuvZS5qvarpt/hO2pjGmnw==",
+ "version": "12.43.0",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.43.0.tgz",
+ "integrity": "sha512-1eaL3RvR/kAlbG7UYcpMptEyzPoENO0c6w7ZnB3/hh2vSAz/6uGAFn6fdoqTBguNstf3MsFhJHsD/0DHiclG+g==",
"license": "MIT",
"dependencies": {
- "motion-dom": "^12.42.2",
+ "motion-dom": "^12.43.0",
"motion-utils": "^12.39.0",
"tslib": "^2.4.0"
},
@@ -3599,19 +3599,18 @@
}
},
"node_modules/fumadocs-core": {
- "version": "16.12.1",
- "resolved": "https://registry.npmjs.org/fumadocs-core/-/fumadocs-core-16.12.1.tgz",
- "integrity": "sha512-6NnDxUqe0hIiShbWjqvLXvPYV0n0gi01UHmDAkDs5KVcfxfgOPz5bAbj45JDY0Ykq39Mr8z1xRt9h/HwIhe8fw==",
+ "version": "16.14.0",
+ "resolved": "https://registry.npmjs.org/fumadocs-core/-/fumadocs-core-16.14.0.tgz",
+ "integrity": "sha512-CQBsVm2XoxytoK5iTxd2Q3L76XBXY9yrWdThH9iJxZPcZ4aHED7YJCYuHPHZDIWg80fy1UAgVc6ogfE+24jTDA==",
"license": "MIT",
"dependencies": {
- "@orama/orama": "^3.1.18",
"estree-util-value-to-estree": "^3.5.0",
"github-slugger": "^2.0.0",
"hast-util-to-estree": "^3.1.3",
"hast-util-to-jsx-runtime": "^2.3.6",
"mdast-util-mdx": "^3.0.0",
"mdast-util-to-markdown": "^2.1.2",
- "npm-to-yarn": "3.1.0",
+ "npm-to-yarn": "3.2.0",
"remark": "^15.0.1",
"remark-gfm": "^4.0.1",
"remark-rehype": "^11.1.2",
@@ -3621,7 +3620,8 @@
"unified": "^11.0.5",
"unist-util-visit": "^5.1.0",
"vfile": "^6.0.3",
- "yaml": "^2.9.0"
+ "yaml": "^2.9.0",
+ "zbsearch": "^3.3.4"
},
"peerDependencies": {
"@mdx-js/mdx": "*",
@@ -3701,9 +3701,9 @@
}
},
"node_modules/fumadocs-mdx": {
- "version": "15.2.0",
- "resolved": "https://registry.npmjs.org/fumadocs-mdx/-/fumadocs-mdx-15.2.0.tgz",
- "integrity": "sha512-+yBP8QYw5wA9LF5eVdMhwbP7KT1OF4B/YfC6PZoD2jz0amZi1B+6QHTI6XoRRSTmhWrI4cL5LU1DspW0itk+NA==",
+ "version": "15.2.1",
+ "resolved": "https://registry.npmjs.org/fumadocs-mdx/-/fumadocs-mdx-15.2.1.tgz",
+ "integrity": "sha512-lyx35MAFAj9yuLPudNoRGGvauZlT1xRLLw17P0jnvhXikrJNC8mAeg/4WIity5K+3V6ZetBQ2PYIcnli450vMg==",
"license": "MIT",
"dependencies": {
"@mdx-js/mdx": "^3.1.1",
@@ -3712,7 +3712,7 @@
"esbuild": "^0.28.1",
"estree-util-value-to-estree": "^3.5.0",
"github-slugger": "^2.0.0",
- "magic-string": "^0.30.21",
+ "magic-string": "^1.1.0",
"mdast-util-mdx": "^3.0.0",
"picocolors": "^1.1.1",
"picomatch": "^4.0.5",
@@ -3723,7 +3723,7 @@
"unist-util-visit": "^5.1.0",
"vfile": "^6.0.3",
"yaml": "^2.9.0",
- "yuku-analyzer": "^0.6.3",
+ "yuku-analyzer": "^0.8.1",
"zod": "^4.4.3"
},
"bin": {
@@ -3775,28 +3775,37 @@
}
}
},
+ "node_modules/fumadocs-mdx/node_modules/magic-string": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.1.0.tgz",
+ "integrity": "sha512-kS3VHe0nEPST2saQV4Rbkchcd3UBRkVTQHo1D3h/ZTwFDhai/mfKkmtPAtD129EOI7K3HlHIsFOt0WrI2/oU9g==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
"node_modules/fumadocs-ui": {
- "version": "16.12.1",
- "resolved": "https://registry.npmjs.org/fumadocs-ui/-/fumadocs-ui-16.12.1.tgz",
- "integrity": "sha512-/YYERe99PJYw09RiYmCetdcu9uIjrUff+uoYk1EzgTLNtKlt2FNJJCcWYykG76wWlT28hXRs1bt8eFVq9dIU9w==",
+ "version": "16.14.0",
+ "resolved": "https://registry.npmjs.org/fumadocs-ui/-/fumadocs-ui-16.14.0.tgz",
+ "integrity": "sha512-MijJ96VzC1EPOGJutf+t6ptuGRl2y4h33iwECmM79TvEHvf8Uxtnb1vFMQz0labHvuN/lSR1bV2SENH7t28W4w==",
"license": "MIT",
"dependencies": {
"@fuma-translate/react": "^1.0.2",
"@fumadocs/tailwind": "0.1.1",
- "@radix-ui/react-accordion": "^1.2.17",
- "@radix-ui/react-collapsible": "^1.1.17",
- "@radix-ui/react-dialog": "^1.1.20",
- "@radix-ui/react-direction": "^1.1.2",
- "@radix-ui/react-navigation-menu": "^1.2.19",
- "@radix-ui/react-popover": "^1.1.20",
- "@radix-ui/react-presence": "^1.1.8",
- "@radix-ui/react-scroll-area": "^1.2.15",
- "@radix-ui/react-slot": "^1.3.0",
- "@radix-ui/react-tabs": "^1.1.18",
+ "@radix-ui/react-accordion": "^1.2.20",
+ "@radix-ui/react-collapsible": "^1.1.20",
+ "@radix-ui/react-dialog": "^1.1.23",
+ "@radix-ui/react-direction": "^1.1.4",
+ "@radix-ui/react-navigation-menu": "^1.2.22",
+ "@radix-ui/react-popover": "^1.1.23",
+ "@radix-ui/react-presence": "^1.1.10",
+ "@radix-ui/react-scroll-area": "^1.2.18",
+ "@radix-ui/react-slot": "^1.3.3",
+ "@radix-ui/react-tabs": "^1.1.21",
"class-variance-authority": "^0.7.1",
- "cnfast": "^0.0.8",
- "lucide-react": "^1.25.0",
- "motion": "^12.42.2",
+ "cnfast": "^0.1.0",
+ "lucide-react": "^1.27.0",
+ "motion": "^12.43.0",
"next-themes": "^0.4.6",
"react-remove-scroll": "^2.7.2",
"rehype-raw": "^7.0.0",
@@ -3807,7 +3816,7 @@
"peerDependencies": {
"@types/mdx": "*",
"@types/react": "*",
- "fumadocs-core": "16.12.1",
+ "fumadocs-core": "16.14.0",
"next": "16.x.x",
"react": "^19.2.0",
"react-dom": "^19.2.0",
@@ -4564,9 +4573,9 @@
}
},
"node_modules/lucide-react": {
- "version": "1.26.0",
- "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.26.0.tgz",
- "integrity": "sha512-raglYVR2+VkMfJL158krjVmE+rV5ST2lzA/KQm1FRSjMHT4MnWaegHxoVEpmc2So3nOEhp9oGejJwAPX8MoAjg==",
+ "version": "1.28.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.28.0.tgz",
+ "integrity": "sha512-fARAFJULsGuDDydjp6+6blekG/sBIM29TerzLjc9bQUKAcEfrSc4ZQKb25KRz4OMKd87cZTb5dgq0w/T6KufVg==",
"license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
@@ -4576,6 +4585,7 @@
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
@@ -5623,12 +5633,12 @@
"license": "MIT"
},
"node_modules/motion": {
- "version": "12.42.2",
- "resolved": "https://registry.npmjs.org/motion/-/motion-12.42.2.tgz",
- "integrity": "sha512-Atvv11yUKIid41cVrRBDVX5m8tF8kNpExRSlbpt6APClhDjtwQssgFHhQzejxw7/7YYbjHSPKBVbHo05BuJT5Q==",
+ "version": "12.43.0",
+ "resolved": "https://registry.npmjs.org/motion/-/motion-12.43.0.tgz",
+ "integrity": "sha512-BQgQbSa9Hn3/mtbib0MK53y6JSANa+YKUKlaYnWzAVDH424RYQ5LVpV3pNiWH00BA2z4ojsSdMzqT7g2FQwjuQ==",
"license": "MIT",
"dependencies": {
- "framer-motion": "^12.42.2",
+ "framer-motion": "^12.43.0",
"tslib": "^2.4.0"
},
"peerDependencies": {
@@ -5649,9 +5659,9 @@
}
},
"node_modules/motion-dom": {
- "version": "12.42.2",
- "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.42.2.tgz",
- "integrity": "sha512-5gIMWLp/PycBtJRJWRgjxke5n8dlvkSn2DrYW+tr3XcqAZY1xZh6BJyooJXCM8wdfM7wfMjkBJNLge1CKPUIRA==",
+ "version": "12.43.0",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.43.0.tgz",
+ "integrity": "sha512-azKON4d9S65PEoFUiQTMTgPheEmzf2QngdRc50AKfJp9Q9mmcBVw22c8eMq9k8kxOFHdL7+WZY7N/5F/lwiDag==",
"license": "MIT",
"dependencies": {
"motion-utils": "^12.39.0"
@@ -5688,12 +5698,12 @@
}
},
"node_modules/next": {
- "version": "16.2.11",
- "resolved": "https://registry.npmjs.org/next/-/next-16.2.11.tgz",
- "integrity": "sha512-B339zaqbyK8cmxhoAvLrcwoabwCP1wz21zSzfqxqXAemTu2BXnH7tQnfcglKv1vnMUIDBc+Hth7XODQriTZiRQ==",
+ "version": "16.2.12",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.2.12.tgz",
+ "integrity": "sha512-iD59eYQWmbFcEbX7v/acG5DRym9iw1DdaPoD0WTA920naWsE25wShzJW4+UvAs8MK9EC2kBfIH6vtto1H1PHGw==",
"license": "MIT",
"dependencies": {
- "@next/env": "16.2.11",
+ "@next/env": "16.2.12",
"@swc/helpers": "0.5.15",
"baseline-browser-mapping": "^2.9.19",
"caniuse-lite": "^1.0.30001579",
@@ -5707,14 +5717,14 @@
"node": ">=20.9.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "16.2.11",
- "@next/swc-darwin-x64": "16.2.11",
- "@next/swc-linux-arm64-gnu": "16.2.11",
- "@next/swc-linux-arm64-musl": "16.2.11",
- "@next/swc-linux-x64-gnu": "16.2.11",
- "@next/swc-linux-x64-musl": "16.2.11",
- "@next/swc-win32-arm64-msvc": "16.2.11",
- "@next/swc-win32-x64-msvc": "16.2.11",
+ "@next/swc-darwin-arm64": "16.2.12",
+ "@next/swc-darwin-x64": "16.2.12",
+ "@next/swc-linux-arm64-gnu": "16.2.12",
+ "@next/swc-linux-arm64-musl": "16.2.12",
+ "@next/swc-linux-x64-gnu": "16.2.12",
+ "@next/swc-linux-x64-musl": "16.2.12",
+ "@next/swc-win32-arm64-msvc": "16.2.12",
+ "@next/swc-win32-x64-msvc": "16.2.12",
"sharp": "^0.34.5"
},
"peerDependencies": {
@@ -5751,9 +5761,9 @@
}
},
"node_modules/npm-to-yarn": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/npm-to-yarn/-/npm-to-yarn-3.1.0.tgz",
- "integrity": "sha512-9gNsO/JB3LeWOZXBX09cKMsCPwVcu1ExIf+GUuTN9G+0zZvLIK0nU9+lE9jue3MSKAxPdrh0rO072mWNvciqeQ==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/npm-to-yarn/-/npm-to-yarn-3.2.0.tgz",
+ "integrity": "sha512-K1HmQeZT2HrjpsR6KgqbN2FAXL2NrJJmNUSD9ck7HGTVu1JKXox8n9SB+tjbU8m8JGLF4OscrroPepew/L7/Xw==",
"license": "MIT",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -5835,9 +5845,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.23",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz",
- "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==",
+ "version": "8.5.25",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
+ "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
"funding": [
{
"type": "opencollective",
@@ -6711,42 +6721,45 @@
}
},
"node_modules/yuku-analyzer": {
- "version": "0.6.12",
- "resolved": "https://registry.npmjs.org/yuku-analyzer/-/yuku-analyzer-0.6.12.tgz",
- "integrity": "sha512-0zu/gwv6nKA3wm2GMjM1iczw9rbt77ijEyR5tXpPQ8AZcXIpXlll66BXOtMHgYudLn91bJx0ybhpARoJWm5/dw==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/yuku-analyzer/-/yuku-analyzer-0.8.1.tgz",
+ "integrity": "sha512-pe8fmP1Fv0MJh+3+i0EXWzdD2isTzUwJVQc0vmL6mTIcWypo+l0zRiNzwDruO2uZ38kvJ7/CQMhBm5hLuaYWkw==",
"license": "MIT",
"dependencies": {
- "@yuku-toolchain/types": "0.6.11",
- "yuku-ast": "0.6.11"
+ "@yuku-toolchain/types": "^0.8.1",
+ "yuku-ast": "^0.8.1"
},
"optionalDependencies": {
- "@yuku-analyzer/binding-darwin-arm64": "0.6.12",
- "@yuku-analyzer/binding-darwin-x64": "0.6.12",
- "@yuku-analyzer/binding-freebsd-x64": "0.6.12",
- "@yuku-analyzer/binding-linux-arm-gnu": "0.6.12",
- "@yuku-analyzer/binding-linux-arm-musl": "0.6.12",
- "@yuku-analyzer/binding-linux-arm64-gnu": "0.6.12",
- "@yuku-analyzer/binding-linux-arm64-musl": "0.6.12",
- "@yuku-analyzer/binding-linux-x64-gnu": "0.6.12",
- "@yuku-analyzer/binding-linux-x64-musl": "0.6.12",
- "@yuku-analyzer/binding-win32-arm64": "0.6.12",
- "@yuku-analyzer/binding-win32-x64": "0.6.12"
+ "@yuku-analyzer/binding-darwin-arm64": "0.8.1",
+ "@yuku-analyzer/binding-darwin-x64": "0.8.1",
+ "@yuku-analyzer/binding-freebsd-x64": "0.8.1",
+ "@yuku-analyzer/binding-linux-arm-gnu": "0.8.1",
+ "@yuku-analyzer/binding-linux-arm-musl": "0.8.1",
+ "@yuku-analyzer/binding-linux-arm64-gnu": "0.8.1",
+ "@yuku-analyzer/binding-linux-arm64-musl": "0.8.1",
+ "@yuku-analyzer/binding-linux-x64-gnu": "0.8.1",
+ "@yuku-analyzer/binding-linux-x64-musl": "0.8.1",
+ "@yuku-analyzer/binding-win32-arm64": "0.8.1",
+ "@yuku-analyzer/binding-win32-x64": "0.8.1"
}
},
"node_modules/yuku-ast": {
- "version": "0.6.11",
- "resolved": "https://registry.npmjs.org/yuku-ast/-/yuku-ast-0.6.11.tgz",
- "integrity": "sha512-ZfXkFYVsDewS45+kv3WiA/qNB73CRfxFDEQwfnRMUAR4AD5zRI7PRqxmI2U3Jz/oG41GneTVW6mxDOQal0lgeA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/yuku-ast/-/yuku-ast-0.8.1.tgz",
+ "integrity": "sha512-+k1E2f08y0k1+vpdD1KUCzDh2JXvwirMa8YR2Jr7VCS4zAo3eT5A/HbJCqaVGd6idaPY0gwLM9C4seEY4h10Hw==",
"license": "MIT",
"dependencies": {
- "@yuku-toolchain/types": "0.6.8"
+ "@yuku-toolchain/types": "^0.8.1"
}
},
- "node_modules/yuku-ast/node_modules/@yuku-toolchain/types": {
- "version": "0.6.8",
- "resolved": "https://registry.npmjs.org/@yuku-toolchain/types/-/types-0.6.8.tgz",
- "integrity": "sha512-AbUd1775RVkOxJkh8hkldIWoU6kRMTCsZFSZq8Ny53q7GkbaVe5UCfleNZ3RWCoz/ZKE8qwfeB7Cj0xqhLWsKA==",
- "license": "MIT"
+ "node_modules/zbsearch": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/zbsearch/-/zbsearch-3.3.4.tgz",
+ "integrity": "sha512-xGsv9rIwrili/fpLpVwmnCovEcvaAJg1ey+3Ur0+m3x1mnGoVO71iAwn4op420QLGNsQJNmScZjFq5TQ+cRi/g==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 20.0.0"
+ }
},
"node_modules/zod": {
"version": "4.4.3",
diff --git a/apps/web/package.json b/apps/web/package.json
index 5171bf4f3..c8fbdc3af 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -33,28 +33,28 @@
"fumadocs-mdx": "^15.0.12",
"fumadocs-ui": "^16.10.5",
"lucide-react": "^1.14.0",
- "next": "16.2.11",
+ "next": "16.2.12",
"react": "19.2.8",
"react-dom": "19.2.8",
"remark-custom-heading-id": "^2.0.0",
"tailwind-merge": "^3.6.0"
},
"devDependencies": {
- "@biomejs/biome": "2.5.5",
+ "@biomejs/biome": "2.5.6",
"@tailwindcss/postcss": "4.3.3",
"@types/node": "25.9.5",
- "@types/react": "19.2.17",
- "@types/react-dom": "19.2.3",
+ "@types/react": "19.2.18",
+ "@types/react-dom": "19.2.4",
"lefthook": "2.1.10",
"tailwindcss": "4.3.3",
"typescript": "6.0.3"
},
"overrides": {
- "postcss": "8.5.23",
+ "postcss": "8.5.25",
"esbuild": "0.28.1",
- "js-yaml": "4.3.0",
+ "js-yaml": "4.3.1",
"sharp": "0.35.3",
- "@types/react": "19.2.17",
- "@types/react-dom": "19.2.3"
+ "@types/react": "19.2.18",
+ "@types/react-dom": "19.2.4"
}
}
diff --git a/apps/web/src/lib/site-config.ts b/apps/web/src/lib/site-config.ts
index 224da539f..416395f6b 100644
--- a/apps/web/src/lib/site-config.ts
+++ b/apps/web/src/lib/site-config.ts
@@ -15,7 +15,7 @@ export const SITE_CONFIG = {
/** Brand name shown in the header, footer, and metadata. */
name: "Drydock",
/** Current release version shown in the hero badge. */
- version: "1.6.0-rc.11",
+ version: "1.6.0-rc.12",
/** Short product tagline used in page titles and OG metadata. */
tagline: "Container Update Monitoring",
/** Default meta / OpenGraph / Twitter description. */
diff --git a/apps/web/src/lib/site-content.ts b/apps/web/src/lib/site-content.ts
index 8711146f7..31b54387c 100644
--- a/apps/web/src/lib/site-content.ts
+++ b/apps/web/src/lib/site-content.ts
@@ -281,7 +281,7 @@ export const roadmap: Milestone[] = [
],
},
{
- version: "v1.6.0-rc.11",
+ version: "v1.6.0-rc.12",
title: "Notifications, Policy & Release Intel",
emoji: "\u{1F4E8}",
status: "next",
diff --git a/content/docs/current/api/agent.mdx b/content/docs/current/api/agent.mdx
index 0d733b186..7faf7d032 100644
--- a/content/docs/current/api/agent.mdx
+++ b/content/docs/current/api/agent.mdx
@@ -23,7 +23,7 @@ curl http://drydock:3000/api/v1/agents
"host": "192.168.1.50",
"port": 3000,
"connected": true,
- "version": "1.6.0-rc.11",
+ "version": "1.6.0-rc.12",
"os": "linux",
"arch": "amd64",
"cpus": 4,
@@ -153,7 +153,7 @@ Sent immediately upon connection to confirm the handshake.
{
"type": "dd:ack",
"data": {
- "version": "1.6.0-rc.11",
+ "version": "1.6.0-rc.12",
"os": "linux",
"arch": "amd64",
"cpus": 4,
diff --git a/content/docs/current/api/app.mdx b/content/docs/current/api/app.mdx
index ef618d865..adb8430d1 100644
--- a/content/docs/current/api/app.mdx
+++ b/content/docs/current/api/app.mdx
@@ -12,7 +12,7 @@ curl http://drydock:3000/api/v1/app
{
"name":"drydock",
- "version":"1.6.0-rc.11"
+ "version":"1.6.0-rc.12"
}
```
diff --git a/content/docs/current/api/portwing.mdx b/content/docs/current/api/portwing.mdx
index fb870bd26..36b692e5a 100644
--- a/content/docs/current/api/portwing.mdx
+++ b/content/docs/current/api/portwing.mdx
@@ -197,7 +197,7 @@ A versioned alias `/api/v1/portwing/ws` is also accepted and is signature-equiva
"agentId": "edge-host-01",
"agentName": "edge-host-01",
"protocol": "portwing/1.0",
- "version": "1.6.0-rc.11",
+ "version": "1.6.0-rc.12",
"pubKeyId": "3f8a1c2e9b047d56",
"timestamp": 1780329600,
"nonce": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
@@ -220,7 +220,7 @@ A name collision with an already-connected agent under the same key (or the in-f
"data": {
"pollInterval": 300,
"config": {
- "drydockVersion": "1.6.0-rc.11",
+ "drydockVersion": "1.6.0-rc.12",
"supportedProtocols": "portwing/1.0",
"serverCompatLevel": "1.4.0"
}
diff --git a/content/docs/current/quickstart/index.mdx b/content/docs/current/quickstart/index.mdx
index 27b31900c..f0c50bbd4 100644
--- a/content/docs/current/quickstart/index.mdx
+++ b/content/docs/current/quickstart/index.mdx
@@ -108,7 +108,7 @@ Release tags use the same channel names in every registry:
| Tag | Behavior |
| --- | --- |
-| `1.6.0-rc.11` | Immutable release candidate; best for reproducible testing |
+| `1.6.0-rc.12` | Immutable release candidate; best for reproducible testing |
| `1.6-rc` | Rolling release-candidate channel; moves to the newest `1.6.0-rc.N` |
| `1.6` | Rolling stable minor channel; published only for GA releases |
| `1` | Rolling stable major channel; published only for GA releases |
diff --git a/content/docs/current/updates/index.mdx b/content/docs/current/updates/index.mdx
index f6a1c6d62..e32a8c3f3 100644
--- a/content/docs/current/updates/index.mdx
+++ b/content/docs/current/updates/index.mdx
@@ -5,6 +5,14 @@ description: "Release update notes and feature highlights, with direct links to
## Unreleased
+## v1.6.0-rc.12 Highlights — August 4, 2026
+
+- **Security dependency refresh** — `brace-expansion` advanced to 5.0.9 across the app, UI, and e2e workspaces (CVE-2026-69152), `ip-address` to 10.3.1 in the app runtime (CVE-2026-54272, CVE-2026-69192, CVE-2026-69198), and `fast-uri` to 4.1.2 in app and UI (backslash-authority host confusion, CVE-2026-18446) ([#659](https://github.com/CodesWhat/drydock/pull/659)).
+- **Maturity badge and gate agree again** — the hot/mature badge now resolves each container's own `updatePolicy.maturityMinAgeDays` before the global `DD_UI_MATURITY_THRESHOLD_DAYS`, matching the gate, and registry publish-date lookup failures (including GHCR/LSCR auth errors) log at `warn` instead of vanishing at `debug` ([#604](https://github.com/CodesWhat/drydock/issues/604)).
+- **No more transient "Agent Mismatch"** — the container list and SSE stream soften `agent-mismatch`/`no-update-trigger-configured` to soft blockers while an agent's components are mid-(re)registration; update admission stays fail-closed throughout ([#605](https://github.com/CodesWhat/drydock/issues/605)).
+- **WebSocket log streams accept anonymous-auth sessions** — under `DD_ANONYMOUS_AUTH_CONFIRM=true`, both the system and container log-stream upgrades now pass the same auth gate as every REST endpoint ([#636](https://github.com/CodesWhat/drydock/issues/636)).
+- **Explicit 501 for missing agent lifecycle transport** — start/stop/restart/rollback on an agent-owned container without controller Docker transport returns a 501 naming the cause instead of an ambiguous 404 ([#637](https://github.com/CodesWhat/drydock/issues/637)).
+
## v1.6.0-rc.11 Highlights — August 1, 2026
- **Portwing 0.9 Docker watcher, updates, and lifecycle actions now run controller-side** — Drydock 1.6.0-rc.11+ recognizes the exact `transport=docker-api`, `execution=controller`, `events=portwing` watcher marker, starts its native registry checks and Docker action against a loopback-only authenticated bridge, and carries Docker calls over Standard HTTP or Edge correlated request/response/stream transport. Single/batch updates, start/stop/restart, update preview, and backup rollback use this path even though Portwing advertises no remote trigger. Portwing stays authoritative for lifecycle events, and raw false/unknown inventory no longer erases controller enrichment ([#632](https://github.com/CodesWhat/drydock/issues/632), [#637](https://github.com/CodesWhat/drydock/issues/637), [Portwing #76](https://github.com/CodesWhat/portwing/issues/76)).
diff --git a/e2e/package-lock.json b/e2e/package-lock.json
index 64ce3b209..990ec8519 100644
--- a/e2e/package-lock.json
+++ b/e2e/package-lock.json
@@ -3658,9 +3658,9 @@
"license": "MIT"
},
"node_modules/brace-expansion": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
- "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
diff --git a/e2e/package.json b/e2e/package.json
index f5fe345eb..f590bb54b 100644
--- a/e2e/package.json
+++ b/e2e/package.json
@@ -37,7 +37,7 @@
"lodash": "4.18.1"
},
"overrides": {
- "brace-expansion": "5.0.8",
+ "brace-expansion": "5.0.9",
"fast-xml-parser": "5.10.1",
"joi": "18.2.3",
"minimatch": "10.2.5",
diff --git a/e2e/tests/security/brace-expansion-lockfile.test.js b/e2e/tests/security/brace-expansion-lockfile.test.js
index d76fa6339..dac567b6a 100644
--- a/e2e/tests/security/brace-expansion-lockfile.test.js
+++ b/e2e/tests/security/brace-expansion-lockfile.test.js
@@ -3,7 +3,7 @@ const { readFileSync } = require('node:fs');
const { join } = require('node:path');
const test = require('node:test');
-const MINIMUM_SAFE_BRACE_EXPANSION_VERSION = '5.0.7';
+const MINIMUM_SAFE_BRACE_EXPANSION_VERSION = '5.0.9';
function compareSemver(a, b) {
const aParts = a.split('.').map(Number);
diff --git a/package-lock.json b/package-lock.json
index 331f70ef7..c21983ba1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,7 +7,7 @@
"": {
"version": "1.6.0",
"devDependencies": {
- "@biomejs/biome": "2.5.5",
+ "@biomejs/biome": "2.5.6",
"@types/node": "25.9.5",
"lefthook": "2.1.10",
"vitest": "4.1.10",
@@ -18,9 +18,9 @@
}
},
"node_modules/@biomejs/biome": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.5.tgz",
- "integrity": "sha512-r1S8nFsAG1MY+vJFZALzIvwXAJv6ejDQ0mxP21Tgr9YK3ZFtjrvbBwDdNhx1rUqvccEIeNg20cYCNzl6Cr69pQ==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.6.tgz",
+ "integrity": "sha512-lxVNjv7UF6KfhMJfL9gaUHbWdJdHbsAj6OSmwSYNdhRuG67NxNQ4Xdvh3TUxsSK9sBzJBQhEJj3AopmmNJ5pSA==",
"dev": true,
"license": "MIT OR Apache-2.0",
"bin": {
@@ -34,20 +34,20 @@
"url": "https://opencollective.com/biome"
},
"optionalDependencies": {
- "@biomejs/cli-darwin-arm64": "2.5.5",
- "@biomejs/cli-darwin-x64": "2.5.5",
- "@biomejs/cli-linux-arm64": "2.5.5",
- "@biomejs/cli-linux-arm64-musl": "2.5.5",
- "@biomejs/cli-linux-x64": "2.5.5",
- "@biomejs/cli-linux-x64-musl": "2.5.5",
- "@biomejs/cli-win32-arm64": "2.5.5",
- "@biomejs/cli-win32-x64": "2.5.5"
+ "@biomejs/cli-darwin-arm64": "2.5.6",
+ "@biomejs/cli-darwin-x64": "2.5.6",
+ "@biomejs/cli-linux-arm64": "2.5.6",
+ "@biomejs/cli-linux-arm64-musl": "2.5.6",
+ "@biomejs/cli-linux-x64": "2.5.6",
+ "@biomejs/cli-linux-x64-musl": "2.5.6",
+ "@biomejs/cli-win32-arm64": "2.5.6",
+ "@biomejs/cli-win32-x64": "2.5.6"
}
},
"node_modules/@biomejs/cli-darwin-arm64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.5.tgz",
- "integrity": "sha512-kUrAhXVWUrwmAUnV2iXSK7umxKFysTwvqK+Ty6ptUcLY/7T3SnCAjUowE4uvwaEej6nXZ7hu/dTtbokKdsPeag==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.6.tgz",
+ "integrity": "sha512-zMOLZP4oMrjh6m1zcSj1ud2awUPgTuMVbmQhYYWL7J8HwCnbHHBvTm7VBTRuY7epT5bez76IpKYQ11ZAqHFlnw==",
"cpu": [
"arm64"
],
@@ -62,9 +62,9 @@
}
},
"node_modules/@biomejs/cli-darwin-x64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.5.tgz",
- "integrity": "sha512-DamiYc5bUYZ2uxlfc+RLEPtz1Abb6PO5eTbOkufLpSGwd/7AMQAdxhFYiXmwwkJL8IsT8S7GvdgwDHqaMFAvKw==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.6.tgz",
+ "integrity": "sha512-JAC1VqzvO7Th5ZplU0G2uGfkZbxEe9uDDektPAhF0JLusoz1w+T4okp2bkykI0bbaO2vslKiRfj4gU43JaGreA==",
"cpu": [
"x64"
],
@@ -79,9 +79,9 @@
}
},
"node_modules/@biomejs/cli-linux-arm64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.5.tgz",
- "integrity": "sha512-lRKF/pH/1RiYiBKExi3TCZVAtvzEm77aifrvcNiDFrR9WxeAnDUjDnseb6y2XV85mjitLs6SILGm2XG77cHtSQ==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.6.tgz",
+ "integrity": "sha512-6XsYwCFkp5sMxl85ffhgeGpGgs6A7dRYFnkceZ7WVxvycuTnGdD5xa534Z3xfrBQ0JCMK/mujT6ZNPJoghedwg==",
"cpu": [
"arm64"
],
@@ -99,9 +99,9 @@
}
},
"node_modules/@biomejs/cli-linux-arm64-musl": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.5.tgz",
- "integrity": "sha512-U4WMl/sy/E/Q73vf15VspakLRRs2LDFcCeBxJnQfXzssb88zpV6PJPaQ3ezhQ7H6Ht2/8bvuZeHgJWzmoxllZg==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.6.tgz",
+ "integrity": "sha512-eUa3jeeYvfMt19LBeh6E5PUZpxnTC4JqNWo+EDjTtQjAr2xLGnWaxACtVU1DQqmHYbvThlJzLX+ZsYgrqh2qVw==",
"cpu": [
"arm64"
],
@@ -119,9 +119,9 @@
}
},
"node_modules/@biomejs/cli-linux-x64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.5.tgz",
- "integrity": "sha512-H/O39nJEw/2Zm/fm7hrmxxoF8kK/aU1uCoPp70ruXVbomaAdLpJJnCmL11Q2JotT8QVHH06So04Oq53lCSwSwQ==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.6.tgz",
+ "integrity": "sha512-Pop9VXCFUhFTMfFefZ39S+u2rOPyNp5iHlxbZRwXGACHLy2r0jjiRgJHmaEKJzL3SyxlVeGShXhvvElvWowonA==",
"cpu": [
"x64"
],
@@ -139,9 +139,9 @@
}
},
"node_modules/@biomejs/cli-linux-x64-musl": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.5.tgz",
- "integrity": "sha512-m7wC7tjX5Lrmo69dc4md8FeKpPU1NTCY1v7xUoQQ2vadWwNnBS0KZOG8471otFPHrTHihQJAjQPgMObpLvDe6A==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.6.tgz",
+ "integrity": "sha512-2Vp13QdKysH3HIWLaYLhUUwbK+jbZonJD1K+Lr0d0RO4wH7mkYd43vJixEDm8cUWrowoRz4UUHF1nm9Ae7ym8A==",
"cpu": [
"x64"
],
@@ -159,9 +159,9 @@
}
},
"node_modules/@biomejs/cli-win32-arm64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.5.tgz",
- "integrity": "sha512-7BryINPuYypLUAH3o/o5ZdgomJ4zn3EDR0ChZJst7n32S6ZhKbgHXuYydLu+YAnx59ehGFR0z/MG6qnzQi3Yyw==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.6.tgz",
+ "integrity": "sha512-tDGshcm6BdkZOCGnTDX0Y8/U4IfBSlnUU7T56nNDuPEfed+aHg+u8G36NB43fJVl0Os6+QURXIE1yuD7AaEofA==",
"cpu": [
"arm64"
],
@@ -176,9 +176,9 @@
}
},
"node_modules/@biomejs/cli-win32-x64": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.5.tgz",
- "integrity": "sha512-bIBFo+n6MIxdNcVFy5CrurbKiZQiUciK3bt8+O9I4wjFZNTfXLpi+giq47522eXqW5NBc9ulx7dR1SlZKi2J5g==",
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.6.tgz",
+ "integrity": "sha512-WN05KwXnTO/2J45RQPvzZMXf7tZUIofHoR35xIPfCo7pQ2RFidxI8sfb5mGsaTxdMmEOzHzOPRCdA5/fCpc7xQ==",
"cpu": [
"x64"
],
@@ -193,21 +193,21 @@
}
},
"node_modules/@emnapi/core": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
- "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
+ "version": "2.0.0-alpha.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-2.0.0-alpha.3.tgz",
+ "integrity": "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
- "@emnapi/wasi-threads": "1.2.2",
+ "@emnapi/wasi-threads": "2.0.1",
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
- "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
+ "version": "2.0.0-alpha.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-2.0.0-alpha.3.tgz",
+ "integrity": "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -216,9 +216,9 @@
}
},
"node_modules/@emnapi/wasi-threads": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
- "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-2.0.1.tgz",
+ "integrity": "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -234,28 +234,31 @@
"license": "MIT"
},
"node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz",
- "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.1.tgz",
+ "integrity": "sha512-KjZdi8Q1wh89gsVmghvbrMgWl6ZWmRmHV6wjB7/g4Zf0dyO+hH3neZUtuDNPO00qq5YE5RITVWvrIZKRaAmzGQ==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@tybys/wasm-util": "^0.10.3"
},
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
+ },
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
},
"peerDependencies": {
- "@emnapi/core": "^1.7.1",
- "@emnapi/runtime": "^1.7.1"
+ "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3",
+ "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3"
}
},
"node_modules/@oxc-project/types": {
- "version": "0.139.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz",
- "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.142.0.tgz",
+ "integrity": "sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==",
"dev": true,
"license": "MIT",
"funding": {
@@ -263,9 +266,9 @@
}
},
"node_modules/@rolldown/binding-android-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz",
- "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.1.tgz",
+ "integrity": "sha512-02hOeOSryYxVrOIphmLAsqnCJWxwlzFk+pEt/N/i6OgT3lShHO7xGCU5cpgchRDHboAEbSjzgGh+O/u1GswQmA==",
"cpu": [
"arm64"
],
@@ -280,9 +283,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz",
- "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.1.tgz",
+ "integrity": "sha512-fMsTOnN0OjFm3CyppWPitKnc8UlliVARUULW6cfU6AIqjdtgmSFWSk9vecHzZduv/yMWIHDlRhM1e8Iff9uAfA==",
"cpu": [
"arm64"
],
@@ -297,9 +300,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz",
- "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.1.tgz",
+ "integrity": "sha512-1wjKdz/XLGKHaTNHjQveQ/B23TKx4ItAqm1JbyVuvNPc4Ze0Fb48s49TAd/2zcplPl8okE/UbTgmlVfwT7eFeQ==",
"cpu": [
"x64"
],
@@ -314,9 +317,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz",
- "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.1.tgz",
+ "integrity": "sha512-Fa0jHR07E7YBN4vOEsbVf2briYNsuOowfLJaXULZM0ldMlaCaj2LJgLMbMe4iacRyZmvR8efFhgR9wKuGclQUg==",
"cpu": [
"x64"
],
@@ -331,9 +334,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz",
- "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.1.tgz",
+ "integrity": "sha512-pzkgu1SSHGgRRyRZ4fbmSgmajbVt+epaLP99NDjFft69v/ypfTi6swBMiVdh2EkQ0OSnHE1lZDM7DRGkyAzUpA==",
"cpu": [
"arm"
],
@@ -348,9 +351,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz",
- "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.1.tgz",
+ "integrity": "sha512-QI5SEDY8cbiYWHx0VO4vIc3UlS6a32vXHjU8Qy/17adEmZIPuByJg13UEvo9c/UCiUkdcVWY83C+b+JrwnNyUg==",
"cpu": [
"arm64"
],
@@ -368,9 +371,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz",
- "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.1.tgz",
+ "integrity": "sha512-Sm41FyCeXqmYcERoYOCbGIL5hNfd8w9LQ7Y61Bev48HkcjaJqV/iiVOaiDxjVTRMS+QKrZmD8cfPt4uMVnvM+A==",
"cpu": [
"arm64"
],
@@ -388,9 +391,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz",
- "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.1.tgz",
+ "integrity": "sha512-2x+WhXTGl9yJYPbltW/BSEPTVz9OIWQyER4N+gJEDWkkn904eRcBzELqh/Hf7K0w/ubGbKNMv0ZC+94QK/IFEg==",
"cpu": [
"ppc64"
],
@@ -408,9 +411,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz",
- "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.1.tgz",
+ "integrity": "sha512-eEjmQpuRQayHPWWnywaWHkFT3ToPbP3RYy42VVd/B9aBGDA+Ol25EIWHxKQST3IiWJjikCWUF7KtbfqwZrzVwQ==",
"cpu": [
"s390x"
],
@@ -428,9 +431,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz",
- "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.1.tgz",
+ "integrity": "sha512-/Orga1fZYkLc/56jBICcHrKchl8Z2UKdDSr3LG9ToWO1lQ6a4Livk9Xz+9WN91zsz5QR3XQz2NNoSDEvP6qadw==",
"cpu": [
"x64"
],
@@ -448,9 +451,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz",
- "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.1.tgz",
+ "integrity": "sha512-xxBJRL+0q0Kce7orznGWLuylHDY65vuARXZRpX+hPdv+DqK2c3NlCsVA98tlWzWNEE7yPqA/1NQ5nnCrj49Y5A==",
"cpu": [
"x64"
],
@@ -468,9 +471,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz",
- "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.1.tgz",
+ "integrity": "sha512-M6AdXIXw3s+/8XpKMzdGDEXGS1S7kwUsy+rcTIUIOx5Ge4nXKCtAFHFV9YKkXvGcC5WMoTjAteLzlsQROVI0Yw==",
"cpu": [
"arm64"
],
@@ -485,28 +488,25 @@
}
},
"node_modules/@rolldown/binding-wasm32-wasi": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz",
- "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==",
- "cpu": [
- "wasm32"
- ],
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.1.tgz",
+ "integrity": "sha512-/TX0SoRGojHzSAHpfVBbavRVSazg5U3h3Y3VXfcc0cdugq6kxdqw8LPGFiPr+/7gE/60zRcsOY2Vi9b9eT0jww==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
- "@emnapi/core": "1.11.1",
- "@emnapi/runtime": "1.11.1",
- "@napi-rs/wasm-runtime": "^1.1.6"
+ "@emnapi/core": "2.0.0-alpha.3",
+ "@emnapi/runtime": "2.0.0-alpha.3",
+ "@napi-rs/wasm-runtime": "^1.2.0"
},
"engines": {
- "node": "^20.19.0 || >=22.12.0"
+ "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
}
},
"node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz",
- "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.1.tgz",
+ "integrity": "sha512-EvRrivJieyHG+AO9lleZWgq+g0+S7oV2C51yuqlcyU/R9net+sI4Pj0F+lUoP2bEr6TWX3SqFaaS0SzfLxSzkw==",
"cpu": [
"arm64"
],
@@ -521,9 +521,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz",
- "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.1.tgz",
+ "integrity": "sha512-Z4eCmn5QJ/5+azF9knpLWKfVd9aidn0mAe9TpJgvBLId9Ax3t0+JVxBmT25Bv7NBbVW1TZyKjQjQReouMeH5UQ==",
"cpu": [
"x64"
],
@@ -971,9 +971,9 @@
]
},
"node_modules/lightningcss": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
- "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {
@@ -987,23 +987,23 @@
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
- "lightningcss-android-arm64": "1.32.0",
- "lightningcss-darwin-arm64": "1.32.0",
- "lightningcss-darwin-x64": "1.32.0",
- "lightningcss-freebsd-x64": "1.32.0",
- "lightningcss-linux-arm-gnueabihf": "1.32.0",
- "lightningcss-linux-arm64-gnu": "1.32.0",
- "lightningcss-linux-arm64-musl": "1.32.0",
- "lightningcss-linux-x64-gnu": "1.32.0",
- "lightningcss-linux-x64-musl": "1.32.0",
- "lightningcss-win32-arm64-msvc": "1.32.0",
- "lightningcss-win32-x64-msvc": "1.32.0"
+ "lightningcss-android-arm64": "1.33.0",
+ "lightningcss-darwin-arm64": "1.33.0",
+ "lightningcss-darwin-x64": "1.33.0",
+ "lightningcss-freebsd-x64": "1.33.0",
+ "lightningcss-linux-arm-gnueabihf": "1.33.0",
+ "lightningcss-linux-arm64-gnu": "1.33.0",
+ "lightningcss-linux-arm64-musl": "1.33.0",
+ "lightningcss-linux-x64-gnu": "1.33.0",
+ "lightningcss-linux-x64-musl": "1.33.0",
+ "lightningcss-win32-arm64-msvc": "1.33.0",
+ "lightningcss-win32-x64-msvc": "1.33.0"
}
},
"node_modules/lightningcss-android-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
- "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
"cpu": [
"arm64"
],
@@ -1022,9 +1022,9 @@
}
},
"node_modules/lightningcss-darwin-arm64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
- "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
"cpu": [
"arm64"
],
@@ -1043,9 +1043,9 @@
}
},
"node_modules/lightningcss-darwin-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
- "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
"cpu": [
"x64"
],
@@ -1064,9 +1064,9 @@
}
},
"node_modules/lightningcss-freebsd-x64": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
- "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
"cpu": [
"x64"
],
@@ -1085,9 +1085,9 @@
}
},
"node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
- "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
"cpu": [
"arm"
],
@@ -1106,13 +1106,16 @@
}
},
"node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
- "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
"cpu": [
"arm64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1127,13 +1130,16 @@
}
},
"node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
- "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
"cpu": [
"arm64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1148,13 +1154,16 @@
}
},
"node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
- "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
"cpu": [
"x64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1169,13 +1178,16 @@
}
},
"node_modules/lightningcss-linux-x64-musl": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
- "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
"cpu": [
"x64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1190,9 +1202,9 @@
}
},
"node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
- "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
"cpu": [
"arm64"
],
@@ -1211,9 +1223,9 @@
}
},
"node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.32.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
- "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
"cpu": [
"x64"
],
@@ -1299,9 +1311,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.23",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz",
- "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==",
+ "version": "8.5.25",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
+ "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
"dev": true,
"funding": [
{
@@ -1328,13 +1340,13 @@
}
},
"node_modules/rolldown": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz",
- "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.1.tgz",
+ "integrity": "sha512-4FKJhg8d3OiyQOA6Q1Q0hoFFpW9/OoX+VsHzpECsdsIZoOArrAK90gl59YK/Z+gnDel45bgJZK03ozH/9bCqEw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@oxc-project/types": "=0.139.0",
+ "@oxc-project/types": "=0.142.0",
"@rolldown/pluginutils": "^1.0.0"
},
"bin": {
@@ -1344,21 +1356,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
- "@rolldown/binding-android-arm64": "1.1.5",
- "@rolldown/binding-darwin-arm64": "1.1.5",
- "@rolldown/binding-darwin-x64": "1.1.5",
- "@rolldown/binding-freebsd-x64": "1.1.5",
- "@rolldown/binding-linux-arm-gnueabihf": "1.1.5",
- "@rolldown/binding-linux-arm64-gnu": "1.1.5",
- "@rolldown/binding-linux-arm64-musl": "1.1.5",
- "@rolldown/binding-linux-ppc64-gnu": "1.1.5",
- "@rolldown/binding-linux-s390x-gnu": "1.1.5",
- "@rolldown/binding-linux-x64-gnu": "1.1.5",
- "@rolldown/binding-linux-x64-musl": "1.1.5",
- "@rolldown/binding-openharmony-arm64": "1.1.5",
- "@rolldown/binding-wasm32-wasi": "1.1.5",
- "@rolldown/binding-win32-arm64-msvc": "1.1.5",
- "@rolldown/binding-win32-x64-msvc": "1.1.5"
+ "@rolldown/binding-android-arm64": "1.2.1",
+ "@rolldown/binding-darwin-arm64": "1.2.1",
+ "@rolldown/binding-darwin-x64": "1.2.1",
+ "@rolldown/binding-freebsd-x64": "1.2.1",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.1",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.1",
+ "@rolldown/binding-linux-arm64-musl": "1.2.1",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.1",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.1",
+ "@rolldown/binding-linux-x64-gnu": "1.2.1",
+ "@rolldown/binding-linux-x64-musl": "1.2.1",
+ "@rolldown/binding-openharmony-arm64": "1.2.1",
+ "@rolldown/binding-wasm32-wasi": "1.2.1",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.1",
+ "@rolldown/binding-win32-x64-msvc": "1.2.1"
}
},
"node_modules/siginfo": {
@@ -1452,16 +1464,16 @@
"license": "MIT"
},
"node_modules/vite": {
- "version": "8.1.5",
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz",
- "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==",
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.0.tgz",
+ "integrity": "sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "lightningcss": "^1.32.0",
+ "lightningcss": "^1.33.0",
"picomatch": "^4.0.5",
- "postcss": "^8.5.17",
- "rolldown": "~1.1.5",
+ "postcss": "^8.5.23",
+ "rolldown": "~1.2.0",
"tinyglobby": "^0.2.17"
},
"bin": {
@@ -1478,7 +1490,7 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
- "@vitejs/devtools": "^0.3.0",
+ "@vitejs/devtools": "^0.4.0",
"esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
diff --git a/package.json b/package.json
index 54d584ef6..da3d64fba 100644
--- a/package.json
+++ b/package.json
@@ -9,14 +9,14 @@
"node": ">=24.0.0"
},
"devDependencies": {
- "@biomejs/biome": "2.5.5",
+ "@biomejs/biome": "2.5.6",
"@types/node": "25.9.5",
"lefthook": "2.1.10",
"vitest": "4.1.10",
"yaml": "2.9.0"
},
"overrides": {
- "vite": "8.1.5",
- "postcss": "8.5.23"
+ "vite": "8.2.0",
+ "postcss": "8.5.25"
}
}
diff --git a/scripts/changelog-links.test.mjs b/scripts/changelog-links.test.mjs
index 180c02d87..86e816bd9 100644
--- a/scripts/changelog-links.test.mjs
+++ b/scripts/changelog-links.test.mjs
@@ -56,7 +56,8 @@ test('every linked changelog heading has exactly one link definition', () => {
test('v1.6 RC and v1.5.2 GA have a complete chronological comparison-link chain', () => {
const definitions = new Map(getLinkDefinitions(changelog).map(({ label, url }) => [label, url]));
const expected = new Map([
- ['Unreleased', `${repositoryUrl}/compare/v1.6.0-rc.11...HEAD`],
+ ['Unreleased', `${repositoryUrl}/compare/v1.6.0-rc.12...HEAD`],
+ ['1.6.0-rc.12', `${repositoryUrl}/compare/v1.6.0-rc.11...v1.6.0-rc.12`],
['1.6.0-rc.11', `${repositoryUrl}/compare/v1.6.0-rc.10...v1.6.0-rc.11`],
['1.6.0-rc.10', `${repositoryUrl}/compare/v1.6.0-rc.9...v1.6.0-rc.10`],
['1.6.0-rc.9', `${repositoryUrl}/compare/v1.6.0-rc.8...v1.6.0-rc.9`],
diff --git a/scripts/release-docs-identity.test.mjs b/scripts/release-docs-identity.test.mjs
index b1c1cc764..5f71f390b 100644
--- a/scripts/release-docs-identity.test.mjs
+++ b/scripts/release-docs-identity.test.mjs
@@ -2,10 +2,10 @@ import assert from 'node:assert/strict';
import { readdirSync, readFileSync } from 'node:fs';
import test from 'node:test';
-const RC_VERSION = '1.6.0-rc.11';
-const PREV_RC_VERSION = '1.6.0-rc.10';
-const RC_DATE = '2026-08-01';
-const RC_DISPLAY_DATE = 'August 1, 2026';
+const RC_VERSION = '1.6.0-rc.12';
+const PREV_RC_VERSION = '1.6.0-rc.11';
+const RC_DATE = '2026-08-04';
+const RC_DISPLAY_DATE = 'August 4, 2026';
const DOC_ROOTS = ['content/docs/current', 'content/docs/v1.5'];
const BROAD_401_CLAIM =
/(?:all|every) API (?:call|request)s?(?: (?:is|are) rejected with| returns?) `401`/iu;
diff --git a/scripts/release-identity.test.mjs b/scripts/release-identity.test.mjs
index 0e77d78c4..7d6dbfdc8 100644
--- a/scripts/release-identity.test.mjs
+++ b/scripts/release-identity.test.mjs
@@ -3,7 +3,7 @@ import { readFileSync } from 'node:fs';
import test from 'node:test';
const BASE_VERSION = '1.6.0';
-const RC_VERSION = '1.6.0-rc.11';
+const RC_VERSION = '1.6.0-rc.12';
const DEMO_RELEASE_FIXTURES = [
{
path: 'apps/demo/src/mocks/data/server.ts',
diff --git a/scripts/security-dependency-versions.test.mjs b/scripts/security-dependency-versions.test.mjs
index fc85132fd..fc4a05c30 100644
--- a/scripts/security-dependency-versions.test.mjs
+++ b/scripts/security-dependency-versions.test.mjs
@@ -22,39 +22,66 @@ function resolvedVersion(lockfile, packageName) {
return lockfile.packages?.[`node_modules/${packageName}`]?.version;
}
-// The CVE-2026-16221 fix was backported per-line: 3.1.4 on the 3.x line,
-// 4.1.1 on the 4.x line. A plain ">= 3.1.4" semver floor would wrongly pass
-// 4.0.0 and 4.1.0, which are newer than 3.1.4 but predate the 4.x backport
-// and are still vulnerable. Require the patched floor for whichever major
-// line the resolved version is on.
+// Only the 4.x line is vetted now: 4.1.2 carries both the CVE-2026-16221 fix
+// and the backslash-authority host-confusion fix (GHSA-7p8r-x3mc-p8w7).
+// The transitional 3.1.4 branch was dropped once the override moved to 4.x,
+// and any other major (including a future 5.x) fails until explicitly vetted.
function isFastUriPatched(version) {
const major = Number(version.split('.')[0]);
- return major === 3 ? compareSemver(version, '3.1.4') >= 0 : compareSemver(version, '4.1.1') >= 0;
+ return major === 4 && compareSemver(version, '4.1.2') >= 0;
}
-test('isFastUriPatched rejects unpatched 4.x releases newer than 3.1.4', () => {
- assert.ok(isFastUriPatched('3.1.4'), '3.1.4 (3.x floor) should pass');
- assert.ok(!isFastUriPatched('4.1.0'), '4.1.0 predates the 4.x backport and should fail');
- assert.ok(isFastUriPatched('4.1.1'), '4.1.1 (4.x floor) should pass');
+test('isFastUriPatched only accepts vetted 4.x releases at or above 4.1.2', () => {
+ assert.ok(!isFastUriPatched('3.1.4'), '3.x is no longer a supported line and should fail');
+ assert.ok(
+ !isFastUriPatched('4.1.1'),
+ '4.1.1 predates the backslash-authority fix and should fail',
+ );
+ assert.ok(isFastUriPatched('4.1.2'), '4.1.2 (current floor) should pass');
+ assert.ok(!isFastUriPatched('5.0.0'), 'an unvetted future major should fail');
});
-// fast-uri was pinned to 3.1.4 in app/ and ui/ for CVE-2026-16221
-// (GHSA-v2hh-gcrm-f6hx). 4.1.1 retains the fix, and Renovate's override
-// bump to 4.1.1 (#617) is accepted alongside the original pin below.
-// Transitional: drop the 3.1.4 branch once #617 lands.
+// fast-uri is pinned to 4.1.2 in app/ and ui/: it carries the CVE-2026-16221
+// fix (GHSA-v2hh-gcrm-f6hx) plus the backslash-authority host-confusion fix.
test('fast-uri is pinned to a patched release in app and ui', () => {
for (const workspace of ['app', 'ui']) {
const manifest = readJson(`${workspace}/package.json`);
const lockfile = readJson(`${workspace}/package-lock.json`);
+ assert.ok(isFastUriPatched(manifest.overrides?.['fast-uri']), `${workspace} override`);
+ assert.ok(isFastUriPatched(resolvedVersion(lockfile, 'fast-uri')), `${workspace} lockfile`);
+ }
+});
+
+// brace-expansion 5.0.8 was vulnerable to CVE-2026-69152 (GHSA-rgw5-rvv9-x895),
+// patched in 5.0.9.
+test('brace-expansion is pinned to a patched release in app, ui, and e2e', () => {
+ for (const workspace of ['app', 'ui', 'e2e']) {
+ const manifest = readJson(`${workspace}/package.json`);
+ const lockfile = readJson(`${workspace}/package-lock.json`);
+
assert.ok(
- ['3.1.4', '4.1.1'].includes(manifest.overrides?.['fast-uri']),
+ compareSemver(manifest.overrides?.['brace-expansion'], '5.0.9') >= 0,
`${workspace} override`,
);
- assert.ok(isFastUriPatched(resolvedVersion(lockfile, 'fast-uri')), `${workspace} lockfile`);
+ assert.ok(
+ compareSemver(resolvedVersion(lockfile, 'brace-expansion'), '5.0.9') >= 0,
+ `${workspace} lockfile`,
+ );
}
});
+// ip-address 10.2.0 was vulnerable to CVE-2026-54272, CVE-2026-69192, and
+// CVE-2026-69198 (pulled in via express-rate-limit and mqtt -> socks in
+// app), patched in 10.3.1.
+test('ip-address is pinned to a patched release in app', () => {
+ const manifest = readJson('app/package.json');
+ const lockfile = readJson('app/package-lock.json');
+
+ assert.ok(compareSemver(manifest.overrides?.['ip-address'], '10.3.1') >= 0, 'app override');
+ assert.ok(compareSemver(resolvedVersion(lockfile, 'ip-address'), '10.3.1') >= 0, 'app lockfile');
+});
+
test('fast-xml-parser is pinned to the patched release in app', () => {
const manifest = readJson('app/package.json');
const lockfile = readJson('app/package-lock.json');
@@ -76,7 +103,12 @@ test('Next.js is pinned past the 16.2.9 security advisory batch', () => {
const manifest = readJson('apps/web/package.json');
const lockfile = readJson('apps/web/package-lock.json');
- assert.equal(manifest.dependencies?.next, '16.2.11');
+ // Floor, not an exact pin: 16.2.11 closed the advisory batch, and routine
+ // Renovate bumps past it must not fail the guard (16.x only — a new major
+ // is a deliberate migration, not a routine bump).
+ const manifestNext = manifest.dependencies?.next;
+ assert.ok(manifestNext?.startsWith('16.'), 'apps/web next must stay on the vetted 16.x line');
+ assert.ok(compareSemver(manifestNext, '16.2.11') >= 0);
assert.ok(compareSemver(resolvedVersion(lockfile, 'next'), '16.2.11') >= 0);
});
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 08c508fbc..9de7f3259 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -27,7 +27,7 @@
"@iconify-json/fa6-solid": "1.2.4",
"@iconify-json/heroicons": "1.2.3",
"@iconify-json/iconoir": "1.2.11",
- "@iconify-json/lucide": "1.2.120",
+ "@iconify-json/lucide": "1.2.121",
"@iconify-json/ph": "1.2.2",
"@iconify-json/tabler": "1.2.38",
"@stryker-mutator/core": "9.6.1",
@@ -39,9 +39,9 @@
"@vitest/coverage-v8": "4.1.10",
"@vue/test-utils": "2.4.11",
"jsdom": "29.1.1",
- "knip": "6.29.0",
+ "knip": "6.31.0",
"typescript": "6.0.3",
- "vite": "8.1.5",
+ "vite": "8.2.0",
"vitest": "4.1.10"
},
"engines": {
@@ -795,6 +795,7 @@
"integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
"license": "MIT",
"optional": true,
+ "peer": true,
"dependencies": {
"@emnapi/wasi-threads": "1.2.2",
"tslib": "^2.4.0"
@@ -806,6 +807,7 @@
"integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
"license": "MIT",
"optional": true,
+ "peer": true,
"dependencies": {
"tslib": "^2.4.0"
}
@@ -928,9 +930,9 @@
}
},
"node_modules/@iconify-json/lucide": {
- "version": "1.2.120",
- "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.120.tgz",
- "integrity": "sha512-4ECF24fxag1n5tZlPGrbWuCGqhkwD0rvAzfCXretqQb4KEC8Y6ja3khF8qmvpR1Mk0NQDhBTRK3Fr/YoV8QyJw==",
+ "version": "1.2.121",
+ "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.121.tgz",
+ "integrity": "sha512-zSoQQSmsyFaeTpSwURHJ9PIrsDcGFpDNhGlpiTrs+Ua4uFeH5UsE26L4OEBLrgLWoSK0UO+JhsO8yehSw0403g==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -1432,21 +1434,24 @@
}
},
"node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz",
- "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz",
+ "integrity": "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==",
"license": "MIT",
"optional": true,
"dependencies": {
"@tybys/wasm-util": "^0.10.3"
},
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
+ },
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
},
"peerDependencies": {
- "@emnapi/core": "^1.7.1",
- "@emnapi/runtime": "^1.7.1"
+ "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3",
+ "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3"
}
},
"node_modules/@one-ini/wasm": {
@@ -1457,9 +1462,9 @@
"license": "MIT"
},
"node_modules/@oxc-parser/binding-android-arm-eabi": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.140.0.tgz",
- "integrity": "sha512-ZfjDZ422mo7eo3b3VltqNsV9kmv1qt/sPEAMSl64iOSwhVfd0eIZ9LB79Mbs1xYXJnk7WSROwzBCKDIiVxPTvQ==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.142.0.tgz",
+ "integrity": "sha512-ZiRGDutGsv1G6bL/ozy/koC0Sv39T1DqyoC4KD1DOy9ZoACm1O5UWhEK2c02Qdk+4lfLVkvFa/mQ0fm/4h1BtQ==",
"cpu": [
"arm"
],
@@ -1474,9 +1479,9 @@
}
},
"node_modules/@oxc-parser/binding-android-arm64": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.140.0.tgz",
- "integrity": "sha512-Ia8jSvikUX6Sf+Ht+KOCUF/k1HpR0VlmqIYymubmWDebOEGtsyliHDR6JxsZ4IX3/c/GbrB1uh09aVGQv/LQmQ==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.142.0.tgz",
+ "integrity": "sha512-WZkvGRLNQTz8lR9zP5nLjUdlroRCopBu3g9zF1p/laE6DzT1UbQo8Rdz5MWhaJUPYg/6gp+jo7HUgsyKaN1FtQ==",
"cpu": [
"arm64"
],
@@ -1491,9 +1496,9 @@
}
},
"node_modules/@oxc-parser/binding-darwin-arm64": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.140.0.tgz",
- "integrity": "sha512-G6VK0nK61pH0d0mBjUqSZbVxGqqO5uzeginLDQj+gOO6ObfJjXRwgkD/ol0w1INcnFeAb6YGGO7qc3ueGHaycQ==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.142.0.tgz",
+ "integrity": "sha512-l4khS8LQOOVYsGRVARo1gSaCT/aBSceUVXgtovWc2+drnxVuDr082WA3OCHVdVzIz5JIrP/y9CWsSKxBDNmYGg==",
"cpu": [
"arm64"
],
@@ -1508,9 +1513,9 @@
}
},
"node_modules/@oxc-parser/binding-darwin-x64": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.140.0.tgz",
- "integrity": "sha512-HazBOuZzd2pO1C2uMmp8Gv7mhzMHqKSKDS1OZfcLEvpIcgA+48J92HEtNanVHDIzRD9PRPCV6aS6fkZIWOVl8Q==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.142.0.tgz",
+ "integrity": "sha512-QBsNF3nqlXmcH2B1YOPqQYmCJoy4HuIjUxGbBO/k5JAJUl68ghU2psRY2zPk+RyBaWqKP/qfL4oaFgEMCdwskA==",
"cpu": [
"x64"
],
@@ -1525,9 +1530,9 @@
}
},
"node_modules/@oxc-parser/binding-freebsd-x64": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.140.0.tgz",
- "integrity": "sha512-9hSUU+HmTUyOe4JzMHxNGgLWNY7rrO+6ShicZwImNJacEAACDMIkuEQQkvXSL+WJN50jaNtLYJv8s4OcBdpyUQ==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.142.0.tgz",
+ "integrity": "sha512-b7Q7m4Cqc6XqNhri3R+QhU+GVy646Pn+bkdhrDdWym/Fdi0ZUa+d73H9dm5H91JtbtAQ/z1d8XKMW3oOV8a4tQ==",
"cpu": [
"x64"
],
@@ -1542,9 +1547,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-arm-gnueabihf": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.140.0.tgz",
- "integrity": "sha512-RAEuQsYtS0KcDFqN0ABTjyyNlokS91JeuDuoW9tEbG0JTbRNXnpQUdbYc/16JoA6Z/2ALbNrE3KmxtqDiuIjCQ==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.142.0.tgz",
+ "integrity": "sha512-3riVS5IhdH3uCZj1Y9ftDQlR0dvLsIlw/edrRqk8JhgNd5K0XSs+UBtgh50N13CAlW9/TXj6sVGXaKNBocd0Yg==",
"cpu": [
"arm"
],
@@ -1559,9 +1564,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-arm-musleabihf": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.140.0.tgz",
- "integrity": "sha512-c4CkHvPvqfojouredJ0w3e6+jiBq0SbFyhH61kr/zPb/7XsaYTNKQ54vmlSsopfdQbNDX40ZeK9Abs2Qet6wcw==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.142.0.tgz",
+ "integrity": "sha512-NmXUOpgpTSkhl795TiXmWppTwmSJ92RC1qvD6e4XOF+slgmo3e6Ah+kEu+6AN8s7NAOEwqGmir58MgSQSWmBSA==",
"cpu": [
"arm"
],
@@ -1576,9 +1581,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-arm64-gnu": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.140.0.tgz",
- "integrity": "sha512-yrjmLj8ixPB25yqvPGr28meGjb+keed7m1GqqY/0uqkhZIoT4t9zmfwUgFEtC33C7dtE+UQ7TU0IaVxf97SWJg==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.142.0.tgz",
+ "integrity": "sha512-gc0EXsKtXgerujmU2Bql3u1L1HsSQ2774R83idq/FoNMPVV/RY/1ErFsvnit7KoiP/sLvzQixeUo4Ut0ic0wmw==",
"cpu": [
"arm64"
],
@@ -1596,9 +1601,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-arm64-musl": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.140.0.tgz",
- "integrity": "sha512-ggGMQTN8Agwxp2WiLMpdY671dt0qTDJWiWlJeig3HnUwTnerRl0J2JdGVghWBeDcss2D9S2V2Js6dZHEiVabVA==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.142.0.tgz",
+ "integrity": "sha512-F2XvmWSE0uWpie+jHKKIFgdVOe9ypGhkEZxKx5DuW215K6cbAC274yYaPkcM7EqY4Df3Weyhpcz3lsURyH2LVg==",
"cpu": [
"arm64"
],
@@ -1616,9 +1621,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-ppc64-gnu": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.140.0.tgz",
- "integrity": "sha512-IgTs8xYAFgAUGNmR65tIqjlJ8vKgrfXzC515e9goSdfMyKQV4aJpd2pUUudU4u51G64H0/DSEJEXKOraxm9ZCA==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.142.0.tgz",
+ "integrity": "sha512-wLMbT21U/QxknQsk+VvNF0b9D2/aGWhcaQQQ+VYlE8FwD5+GoWZIPPXNzyHmkYyhm0KB3itL+TBavjMatqNnYA==",
"cpu": [
"ppc64"
],
@@ -1636,9 +1641,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-riscv64-gnu": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.140.0.tgz",
- "integrity": "sha512-A1x+PMWZmSGaFVOx2YeNTFau8uD+QO14/vLP4GrcuvUPs3+nBkUOjy9Lus86ftHsDojjYMbvBelmKc3F7Rv08g==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.142.0.tgz",
+ "integrity": "sha512-+G8F/4ckwT7FCJV4H2bt09xEzJbjNCfuL4Sp1AYNaFtFMVtgIGMuJlteT82U+K0UIZ/DzAR/LDlMFnEuajG7Kw==",
"cpu": [
"riscv64"
],
@@ -1656,9 +1661,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-riscv64-musl": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.140.0.tgz",
- "integrity": "sha512-zBqpfRo2myWPrPo5xUjeZqlnPXPXsX8BcWtWff66/eGRQdbPjhzPgXa/F+AtxT2afUViPxbuDlwscMKzQ5tg+g==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.142.0.tgz",
+ "integrity": "sha512-hTsHtTLxMAfCo+rpF5K3qZJKW2NpPN/CHd4mYB3y7XlSdspHkd2gehDIofP64AacA9nWQw2tY3O7wR6UY8IVOA==",
"cpu": [
"riscv64"
],
@@ -1676,9 +1681,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-s390x-gnu": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.140.0.tgz",
- "integrity": "sha512-2M1DPm/8w9I//YzFlFC9qXw+r2tJFh5CYwRlYTq2vUJQS7qoQftEDeCZ8EnN7KHtvSiXvYj8mZI5pR7DpXmcEw==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.142.0.tgz",
+ "integrity": "sha512-6y7qYY3TCUDYjqswImdTGl92y+KA/80twALegQPN27kfY+bG7Ib1+L3jbmrCZQx6wrVnai9IPsEZp07I0hx7JQ==",
"cpu": [
"s390x"
],
@@ -1696,9 +1701,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-x64-gnu": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.140.0.tgz",
- "integrity": "sha512-8aRDbZ/U/jO8N7go1MO72jtbpb4uswV8d7vOkMvt/BPgZiyEYvl1VIWK4ESxZZhnJ4tqwVldgX7dNiP/eB1Jdg==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.142.0.tgz",
+ "integrity": "sha512-i69kAWU+2LgoH5bR+zWiiu+UzAw7Oxkwv7COeJTeY19pn4e70nKQcr9Pm6cL2Z0Z54d+gl9qADlK/0yyuCPiBA==",
"cpu": [
"x64"
],
@@ -1716,9 +1721,9 @@
}
},
"node_modules/@oxc-parser/binding-linux-x64-musl": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.140.0.tgz",
- "integrity": "sha512-xRqpeI8U2sQQS1W5BMWRyMTxtagkuLG2dEWruet5lFsWHTvBth11/TpSaJatHdqVVwHN0q3uuoS9zRsGinq8hg==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.142.0.tgz",
+ "integrity": "sha512-4SQs678MmjYVrmhAgCWD4o0vpaFszXw9xLX5p2Z9MMFcltxiLkA88wQjh80YHjPrXtpyZ2CWI5m+1yNKM0m2Pw==",
"cpu": [
"x64"
],
@@ -1736,9 +1741,9 @@
}
},
"node_modules/@oxc-parser/binding-openharmony-arm64": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.140.0.tgz",
- "integrity": "sha512-GbGRe26MqAKciFRvXeHNQJ6VAHYs9R4miP89sEAncysM3n+f4lnyLWgsa9kklJNpfnxdq2yRoNYHFqwBckVimw==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.142.0.tgz",
+ "integrity": "sha512-YHpx9N7Ln3a++Tc8rv+H7mrK1zyJQOAwCFg8LZ3lTs1T5afGWeZrLPhPT9HLnIwSjCyJqPWVMIrMxbjcmBr2oQ==",
"cpu": [
"arm64"
],
@@ -1753,9 +1758,9 @@
}
},
"node_modules/@oxc-parser/binding-wasm32-wasi": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.140.0.tgz",
- "integrity": "sha512-vFiC1hqys+hkX1GnQkIoiTQJNiUm43Z0lO35ETKXTw0YtpW7+cN58YRRXFAQQ+TgpkIi3lrhcxdlnqz+Oi3ptQ==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.142.0.tgz",
+ "integrity": "sha512-3pLDyY3+oogW73RM5uehNgAiR/Xfb7fvO2Q1Z1gIqZ2+50XDVQmBVlRkHXZTU4gKnQHpwETNsYQVsJ3joVB2iA==",
"cpu": [
"wasm32"
],
@@ -1795,9 +1800,9 @@
}
},
"node_modules/@oxc-parser/binding-win32-arm64-msvc": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.140.0.tgz",
- "integrity": "sha512-fGSQldwEYKhM+H8uLt76Op8hh5+FYaR6lvvQ1Txw3Mhn86DyQXLcI0fi1EkFlTK7F+46OCk/j0AJMzZQm6g5Xg==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.142.0.tgz",
+ "integrity": "sha512-Had/VeVY28Oyb0K+Q4FV8KCzoBycIh93oDK6pCbya9lkzdq+ikMHMgBubsdqqlybjJmQRawCQRrnBRHyQwYvcQ==",
"cpu": [
"arm64"
],
@@ -1812,9 +1817,9 @@
}
},
"node_modules/@oxc-parser/binding-win32-ia32-msvc": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.140.0.tgz",
- "integrity": "sha512-sDS2Bai+g3ZWYwfZqmosiSuFDBcVnZ3Ta6pszzsiJoLMqsJEWKcxXXbGa7b7yXr++W2lQNPb3ZRJ8czseqL7RA==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.142.0.tgz",
+ "integrity": "sha512-GGi3+YphVHavvgs6gum2UXoNCqzHAmPt/nXkn8ZQZstV2Q1qZD1Mn8fz/nWrDkefHQtrG/+1/XrbMxsBTo6Svw==",
"cpu": [
"ia32"
],
@@ -1829,9 +1834,9 @@
}
},
"node_modules/@oxc-parser/binding-win32-x64-msvc": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.140.0.tgz",
- "integrity": "sha512-kHbE1zWyb5OQgJA6/5P4WjiuB01sYdQwtZnSSyE58FQEXDAMnyeeq4vj7KgN75i5SlBzOs8A5MrtlD3gOlDKqQ==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.142.0.tgz",
+ "integrity": "sha512-Ny/Wv4Us1LGC/ljwNTp+Hx3r/pH15EFfeDF0p+n898gt+TtRd6C9SccHcuUhDiNTb8s5tt7jdeAMDRQZ4Vq6hg==",
"cpu": [
"x64"
],
@@ -1846,10 +1851,10 @@
}
},
"node_modules/@oxc-project/types": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.140.0.tgz",
- "integrity": "sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==",
- "dev": true,
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.142.0.tgz",
+ "integrity": "sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==",
+ "devOptional": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/Boshen"
@@ -2185,9 +2190,9 @@
}
},
"node_modules/@rolldown/binding-android-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz",
- "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.1.tgz",
+ "integrity": "sha512-02hOeOSryYxVrOIphmLAsqnCJWxwlzFk+pEt/N/i6OgT3lShHO7xGCU5cpgchRDHboAEbSjzgGh+O/u1GswQmA==",
"cpu": [
"arm64"
],
@@ -2201,9 +2206,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz",
- "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.1.tgz",
+ "integrity": "sha512-fMsTOnN0OjFm3CyppWPitKnc8UlliVARUULW6cfU6AIqjdtgmSFWSk9vecHzZduv/yMWIHDlRhM1e8Iff9uAfA==",
"cpu": [
"arm64"
],
@@ -2217,9 +2222,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz",
- "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.1.tgz",
+ "integrity": "sha512-1wjKdz/XLGKHaTNHjQveQ/B23TKx4ItAqm1JbyVuvNPc4Ze0Fb48s49TAd/2zcplPl8okE/UbTgmlVfwT7eFeQ==",
"cpu": [
"x64"
],
@@ -2233,9 +2238,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz",
- "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.1.tgz",
+ "integrity": "sha512-Fa0jHR07E7YBN4vOEsbVf2briYNsuOowfLJaXULZM0ldMlaCaj2LJgLMbMe4iacRyZmvR8efFhgR9wKuGclQUg==",
"cpu": [
"x64"
],
@@ -2249,9 +2254,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz",
- "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.1.tgz",
+ "integrity": "sha512-pzkgu1SSHGgRRyRZ4fbmSgmajbVt+epaLP99NDjFft69v/ypfTi6swBMiVdh2EkQ0OSnHE1lZDM7DRGkyAzUpA==",
"cpu": [
"arm"
],
@@ -2265,9 +2270,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz",
- "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.1.tgz",
+ "integrity": "sha512-QI5SEDY8cbiYWHx0VO4vIc3UlS6a32vXHjU8Qy/17adEmZIPuByJg13UEvo9c/UCiUkdcVWY83C+b+JrwnNyUg==",
"cpu": [
"arm64"
],
@@ -2284,9 +2289,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz",
- "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.1.tgz",
+ "integrity": "sha512-Sm41FyCeXqmYcERoYOCbGIL5hNfd8w9LQ7Y61Bev48HkcjaJqV/iiVOaiDxjVTRMS+QKrZmD8cfPt4uMVnvM+A==",
"cpu": [
"arm64"
],
@@ -2303,9 +2308,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz",
- "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.1.tgz",
+ "integrity": "sha512-2x+WhXTGl9yJYPbltW/BSEPTVz9OIWQyER4N+gJEDWkkn904eRcBzELqh/Hf7K0w/ubGbKNMv0ZC+94QK/IFEg==",
"cpu": [
"ppc64"
],
@@ -2322,9 +2327,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz",
- "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.1.tgz",
+ "integrity": "sha512-eEjmQpuRQayHPWWnywaWHkFT3ToPbP3RYy42VVd/B9aBGDA+Ol25EIWHxKQST3IiWJjikCWUF7KtbfqwZrzVwQ==",
"cpu": [
"s390x"
],
@@ -2341,9 +2346,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz",
- "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.1.tgz",
+ "integrity": "sha512-/Orga1fZYkLc/56jBICcHrKchl8Z2UKdDSr3LG9ToWO1lQ6a4Livk9Xz+9WN91zsz5QR3XQz2NNoSDEvP6qadw==",
"cpu": [
"x64"
],
@@ -2360,9 +2365,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz",
- "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.1.tgz",
+ "integrity": "sha512-xxBJRL+0q0Kce7orznGWLuylHDY65vuARXZRpX+hPdv+DqK2c3NlCsVA98tlWzWNEE7yPqA/1NQ5nnCrj49Y5A==",
"cpu": [
"x64"
],
@@ -2379,9 +2384,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz",
- "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.1.tgz",
+ "integrity": "sha512-M6AdXIXw3s+/8XpKMzdGDEXGS1S7kwUsy+rcTIUIOx5Ge4nXKCtAFHFV9YKkXvGcC5WMoTjAteLzlsQROVI0Yw==",
"cpu": [
"arm64"
],
@@ -2395,27 +2400,55 @@
}
},
"node_modules/@rolldown/binding-wasm32-wasi": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz",
- "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==",
- "cpu": [
- "wasm32"
- ],
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.1.tgz",
+ "integrity": "sha512-/TX0SoRGojHzSAHpfVBbavRVSazg5U3h3Y3VXfcc0cdugq6kxdqw8LPGFiPr+/7gE/60zRcsOY2Vi9b9eT0jww==",
"license": "MIT",
"optional": true,
"dependencies": {
- "@emnapi/core": "1.11.1",
- "@emnapi/runtime": "1.11.1",
- "@napi-rs/wasm-runtime": "^1.1.6"
+ "@emnapi/core": "2.0.0-alpha.3",
+ "@emnapi/runtime": "2.0.0-alpha.3",
+ "@napi-rs/wasm-runtime": "^1.2.0"
},
"engines": {
- "node": "^20.19.0 || >=22.12.0"
+ "node": "^20.19.0 || ^22.13.0 || >=23.5.0"
+ }
+ },
+ "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/core": {
+ "version": "2.0.0-alpha.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-2.0.0-alpha.3.tgz",
+ "integrity": "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "2.0.1",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/runtime": {
+ "version": "2.0.0-alpha.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-2.0.0-alpha.3.tgz",
+ "integrity": "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-2.0.1.tgz",
+ "integrity": "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
}
},
"node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz",
- "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.1.tgz",
+ "integrity": "sha512-EvRrivJieyHG+AO9lleZWgq+g0+S7oV2C51yuqlcyU/R9net+sI4Pj0F+lUoP2bEr6TWX3SqFaaS0SzfLxSzkw==",
"cpu": [
"arm64"
],
@@ -2429,9 +2462,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz",
- "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.1.tgz",
+ "integrity": "sha512-Z4eCmn5QJ/5+azF9knpLWKfVd9aidn0mAe9TpJgvBLId9Ax3t0+JVxBmT25Bv7NBbVW1TZyKjQjQReouMeH5UQ==",
"cpu": [
"x64"
],
@@ -3534,9 +3567,9 @@
}
},
"node_modules/brace-expansion": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
- "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4078,9 +4111,9 @@
}
},
"node_modules/fast-uri": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-4.1.1.tgz",
- "integrity": "sha512-YPOs1zD5TG2+EZt+r88LwF6mclA7TPkpwMP7ZN3TO2HiHS8TXvq7QA/17iJsV9dubcLo/f8eEYqMBruyQV21hQ==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-4.1.2.tgz",
+ "integrity": "sha512-TyGmBcbDTZXcb2cj5MV89DrF42DKvb3y5DDUNh95iO+IMeAzMkVSxK1PZRrRIpc9yg8U2GhGdbofNa0LS/a4Bw==",
"dev": true,
"funding": [
{
@@ -4713,9 +4746,9 @@
}
},
"node_modules/knip": {
- "version": "6.29.0",
- "resolved": "https://registry.npmjs.org/knip/-/knip-6.29.0.tgz",
- "integrity": "sha512-A3kXqSBky1tWBAqiU9srdtu0Larhzkuyor0aD/gg+ToiqyBncCCs2Q60sLsxmcKhV0OsKss9LV0hMPpwLv711Q==",
+ "version": "6.31.0",
+ "resolved": "https://registry.npmjs.org/knip/-/knip-6.31.0.tgz",
+ "integrity": "sha512-NbeIEmUS2VUMjAkbiSNOKPJeV9wpCsr0660sUyKyMQbk4Iom0++nTLInVp4MJ+LfR4kORnw67bDi5tvO7YLnzA==",
"dev": true,
"funding": [
{
@@ -4733,13 +4766,13 @@
"formatly": "^0.3.0",
"get-tsconfig": "4.14.0",
"jiti": "^2.7.0",
- "oxc-parser": "^0.140.0",
+ "oxc-parser": "^0.142.0",
"oxc-resolver": "11.24.2",
"picomatch": "^4.0.5",
- "smol-toml": "^1.7.0",
+ "smol-toml": "^1.7.1",
"strip-json-comments": "5.0.3",
"tinyglobby": "^0.2.17",
- "unbash": "^4.0.3",
+ "unbash": "^4.0.4",
"yaml": "^2.9.0",
"zod": "^4.4.3"
},
@@ -4755,7 +4788,7 @@
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
"integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
- "devOptional": true,
+ "dev": true,
"license": "MPL-2.0",
"dependencies": {
"detect-libc": "^2.0.3"
@@ -4788,6 +4821,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4808,6 +4842,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4828,6 +4863,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4848,6 +4884,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4868,6 +4905,7 @@
"cpu": [
"arm"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4888,6 +4926,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4908,6 +4947,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4928,6 +4968,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4948,6 +4989,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4968,6 +5010,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -4988,6 +5031,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -5337,13 +5381,13 @@
"license": "MIT"
},
"node_modules/oxc-parser": {
- "version": "0.140.0",
- "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.140.0.tgz",
- "integrity": "sha512-h6QFWd6lBMfjESqgQ27GjzrSDb0qbznp7VDQqp2zvgsrWut4vcchyMIzOVXvGQ2GMZgKw9RWrFNWv9WqGL0p7Q==",
+ "version": "0.142.0",
+ "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.142.0.tgz",
+ "integrity": "sha512-kKR+jPiRJYJDexVoziIg/FVGvr1fT1FZSSJOk6tVoMKKSlsf1Cso+cgGCJkOEDWOP174vRntCPFKg+AS7InWvw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@oxc-project/types": "^0.140.0"
+ "@oxc-project/types": "^0.142.0"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
@@ -5352,26 +5396,26 @@
"url": "https://github.com/sponsors/Boshen"
},
"optionalDependencies": {
- "@oxc-parser/binding-android-arm-eabi": "0.140.0",
- "@oxc-parser/binding-android-arm64": "0.140.0",
- "@oxc-parser/binding-darwin-arm64": "0.140.0",
- "@oxc-parser/binding-darwin-x64": "0.140.0",
- "@oxc-parser/binding-freebsd-x64": "0.140.0",
- "@oxc-parser/binding-linux-arm-gnueabihf": "0.140.0",
- "@oxc-parser/binding-linux-arm-musleabihf": "0.140.0",
- "@oxc-parser/binding-linux-arm64-gnu": "0.140.0",
- "@oxc-parser/binding-linux-arm64-musl": "0.140.0",
- "@oxc-parser/binding-linux-ppc64-gnu": "0.140.0",
- "@oxc-parser/binding-linux-riscv64-gnu": "0.140.0",
- "@oxc-parser/binding-linux-riscv64-musl": "0.140.0",
- "@oxc-parser/binding-linux-s390x-gnu": "0.140.0",
- "@oxc-parser/binding-linux-x64-gnu": "0.140.0",
- "@oxc-parser/binding-linux-x64-musl": "0.140.0",
- "@oxc-parser/binding-openharmony-arm64": "0.140.0",
- "@oxc-parser/binding-wasm32-wasi": "0.140.0",
- "@oxc-parser/binding-win32-arm64-msvc": "0.140.0",
- "@oxc-parser/binding-win32-ia32-msvc": "0.140.0",
- "@oxc-parser/binding-win32-x64-msvc": "0.140.0"
+ "@oxc-parser/binding-android-arm-eabi": "0.142.0",
+ "@oxc-parser/binding-android-arm64": "0.142.0",
+ "@oxc-parser/binding-darwin-arm64": "0.142.0",
+ "@oxc-parser/binding-darwin-x64": "0.142.0",
+ "@oxc-parser/binding-freebsd-x64": "0.142.0",
+ "@oxc-parser/binding-linux-arm-gnueabihf": "0.142.0",
+ "@oxc-parser/binding-linux-arm-musleabihf": "0.142.0",
+ "@oxc-parser/binding-linux-arm64-gnu": "0.142.0",
+ "@oxc-parser/binding-linux-arm64-musl": "0.142.0",
+ "@oxc-parser/binding-linux-ppc64-gnu": "0.142.0",
+ "@oxc-parser/binding-linux-riscv64-gnu": "0.142.0",
+ "@oxc-parser/binding-linux-riscv64-musl": "0.142.0",
+ "@oxc-parser/binding-linux-s390x-gnu": "0.142.0",
+ "@oxc-parser/binding-linux-x64-gnu": "0.142.0",
+ "@oxc-parser/binding-linux-x64-musl": "0.142.0",
+ "@oxc-parser/binding-openharmony-arm64": "0.142.0",
+ "@oxc-parser/binding-wasm32-wasi": "0.142.0",
+ "@oxc-parser/binding-win32-arm64-msvc": "0.142.0",
+ "@oxc-parser/binding-win32-ia32-msvc": "0.142.0",
+ "@oxc-parser/binding-win32-x64-msvc": "0.142.0"
}
},
"node_modules/oxc-resolver": {
@@ -5574,9 +5618,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.24",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.24.tgz",
- "integrity": "sha512-8RyVklq0owXUTa4xlpzu4l9AaVKIdQvAcOHZWaMh98HgySsUtxRVf/chRe3dsSLqb6i40BzGRzEUddRaI+9TSw==",
+ "version": "8.5.25",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
+ "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
"funding": [
{
"type": "opencollective",
@@ -5717,13 +5761,13 @@
"license": "MIT"
},
"node_modules/rolldown": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz",
- "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.1.tgz",
+ "integrity": "sha512-4FKJhg8d3OiyQOA6Q1Q0hoFFpW9/OoX+VsHzpECsdsIZoOArrAK90gl59YK/Z+gnDel45bgJZK03ozH/9bCqEw==",
"devOptional": true,
"license": "MIT",
"dependencies": {
- "@oxc-project/types": "=0.139.0",
+ "@oxc-project/types": "=0.142.0",
"@rolldown/pluginutils": "^1.0.0"
},
"bin": {
@@ -5733,31 +5777,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
- "@rolldown/binding-android-arm64": "1.1.5",
- "@rolldown/binding-darwin-arm64": "1.1.5",
- "@rolldown/binding-darwin-x64": "1.1.5",
- "@rolldown/binding-freebsd-x64": "1.1.5",
- "@rolldown/binding-linux-arm-gnueabihf": "1.1.5",
- "@rolldown/binding-linux-arm64-gnu": "1.1.5",
- "@rolldown/binding-linux-arm64-musl": "1.1.5",
- "@rolldown/binding-linux-ppc64-gnu": "1.1.5",
- "@rolldown/binding-linux-s390x-gnu": "1.1.5",
- "@rolldown/binding-linux-x64-gnu": "1.1.5",
- "@rolldown/binding-linux-x64-musl": "1.1.5",
- "@rolldown/binding-openharmony-arm64": "1.1.5",
- "@rolldown/binding-wasm32-wasi": "1.1.5",
- "@rolldown/binding-win32-arm64-msvc": "1.1.5",
- "@rolldown/binding-win32-x64-msvc": "1.1.5"
- }
- },
- "node_modules/rolldown/node_modules/@oxc-project/types": {
- "version": "0.139.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz",
- "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==",
- "devOptional": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/Boshen"
+ "@rolldown/binding-android-arm64": "1.2.1",
+ "@rolldown/binding-darwin-arm64": "1.2.1",
+ "@rolldown/binding-darwin-x64": "1.2.1",
+ "@rolldown/binding-freebsd-x64": "1.2.1",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.1",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.1",
+ "@rolldown/binding-linux-arm64-musl": "1.2.1",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.1",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.1",
+ "@rolldown/binding-linux-x64-gnu": "1.2.1",
+ "@rolldown/binding-linux-x64-musl": "1.2.1",
+ "@rolldown/binding-openharmony-arm64": "1.2.1",
+ "@rolldown/binding-wasm32-wasi": "1.2.1",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.1",
+ "@rolldown/binding-win32-x64-msvc": "1.2.1"
}
},
"node_modules/rxjs": {
@@ -6477,16 +6511,16 @@
}
},
"node_modules/vite": {
- "version": "8.1.5",
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz",
- "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==",
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.0.tgz",
+ "integrity": "sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
- "lightningcss": "^1.32.0",
+ "lightningcss": "^1.33.0",
"picomatch": "^4.0.5",
- "postcss": "^8.5.17",
- "rolldown": "~1.1.5",
+ "postcss": "^8.5.23",
+ "rolldown": "~1.2.0",
"tinyglobby": "^0.2.17"
},
"bin": {
@@ -6503,7 +6537,7 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
- "@vitejs/devtools": "^0.3.0",
+ "@vitejs/devtools": "^0.4.0",
"esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
@@ -6554,6 +6588,268 @@
}
}
},
+ "node_modules/vite/node_modules/lightningcss": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
+ "devOptional": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.33.0",
+ "lightningcss-darwin-arm64": "1.33.0",
+ "lightningcss-darwin-x64": "1.33.0",
+ "lightningcss-freebsd-x64": "1.33.0",
+ "lightningcss-linux-arm-gnueabihf": "1.33.0",
+ "lightningcss-linux-arm64-gnu": "1.33.0",
+ "lightningcss-linux-arm64-musl": "1.33.0",
+ "lightningcss-linux-x64-gnu": "1.33.0",
+ "lightningcss-linux-x64-musl": "1.33.0",
+ "lightningcss-win32-arm64-msvc": "1.33.0",
+ "lightningcss-win32-x64-msvc": "1.33.0"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-android-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-darwin-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-darwin-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-freebsd-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
"node_modules/vitest": {
"version": "4.1.10",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz",
diff --git a/ui/package.json b/ui/package.json
index 1a7a488ca..2c364527a 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -45,7 +45,7 @@
"@iconify-json/fa6-solid": "1.2.4",
"@iconify-json/heroicons": "1.2.3",
"@iconify-json/iconoir": "1.2.11",
- "@iconify-json/lucide": "1.2.120",
+ "@iconify-json/lucide": "1.2.121",
"@iconify-json/ph": "1.2.2",
"@iconify-json/tabler": "1.2.38",
"@stryker-mutator/core": "9.6.1",
@@ -57,17 +57,18 @@
"@vitest/coverage-v8": "4.1.10",
"@vue/test-utils": "2.4.11",
"jsdom": "29.1.1",
- "knip": "6.29.0",
+ "knip": "6.31.0",
"typescript": "6.0.3",
- "vite": "8.1.5",
+ "vite": "8.2.0",
"vitest": "4.1.10"
},
"overrides": {
- "fast-uri": "4.1.1",
+ "brace-expansion": "5.0.9",
+ "fast-uri": "4.1.2",
"js-cookie": "3.0.8",
"minimatch": "10.2.6",
"picomatch": "4.0.5",
- "postcss": "8.5.24",
+ "postcss": "8.5.25",
"qs": "6.15.3",
"yaml": "2.9.0",
"@babel/core": "7.29.7",
diff --git a/ui/src/locales/fr/containerComponents.json b/ui/src/locales/fr/containerComponents.json
index 66f529aeb..0226a29d9 100644
--- a/ui/src/locales/fr/containerComponents.json
+++ b/ui/src/locales/fr/containerComponents.json
@@ -169,7 +169,7 @@
"statusLive": "En direct",
"statusOffline": "Hors ligne",
"stdout": "stdout",
- "stderr": "stderr"
+ "stderr": "sdterr"
},
"groupedViews": {
"statusQueued": "En file",