@camstack/types 1.2.364 → 1.2.365

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.
package/dist/addon.js CHANGED
@@ -16,7 +16,7 @@ const require_err_msg = require("./err-msg-Dx2Kor0g.js");
16
16
  * Plain data, zero Zod: a forked runner must not import the schema barrel
17
17
  * (~144MB RSS per runner — D28).
18
18
  *
19
- * Coverage: 25 caps, 66 methods with defaults.
19
+ * Coverage: 26 caps, 67 methods with defaults.
20
20
  */
21
21
  var CAP_INPUT_DEFAULTS = Object.freeze({
22
22
  "addons": { "getLogs": { "limit": 100 } },
@@ -39,6 +39,7 @@ var CAP_INPUT_DEFAULTS = Object.freeze({
39
39
  "page": 1,
40
40
  "pageSize": 50
41
41
  } },
42
+ "device-credentials": { "listDeviceCredentials": { "includeRevoked": false } },
42
43
  "device-manager": { "adoptionListCandidates": {
43
44
  "page": 1,
44
45
  "pageSize": 50
package/dist/addon.mjs CHANGED
@@ -15,7 +15,7 @@ import { a as DeviceType, t as errMsg } from "./err-msg-DX6i_MY4.mjs";
15
15
  * Plain data, zero Zod: a forked runner must not import the schema barrel
16
16
  * (~144MB RSS per runner — D28).
17
17
  *
18
- * Coverage: 25 caps, 66 methods with defaults.
18
+ * Coverage: 26 caps, 67 methods with defaults.
19
19
  */
20
20
  var CAP_INPUT_DEFAULTS = Object.freeze({
21
21
  "addons": { "getLogs": { "limit": 100 } },
@@ -38,6 +38,7 @@ var CAP_INPUT_DEFAULTS = Object.freeze({
38
38
  "page": 1,
39
39
  "pageSize": 50
40
40
  } },
41
+ "device-credentials": { "listDeviceCredentials": { "includeRevoked": false } },
41
42
  "device-manager": { "adoptionListCandidates": {
42
43
  "page": 1,
43
44
  "pageSize": 50
@@ -0,0 +1,372 @@
1
+ /**
2
+ * Device certificates (D855) — the wire contract shared by the hub, the admin
3
+ * UI and the native viewer.
4
+ *
5
+ * A device (a phone) generates its OWN P-256 key pair in hardware (Secure
6
+ * Enclave / Android Keystore / a non-extractable WebCrypto key). The private
7
+ * key never travels. The hub signs the PUBLIC key into an X.509 leaf under a
8
+ * dedicated device CA; the device later proves possession of the key by
9
+ * signing a hub-issued nonce, and the hub answers with the same session a
10
+ * password login opens.
11
+ *
12
+ * Everything on the wire is a small string (a PEM, a base64url signature):
13
+ * D613 is about bulk bytes, and a certificate is ~600 bytes.
14
+ */
15
+ import { z } from 'zod';
16
+ /** Signature algorithm of every device credential: ECDSA, curve P-256, SHA-256. */
17
+ export declare const DEVICE_CERT_SIGNATURE: 'ecdsa-p256-sha256';
18
+ /** First line of every signed message; a change of format bumps the version. */
19
+ export declare const DEVICE_SIGNATURE_MESSAGE_VERSION: 'camstack-device-cert-v1';
20
+ /** What a signature is for. A login signature can never be replayed as a renewal. */
21
+ export declare const DeviceSignaturePurposeSchema: z.ZodEnum<{
22
+ login: "login";
23
+ renew: "renew";
24
+ revoke: "revoke";
25
+ }>;
26
+ export type DeviceSignaturePurpose = z.infer<typeof DeviceSignaturePurposeSchema>;
27
+ /** Leaf lifetime and the window in which the app renews it. */
28
+ export declare const DEVICE_CERT_VALIDITY_DAYS = 365;
29
+ export declare const DEVICE_CERT_RENEW_WINDOW_DAYS = 30;
30
+ /** One-shot enrollment code and login nonce lifetimes. */
31
+ export declare const DEVICE_ENROLLMENT_TTL_MS: number;
32
+ export declare const DEVICE_NONCE_TTL_MS = 60000;
33
+ /** SAN URI prefixes of a device leaf. */
34
+ export declare const DEVICE_SAN_CREDENTIAL_PREFIX: 'camstack:credential:';
35
+ export declare const DEVICE_SAN_USER_PREFIX: 'camstack:user:';
36
+ /**
37
+ * The exact bytes a device signs (UTF-8, `\n` separators, no trailing newline):
38
+ *
39
+ * camstack-device-cert-v1
40
+ * <login|renew>
41
+ * <origin> the hub origin returned by `getDeviceChallenge`
42
+ * <nonce>
43
+ *
44
+ * The origin is part of the message so a signature collected by a look-alike
45
+ * hub is worthless on the real one; the hub additionally binds the nonce to
46
+ * the origin it issued it for and refuses any other.
47
+ */
48
+ export declare function buildDeviceSignatureMessage(input: {
49
+ readonly purpose: DeviceSignaturePurpose;
50
+ readonly origin: string;
51
+ readonly nonce: string;
52
+ }): string;
53
+ /** The deep link a QR carries: `camstack://enroll?hub=<origin>&code=<code>`. */
54
+ export declare function buildDeviceEnrollmentLink(input: {
55
+ readonly hub?: string;
56
+ readonly code: string;
57
+ readonly scheme?: string;
58
+ }): string;
59
+ /** Parse an enrollment deep link; `null` when it is not one. `hub` is absent when the link names none. */
60
+ export declare function parseDeviceEnrollmentLink(raw: string): {
61
+ readonly hub: string | null;
62
+ readonly code: string;
63
+ } | null;
64
+ export declare const DevicePlatformSchema: z.ZodEnum<{
65
+ android: "android";
66
+ ios: "ios";
67
+ other: "other";
68
+ web: "web";
69
+ }>;
70
+ export type DevicePlatform = z.infer<typeof DevicePlatformSchema>;
71
+ /**
72
+ * Why a device-certificate endpoint said no. Distinct from a transport / 5xx
73
+ * failure: those carry no reason and mean "try again", never "the credential is
74
+ * dead". The viewer switches on this exhaustively.
75
+ */
76
+ export declare const DeviceRefusalReasonSchema: z.ZodEnum<{
77
+ "bad-public-key": "bad-public-key";
78
+ "bad-signature": "bad-signature";
79
+ "code-invalid": "code-invalid";
80
+ expired: "expired";
81
+ "invalid-certificate": "invalid-certificate";
82
+ "nonce-invalid": "nonce-invalid";
83
+ "rate-limited": "rate-limited";
84
+ revoked: "revoked";
85
+ "self-enrollment-disabled": "self-enrollment-disabled";
86
+ "step-up-required": "step-up-required";
87
+ superseded: "superseded";
88
+ unavailable: "unavailable";
89
+ "unknown-credential": "unknown-credential";
90
+ "user-gone": "user-gone";
91
+ }>;
92
+ export type DeviceRefusalReason = z.infer<typeof DeviceRefusalReasonSchema>;
93
+ /** The only answers after which the app may count towards deleting its credential. */
94
+ export declare const DEFINITIVE_DEVICE_REFUSALS: readonly DeviceRefusalReason[];
95
+ /** Consecutive DEFINITIVE answers before the app deletes its key and certificate. */
96
+ export declare const DEVICE_DEFINITIVE_REFUSALS_BEFORE_DELETE = 3;
97
+ export declare function isDefinitiveDeviceRefusal(reason: DeviceRefusalReason): boolean;
98
+ export declare const DeviceRefusalSchema: z.ZodObject<{
99
+ ok: z.ZodLiteral<false>;
100
+ reason: z.ZodEnum<{
101
+ "bad-public-key": "bad-public-key";
102
+ "bad-signature": "bad-signature";
103
+ "code-invalid": "code-invalid";
104
+ expired: "expired";
105
+ "invalid-certificate": "invalid-certificate";
106
+ "nonce-invalid": "nonce-invalid";
107
+ "rate-limited": "rate-limited";
108
+ revoked: "revoked";
109
+ "self-enrollment-disabled": "self-enrollment-disabled";
110
+ "step-up-required": "step-up-required";
111
+ superseded: "superseded";
112
+ unavailable: "unavailable";
113
+ "unknown-credential": "unknown-credential";
114
+ "user-gone": "user-gone";
115
+ }>;
116
+ definitive: z.ZodBoolean;
117
+ retryAfterSeconds: z.ZodOptional<z.ZodNumber>;
118
+ }, z.core.$strip>;
119
+ export type DeviceRefusal = z.infer<typeof DeviceRefusalSchema>;
120
+ /**
121
+ * A credential-bound session that can no longer refresh answers
122
+ * `auth.refreshSession` with UNAUTHORIZED whose message is this prefix + the
123
+ * reason; {@link deviceRefusalFromMessage} reads it back.
124
+ */
125
+ export declare const DEVICE_REFRESH_REFUSAL_PREFIX: 'device-credential:';
126
+ export declare function deviceRefusalFromMessage(message: string): DeviceRefusalReason | null;
127
+ export declare const CompleteEnrollmentInputSchema: z.ZodObject<{
128
+ code: z.ZodString;
129
+ publicKeySpki: z.ZodString;
130
+ deviceName: z.ZodOptional<z.ZodString>;
131
+ platform: z.ZodEnum<{
132
+ android: "android";
133
+ ios: "ios";
134
+ other: "other";
135
+ web: "web";
136
+ }>;
137
+ }, z.core.$strip>;
138
+ export type CompleteEnrollmentInput = z.infer<typeof CompleteEnrollmentInputSchema>;
139
+ export declare const CompleteEnrollmentOutputSchema: z.ZodObject<{
140
+ credentialId: z.ZodString;
141
+ certPem: z.ZodString;
142
+ chainPem: z.ZodString;
143
+ notAfter: z.ZodNumber;
144
+ user: z.ZodObject<{
145
+ id: z.ZodString;
146
+ username: z.ZodString;
147
+ }, z.core.$strip>;
148
+ }, z.core.$strip>;
149
+ export type CompleteEnrollmentOutput = z.infer<typeof CompleteEnrollmentOutputSchema>;
150
+ export declare const CompleteEnrollmentResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
151
+ credentialId: z.ZodString;
152
+ certPem: z.ZodString;
153
+ chainPem: z.ZodString;
154
+ notAfter: z.ZodNumber;
155
+ user: z.ZodObject<{
156
+ id: z.ZodString;
157
+ username: z.ZodString;
158
+ }, z.core.$strip>;
159
+ ok: z.ZodLiteral<true>;
160
+ }, z.core.$strip>, z.ZodObject<{
161
+ ok: z.ZodLiteral<false>;
162
+ reason: z.ZodEnum<{
163
+ "bad-public-key": "bad-public-key";
164
+ "bad-signature": "bad-signature";
165
+ "code-invalid": "code-invalid";
166
+ expired: "expired";
167
+ "invalid-certificate": "invalid-certificate";
168
+ "nonce-invalid": "nonce-invalid";
169
+ "rate-limited": "rate-limited";
170
+ revoked: "revoked";
171
+ "self-enrollment-disabled": "self-enrollment-disabled";
172
+ "step-up-required": "step-up-required";
173
+ superseded: "superseded";
174
+ unavailable: "unavailable";
175
+ "unknown-credential": "unknown-credential";
176
+ "user-gone": "user-gone";
177
+ }>;
178
+ definitive: z.ZodBoolean;
179
+ retryAfterSeconds: z.ZodOptional<z.ZodNumber>;
180
+ }, z.core.$strip>], "ok">;
181
+ export type CompleteEnrollmentResult = z.infer<typeof CompleteEnrollmentResultSchema>;
182
+ export declare const EnrollSelfInputSchema: z.ZodObject<{
183
+ proof: z.ZodString;
184
+ publicKeySpki: z.ZodString;
185
+ deviceName: z.ZodString;
186
+ platform: z.ZodEnum<{
187
+ android: "android";
188
+ ios: "ios";
189
+ other: "other";
190
+ web: "web";
191
+ }>;
192
+ }, z.core.$strip>;
193
+ export type EnrollSelfInput = z.infer<typeof EnrollSelfInputSchema>;
194
+ export declare const DeviceEnrollProofSchema: z.ZodObject<{
195
+ proof: z.ZodString;
196
+ expiresAt: z.ZodNumber;
197
+ }, z.core.$strip>;
198
+ export declare const DeviceChallengeSchema: z.ZodObject<{
199
+ nonce: z.ZodString;
200
+ origin: z.ZodString;
201
+ expiresAt: z.ZodNumber;
202
+ signature: z.ZodLiteral<"ecdsa-p256-sha256">;
203
+ }, z.core.$strip>;
204
+ export type DeviceChallenge = z.infer<typeof DeviceChallengeSchema>;
205
+ export declare const DeviceChallengeResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
206
+ nonce: z.ZodString;
207
+ origin: z.ZodString;
208
+ expiresAt: z.ZodNumber;
209
+ signature: z.ZodLiteral<"ecdsa-p256-sha256">;
210
+ ok: z.ZodLiteral<true>;
211
+ }, z.core.$strip>, z.ZodObject<{
212
+ ok: z.ZodLiteral<false>;
213
+ reason: z.ZodEnum<{
214
+ "bad-public-key": "bad-public-key";
215
+ "bad-signature": "bad-signature";
216
+ "code-invalid": "code-invalid";
217
+ expired: "expired";
218
+ "invalid-certificate": "invalid-certificate";
219
+ "nonce-invalid": "nonce-invalid";
220
+ "rate-limited": "rate-limited";
221
+ revoked: "revoked";
222
+ "self-enrollment-disabled": "self-enrollment-disabled";
223
+ "step-up-required": "step-up-required";
224
+ superseded: "superseded";
225
+ unavailable: "unavailable";
226
+ "unknown-credential": "unknown-credential";
227
+ "user-gone": "user-gone";
228
+ }>;
229
+ definitive: z.ZodBoolean;
230
+ retryAfterSeconds: z.ZodOptional<z.ZodNumber>;
231
+ }, z.core.$strip>], "ok">;
232
+ export type DeviceChallengeResult = z.infer<typeof DeviceChallengeResultSchema>;
233
+ export declare const DeviceProofInputSchema: z.ZodObject<{
234
+ certPem: z.ZodString;
235
+ nonce: z.ZodString;
236
+ signature: z.ZodString;
237
+ }, z.core.$strip>;
238
+ export type DeviceProofInput = z.infer<typeof DeviceProofInputSchema>;
239
+ export declare const RenewDeviceCertificateOutputSchema: z.ZodObject<{
240
+ credentialId: z.ZodString;
241
+ certPem: z.ZodString;
242
+ chainPem: z.ZodString;
243
+ notAfter: z.ZodNumber;
244
+ }, z.core.$strip>;
245
+ export type RenewDeviceCertificateOutput = z.infer<typeof RenewDeviceCertificateOutputSchema>;
246
+ export declare const RenewDeviceCertificateResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
247
+ credentialId: z.ZodString;
248
+ certPem: z.ZodString;
249
+ chainPem: z.ZodString;
250
+ notAfter: z.ZodNumber;
251
+ ok: z.ZodLiteral<true>;
252
+ }, z.core.$strip>, z.ZodObject<{
253
+ ok: z.ZodLiteral<false>;
254
+ reason: z.ZodEnum<{
255
+ "bad-public-key": "bad-public-key";
256
+ "bad-signature": "bad-signature";
257
+ "code-invalid": "code-invalid";
258
+ expired: "expired";
259
+ "invalid-certificate": "invalid-certificate";
260
+ "nonce-invalid": "nonce-invalid";
261
+ "rate-limited": "rate-limited";
262
+ revoked: "revoked";
263
+ "self-enrollment-disabled": "self-enrollment-disabled";
264
+ "step-up-required": "step-up-required";
265
+ superseded: "superseded";
266
+ unavailable: "unavailable";
267
+ "unknown-credential": "unknown-credential";
268
+ "user-gone": "user-gone";
269
+ }>;
270
+ definitive: z.ZodBoolean;
271
+ retryAfterSeconds: z.ZodOptional<z.ZodNumber>;
272
+ }, z.core.$strip>], "ok">;
273
+ export type RenewDeviceCertificateResult = z.infer<typeof RenewDeviceCertificateResultSchema>;
274
+ export declare const RevokeOwnDeviceCertificateResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
275
+ ok: z.ZodLiteral<true>;
276
+ credentialId: z.ZodString;
277
+ sessionsEnded: z.ZodNumber;
278
+ }, z.core.$strip>, z.ZodObject<{
279
+ ok: z.ZodLiteral<false>;
280
+ reason: z.ZodEnum<{
281
+ "bad-public-key": "bad-public-key";
282
+ "bad-signature": "bad-signature";
283
+ "code-invalid": "code-invalid";
284
+ expired: "expired";
285
+ "invalid-certificate": "invalid-certificate";
286
+ "nonce-invalid": "nonce-invalid";
287
+ "rate-limited": "rate-limited";
288
+ revoked: "revoked";
289
+ "self-enrollment-disabled": "self-enrollment-disabled";
290
+ "step-up-required": "step-up-required";
291
+ superseded: "superseded";
292
+ unavailable: "unavailable";
293
+ "unknown-credential": "unknown-credential";
294
+ "user-gone": "user-gone";
295
+ }>;
296
+ definitive: z.ZodBoolean;
297
+ retryAfterSeconds: z.ZodOptional<z.ZodNumber>;
298
+ }, z.core.$strip>], "ok">;
299
+ export type RevokeOwnDeviceCertificateResult = z.infer<typeof RevokeOwnDeviceCertificateResultSchema>;
300
+ /** Who revoked a credential, as `revokedBy` records it: `admin:<userId>` | `user:<userId>` | `device`. */
301
+ export type DeviceRevoker = {
302
+ readonly kind: 'admin';
303
+ readonly userId: string;
304
+ } | {
305
+ readonly kind: 'user';
306
+ readonly userId: string;
307
+ } | {
308
+ readonly kind: 'device';
309
+ };
310
+ export declare function formatDeviceRevoker(revoker: DeviceRevoker): string;
311
+ export declare const DeviceCredentialStatusSchema: z.ZodEnum<{
312
+ active: "active";
313
+ expired: "expired";
314
+ revoked: "revoked";
315
+ }>;
316
+ export type DeviceCredentialStatus = z.infer<typeof DeviceCredentialStatusSchema>;
317
+ export declare const DeviceCredentialSchema: z.ZodObject<{
318
+ id: z.ZodString;
319
+ userId: z.ZodString;
320
+ username: z.ZodNullable<z.ZodString>;
321
+ deviceName: z.ZodString;
322
+ platform: z.ZodEnum<{
323
+ android: "android";
324
+ ios: "ios";
325
+ other: "other";
326
+ web: "web";
327
+ }>;
328
+ enrolledVia: z.ZodEnum<{
329
+ qr: "qr";
330
+ self: "self";
331
+ }>;
332
+ fingerprint: z.ZodString;
333
+ issuedAt: z.ZodNumber;
334
+ expiresAt: z.ZodNumber;
335
+ lastUsedAt: z.ZodNullable<z.ZodNumber>;
336
+ lastUsedFrom: z.ZodNullable<z.ZodString>;
337
+ revokedAt: z.ZodNullable<z.ZodNumber>;
338
+ revokedBy: z.ZodNullable<z.ZodString>;
339
+ status: z.ZodEnum<{
340
+ active: "active";
341
+ expired: "expired";
342
+ revoked: "revoked";
343
+ }>;
344
+ }, z.core.$strip>;
345
+ export type DeviceCredential = z.infer<typeof DeviceCredentialSchema>;
346
+ export declare const StartEnrollmentOutputSchema: z.ZodObject<{
347
+ code: z.ZodString;
348
+ expiresAt: z.ZodNumber;
349
+ enrollUrl: z.ZodString;
350
+ hubOrigin: z.ZodNullable<z.ZodString>;
351
+ hubOrigins: z.ZodArray<z.ZodString>;
352
+ }, z.core.$strip>;
353
+ export type StartEnrollmentOutput = z.infer<typeof StartEnrollmentOutputSchema>;
354
+ /** The `device-certificate` arm of `auth.listLoginMethods`. */
355
+ export declare const DeviceCertificateLoginMethodSchema: z.ZodObject<{
356
+ kind: z.ZodLiteral<"device-certificate">;
357
+ id: z.ZodLiteral<"device-certificate">;
358
+ label: z.ZodString;
359
+ stage: z.ZodLiteral<"primary">;
360
+ challengePath: z.ZodLiteral<"auth.getDeviceChallenge">;
361
+ revokePath: z.ZodLiteral<"auth.revokeOwnDeviceCertificate">;
362
+ enrollSelfPath: z.ZodLiteral<"auth.enrollSelf">;
363
+ loginPath: z.ZodLiteral<"auth.loginWithDeviceCertificate">;
364
+ renewPath: z.ZodLiteral<"auth.renewDeviceCertificate">;
365
+ signature: z.ZodLiteral<"ecdsa-p256-sha256">;
366
+ messageVersion: z.ZodLiteral<"camstack-device-cert-v1">;
367
+ clients: z.ZodArray<z.ZodEnum<{
368
+ native: "native";
369
+ web: "web";
370
+ }>>;
371
+ }, z.core.$strip>;
372
+ export type DeviceCertificateLoginMethod = z.infer<typeof DeviceCertificateLoginMethodSchema>;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The hub address an OIDC sign-in STARTED at — so it returns there (D791).
3
+ *
4
+ * The browser must come back to the origin it left from: the session cookie,
5
+ * the admin UI's stored token and a popup's `window.opener` all belong to
6
+ * one origin. Before this the `redirect_uri` was the hub's single browser
7
+ * address (`hubBrowserOrigin`), so a sign-in started on the LAN address
8
+ * (`https://192.168.x.x:4443`) finished on the public tunnel.
9
+ *
10
+ * The origin is read from the `/start` request — `X-Forwarded-Host` /
11
+ * `Host`, `X-Forwarded-Proto` — and is NEVER trusted as such: a forged
12
+ * `Host` would otherwise choose where the IdP sends the authorization code.
13
+ * It is used only when it equals, exactly, an origin the hub advertises
14
+ * itself at (the Network page's addresses: detected, custom, the public
15
+ * endpoint, the app-connection set) or the origin of the operator's
16
+ * configured redirect override. Anything else falls back to the default
17
+ * browser address, exactly as before.
18
+ *
19
+ * The mount prefix (`X-Forwarded-Prefix`, the reverse-proxy relay) is kept on
20
+ * the path when well-formed — it can only move the callback within an
21
+ * allowlisted origin, where the hub serves or 404s it and a strict IdP
22
+ * refuses an unregistered one.
23
+ */
24
+ import type { HubAddressBook } from '../capabilities/local-network.cap.js';
25
+ /** A request's headers as the addon-routes bridge hands them (lower-cased names). */
26
+ export type RequestHeaders = Readonly<Record<string, string | undefined>>;
27
+ /** `scheme://host[:port]` normalised by WHATWG URL, or `null` if it is not an http(s) origin. */
28
+ export declare function normalizeOrigin(value: string): string | null;
29
+ /** The mount prefix the relay named (no trailing slash), or `''`. Invalid = absent. */
30
+ export declare function requestMountPrefix(headers: RequestHeaders): string;
31
+ /**
32
+ * The origins the request CLAIMS, most specific first: the proxy's
33
+ * `X-Forwarded-Host` over `Host`; the named `X-Forwarded-Proto`, or https
34
+ * then http when none is named (the hub terminates TLS itself on 4443).
35
+ */
36
+ export declare function claimedRequestOrigins(headers: RequestHeaders): readonly string[];
37
+ /** Every origin the hub advertises itself at, normalised. Never the app link, never loopback. */
38
+ export declare function advertisedHubOrigins(book: HubAddressBook): ReadonlySet<string>;
39
+ /**
40
+ * The origin to send the browser back to: the first claimed origin that is in
41
+ * `allowed`, or `null` (the caller then uses its default address).
42
+ */
43
+ export declare function pickRequestOrigin(headers: RequestHeaders, allowed: ReadonlySet<string>): string | null;
@@ -0,0 +1,174 @@
1
+ import { z } from 'zod';
2
+ import { type InferProvider } from './capability-definition.js';
3
+ export declare const DeviceCaStatusSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
4
+ state: z.ZodLiteral<"absent">;
5
+ }, z.core.$strip>, z.ZodObject<{
6
+ state: z.ZodLiteral<"ready">;
7
+ subject: z.ZodString;
8
+ fingerprintSha256: z.ZodString;
9
+ validTo: z.ZodString;
10
+ }, z.core.$strip>, z.ZodObject<{
11
+ state: z.ZodLiteral<"unavailable">;
12
+ reason: z.ZodString;
13
+ }, z.core.$strip>], "state">;
14
+ export type DeviceCaStatus = z.infer<typeof DeviceCaStatusSchema>;
15
+ export declare const DeviceCertificateSettingsSchema: z.ZodObject<{
16
+ selfEnrollment: z.ZodEnum<{
17
+ allowed: "allowed";
18
+ disabled: "disabled";
19
+ }>;
20
+ }, z.core.$strip>;
21
+ export type DeviceCertificateSettings = z.infer<typeof DeviceCertificateSettingsSchema>;
22
+ /**
23
+ * `device-credentials` — the admin surface of device certificates (D855).
24
+ *
25
+ * Everything a device does ITSELF — completing an enrollment, getting a
26
+ * challenge, signing in, renewing — is a PUBLIC procedure of the hub's `auth`
27
+ * router (`auth.completeEnrollment`, `getDeviceChallenge`,
28
+ * `loginWithDeviceCertificate`, `renewDeviceCertificate`): those legs are
29
+ * proofs of possession, not capability calls, and must not be reachable as
30
+ * cap methods. This cap holds only what an operator does about them.
31
+ *
32
+ * Provider: `local-auth`, which also owns the device CA and the registry.
33
+ * The hub is the only node that persists device credentials.
34
+ */
35
+ export declare const deviceCredentialsCapability: {
36
+ readonly name: 'device-credentials';
37
+ readonly scope: 'system';
38
+ readonly mode: 'singleton';
39
+ readonly methods: {
40
+ /**
41
+ * Every enrolled device, newest first; `userId` narrows to one user.
42
+ * `status` is derived: revoked wins over expired.
43
+ */
44
+ readonly listDeviceCredentials: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
45
+ userId: z.ZodOptional<z.ZodString>;
46
+ includeRevoked: z.ZodDefault<z.ZodBoolean>;
47
+ }, z.core.$strip>, z.ZodReadonly<z.ZodArray<z.ZodObject<{
48
+ id: z.ZodString;
49
+ userId: z.ZodString;
50
+ username: z.ZodNullable<z.ZodString>;
51
+ deviceName: z.ZodString;
52
+ platform: z.ZodEnum<{
53
+ android: "android";
54
+ ios: "ios";
55
+ other: "other";
56
+ web: "web";
57
+ }>;
58
+ enrolledVia: z.ZodEnum<{
59
+ qr: "qr";
60
+ self: "self";
61
+ }>;
62
+ fingerprint: z.ZodString;
63
+ issuedAt: z.ZodNumber;
64
+ expiresAt: z.ZodNumber;
65
+ lastUsedAt: z.ZodNullable<z.ZodNumber>;
66
+ lastUsedFrom: z.ZodNullable<z.ZodString>;
67
+ revokedAt: z.ZodNullable<z.ZodNumber>;
68
+ revokedBy: z.ZodNullable<z.ZodString>;
69
+ status: z.ZodEnum<{
70
+ active: "active";
71
+ expired: "expired";
72
+ revoked: "revoked";
73
+ }>;
74
+ }, z.core.$strip>>>, import("./capability-definition.js").CapabilityMethodKind>;
75
+ /**
76
+ * Mint a one-shot enrollment code for `userId` and a device name: 128-bit
77
+ * random, single use, 10 minutes, kept only as a hash. Returns the code
78
+ * once, with the `camstack://enroll?hub=…&code=…` link a QR carries.
79
+ * `caller` (the admin) is recorded in the audit trail.
80
+ */
81
+ readonly startEnrollment: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
82
+ userId: z.ZodString;
83
+ deviceName: z.ZodString;
84
+ }, z.core.$strip>, z.ZodObject<{
85
+ code: z.ZodString;
86
+ expiresAt: z.ZodNumber;
87
+ enrollUrl: z.ZodString;
88
+ hubOrigin: z.ZodNullable<z.ZodString>;
89
+ hubOrigins: z.ZodArray<z.ZodString>;
90
+ }, z.core.$strip>, "mutation"> & {
91
+ readonly caller: 'required';
92
+ };
93
+ /**
94
+ * Revoke a credential: its certificate stops logging in at once, and every
95
+ * session it opened ends (an open session also dies at its next refresh
96
+ * even if this call raced it). Idempotent.
97
+ */
98
+ readonly revokeDeviceCredential: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
99
+ id: z.ZodString;
100
+ }, z.core.$strip>, z.ZodObject<{
101
+ revoked: z.ZodBoolean;
102
+ sessionsEnded: z.ZodNumber;
103
+ status: z.ZodEnum<{
104
+ active: "active";
105
+ expired: "expired";
106
+ revoked: "revoked";
107
+ }>;
108
+ }, z.core.$strip>, "mutation"> & {
109
+ readonly caller: 'required';
110
+ };
111
+ /**
112
+ * Hub-wide device-certificate settings. `selfEnrollment`: `allowed`
113
+ * (default) lets a signed-in user enroll their own device after a step-up
114
+ * sign-in; `disabled` makes `auth.enrollSelf` refuse. The admin QR path is
115
+ * unaffected. Hub-wide only (no per-role switch).
116
+ */
117
+ readonly getDeviceCertificateSettings: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{}, z.core.$strip>, z.ZodObject<{
118
+ selfEnrollment: z.ZodEnum<{
119
+ allowed: "allowed";
120
+ disabled: "disabled";
121
+ }>;
122
+ }, z.core.$strip>, import("./capability-definition.js").CapabilityMethodKind>;
123
+ readonly setDeviceCertificateSettings: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
124
+ selfEnrollment: z.ZodEnum<{
125
+ allowed: "allowed";
126
+ disabled: "disabled";
127
+ }>;
128
+ }, z.core.$strip>, z.ZodObject<{
129
+ selfEnrollment: z.ZodEnum<{
130
+ allowed: "allowed";
131
+ disabled: "disabled";
132
+ }>;
133
+ }, z.core.$strip>, "mutation">;
134
+ /**
135
+ * Delete the registry row of a REVOKED credential (clean-up; the audit trail
136
+ * keeps the revocation). Refuses a live credential: revoke it first. After
137
+ * the row is gone the device's next call answers `unknown-credential`.
138
+ */
139
+ readonly deleteDeviceCredential: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
140
+ id: z.ZodString;
141
+ }, z.core.$strip>, z.ZodObject<{
142
+ result: z.ZodEnum<{
143
+ deleted: "deleted";
144
+ live: "live";
145
+ unknown: "unknown";
146
+ }>;
147
+ }, z.core.$strip>, "mutation"> & {
148
+ readonly caller: 'required';
149
+ };
150
+ /**
151
+ * The device CA: `absent` until the first enrollment creates it (lazily,
152
+ * never rotated on boot), `unavailable` while the keychain cannot answer.
153
+ */
154
+ readonly getDeviceCaStatus: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{}, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
155
+ state: z.ZodLiteral<"absent">;
156
+ }, z.core.$strip>, z.ZodObject<{
157
+ state: z.ZodLiteral<"ready">;
158
+ subject: z.ZodString;
159
+ fingerprintSha256: z.ZodString;
160
+ validTo: z.ZodString;
161
+ }, z.core.$strip>, z.ZodObject<{
162
+ state: z.ZodLiteral<"unavailable">;
163
+ reason: z.ZodString;
164
+ }, z.core.$strip>], "state">, import("./capability-definition.js").CapabilityMethodKind>;
165
+ /** Rename a credential (the label only; the certificate is unchanged). */
166
+ readonly renameDeviceCredential: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
167
+ id: z.ZodString;
168
+ deviceName: z.ZodString;
169
+ }, z.core.$strip>, z.ZodObject<{
170
+ renamed: z.ZodBoolean;
171
+ }, z.core.$strip>, "mutation">;
172
+ };
173
+ };
174
+ export type IDeviceCredentialsProvider = InferProvider<typeof deviceCredentialsCapability>;