@camstack/types 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/capabilities/addons.cap.d.ts +155 -3
  2. package/dist/capabilities/addons.cap.d.ts.map +1 -1
  3. package/dist/capabilities/device-export.cap.d.ts +55 -1
  4. package/dist/capabilities/device-export.cap.d.ts.map +1 -1
  5. package/dist/capabilities/index.d.ts +1 -1
  6. package/dist/capabilities/index.d.ts.map +1 -1
  7. package/dist/capabilities/mesh-network.cap.d.ts +58 -2
  8. package/dist/capabilities/mesh-network.cap.d.ts.map +1 -1
  9. package/dist/capabilities/mesh-orchestrator.cap.d.ts +67 -0
  10. package/dist/capabilities/mesh-orchestrator.cap.d.ts.map +1 -1
  11. package/dist/capabilities/nodes.cap.d.ts +36 -1
  12. package/dist/capabilities/nodes.cap.d.ts.map +1 -1
  13. package/dist/capabilities/user-management.cap.d.ts +4 -0
  14. package/dist/capabilities/user-management.cap.d.ts.map +1 -1
  15. package/dist/enums/event-category.d.ts +10 -0
  16. package/dist/enums/event-category.d.ts.map +1 -1
  17. package/dist/generated/addon-api.d.ts +386 -8
  18. package/dist/generated/addon-api.d.ts.map +1 -1
  19. package/dist/generated/capability-router-map.d.ts.map +1 -1
  20. package/dist/generated/method-access-map.d.ts +1 -1
  21. package/dist/generated/method-access-map.d.ts.map +1 -1
  22. package/dist/generated/system-proxy.d.ts +4 -4
  23. package/dist/generated/system-proxy.d.ts.map +1 -1
  24. package/dist/{index-BBVUwOlZ.mjs → index-Ce7RZWP4.mjs} +491 -170
  25. package/dist/index-Ce7RZWP4.mjs.map +1 -0
  26. package/dist/{index-BUBhoPUu.js → index-DS7418lf.js} +331 -10
  27. package/dist/index-DS7418lf.js.map +1 -0
  28. package/dist/index.js +23 -2
  29. package/dist/index.js.map +1 -1
  30. package/dist/index.mjs +184 -163
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/interfaces/addon.d.ts +21 -0
  33. package/dist/interfaces/addon.d.ts.map +1 -1
  34. package/dist/interfaces/api-responses.d.ts +6 -0
  35. package/dist/interfaces/api-responses.d.ts.map +1 -1
  36. package/dist/interfaces/event-bus.d.ts +21 -1
  37. package/dist/interfaces/event-bus.d.ts.map +1 -1
  38. package/dist/interfaces/storage.d.ts +1 -1
  39. package/dist/interfaces/storage.d.ts.map +1 -1
  40. package/dist/node.js +6 -6
  41. package/dist/node.js.map +1 -1
  42. package/dist/node.mjs +6 -6
  43. package/dist/node.mjs.map +1 -1
  44. package/dist/storage/filesystem-storage-provider.d.ts +1 -1
  45. package/dist/storage/filesystem-storage-provider.d.ts.map +1 -1
  46. package/package.json +6 -1
  47. package/dist/index-BBVUwOlZ.mjs.map +0 -1
  48. package/dist/index-BUBhoPUu.js.map +0 -1
@@ -3869,10 +3869,30 @@ const mqttBrokerCapability = {
3869
3869
  }
3870
3870
  };
3871
3871
  const LinkStateSchema = zod.z.enum(["unlinked", "linked", "error"]);
3872
+ const ExportSetupFieldSchema = zod.z.object({
3873
+ label: zod.z.string(),
3874
+ value: zod.z.string(),
3875
+ /** Mask the value by default + render a reveal toggle (client id, secrets). */
3876
+ secret: zod.z.boolean().optional()
3877
+ });
3878
+ const ExportSetupSchema = zod.z.object({
3879
+ /** A string to render as a scannable QR — HAP `X-HM://…` URI, a pairing URL, etc. Omitted when there's nothing to scan. */
3880
+ qr: zod.z.string().optional(),
3881
+ /** Label/value rows shown with a copy button (HAP setup code, OAuth URLs, client id, linked-account count, …). */
3882
+ fields: zod.z.array(ExportSetupFieldSchema).readonly().optional(),
3883
+ /** Free-form operator instructions rendered above the fields. */
3884
+ note: zod.z.string().optional()
3885
+ });
3872
3886
  const DeviceExportStatusSchema = zod.z.object({
3873
3887
  linkState: LinkStateSchema,
3874
3888
  exposedDeviceCount: zod.z.number(),
3875
- error: zod.z.string().optional()
3889
+ error: zod.z.string().optional(),
3890
+ /**
3891
+ * Optional pairing/account info the panel renders in a generic
3892
+ * "Setup" section. Addon-agnostic — the addon id identifies the
3893
+ * export target, never an `ecosystem` key here.
3894
+ */
3895
+ setup: ExportSetupSchema.optional()
3876
3896
  });
