@camstack/system 1.2.427 → 1.2.429

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 (100) hide show
  1. package/dist/agent-https-names-CpUSuP4w.js +120 -0
  2. package/dist/agent-https-names-uetr4OQl.mjs +91 -0
  3. package/dist/auth/auth-audit-log.d.ts +1 -1
  4. package/dist/auth/device-ca-store.d.ts +57 -0
  5. package/dist/auth/device-ca.d.ts +75 -0
  6. package/dist/auth/device-credential-manager.d.ts +154 -0
  7. package/dist/auth/login-session-manager.d.ts +14 -2
  8. package/dist/auth/user-management-internal.d.ts +10 -1
  9. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  10. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  11. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  12. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  13. package/dist/builtins/alerts/alerts.addon.js +1 -1
  14. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  15. package/dist/builtins/autotrack/index.js +1 -1
  16. package/dist/builtins/autotrack/index.mjs +1 -1
  17. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  18. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  19. package/dist/builtins/calendars/calendars.addon.js +1 -1
  20. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  21. package/dist/builtins/camera-grid/index.js +1 -1
  22. package/dist/builtins/camera-grid/index.mjs +1 -1
  23. package/dist/builtins/composer/composer.addon.js +2 -2
  24. package/dist/builtins/composer/composer.addon.mjs +2 -2
  25. package/dist/builtins/console-logging/index.js +1 -1
  26. package/dist/builtins/console-logging/index.mjs +1 -1
  27. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  28. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  29. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  30. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  31. package/dist/builtins/hub-forwarder/index.js +1 -1
  32. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  33. package/dist/builtins/keychain/index.js +10 -6
  34. package/dist/builtins/keychain/index.mjs +8 -4
  35. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  36. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  37. package/dist/builtins/local-auth/local-auth.addon.d.ts +6 -0
  38. package/dist/builtins/local-auth/local-auth.addon.js +955 -47
  39. package/dist/builtins/local-auth/local-auth.addon.mjs +946 -41
  40. package/dist/builtins/local-network/local-network.addon.js +2 -2
  41. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  42. package/dist/builtins/loki-logging/index.js +1 -1
  43. package/dist/builtins/loki-logging/index.mjs +1 -1
  44. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  45. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  46. package/dist/builtins/platform-probe/index.js +1 -1
  47. package/dist/builtins/platform-probe/index.mjs +1 -1
  48. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  49. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  50. package/dist/builtins/snapshot/index.js +1 -1
  51. package/dist/builtins/snapshot/index.mjs +1 -1
  52. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  53. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  54. package/dist/builtins/sqlite-storage/index.js +1 -1
  55. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  56. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +3 -3
  57. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +3 -3
  58. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  59. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  60. package/dist/builtins/system-config/system-config.addon.d.ts +18 -0
  61. package/dist/builtins/system-config/system-config.addon.js +834 -18
  62. package/dist/builtins/system-config/system-config.addon.mjs +819 -19
  63. package/dist/builtins/winston-logging/index.js +1 -1
  64. package/dist/builtins/winston-logging/index.mjs +1 -1
  65. package/dist/{composition-sources-DvCGZEUI.js → composition-sources-C2VNX6tF.js} +1 -1
  66. package/dist/{composition-sources-BQNxXQZG.mjs → composition-sources-SYtYuAgh.mjs} +1 -1
  67. package/dist/{constants-CR4If_lP.mjs → constants-CKuWoWvc.mjs} +1 -1
  68. package/dist/{constants-CCSJGnjs.js → constants-RI-hGP5S.js} +1 -1
  69. package/dist/device-ca-BWfdDB3k.js +462 -0
  70. package/dist/device-ca-R7DKKZL6.mjs +355 -0
  71. package/dist/{dist-BQG3QFg7.js → dist-Bgy_AmwX.js} +554 -0
  72. package/dist/{dist-DHSJV4Qc.mjs → dist-CSSfTM18.mjs} +507 -1
  73. package/dist/file-host-worker.js +1 -1
  74. package/dist/file-host-worker.mjs +1 -1
  75. package/dist/index.d.ts +4 -1
  76. package/dist/index.js +59 -12
  77. package/dist/index.mjs +10 -9
  78. package/dist/kernel/index.d.ts +2 -2
  79. package/dist/kernel/moleculer/mesh-mtls/index.d.ts +4 -1
  80. package/dist/kernel/moleculer/mesh-mtls/mesh-certificate-registry.d.ts +91 -0
  81. package/dist/kernel/moleculer/mesh-mtls/mesh-enroll.d.ts +4 -0
  82. package/dist/kernel/moleculer/mesh-mtls/mesh-peer-transport.d.ts +23 -0
  83. package/dist/kernel/moleculer/mesh-mtls/mesh-renewal.d.ts +126 -0
  84. package/dist/kernel/moleculer/mesh-mtls/mesh-tls-gate.d.ts +40 -0
  85. package/dist/kernel/moleculer/mesh-mtls/tls-tcp-transporter.d.ts +15 -0
  86. package/dist/{restore-archive-DH1Pxq_1.mjs → restore-archive-AIwMHO5_.mjs} +1 -1
  87. package/dist/{restore-archive-Dccm8lkA.js → restore-archive-BYUEMsog.js} +1 -1
  88. package/dist/{retired-settings-keys-BfGaSeQI.js → retired-settings-keys-BTPkRLTS.js} +1 -1
  89. package/dist/{retired-settings-keys-CPz7zpza.mjs → retired-settings-keys-H0rYXT27.mjs} +1 -1
  90. package/dist/tls/agent-https-names.d.ts +27 -0
  91. package/dist/tls/agent-https.d.ts +111 -0
  92. package/dist/tls/cert-issue.d.ts +7 -0
  93. package/dist/tls/index.d.ts +3 -0
  94. package/dist/{tls-BgImdxCO.js → tls-C5IYg3V5.js} +406 -0
  95. package/dist/{tls-CaOLZ09W.mjs → tls-CpcGkeJV.mjs} +314 -4
  96. package/dist/{wal-maintenance-DItkuOvu.js → wal-maintenance-BSGsxKW7.js} +0 -0
  97. package/dist/{wal-maintenance-Drqhcjit.mjs → wal-maintenance-DW0FfGV7.mjs} +0 -0
  98. package/package.json +4 -1
  99. package/dist/jwt-signing-key-BZm055IP.js +0 -174
  100. package/dist/jwt-signing-key-DL-qk1SM.mjs +0 -127