3877
3897
  const DeviceKindSchema = zod.z.string();
3878
3898
  const ExposedDeviceSchema = zod.z.object({
@@ -7470,7 +7490,9 @@ const MeshPeerSchema = zod.z.object({
7470
7490
  id: zod.z.string(),
7471
7491
  /** Hostname / device name as shown in the mesh dashboard. */
7472
7492
  hostname: zod.z.string(),
7473
- /** Mesh IP(s). Multiple when the peer is dual-stacked. */
7493
+ /** MagicDNS / mesh DNS name (e.g. `peer-foo.tail-abc.ts.net`). Empty when the provider doesn't support DNS or peer-side resolution is disabled. */
7494
+ magicDns: zod.z.string(),
7495
+ /** Mesh IPv4 / IPv6 addresses combined. Multiple when dual-stacked. */
7474
7496
  addresses: zod.z.array(zod.z.string()).readonly(),
7475
7497
  /** Operating system reported by the peer (informational). */
7476
7498
  os: zod.z.string().optional(),
@@ -7479,7 +7501,32 @@ const MeshPeerSchema = zod.z.object({
7479
7501
  /** Last-seen timestamp (epoch ms). 0 when never seen. */
7480
7502
  lastSeenMs: zod.z.number(),
7481
7503
  /** True for the row representing the current host. */
7482
- isSelf: zod.z.boolean()
7504
+ isSelf: zod.z.boolean(),
7505
+ /**
7506
+ * Connection mode to this peer:
7507
+ * - `direct`: NAT-traversed P2P (UDP punched)
7508
+ * - `relay`: traffic relayed through provider edge (Tailscale DERP)
7509
+ * - `idle`: peer reachable but no recent traffic / handshake
7510
+ */
7511
+ connection: zod.z.enum(["direct", "relay", "idle"]),
7512
+ /** DERP region / relay node identifier when `connection: relay`. Null otherwise. */
7513
+ relay: zod.z.string().nullable(),
7514
+ /** Last successful handshake timestamp (epoch ms). 0 when never. */
7515
+ lastHandshakeMs: zod.z.number(),
7516
+ /** Bytes received from this peer since the daemon started. */
7517
+ rxBytes: zod.z.number(),
7518
+ /** Bytes transmitted to this peer since the daemon started. */
7519
+ txBytes: zod.z.number(),
7520
+ /** ACL tags this peer carries (e.g. `["tag:server"]`). Empty when human-owned. */
7521
+ tags: zod.z.array(zod.z.string()).readonly(),
7522
+ /** True when the peer advertises itself as an exit-node candidate. */
7523
+ exitNodeOption: zod.z.boolean(),
7524
+ /** Subnet routes the peer advertises (e.g. `["192.168.1.0/24"]`). */
7525
+ advertisedRoutes: zod.z.array(zod.z.string()).readonly(),
7526
+ /** Owner account login (e.g. `foo@example.com`). Null for tagged peers. */
7527
+ userLogin: zod.z.string().nullable(),
7528
+ /** Pre-auth key / machine-key expiry (epoch ms). Null when keys don't expire. */
7529
+ keyExpiry: zod.z.number().nullable()
7483
7530
  });
7484
7531
  const MeshStatusSchema = zod.z.object({
7485
7532
  /** True when the host is joined and the daemon reports healthy. */
@@ -7493,7 +7540,56 @@ const MeshStatusSchema = zod.z.object({
7493
7540
  /** Every endpoint this provider exposes for the current host. */
7494
7541
  endpoints: zod.z.array(MeshEndpointSchema$1).readonly(),
7495
7542
  /** Last error from the daemon, when not joined. */
7496
- error: zod.z.string().optional()
7543
+ error: zod.z.string().optional(),
7544
+ // ── Account / tenant identity (generic across providers) ────────
7545
+ /**
7546
+ * Tenant / tailnet / network display name (Tailscale = tailnet
7547
+ * domain, Headscale = namespace, ZeroTier = network name). Empty
7548
+ * pre-join. Per-provider semantics, common slot.
7549
+ */
7550
+ tenantName: zod.z.string(),
7551
+ /**
7552
+ * Mesh DNS suffix when the provider exposes peer-resolvable DNS
7553
+ * (Tailscale MagicDNS, Headscale MagicDNS, …). Empty when the
7554
+ * provider doesn't ship DNS (e.g. ZeroTier).
7555
+ */
7556
+ magicDnsSuffix: zod.z.string(),
7557
+ /**
7558
+ * Authenticated user / account login bound to this host. Null when
7559
+ * the provider authenticates with a long-lived network token rather
7560
+ * than a user account (e.g. ZeroTier API token).
7561
+ */
7562
+ userLogin: zod.z.string().nullable(),
7563
+ /**
7564
+ * Provider control-plane URL (Tailscale SaaS `https://login.tailscale.com`,
7565
+ * self-hosted Headscale, ZeroTier Central, …). Empty when not
7566
+ * applicable (rare).
7567
+ */
7568
+ controlPlaneUrl: zod.z.string(),
7569
+ /**
7570
+ * Machine-key / node-key expiry (epoch ms). Null when the provider
7571
+ * doesn't rotate keys for the bound host. Operator-facing surface
7572
+ * for "your access expires on …" banners.
7573
+ */
7574
+ keyExpiry: zod.z.number().nullable(),
7575
+ // ── Onboard-daemon handoff (Tailscale, generic slot) ────────────
7576
+ /**
7577
+ * When the provider runs its OWN mesh daemon (e.g. the Tailscale
7578
+ * client addon in `onboard` mode spawns a private `tailscaled`),
7579
+ * this carries the local control-socket path. Companion addons that
7580
+ * must drive the SAME daemon — chiefly `tailscale-ingress` for
7581
+ * Serve/Funnel — read it to point their CLI at the right socket
7582
+ * instead of the system default. Empty when the provider uses the
7583
+ * host's system daemon (or doesn't have the concept).
7584
+ */
7585
+ daemonSocket: zod.z.string().optional(),
7586
+ /**
7587
+ * Path to the mesh CLI binary the provider downloaded for onboard
7588
+ * mode. Companion addons reuse it so they don't need a system
7589
+ * install when the operator chose a fully self-contained mesh.
7590
+ * Empty in host mode.
7591
+ */
7592
+ daemonCliPath: zod.z.string().optional()
7497
7593
  });
7498
7594
  const meshNetworkCapability = {
7499
7595
  name: "mesh-network",
@@ -7545,12 +7641,26 @@ const meshNetworkCapability = {
7545
7641
  { kind: "mutation" }
7546
7642
  ),
7547
7643
  /** Leave the mesh. After this the meshIp/magicDnsHostname/etc.
7548
- * vanish until the next `join`. */
7644
+ * vanish until the next `join`. The bound account stays — a
7645
+ * subsequent `join` reuses it without prompting for a new login. */
7549
7646
  leave: method(
7550
7647
  zod.z.void(),
7551
7648
  zod.z.object({ left: zod.z.literal(true) }),
7552
7649
  { kind: "mutation" }
7553
7650
  ),
7651
+ /**
7652
+ * Sign out of the mesh account entirely. Distinct from `leave`:
7653
+ * `leave` only takes the host off-mesh (`tailscale down`) while the
7654
+ * account binding survives, so the next `join` reconnects silently.
7655
+ * `logout` (`tailscale logout`) wipes the daemon's stored
7656
+ * credentials — the next `startLogin` MUST go through a fresh
7657
+ * browser-redirect flow to bind a new account.
7658
+ */
7659
+ logout: method(
7660
+ zod.z.void(),
7661
+ zod.z.object({ loggedOut: zod.z.literal(true) }),
7662
+ { kind: "mutation" }
7663
+ ),
7554
7664
  /** Enumerate every peer the daemon currently knows about. */
7555
7665
  listPeers: method(zod.z.void(), zod.z.object({
7556
7666
  peers: zod.z.array(MeshPeerSchema).readonly()
@@ -7584,6 +7694,15 @@ const meshNetworkCapability = {
7584
7694
  }),
7585
7695
  { kind: "mutation" }
7586
7696
  )
7697
+ // Provider-specific runtime knobs (accept-routes / advertise-routes /
7698
+ // shields-up / ssh / exit-node, …) live on the addon's own
7699
+ // `getSettingsUISchema` (form-builder), NOT here. Different mesh
7700
+ // providers (Tailscale, Headscale, ZeroTier, Nebula) have very
7701
+ // different config surfaces — picking one shape and forcing all
7702
+ // implementations to honour it would either lose options or
7703
+ // misrepresent them. The Mesh page renders the addon's settings
7704
+ // schema as a "Settings" tab next to the generic Status / Peers
7705
+ // tabs driven by this cap.
7587
7706
  }
7588
7707
  };
7589
7708
  const MeshEndpointSchema = zod.z.object({
@@ -7611,7 +7730,18 @@ const MeshProviderInfoSchema = zod.z.object({
7611
7730
  /** Active endpoints (mesh IP + MagicDNS + optional public Funnel). */
7612
7731
  endpoints: zod.z.array(MeshEndpointSchema).readonly(),
7613
7732
  /** Last error reported by the provider. */
7614
- error: zod.z.string().optional()
7733
+ error: zod.z.string().optional(),
7734
+ // ── Generic identity fields mirrored from MeshStatus ─────────────
7735
+ /** Tenant / tailnet / network display name. Empty pre-join. */
7736
+ tenantName: zod.z.string(),
7737
+ /** Mesh DNS suffix (e.g. tailXXXX.ts.net). Empty when not configured. */
7738
+ magicDnsSuffix: zod.z.string(),
7739
+ /** Authenticated user / account login. Null for token-only providers. */
7740
+ userLogin: zod.z.string().nullable(),
7741
+ /** Provider control-plane URL. */
7742
+ controlPlaneUrl: zod.z.string(),
7743
+ /** Machine-key expiry (epoch ms). Null when keys don't rotate. */
7744
+ keyExpiry: zod.z.number().nullable()
7615
7745
  });
7616
7746
  const meshOrchestratorCapability = {
7617
7747
  name: "mesh-orchestrator",
@@ -7637,6 +7767,43 @@ const meshOrchestratorCapability = {
7637
7767
  zod.z.object({ addonId: zod.z.string() }),
7638
7768
  zod.z.object({ success: zod.z.literal(true) }),
7639
7769
  { kind: "mutation" }
7770
+ ),
7771
+ /**
7772
+ * Browser-redirect login flow. Forwards to the named provider's
7773
+ * `mesh-network.startLogin` and returns the URL the daemon
7774
+ * prints. UI opens it in a new tab, then polls `listProviders`
7775
+ * for `joined: true`.
7776
+ */
7777
+ startLoginProvider: method(
7778
+ zod.z.object({
7779
+ addonId: zod.z.string(),
7780
+ hostname: zod.z.string().optional()
7781
+ }),
7782
+ zod.z.object({ loginUrl: zod.z.string() }),
7783
+ { kind: "mutation" }
7784
+ ),
7785
+ /**
7786
+ * Sign out of the provider's account entirely (`mesh-network.logout`).
7787
+ * Distinct from `leaveProvider` which only takes the host off-mesh;
7788
+ * `logoutProvider` wipes credentials so the next start requires a
7789
+ * fresh login.
7790
+ */
7791
+ logoutProvider: method(
7792
+ zod.z.object({ addonId: zod.z.string() }),
7793
+ zod.z.object({ loggedOut: zod.z.literal(true) }),
7794
+ { kind: "mutation" }
7795
+ ),
7796
+ /**
7797
+ * Per-provider peer list. Forwards to `mesh-network.listPeers` on
7798
+ * the addressed provider. Separate from `listProviders` because
7799
+ * peer payloads can be large on a heavily-populated tailnet —
7800
+ * fetch only when the operator opens the Peers tab.
7801
+ */
7802
+ listProviderPeers: method(
7803
+ zod.z.object({ addonId: zod.z.string() }),
7804
+ zod.z.object({
7805
+ peers: zod.z.array(MeshPeerSchema).readonly()
7806
+ })
7640
7807
  )
7641
7808
  }
7642
7809
  };
@@ -7724,6 +7891,13 @@ const UserSummarySchema = zod.z.object({
7724
7891
  allowedProviders: zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")]),
7725
7892
  allowedDevices: zod.z.record(zod.z.string(), zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")])),
7726
7893
  scopes: zod.z.array(TokenScopeSchema).default([]),
7894
+ /**
7895
+ * True iff this user has a CONFIRMED TOTP enrollment. Surfaced on
7896
+ * `listUsers` so the admin Users page can render the "Remove 2FA"
7897
+ * action conditionally without firing one `getTotpStatus` query per
7898
+ * row. Self-service enrollment lives on the user's profile page.
7899
+ */
7900
+ totpEnabled: zod.z.boolean().default(false),
7727
7901
  createdAt: zod.z.number(),
7728
7902
  updatedAt: zod.z.number()
7729
7903
  });
@@ -8022,6 +8196,12 @@ const NodeAddonInputSchema = zod.z.object({
8022
8196
  nodeId: zod.z.string(),
8023
8197
  addonId: zod.z.string()
8024
8198
  });
8199
+ const NodeAddonEntrySchema = zod.z.object({
8200
+ id: zod.z.string(),
8201
+ status: zod.z.string(),
8202
+ version: zod.z.string().optional(),
8203
+ packageName: zod.z.string().optional()
8204
+ });
8025
8205
  const SuccessSchema = zod.z.object({ success: zod.z.boolean() });
8026
8206
  const RestartProcessResultSchema = zod.z.object({
8027
8207
  success: zod.z.boolean(),
@@ -8039,6 +8219,7 @@ const nodesCapability = {
8039
8219
  name: "nodes",
8040
8220
  scope: "system",
8041
8221
  mode: "singleton",
8222
+ nodeIdMode: "data",
8042
8223
  methods: {
8043
8224
  topology: method(
8044
8225
  zod.z.void(),
@@ -8082,6 +8263,19 @@ const nodesCapability = {
8082
8263
  zod.z.record(zod.z.string(), ClusterAddonStatusEntrySchema),
8083
8264
  { auth: "admin" }
8084
8265
  ),
8266
+ /**
8267
+ * Direct per-node addon listing — calls `$agent.status` on the target
8268
+ * node (or returns the hub registry for `nodeId === 'hub'`) and surfaces
8269
+ * the full addon roster including `version` + `packageName`. The
8270
+ * `topology` cap also includes addons but strips them down to
8271
+ * `{id, capabilities, status}` for the cluster diagram; this method
8272
+ * is the one the per-node "Addons" tab should call.
8273
+ */
8274
+ getNodeAddons: method(
8275
+ zod.z.object({ nodeId: zod.z.string() }),
8276
+ zod.z.array(NodeAddonEntrySchema).readonly(),
8277
+ { auth: "admin" }
8278
+ ),
8085
8279
  setProcessLogLevel: method(
8086
8280
  zod.z.object({ nodeId: zod.z.string(), level: zod.z.string() }),
8087
8281
  SuccessSchema,
@@ -8307,6 +8501,21 @@ const AddonAutoUpdateSchema = ChannelWithInheritSchema;
8307
8501
  const RestartAddonResultSchema = zod.z.unknown();
8308
8502
  const InstallPackageResultSchema = zod.z.unknown();
8309
8503
  const ReloadPackagesResultSchema = zod.z.unknown();
8504
+ const UpdateFrameworkPackageResultSchema = zod.z.object({
8505
+ packageName: zod.z.string(),
8506
+ fromVersion: zod.z.string(),
8507
+ toVersion: zod.z.string(),
8508
+ /** Ms-epoch the server scheduled its self-restart. */
8509
+ restartingAt: zod.z.number()
8510
+ });
8511
+ const FrameworkPackageStatusSchema = zod.z.object({
8512
+ packageName: zod.z.string(),
8513
+ currentVersion: zod.z.string(),
8514
+ latestVersion: zod.z.string().nullable(),
8515
+ hasUpdate: zod.z.boolean(),
8516
+ /** Optional manifest description for the row tooltip. */
8517
+ description: zod.z.string().optional()
8518
+ });
8310
8519
  const LogStreamEntrySchema = zod.z.object({
8311
8520
  timestamp: zod.z.string(),
8312
8521
  level: zod.z.string(),
@@ -8323,6 +8532,7 @@ const addonsCapability = {
8323
8532
  name: "addons",
8324
8533
  scope: "system",
8325
8534
  mode: "singleton",
8535
+ nodeIdMode: "data",
8326
8536
  methods: {
8327
8537
  // ── Listing ──────────────────────────────────────────────────────
8328
8538
  list: method(zod.z.void(), zod.z.array(AddonListItemSchema).readonly()),
@@ -8369,13 +8579,29 @@ const addonsCapability = {
8369
8579
  zod.z.object({ query: zod.z.string().optional() }),
8370
8580
  zod.z.array(SearchResultSchema)
8371
8581
  ),
8582
+ /**
8583
+ * Available package updates for a node. `nodeId` omitted (or
8584
+ * `'hub'`) checks the hub's own installed packages; an agent
8585
+ * `nodeId` checks that agent's installed roster against npm
8586
+ * (the hub does the npm lookups + diff — agents stay npm-free).
8587
+ */
8372
8588
  listUpdates: method(
8373
- zod.z.void(),
8589
+ zod.z.object({ nodeId: zod.z.string().optional() }),
8374
8590
  zod.z.array(PackageUpdateSchema).readonly(),
8375
8591
  { auth: "admin" }
8376
8592
  ),
8593
+ /**
8594
+ * Update one package on a node. `nodeId` omitted (or `'hub'`)
8595
+ * installs on the hub via npm; an agent `nodeId` makes the hub
8596
+ * pack the resolved version and push the tarball to that agent
8597
+ * (`$agent.deploy` + `$agent.reload`) — agents need no npm runtime.
8598
+ */
8377
8599
  updatePackage: method(
8378
- zod.z.object({ name: zod.z.string().min(1), version: zod.z.string().optional() }),
8600
+ zod.z.object({
8601
+ name: zod.z.string().min(1),
8602
+ version: zod.z.string().optional(),
8603
+ nodeId: zod.z.string().optional()
8604
+ }),
8379
8605
  zod.z.unknown(),
8380
8606
  { kind: "mutation", auth: "admin" }
8381
8607
  ),
@@ -8396,12 +8622,105 @@ const addonsCapability = {
8396
8622
  zod.z.object({ rolledBackTo: zod.z.string().nullable() }),
8397
8623
  { kind: "mutation", auth: "admin" }
8398
8624
  ),
8399
- forceRefresh: method(zod.z.void(), zod.z.unknown(), { kind: "mutation", auth: "admin" }),
8625
+ /** Re-check updates for a node, bypassing any cache. `nodeId`
8626
+ * omitted (or `'hub'`) refreshes the hub; an agent `nodeId`
8627
+ * re-checks that agent's roster. */
8628
+ forceRefresh: method(
8629
+ zod.z.object({ nodeId: zod.z.string().optional() }),
8630
+ zod.z.unknown(),
8631
+ { kind: "mutation", auth: "admin" }
8632
+ ),
8400
8633
  restartServer: method(
8401
8634
  zod.z.object({ confirm: zod.z.literal(true) }),
8402
8635
  zod.z.unknown(),
8403
8636
  { kind: "mutation", auth: "admin" }
8404
8637
  ),
8638
+ /**
8639
+ * Most-recent restart marker (kind / packageName / from→to versions
8640
+ * / requestedBy / requestedAt). Returns `null` when this process
8641
+ * didn't boot from a tracked restart, or when the
8642
+ * post-boot retention window (5 min) has elapsed.
8643
+ *
8644
+ * Drives the admin-UI reconnect overlay's success toast — the
8645
+ * `system.restart-completed` event itself is fired before the
8646
+ * client has time to re-subscribe, so the client queries this on
8647
+ * first reconnect instead.
8648
+ */
8649
+ getLastRestart: method(
8650
+ zod.z.void(),
8651
+ zod.z.object({
8652
+ kind: zod.z.enum(["framework-update", "manual", "system"]),
8653
+ packageName: zod.z.string().optional(),
8654
+ fromVersion: zod.z.string().optional(),
8655
+ toVersion: zod.z.string().optional(),
8656
+ requestedBy: zod.z.string().optional(),
8657
+ requestedAt: zod.z.number()
8658
+ }).nullable(),
8659
+ { auth: "admin" }
8660
+ ),
8661
+ /**
8662
+ * Snapshot of the framework packages installed under the hub's
8663
+ * `<appRoot>/node_modules/`. Each row carries the currently
8664
+ * installed version and (best-effort) the latest version
8665
+ * available on npm. Drives the admin-UI "System packages" panel.
8666
+ *
8667
+ * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
8668
+ */
8669
+ listFrameworkPackages: method(
8670
+ zod.z.void(),
8671
+ zod.z.array(FrameworkPackageStatusSchema).readonly(),
8672
+ { auth: "admin" }
8673
+ ),
8674
+ /**
8675
+ * Cluster-wide capability-provider discovery. Returns the list of
8676
+ * `{ addonId, mode, isActive }` tuples for whatever addon(s)
8677
+ * currently provide the requested capability across the cluster.
8678
+ *
8679
+ * Why this lives on `addons` (and not on a `capabilities` cap of
8680
+ * its own): the hub's main-process `CapabilityRegistry` already
8681
+ * aggregates registrations from every forked group-runner and
8682
+ * remote agent via Moleculer event propagation — there's no
8683
+ * cross-process registry mirror to build, just an introspection
8684
+ * shim.
8685
+ *
8686
+ * Use this from addon code when you need to know whether another
8687
+ * addon has registered a specific cap (e.g. `tailscale-ingress`
8688
+ * checking `tailscale-client` is up before calling `tailscale
8689
+ * serve`). Don't reach for `ctx.capabilities.getCollectionEntries`
8690
+ * — that reads the LOCAL registry of the calling addon's group
8691
+ * runner and never sees providers in other processes. See
8692
+ * `CLAUDE.md` → Critical rules → ctx.api vs ctx.capabilities.
8693
+ */
8694
+ listCapabilityProviders: method(
8695
+ zod.z.object({ capName: zod.z.string().min(1) }),
8696
+ zod.z.array(zod.z.object({
8697
+ addonId: zod.z.string(),
8698
+ mode: zod.z.enum(["singleton", "collection"]),
8699
+ isActive: zod.z.boolean()
8700
+ })).readonly()
8701
+ ),
8702
+ /**
8703
+ * Live-update one of the framework packages marked
8704
+ * `camstack.system: true` (`@camstack/types|kernel|core|sdk|ui-library`).
8705
+ * Runs `npm install --prefix <appRoot> <name>@<version> --no-save`,
8706
+ * writes a `.restart-pending` marker, emits `system.restarting`
8707
+ * and schedules a graceful process exit. The supervisor (Docker /
8708
+ * Electron / systemd) brings the hub back up; on first boot after
8709
+ * the restart the marker fires `system.restart-completed`.
8710
+ *
8711
+ * `version` defaults to `'latest'`. The allow-list of valid
8712
+ * `packageName` values is enforced server-side.
8713
+ *
8714
+ * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
8715
+ */
8716
+ updateFrameworkPackage: method(
8717
+ zod.z.object({
8718
+ packageName: zod.z.string().min(1),
8719
+ version: zod.z.string().optional()
8720
+ }),
8721
+ UpdateFrameworkPackageResultSchema,
8722
+ { kind: "mutation", auth: "admin" }
8723
+ ),
8405
8724
  getVersions: method(
8406
8725
  zod.z.object({ name: zod.z.string() }),
8407
8726
  zod.z.array(PackageVersionInfoSchema).readonly()
@@ -8598,6 +8917,8 @@ exports.EndDownloadInputSchema = EndDownloadInputSchema;
8598
8917
  exports.EnrichedWidgetMetadataSchema = EnrichedWidgetMetadataSchema;
8599
8918
  exports.EventItemSchema = EventItemSchema;
8600
8919
  exports.EventKindSchema = EventKindSchema;
8920
+ exports.ExportSetupFieldSchema = ExportSetupFieldSchema;
8921
+ exports.ExportSetupSchema = ExportSetupSchema;
8601
8922
  exports.ExposeInputSchema = ExposeInputSchema;
8602
8923
  exports.ExposedDeviceSchema = ExposedDeviceSchema;
8603
8924
  exports.ExposedResourceSchema = ExposedResourceSchema;
@@ -8841,4 +9162,4 @@ exports.webrtcSessionCapability = webrtcSessionCapability;
8841
9162
  exports.zoneAnalyticsCapability = zoneAnalyticsCapability;
8842
9163
  exports.zoneRulesCapability = zoneRulesCapability;
8843
9164
  exports.zonesCapability = zonesCapability;
8844
- //# sourceMappingURL=index-BUBhoPUu.js.map
9165
+ //# sourceMappingURL=index-DS7418lf.js.map