@@ -9769,6 +9769,206 @@ function scopesAllowAddon(scopes, addonId, access) {
9769
9769
  return scopes.some((s) => s.type === "addon" && s.target === addonId && s.access.includes(access));
9770
9770
  }
9771
9771
  /**
9772
+ * Device certificates (D855) — the wire contract shared by the hub, the admin
9773
+ * UI and the native viewer.
9774
+ *
9775
+ * A device (a phone) generates its OWN P-256 key pair in hardware (Secure
9776
+ * Enclave / Android Keystore / a non-extractable WebCrypto key). The private
9777
+ * key never travels. The hub signs the PUBLIC key into an X.509 leaf under a
9778
+ * dedicated device CA; the device later proves possession of the key by
9779
+ * signing a hub-issued nonce, and the hub answers with the same session a
9780
+ * password login opens.
9781
+ *
9782
+ * Everything on the wire is a small string (a PEM, a base64url signature):
9783
+ * D613 is about bulk bytes, and a certificate is ~600 bytes.
9784
+ */
9785
+ /** Signature algorithm of every device credential: ECDSA, curve P-256, SHA-256. */
9786
+ var DEVICE_CERT_SIGNATURE = "ecdsa-p256-sha256";
9787
+ /** First line of every signed message; a change of format bumps the version. */
9788
+ var DEVICE_SIGNATURE_MESSAGE_VERSION = "camstack-device-cert-v1";
9789
+ zod.z.enum([
9790
+ "login",
9791
+ "renew",
9792
+ "revoke"
9793
+ ]);
9794
+ /** One-shot enrollment code and login nonce lifetimes. */
9795
+ var DEVICE_ENROLLMENT_TTL_MS = 10 * 6e4;
9796
+ var DEVICE_NONCE_TTL_MS = 6e4;
9797
+ /** SAN URI prefixes of a device leaf. */
9798
+ var DEVICE_SAN_CREDENTIAL_PREFIX = "camstack:credential:";
9799
+ var DEVICE_SAN_USER_PREFIX = "camstack:user:";
9800
+ /**
9801
+ * The exact bytes a device signs (UTF-8, `\n` separators, no trailing newline):
9802
+ *
9803
+ * camstack-device-cert-v1
9804
+ * <login|renew>
9805
+ * <origin> the hub origin returned by `getDeviceChallenge`
9806
+ * <nonce>
9807
+ *
9808
+ * The origin is part of the message so a signature collected by a look-alike
9809
+ * hub is worthless on the real one; the hub additionally binds the nonce to
9810
+ * the origin it issued it for and refuses any other.
9811
+ */
9812
+ function buildDeviceSignatureMessage(input) {
9813
+ return [
9814
+ DEVICE_SIGNATURE_MESSAGE_VERSION,
9815
+ input.purpose,
9816
+ input.origin,
9817
+ input.nonce
9818
+ ].join("\n");
9819
+ }
9820
+ /** The deep link a QR carries: `camstack://enroll?hub=<origin>&code=<code>`. */
9821
+ function buildDeviceEnrollmentLink(input) {
9822
+ const query = new URLSearchParams();
9823
+ if (input.hub !== void 0) query.set("hub", input.hub);
9824
+ query.set("code", input.code);
9825
+ return `${input.scheme ?? "camstack"}://enroll?${query.toString()}`;
9826
+ }
9827
+ var DevicePlatformSchema = zod.z.enum([
9828
+ "ios",
9829
+ "android",
9830
+ "web",
9831
+ "other"
9832
+ ]);
9833
+ var Base64UrlSchema = zod.z.string().min(1).max(4096).regex(/^[A-Za-z0-9_-]+$/);
9834
+ var PemSchema = zod.z.string().min(1).max(16384);
9835
+ /**
9836
+ * Why a device-certificate endpoint said no. Distinct from a transport / 5xx
9837
+ * failure: those carry no reason and mean "try again", never "the credential is
9838
+ * dead". The viewer switches on this exhaustively.
9839
+ */
9840
+ var DeviceRefusalReasonSchema = zod.z.enum([
9841
+ "revoked",
9842
+ "unknown-credential",
9843
+ "expired",
9844
+ "bad-signature",
9845
+ "nonce-invalid",
9846
+ "rate-limited",
9847
+ "invalid-certificate",
9848
+ "superseded",
9849
+ "user-gone",
9850
+ "unavailable",
9851
+ "code-invalid",
9852
+ "self-enrollment-disabled",
9853
+ "step-up-required",
9854
+ "bad-public-key"
9855
+ ]);
9856
+ var DeviceRefusalSchema = zod.z.object({
9857
+ ok: zod.z.literal(false),
9858
+ reason: DeviceRefusalReasonSchema,
9859
+ definitive: zod.z.boolean(),
9860
+ retryAfterSeconds: zod.z.number().optional()
9861
+ });
9862
+ zod.z.object({
9863
+ code: zod.z.string().min(1).max(256),
9864
+ /** SubjectPublicKeyInfo DER of the device's P-256 public key, base64url. */
9865
+ publicKeySpki: Base64UrlSchema,
9866
+ deviceName: zod.z.string().min(1).max(80).optional(),
9867
+ platform: DevicePlatformSchema
9868
+ });
9869
+ var CompleteEnrollmentOutputSchema = zod.z.object({
9870
+ credentialId: zod.z.string(),
9871
+ certPem: PemSchema,
9872
+ /** The device CA certificate the leaf chains to. */
9873
+ chainPem: PemSchema,
9874
+ notAfter: zod.z.number(),
9875
+ user: zod.z.object({
9876
+ id: zod.z.string(),
9877
+ username: zod.z.string()
9878
+ })
9879
+ });
9880
+ zod.z.discriminatedUnion("ok", [CompleteEnrollmentOutputSchema.extend({ ok: zod.z.literal(true) }), DeviceRefusalSchema]);
9881
+ zod.z.object({
9882
+ /** The single-use step-up proof (`auth.deviceEnrollProofFrom…`). */
9883
+ proof: zod.z.string().min(1).max(512),
9884
+ publicKeySpki: Base64UrlSchema,
9885
+ deviceName: zod.z.string().min(1).max(80),
9886
+ platform: DevicePlatformSchema
9887
+ });
9888
+ zod.z.object({
9889
+ proof: zod.z.string(),
9890
+ expiresAt: zod.z.number()
9891
+ });
9892
+ var DeviceChallengeSchema = zod.z.object({
9893
+ nonce: zod.z.string(),
9894
+ /** The origin to put in the signed message. The app compares it to the hub it dialled. */
9895
+ origin: zod.z.string(),
9896
+ expiresAt: zod.z.number(),
9897
+ signature: zod.z.literal(DEVICE_CERT_SIGNATURE)
9898
+ });
9899
+ zod.z.discriminatedUnion("ok", [DeviceChallengeSchema.extend({ ok: zod.z.literal(true) }), DeviceRefusalSchema]);
9900
+ zod.z.object({
9901
+ certPem: PemSchema,
9902
+ nonce: zod.z.string().min(1).max(256),
9903
+ /** ECDSA P-256 SHA-256 over {@link buildDeviceSignatureMessage}; raw r||s or DER, base64url. */
9904
+ signature: Base64UrlSchema
9905
+ });
9906
+ var RenewDeviceCertificateOutputSchema = zod.z.object({
9907
+ credentialId: zod.z.string(),
9908
+ certPem: PemSchema,
9909
+ chainPem: PemSchema,
9910
+ notAfter: zod.z.number()
9911
+ });
9912
+ zod.z.discriminatedUnion("ok", [RenewDeviceCertificateOutputSchema.extend({ ok: zod.z.literal(true) }), DeviceRefusalSchema]);
9913
+ zod.z.discriminatedUnion("ok", [zod.z.object({
9914
+ ok: zod.z.literal(true),
9915
+ credentialId: zod.z.string(),
9916
+ sessionsEnded: zod.z.number().int()
9917
+ }), DeviceRefusalSchema]);
9918
+ function formatDeviceRevoker(revoker) {
9919
+ return revoker.kind === "device" ? "device" : `${revoker.kind}:${revoker.userId}`;
9920
+ }
9921
+ var DeviceCredentialStatusSchema = zod.z.enum([
9922
+ "active",
9923
+ "expired",
9924
+ "revoked"
9925
+ ]);
9926
+ var DeviceCredentialSchema = zod.z.object({
9927
+ id: zod.z.string(),
9928
+ userId: zod.z.string(),
9929
+ username: zod.z.string().nullable(),
9930
+ deviceName: zod.z.string(),
9931
+ platform: DevicePlatformSchema,
9932
+ enrolledVia: zod.z.enum(["qr", "self"]),
9933
+ /** SHA-256 of the leaf certificate DER, colon-hex. */
9934
+ fingerprint: zod.z.string(),
9935
+ issuedAt: zod.z.number(),
9936
+ expiresAt: zod.z.number(),
9937
+ lastUsedAt: zod.z.number().nullable(),
9938
+ lastUsedFrom: zod.z.string().nullable(),
9939
+ revokedAt: zod.z.number().nullable(),
9940
+ /** `admin:<userId>` | `user:<userId>` | `device` | `user-deleted`. */
9941
+ revokedBy: zod.z.string().nullable(),
9942
+ status: DeviceCredentialStatusSchema
9943
+ });
9944
+ var StartEnrollmentOutputSchema = zod.z.object({
9945
+ /** Shown once; only its hash is kept. */
9946
+ code: zod.z.string(),
9947
+ expiresAt: zod.z.number(),
9948
+ /** `camstack://enroll?hub=…&code=…` — what the QR encodes. */
9949
+ enrollUrl: zod.z.string(),
9950
+ /** The hub origin in the link, or `null` when the hub could not name one (the link then has no `hub`). */
9951
+ hubOrigin: zod.z.string().nullable(),
9952
+ /** Every origin the apps may try (role `appConnections`). */
9953
+ hubOrigins: zod.z.array(zod.z.string())
9954
+ });
9955
+ zod.z.object({
9956
+ kind: zod.z.literal("device-certificate"),
9957
+ id: zod.z.literal("device-certificate"),
9958
+ label: zod.z.string(),
9959
+ stage: zod.z.literal("primary"),
9960
+ /** tRPC paths under the hub's `auth` router, so a client names no literal. */
9961
+ challengePath: zod.z.literal("auth.getDeviceChallenge"),
9962
+ revokePath: zod.z.literal("auth.revokeOwnDeviceCertificate"),
9963
+ enrollSelfPath: zod.z.literal("auth.enrollSelf"),
9964
+ loginPath: zod.z.literal("auth.loginWithDeviceCertificate"),
9965
+ renewPath: zod.z.literal("auth.renewDeviceCertificate"),
9966
+ signature: zod.z.literal(DEVICE_CERT_SIGNATURE),
9967
+ messageVersion: zod.z.literal(DEVICE_SIGNATURE_MESSAGE_VERSION),
9968
+ /** Which clients can execute it: a native app silently, a browser with a non-extractable WebCrypto key. */
9969
+ clients: zod.z.array(zod.z.enum(["native", "web"]))
9970
+ });
9971
+ /**
9772
9972
  * What an expression's named bindings READ from.
9773
9973
  *
9774
9974
  * Salvaged verbatim from the deleted device-link mechanism. Wiring's source
@@ -16009,6 +16209,220 @@ var keychainCapability = {
16009
16209
  getState: method(zod.z.object({}), KeychainStateSchema, { auth: "admin" })
16010
16210
  }
16011
16211
  };
16212
+ var DeviceCaStatusSchema = zod.z.discriminatedUnion("state", [
16213
+ zod.z.object({ state: zod.z.literal("absent") }),
16214
+ zod.z.object({
16215
+ state: zod.z.literal("ready"),
16216
+ subject: zod.z.string(),
16217
+ fingerprintSha256: zod.z.string(),
16218
+ validTo: zod.z.string()
16219
+ }),
16220
+ zod.z.object({
16221
+ state: zod.z.literal("unavailable"),
16222
+ reason: zod.z.string()
16223
+ })
16224
+ ]);
16225
+ var DeviceCertificateSettingsSchema = zod.z.object({ selfEnrollment: zod.z.enum(["allowed", "disabled"]) });
16226
+ /**
16227
+ * `device-credentials` — the admin surface of device certificates (D855).
16228
+ *
16229
+ * Everything a device does ITSELF — completing an enrollment, getting a
16230
+ * challenge, signing in, renewing — is a PUBLIC procedure of the hub's `auth`
16231
+ * router (`auth.completeEnrollment`, `getDeviceChallenge`,
16232
+ * `loginWithDeviceCertificate`, `renewDeviceCertificate`): those legs are
16233
+ * proofs of possession, not capability calls, and must not be reachable as
16234
+ * cap methods. This cap holds only what an operator does about them.
16235
+ *
16236
+ * Provider: `local-auth`, which also owns the device CA and the registry.
16237
+ * The hub is the only node that persists device credentials.
16238
+ */
16239
+ var deviceCredentialsCapability = {
16240
+ name: "device-credentials",
16241
+ scope: "system",
16242
+ mode: "singleton",
16243
+ methods: {
16244
+ /**
16245
+ * Every enrolled device, newest first; `userId` narrows to one user.
16246
+ * `status` is derived: revoked wins over expired.
16247
+ */
16248
+ listDeviceCredentials: method(zod.z.object({
16249
+ userId: zod.z.string().min(1).optional(),
16250
+ includeRevoked: zod.z.boolean().default(false)
16251
+ }), zod.z.array(DeviceCredentialSchema).readonly(), { auth: "admin" }),
16252
+ /**
16253
+ * Mint a one-shot enrollment code for `userId` and a device name: 128-bit
16254
+ * random, single use, 10 minutes, kept only as a hash. Returns the code
16255
+ * once, with the `camstack://enroll?hub=…&code=…` link a QR carries.
16256
+ * `caller` (the admin) is recorded in the audit trail.
16257
+ */
16258
+ startEnrollment: method(zod.z.object({
16259
+ userId: zod.z.string().min(1),
16260
+ deviceName: zod.z.string().min(1).max(80)
16261
+ }), StartEnrollmentOutputSchema, {
16262
+ kind: "mutation",
16263
+ auth: "admin",
16264
+ caller: "required"
16265
+ }),
16266
+ /**
16267
+ * Revoke a credential: its certificate stops logging in at once, and every
16268
+ * session it opened ends (an open session also dies at its next refresh
16269
+ * even if this call raced it). Idempotent.
16270
+ */
16271
+ revokeDeviceCredential: method(zod.z.object({ id: zod.z.string().min(1) }), zod.z.object({
16272
+ revoked: zod.z.boolean(),
16273
+ sessionsEnded: zod.z.number().int(),
16274
+ status: DeviceCredentialStatusSchema
16275
+ }), {
16276
+ kind: "mutation",
16277
+ auth: "admin",
16278
+ caller: "required"
16279
+ }),
16280
+ /**
16281
+ * Hub-wide device-certificate settings. `selfEnrollment`: `allowed`
16282
+ * (default) lets a signed-in user enroll their own device after a step-up
16283
+ * sign-in; `disabled` makes `auth.enrollSelf` refuse. The admin QR path is
16284
+ * unaffected. Hub-wide only (no per-role switch).
16285
+ */
16286
+ getDeviceCertificateSettings: method(zod.z.object({}), DeviceCertificateSettingsSchema, { auth: "admin" }),
16287
+ setDeviceCertificateSettings: method(DeviceCertificateSettingsSchema, DeviceCertificateSettingsSchema, {
16288
+ kind: "mutation",
16289
+ auth: "admin"
16290
+ }),
16291
+ /**
16292
+ * Delete the registry row of a REVOKED credential (clean-up; the audit trail
16293
+ * keeps the revocation). Refuses a live credential: revoke it first. After
16294
+ * the row is gone the device's next call answers `unknown-credential`.
16295
+ */
16296
+ deleteDeviceCredential: method(zod.z.object({ id: zod.z.string().min(1) }), zod.z.object({ result: zod.z.enum([
16297
+ "deleted",
16298
+ "live",
16299
+ "unknown"
16300
+ ]) }), {
16301
+ kind: "mutation",
16302
+ auth: "admin",
16303
+ caller: "required"
16304
+ }),
16305
+ /**
16306
+ * The device CA: `absent` until the first enrollment creates it (lazily,
16307
+ * never rotated on boot), `unavailable` while the keychain cannot answer.
16308
+ */
16309
+ getDeviceCaStatus: method(zod.z.object({}), DeviceCaStatusSchema, { auth: "admin" }),
16310
+ /** Rename a credential (the label only; the certificate is unchanged). */
16311
+ renameDeviceCredential: method(zod.z.object({
16312
+ id: zod.z.string().min(1),
16313
+ deviceName: zod.z.string().min(1).max(80)
16314
+ }), zod.z.object({ renamed: zod.z.boolean() }), {
16315
+ kind: "mutation",
16316
+ auth: "admin"
16317
+ })
16318
+ }
16319
+ };
16320
+ /**
16321
+ * `node-certificates` - what a node holds and the two renewals the hub drives
16322
+ * (D856): the node's MESH leaf (mutual TLS to the hub) and its HTTPS leaf (issued
16323
+ * from the hub's local CA so a device that trusts the hub root trusts the node).
16324
+ *
16325
+ * Provided by the AGENT RUNTIME (the synthetic `agent-runtime` addon id, like
16326
+ * `server-management`): the hub reaches it through the ordinary node-pinned
16327
+ * capability call - no new Moleculer action. The hub's own certificates are
16328
+ * handled in-process by the hub (`certificates` router), so this cap has no hub
16329
+ * provider.
16330
+ *
16331
+ * No private key ever crosses the mesh: the node generates its key pair, sends a
16332
+ * CSR, and the hub returns only the signed certificate.
16333
+ */
16334
+ var MeshLeafInfoSchema = zod.z.object({
16335
+ cn: zod.z.string(),
16336
+ serial: zod.z.string(),
16337
+ fingerprintSha256: zod.z.string(),
16338
+ notBefore: zod.z.number(),
16339
+ notAfter: zod.z.number()
16340
+ });
16341
+ var HttpsLeafInfoSchema = zod.z.object({
16342
+ fingerprintSha256: zod.z.string(),
16343
+ issuer: zod.z.string(),
16344
+ sans: zod.z.array(zod.z.string()),
16345
+ notBefore: zod.z.number(),
16346
+ notAfter: zod.z.number()
16347
+ });
16348
+ var NodeHttpsStateSchema = zod.z.discriminatedUnion("state", [zod.z.object({
16349
+ state: zod.z.literal("served"),
16350
+ leaf: HttpsLeafInfoSchema
16351
+ }), zod.z.object({
16352
+ state: zod.z.literal("not-issued"),
16353
+ reason: zod.z.string()
16354
+ })]);
16355
+ var nodeCertificatesCapability = {
16356
+ name: "node-certificates",
16357
+ scope: "system",
16358
+ mode: "singleton",
16359
+ internal: true,
16360
+ methods: {
16361
+ /** The node's current mesh leaf (`null` when it is not enrolled on mTLS) and HTTPS state. */
16362
+ getCertificates: method(zod.z.object({}), zod.z.object({
16363
+ nodeId: zod.z.string(),
16364
+ mesh: MeshLeafInfoSchema.nullable(),
16365
+ https: NodeHttpsStateSchema
16366
+ }), { auth: "admin" }),
16367
+ /** Generate a NEW mesh key pair on the node; return the CSR (CN = node id). The key stays here. */
16368
+ prepareMeshRenewal: method(zod.z.object({}), zod.z.object({ csrPem: zod.z.string() }), {
16369
+ kind: "mutation",
16370
+ auth: "admin"
16371
+ }),
16372
+ /**
16373
+ * Install the hub-signed leaf for the key made by `prepareMeshRenewal`: persist it
16374
+ * (keeping the previous one), then reconnect to the hub with it. The node reverts to
16375
+ * the previous leaf by itself unless `confirmMeshLeaf` arrives within `confirmWithinMs`.
16376
+ */
16377
+ installMeshLeaf: method(zod.z.object({
16378
+ certPem: zod.z.string().min(1),
16379
+ caCertPem: zod.z.string().min(1),
16380
+ confirmWithinMs: zod.z.number().int().min(1e4).max(6e5)
16381
+ }), zod.z.object({
16382
+ fingerprintSha256: zod.z.string(),
16383
+ serial: zod.z.string()
16384
+ }), {
16385
+ kind: "mutation",
16386
+ auth: "admin"
16387
+ }),
16388
+ /** The hub saw the node reconnect with the new leaf: keep it, forget the previous one. */
16389
+ confirmMeshLeaf: method(zod.z.object({ fingerprintSha256: zod.z.string() }), zod.z.object({ confirmed: zod.z.boolean() }), {
16390
+ kind: "mutation",
16391
+ auth: "admin"
16392
+ }),
16393
+ /** Go back to the previous leaf now. `false` when there is none to go back to. */
16394
+ rollbackMeshLeaf: method(zod.z.object({}), zod.z.object({ rolledBack: zod.z.boolean() }), {
16395
+ kind: "mutation",
16396
+ auth: "admin"
16397
+ }),
16398
+ /** A key pair + CSR for the node's HTTPS leaf, and the names the node reports for itself. */
16399
+ prepareHttpsCertificate: method(zod.z.object({}), zod.z.object({
16400
+ csrPem: zod.z.string(),
16401
+ hostnames: zod.z.array(zod.z.string()),
16402
+ addresses: zod.z.array(zod.z.string()),
16403
+ /** SHA-256 of the hub local CA this node pinned at its first install; `null` before one. */
16404
+ pinnedCaFingerprintSha256: zod.z.string().nullable()
16405
+ }), {
16406
+ kind: "mutation",
16407
+ auth: "admin"
16408
+ }),
16409
+ /** Install the hub-signed HTTPS leaf and hot-swap the serving context (no restart). */
16410
+ installHttpsCertificate: method(zod.z.object({
16411
+ certPem: zod.z.string().min(1),
16412
+ caCertPem: zod.z.string().min(1),
16413
+ /**
16414
+ * The hub signals that its local CA was rotated (D227) and this leaf chains to the NEW
16415
+ * one. Only the hub, over the authenticated mesh, can say so; a leaf with a different CA
16416
+ * and no signal is refused.
16417
+ */
16418
+ caRotation: zod.z.boolean().optional()
16419
+ }), HttpsLeafInfoSchema, {
16420
+ kind: "mutation",
16421
+ auth: "admin"
16422
+ })
16423
+ },
16424
+ mount: { kind: "skip" }
16425
+ };
16012
16426
  /**
16013
16427
  * `keychain-admin` — the operator's view of the keychain (System → Secrets).
16014
16428
  *
@@ -73219,6 +73633,54 @@ var METHOD_ACCESS_MAP = Object.freeze({
73219
73633
  addonId: null,
73220
73634
  access: "create"
73221
73635
  },
73636
+ "deviceCredentials.deleteDeviceCredential": {
73637
+ capName: "device-credentials",
73638
+ capScope: "system",
73639
+ addonId: null,
73640
+ access: "delete"
73641
+ },
73642
+ "deviceCredentials.getDeviceCaStatus": {
73643
+ capName: "device-credentials",
73644
+ capScope: "system",
73645
+ addonId: null,
73646
+ access: "view"
73647
+ },
73648
+ "deviceCredentials.getDeviceCertificateSettings": {
73649
+ capName: "device-credentials",
73650
+ capScope: "system",
73651
+ addonId: null,
73652
+ access: "view"
73653
+ },
73654
+ "deviceCredentials.listDeviceCredentials": {
73655
+ capName: "device-credentials",
73656
+ capScope: "system",
73657
+ addonId: null,
73658
+ access: "view"
73659
+ },
73660
+ "deviceCredentials.renameDeviceCredential": {
73661
+ capName: "device-credentials",
73662
+ capScope: "system",
73663
+ addonId: null,
73664
+ access: "create"
73665
+ },
73666
+ "deviceCredentials.revokeDeviceCredential": {
73667
+ capName: "device-credentials",
73668
+ capScope: "system",
73669
+ addonId: null,
73670
+ access: "delete"
73671
+ },
73672
+ "deviceCredentials.setDeviceCertificateSettings": {
73673
+ capName: "device-credentials",
73674
+ capScope: "system",
73675
+ addonId: null,
73676
+ access: "create"
73677
+ },
73678
+ "deviceCredentials.startEnrollment": {
73679
+ capName: "device-credentials",
73680
+ capScope: "system",
73681
+ addonId: null,
73682
+ access: "create"
73683
+ },
73222
73684
  "deviceDiscovery.adoptDevice": {
73223
73685
  capName: "device-discovery",
73224
73686
  capScope: "device",
@@ -75379,6 +75841,48 @@ var METHOD_ACCESS_MAP = Object.freeze({
75379
75841
  addonId: null,
75380
75842
  access: "create"
75381
75843
  },
75844
+ "nodeCertificates.confirmMeshLeaf": {
75845
+ capName: "node-certificates",
75846
+ capScope: "system",
75847
+ addonId: null,
75848
+ access: "create"
75849
+ },
75850
+ "nodeCertificates.getCertificates": {
75851
+ capName: "node-certificates",
75852
+ capScope: "system",
75853
+ addonId: null,
75854
+ access: "view"
75855
+ },
75856
+ "nodeCertificates.installHttpsCertificate": {
75857
+ capName: "node-certificates",
75858
+ capScope: "system",
75859
+ addonId: null,
75860
+ access: "create"
75861
+ },
75862
+ "nodeCertificates.installMeshLeaf": {
75863
+ capName: "node-certificates",
75864
+ capScope: "system",
75865
+ addonId: null,
75866
+ access: "create"
75867
+ },
75868
+ "nodeCertificates.prepareHttpsCertificate": {
75869
+ capName: "node-certificates",
75870
+ capScope: "system",
75871
+ addonId: null,
75872
+ access: "create"
75873
+ },
75874
+ "nodeCertificates.prepareMeshRenewal": {
75875
+ capName: "node-certificates",
75876
+ capScope: "system",
75877
+ addonId: null,
75878
+ access: "create"
75879
+ },
75880
+ "nodeCertificates.rollbackMeshLeaf": {
75881
+ capName: "node-certificates",
75882
+ capScope: "system",
75883
+ addonId: null,
75884
+ access: "create"
75885
+ },
75382
75886
  "nodes.clusterAddonStatus": {
75383
75887
  capName: "nodes",
75384
75888
  capScope: "system",
@@ -79745,6 +80249,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
79745
80249
  detectionPipelineCapability,
79746
80250
  deviceAdminLinkCapability,
79747
80251
  deviceAdoptionCapability,
80252
+ deviceCredentialsCapability,
79748
80253
  deviceDiscoveryCapability,
79749
80254
  deviceExportCapability,
79750
80255
  deviceExtensionCapability,
@@ -79796,6 +80301,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
79796
80301
  networkAccessCapability,
79797
80302
  networkLinkCapability,
79798
80303
  networkQualityCapability,
80304
+ nodeCertificatesCapability,
79799
80305
  nodesCapability,
79800
80306
  notificationOutputCapability,
79801
80307
  notificationRulesCapability,
@@ -84288,6 +84794,30 @@ Object.defineProperty(exports, "DERIVED_CAMERA_SILENCED_CAP_NAMES", {
84288
84794
  return DERIVED_CAMERA_SILENCED_CAP_NAMES;
84289
84795
  }
84290
84796
  });
84797
+ Object.defineProperty(exports, "DEVICE_ENROLLMENT_TTL_MS", {
84798
+ enumerable: true,
84799
+ get: function() {
84800
+ return DEVICE_ENROLLMENT_TTL_MS;
84801
+ }
84802
+ });
84803
+ Object.defineProperty(exports, "DEVICE_NONCE_TTL_MS", {
84804
+ enumerable: true,
84805
+ get: function() {
84806
+ return DEVICE_NONCE_TTL_MS;
84807
+ }
84808
+ });
84809
+ Object.defineProperty(exports, "DEVICE_SAN_CREDENTIAL_PREFIX", {
84810
+ enumerable: true,
84811
+ get: function() {
84812
+ return DEVICE_SAN_CREDENTIAL_PREFIX;
84813
+ }
84814
+ });
84815
+ Object.defineProperty(exports, "DEVICE_SAN_USER_PREFIX", {
84816
+ enumerable: true,
84817
+ get: function() {
84818
+ return DEVICE_SAN_USER_PREFIX;
84819
+ }
84820
+ });
84291
84821
  Object.defineProperty(exports, "DEVICE_SETTINGS_CONTRIBUTION_METHODS", {
84292
84822
  enumerable: true,
84293
84823
  get: function() {
@@ -84570,6 +85100,18 @@ Object.defineProperty(exports, "buildCapabilityLookup", {
84570
85100
  return buildCapabilityLookup;
84571
85101
  }
84572
85102
  });
85103
+ Object.defineProperty(exports, "buildDeviceEnrollmentLink", {
85104
+ enumerable: true,
85105
+ get: function() {
85106
+ return buildDeviceEnrollmentLink;
85107
+ }
85108
+ });
85109
+ Object.defineProperty(exports, "buildDeviceSignatureMessage", {
85110
+ enumerable: true,
85111
+ get: function() {
85112
+ return buildDeviceSignatureMessage;
85113
+ }
85114
+ });
84573
85115
  Object.defineProperty(exports, "buildFfmpegArgs", {
84574
85116
  enumerable: true,
84575
85117
  get: function() {
@@ -84786,6 +85328,12 @@ Object.defineProperty(exports, "describeComposableCaps", {
84786
85328
  return describeComposableCaps;
84787
85329
  }
84788
85330
  });
85331
+ Object.defineProperty(exports, "deviceCredentialsCapability", {
85332
+ enumerable: true,
85333
+ get: function() {
85334
+ return deviceCredentialsCapability;
85335
+ }
85336
+ });
84789
85337
  Object.defineProperty(exports, "deviceExtensionCapability", {
84790
85338
  enumerable: true,
84791
85339
  get: function() {
@@ -84900,6 +85448,12 @@ Object.defineProperty(exports, "foldSnapshotByFunction", {
84900
85448
  return foldSnapshotByFunction;
84901
85449
  }
84902
85450
  });
85451
+ Object.defineProperty(exports, "formatDeviceRevoker", {
85452
+ enumerable: true,
85453
+ get: function() {
85454
+ return formatDeviceRevoker;
85455
+ }
85456
+ });
84903
85457
  Object.defineProperty(exports, "formatMinutes", {
84904
85458
  enumerable: true,
84905
85459
  get: function() {