@camstack/core 0.1.33 → 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 (34) hide show
  1. package/dist/auth/api-key-manager.d.ts +2 -2
  2. package/dist/auth/api-key-manager.d.ts.map +1 -1
  3. package/dist/auth/auth-manager.d.ts +62 -3
  4. package/dist/auth/auth-manager.d.ts.map +1 -1
  5. package/dist/auth/totp-manager.d.ts +53 -0
  6. package/dist/auth/totp-manager.d.ts.map +1 -0
  7. package/dist/auth/user-manager.d.ts +3 -3
  8. package/dist/auth/user-manager.d.ts.map +1 -1
  9. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts.map +1 -1
  10. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js +29 -9
  11. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js.map +1 -1
  12. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs +29 -9
  13. package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs.map +1 -1
  14. package/dist/builtins/local-auth/auth-schema.d.ts +14 -0
  15. package/dist/builtins/local-auth/auth-schema.d.ts.map +1 -1
  16. package/dist/builtins/local-auth/local-auth.addon.d.ts +1 -0
  17. package/dist/builtins/local-auth/local-auth.addon.d.ts.map +1 -1
  18. package/dist/builtins/local-auth/local-auth.addon.js +1011 -22
  19. package/dist/builtins/local-auth/local-auth.addon.js.map +1 -1
  20. package/dist/builtins/local-auth/local-auth.addon.mjs +1022 -33
  21. package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -1
  22. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +8 -0
  23. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts.map +1 -1
  24. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +27 -21
  25. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js.map +1 -1
  26. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +27 -21
  27. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs.map +1 -1
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +400 -41
  31. package/dist/index.js.map +1 -1
  32. package/dist/index.mjs +400 -41
  33. package/dist/index.mjs.map +1 -1
  34. package/package.json +2 -1
package/dist/index.mjs CHANGED
@@ -31,7 +31,7 @@ import { promisify } from "node:util";
31
31
  import { errMsg, parseJsonObject } from "@camstack/types";
32
32
  import * as vm from "node:vm";
33
33
  import * as os from "node:os";
34
- //#region ../types/dist/index-DVKPWMwv.mjs
34
+ //#region ../types/dist/index-BKnvgAep.mjs
35
35
  var MODEL_FORMATS = [
36
36
  "onnx",
37
37
  "coreml",
@@ -2372,7 +2372,8 @@ var CollectionColumnSchema = z.object({
2372
2372
  "TEXT",
2373
2373
  "INTEGER",
2374
2374
  "REAL",
2375
- "JSON"
2375
+ "JSON",
2376
+ "BOOLEAN"
2376
2377
  ]),
2377
2378
  primaryKey: z.boolean().optional(),
2378
2379
  notNull: z.boolean().optional(),
@@ -2445,6 +2446,233 @@ method(LogEntrySchema, z.void(), { kind: "mutation" }), method(z.object({
2445
2446
  tags: z.record(z.string(), z.string()).optional()
2446
2447
  }), z.array(LogEntrySchema).readonly());
2447
2448
  method(z.void(), z.string()), method(z.void(), z.string());
2449
+ var SsoBridgeClaimsSchema = z.object({
2450
+ userId: z.string(),
2451
+ username: z.string(),
2452
+ isAdmin: z.boolean(),
2453
+ provider: z.string(),
2454
+ email: z.string().optional(),
2455
+ displayName: z.string().optional()
2456
+ });
2457
+ method(z.object({
2458
+ claims: SsoBridgeClaimsSchema,
2459
+ ttlSec: z.number().int().positive().optional()
2460
+ }), z.object({ token: z.string() })), method(z.object({ token: z.string() }), SsoBridgeClaimsSchema.nullable());
2461
+ var PasskeySummarySchema = z.object({
2462
+ credentialId: z.string(),
2463
+ label: z.string(),
2464
+ createdAt: z.number(),
2465
+ lastUsedAt: z.number().nullable(),
2466
+ transports: z.array(z.string()).default([])
2467
+ });
2468
+ method(z.object({
2469
+ userId: z.string(),
2470
+ username: z.string()
2471
+ }), z.object({ optionsJSON: z.record(z.string(), z.unknown()) }), {
2472
+ kind: "mutation",
2473
+ auth: "admin",
2474
+ access: "create"
2475
+ }), method(z.object({
2476
+ userId: z.string(),
2477
+ /** RegistrationResponseJSON from the browser. */
2478
+ response: z.record(z.string(), z.unknown()),
2479
+ /** Operator-visible label (e.g. "MacBook Touch ID"). */
2480
+ label: z.string()
2481
+ }), z.object({
2482
+ success: z.literal(true),
2483
+ credentialId: z.string()
2484
+ }), {
2485
+ kind: "mutation",
2486
+ auth: "admin",
2487
+ access: "create"
2488
+ }), method(z.object({ userId: z.string().optional() }), z.object({ optionsJSON: z.record(z.string(), z.unknown()) }), {
2489
+ kind: "mutation",
2490
+ access: "view"
2491
+ }), method(z.object({
2492
+ /** Required — the user the assertion belongs to (verified). */
2493
+ userId: z.string(),
2494
+ /** AuthenticationResponseJSON from the browser. */
2495
+ response: z.record(z.string(), z.unknown())
2496
+ }), z.object({ verified: z.boolean() }), {
2497
+ kind: "mutation",
2498
+ access: "view"
2499
+ }), method(z.object({ userId: z.string() }), z.array(PasskeySummarySchema), { auth: "admin" }), method(z.object({
2500
+ userId: z.string(),
2501
+ credentialId: z.string()
2502
+ }), z.object({ success: z.literal(true) }), {
2503
+ kind: "mutation",
2504
+ auth: "admin",
2505
+ access: "delete"
2506
+ });
2507
+ var EmailAddressSchema = z.string().email();
2508
+ var SendEmailInputSchema = z.object({
2509
+ to: z.union([EmailAddressSchema, z.array(EmailAddressSchema).min(1)]),
2510
+ cc: z.array(EmailAddressSchema).optional(),
2511
+ bcc: z.array(EmailAddressSchema).optional(),
2512
+ /** RFC 5322 `From` field. Most relays will reject if the domain
2513
+ * isn't authorised — the addon is responsible for substituting a
2514
+ * sane default when omitted. */
2515
+ from: z.string().optional(),
2516
+ /** Optional `Reply-To` override. */
2517
+ replyTo: z.string().optional(),
2518
+ subject: z.string(),
2519
+ /** Plain-text body. Required even when `html` is present (fallback
2520
+ * for clients that strip HTML — including most spam filters). */
2521
+ text: z.string(),
2522
+ /** Optional HTML body. Renders alongside `text` as multi-part. */
2523
+ html: z.string().optional()
2524
+ });
2525
+ var SendEmailResultSchema = z.object({
2526
+ messageId: z.string(),
2527
+ accepted: z.array(EmailAddressSchema).default([]),
2528
+ rejected: z.array(EmailAddressSchema).default([])
2529
+ });
2530
+ var SmtpStatusSchema = z.object({
2531
+ /** True iff the addon has successfully verified the relay. */
2532
+ ready: z.boolean(),
2533
+ /** Operator-visible host string (no credentials). */
2534
+ host: z.string(),
2535
+ /** Last error message reported by the relay, when not ready. */
2536
+ error: z.string().optional(),
2537
+ /** Last successful verify timestamp (unix ms). */
2538
+ lastVerifiedAt: z.number().optional()
2539
+ });
2540
+ method(SendEmailInputSchema, SendEmailResultSchema, {
2541
+ kind: "mutation",
2542
+ auth: "admin",
2543
+ access: "create"
2544
+ }), method(z.void(), SmtpStatusSchema, {
2545
+ kind: "mutation",
2546
+ auth: "admin",
2547
+ access: "view"
2548
+ }), method(z.void(), SmtpStatusSchema, { auth: "admin" });
2549
+ var QosSchema = z.union([
2550
+ z.literal(0),
2551
+ z.literal(1),
2552
+ z.literal(2)
2553
+ ]);
2554
+ var PublishInputSchema = z.object({
2555
+ topic: z.string(),
2556
+ /** UTF-8 payload. Binary payloads must be base64-encoded by the caller. */
2557
+ payload: z.string(),
2558
+ qos: QosSchema.default(0),
2559
+ retain: z.boolean().default(false)
2560
+ });
2561
+ var SubscribeInputSchema = z.object({
2562
+ /** MQTT topic filter (supports `+` single-level and `#` multi-level wildcards). */
2563
+ topic: z.string(),
2564
+ qos: QosSchema.default(0),
2565
+ /**
2566
+ * Caller-supplied owner tag. Useful for debugging + the
2567
+ * `listSubscriptions` admin view ("which consumer owns this?").
2568
+ * When omitted, the addon synthesizes one from the caller's addon id.
2569
+ */
2570
+ owner: z.string().optional()
2571
+ });
2572
+ var SubscribeResultSchema = z.object({
2573
+ success: z.literal(true),
2574
+ /** Server-generated subscription id. Pass to `unsubscribe` to release. */
2575
+ subscriptionId: z.string()
2576
+ });
2577
+ var UnsubscribeInputSchema = z.object({
2578
+ /** Subscription id from `subscribe`. */
2579
+ subscriptionId: z.string() });
2580
+ var MqttStatusSchema = z.object({
2581
+ /** True iff the addon has an active connection to the broker. */
2582
+ connected: z.boolean(),
2583
+ /** Operator-visible host string (e.g. `mqtt://broker.example:1883`). */
2584
+ brokerUrl: z.string(),
2585
+ /** Active subscription count (per-owner, NOT broker-side topic count). */
2586
+ subscriptionCount: z.number().int(),
2587
+ /** Last error reported by the broker. */
2588
+ error: z.string().optional(),
2589
+ /** Last successful connection timestamp (unix ms). */
2590
+ connectedAt: z.number().optional()
2591
+ });
2592
+ var SubscriptionInfoSchema = z.object({
2593
+ subscriptionId: z.string(),
2594
+ topic: z.string(),
2595
+ qos: QosSchema,
2596
+ owner: z.string(),
2597
+ /** When this individual subscription was created. */
2598
+ createdAt: z.number()
2599
+ });
2600
+ method(PublishInputSchema, z.object({ success: z.literal(true) }), {
2601
+ kind: "mutation",
2602
+ auth: "admin",
2603
+ access: "create"
2604
+ }), method(SubscribeInputSchema, SubscribeResultSchema, {
2605
+ kind: "mutation",
2606
+ auth: "admin",
2607
+ access: "create"
2608
+ }), method(UnsubscribeInputSchema, z.object({ success: z.literal(true) }), {
2609
+ kind: "mutation",
2610
+ auth: "admin",
2611
+ access: "delete"
2612
+ }), method(z.void(), z.array(SubscriptionInfoSchema), { auth: "admin" }), method(z.void(), MqttStatusSchema, { auth: "admin" });
2613
+ var HaServiceCallSchema = z.object({
2614
+ /** HA domain (e.g. `light`, `switch`, `notify`). */
2615
+ domain: z.string(),
2616
+ /** HA service (e.g. `turn_on`, `toggle`). */
2617
+ service: z.string(),
2618
+ /** Service-specific data payload (e.g. `{entity_id: 'light.kitchen', brightness: 200}`). */
2619
+ serviceData: z.record(z.string(), z.unknown()).optional(),
2620
+ /** Optional target spec (entity_id / device_id / area_id). */
2621
+ target: z.record(z.string(), z.unknown()).optional()
2622
+ });
2623
+ var HaStateSchema = z.object({
2624
+ entity_id: z.string(),
2625
+ state: z.string(),
2626
+ attributes: z.record(z.string(), z.unknown()).default({}),
2627
+ last_changed: z.string().optional(),
2628
+ last_updated: z.string().optional()
2629
+ });
2630
+ var HaStatusSchema = z.object({
2631
+ connected: z.boolean(),
2632
+ host: z.string(),
2633
+ /** Active per-owner subscription count. */
2634
+ subscriptionCount: z.number().int(),
2635
+ /** Last error reported by the WebSocket. */
2636
+ error: z.string().optional(),
2637
+ /** HA version reported during the auth handshake, when reachable. */
2638
+ haVersion: z.string().optional(),
2639
+ connectedAt: z.number().optional()
2640
+ });
2641
+ var HaSubscribeInputSchema = z.object({
2642
+ /**
2643
+ * Specific HA event type to subscribe to (`state_changed`,
2644
+ * `service_called`, etc.). Empty string = all events (firehose —
2645
+ * only for debugging).
2646
+ */
2647
+ eventType: z.string().optional(),
2648
+ /** Caller-supplied tag for listSubscriptions debugging. */
2649
+ owner: z.string().optional()
2650
+ });
2651
+ var HaSubscribeResultSchema = z.object({
2652
+ success: z.literal(true),
2653
+ subscriptionId: z.string()
2654
+ });
2655
+ var HaUnsubscribeInputSchema = z.object({ subscriptionId: z.string() });
2656
+ var HaSubscriptionInfoSchema = z.object({
2657
+ subscriptionId: z.string(),
2658
+ /** Empty string when subscribed to ALL events. */
2659
+ eventType: z.string(),
2660
+ owner: z.string(),
2661
+ createdAt: z.number()
2662
+ });
2663
+ method(HaSubscribeInputSchema, HaSubscribeResultSchema, {
2664
+ kind: "mutation",
2665
+ auth: "admin",
2666
+ access: "create"
2667
+ }), method(HaUnsubscribeInputSchema, z.object({ success: z.literal(true) }), {
2668
+ kind: "mutation",
2669
+ auth: "admin",
2670
+ access: "delete"
2671
+ }), method(HaServiceCallSchema, z.object({ result: z.unknown() }), {
2672
+ kind: "mutation",
2673
+ auth: "admin",
2674
+ access: "create"
2675
+ }), method(z.void(), z.array(HaStateSchema).readonly(), { auth: "admin" }), method(z.object({ entityId: z.string() }), HaStateSchema.nullable(), { auth: "admin" }), method(z.void(), z.array(HaSubscriptionInfoSchema).readonly(), { auth: "admin" }), method(z.void(), HaStatusSchema, { auth: "admin" });
2448
2676
  var AddonPageDeclarationSchema$1 = z.object({
2449
2677
  id: z.string(),
2450
2678
  label: z.string(),
@@ -2548,9 +2776,41 @@ var AddonHttpRouteSchema = z.object({
2548
2776
  "DELETE",
2549
2777
  "PATCH"
2550
2778
  ]),
2551
- path: z.string()
2779
+ path: z.string(),
2780
+ access: z.enum([
2781
+ "public",
2782
+ "authenticated",
2783
+ "admin"
2784
+ ]).optional(),
2785
+ description: z.string().optional()
2552
2786
  });
2553
- method(z.void(), z.array(AddonHttpRouteSchema));
2787
+ var InvokeRequestSchema = z.object({
2788
+ method: z.string(),
2789
+ path: z.string(),
2790
+ params: z.record(z.string(), z.string()),
2791
+ query: z.record(z.string(), z.string()),
2792
+ body: z.unknown(),
2793
+ headers: z.record(z.string(), z.string()),
2794
+ user: z.object({
2795
+ id: z.string(),
2796
+ username: z.string(),
2797
+ isAdmin: z.boolean()
2798
+ }).optional(),
2799
+ scopedToken: z.unknown().optional()
2800
+ });
2801
+ var InvokeReplyEnvelopeSchema = z.object({
2802
+ status: z.number().int(),
2803
+ headers: z.record(z.string(), z.string()),
2804
+ /** When set, the hub MUST `reply.redirect(redirectUrl)` instead of
2805
+ * sending `body`. Status defaults to 302 when this is set unless
2806
+ * the handler called `reply.code(...)` explicitly. */
2807
+ redirectUrl: z.string().nullable(),
2808
+ /** JSON-serializable body. `undefined` is treated as "no body". */
2809
+ body: z.unknown().optional(),
2810
+ /** Set when the handler called `reply.type(mime)`. */
2811
+ contentType: z.string().optional()
2812
+ });
2813
+ method(z.void(), z.array(AddonHttpRouteSchema)), method(InvokeRequestSchema, InvokeReplyEnvelopeSchema, { kind: "mutation" });
2554
2814
  method(z.object({ codec: z.string() }), z.boolean()), method(z.void(), z.object({
2555
2815
  id: z.string(),
2556
2816
  name: z.string(),
@@ -3292,7 +3552,14 @@ var AuthResultSchema = z.object({
3292
3552
  username: z.string(),
3293
3553
  email: z.string().optional(),
3294
3554
  displayName: z.string().optional(),
3295
- roles: z.array(z.string()).optional()
3555
+ /**
3556
+ * Whether the authenticating user is an admin. The auth-provider
3557
+ * surface returns this so the server's login flow can mint a JWT
3558
+ * with the correct bypass flag. Non-admin users authenticated via
3559
+ * an external IdP still need their scopes assigned by an admin via
3560
+ * `setUserScopes` — the SSO flow doesn't carry permissions.
3561
+ */
3562
+ isAdmin: z.boolean().default(false)
3296
3563
  });
3297
3564
  method(z.object({
3298
3565
  username: z.string(),
@@ -3301,6 +3568,14 @@ method(z.object({
3301
3568
  var AuthProviderInfoSchema = z.object({
3302
3569
  /** Stable id matching the addon id (used for `getLoginUrl({addonId,…})`). */
3303
3570
  addonId: z.string(),
3571
+ /**
3572
+ * Per-instance id when one addon registers multiple "logical"
3573
+ * providers (e.g. OIDC with Google + Microsoft + custom). The login
3574
+ * URL becomes `/addon/${addonId}/${instanceId}/start` — handler reads
3575
+ * `:instanceId` from the route. Empty/unset means the addon is a
3576
+ * single-instance provider; the URL is `/addon/${addonId}/start`.
3577
+ */
3578
+ instanceId: z.string().optional(),
3304
3579
  /** Display label shown on the login button + admin row. */
3305
3580
  displayName: z.string(),
3306
3581
  /** Optional iconography hint (lucide-react icon name OR emoji). */
@@ -3311,6 +3586,8 @@ var AuthProviderInfoSchema = z.object({
3311
3586
  /** When true, the provider exposes a credential-form login flow
3312
3587
  * (`validateCredentials` accepts username + password). */
3313
3588
  hasCredentialFlow: z.boolean(),
3589
+ /** Provider kind, drives admin-UI hint dispatch (oidc / saml / totp / …). */
3590
+ kind: z.string().optional(),
3314
3591
  /** Operator-facing status string (e.g. "Connected to https://login.acme.com"). */
3315
3592
  status: z.string().optional(),
3316
3593
  /** When false, the provider is registered but disabled by config; the
@@ -4461,7 +4738,20 @@ method(z.void(), MeshStatusSchema), method(z.object({
4461
4738
  authKey: z.string().min(8),
4462
4739
  /** Optional hostname override the host should advertise. */
4463
4740
  hostname: z.string().optional()
4464
- }), z.object({ joined: z.literal(true) }), { kind: "mutation" }), method(z.void(), z.object({ left: z.literal(true) }), { kind: "mutation" }), method(z.void(), z.object({ peers: z.array(MeshPeerSchema).readonly() })), method(PublicIngressConfigSchema, z.object({ success: z.literal(true) }), { kind: "mutation" }), method(MeshIngressConfigSchema, z.object({ success: z.literal(true) }), { kind: "mutation" });
4741
+ }), z.object({ joined: z.literal(true) }), { kind: "mutation" }), method(z.void(), z.object({ left: z.literal(true) }), { kind: "mutation" }), method(z.void(), z.object({ peers: z.array(MeshPeerSchema).readonly() })), method(PublicIngressConfigSchema, z.object({ success: z.literal(true) }), { kind: "mutation" }), method(MeshIngressConfigSchema, z.object({ success: z.literal(true) }), { kind: "mutation" }), method(z.object({
4742
+ /** Optional auth key — when provided, probes the key validity
4743
+ * against the provider's API. Omit when already joined to
4744
+ * just ping the daemon. */
4745
+ authKey: z.string().optional() }), z.object({
4746
+ ok: z.boolean(),
4747
+ /** Provider-side identifier resolved by the probe (tailnet
4748
+ * name for Tailscale, network id for ZeroTier, etc.). */
4749
+ tenant: z.string().optional(),
4750
+ /** Daemon binary version, when reachable. */
4751
+ daemonVersion: z.string().optional(),
4752
+ /** Human-readable error when `ok: false`. */
4753
+ error: z.string().optional()
4754
+ }), { kind: "mutation" });
4465
4755
  var MeshEndpointSchema = z.object({
4466
4756
  id: z.string(),
4467
4757
  label: z.string(),
@@ -4494,35 +4784,58 @@ method(z.void(), z.array(MeshProviderInfoSchema).readonly()), method(z.object({
4494
4784
  authKey: z.string().min(8),
4495
4785
  hostname: z.string().optional()
4496
4786
  }), z.object({ joined: z.literal(true) }), { kind: "mutation" }), method(z.object({ addonId: z.string() }), z.object({ success: z.literal(true) }), { kind: "mutation" });
4497
- var UserRoleSchema = z.enum([
4498
- "admin",
4499
- "viewer",
4500
- "agent",
4501
- "scoped"
4502
- ]);
4503
- var AllowedProviderSchema = z.union([z.literal("*"), z.array(z.string())]);
4504
- var AllowedDevicesSchema = z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]));
4505
4787
  var MethodAccessSchema = z.enum([
4506
4788
  "view",
4507
4789
  "create",
4508
4790
  "delete"
4509
4791
  ]);
4510
- var TokenScopeSchema = z.object({
4511
- type: z.enum(["addon", "capability"]),
4512
- target: z.string(),
4513
- access: z.array(MethodAccessSchema).min(1)
4514
- });
4792
+ var AllowedProviderSchema = z.union([z.literal("*"), z.array(z.string())]);
4793
+ var AllowedDevicesSchema = z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]));
4794
+ var CapScopeSchema = z.enum(["device", "system"]);
4795
+ var TokenScopeSchema = z.discriminatedUnion("type", [
4796
+ z.object({
4797
+ type: z.literal("category"),
4798
+ target: CapScopeSchema,
4799
+ access: z.array(MethodAccessSchema).min(1)
4800
+ }),
4801
+ z.object({
4802
+ type: z.literal("capability"),
4803
+ target: z.string(),
4804
+ access: z.array(MethodAccessSchema).min(1)
4805
+ }),
4806
+ z.object({
4807
+ type: z.literal("addon"),
4808
+ target: z.string(),
4809
+ access: z.array(MethodAccessSchema).min(1)
4810
+ }),
4811
+ z.object({
4812
+ type: z.literal("device"),
4813
+ /**
4814
+ * One or more deviceIds (serialised as strings for wire-format
4815
+ * consistency with the rest of the union). Matcher accepts if
4816
+ * `input.deviceId` ∈ `targets`. Array shape avoids the row-explosion
4817
+ * of one scope-per-device when granting access to a set of cameras.
4818
+ */
4819
+ targets: z.array(z.string()).min(1),
4820
+ access: z.array(MethodAccessSchema).min(1)
4821
+ })
4822
+ ]);
4515
4823
  z.object({
4516
4824
  id: z.string(),
4517
4825
  username: z.string(),
4518
4826
  passwordHash: z.string(),
4519
- role: UserRoleSchema,
4827
+ /**
4828
+ * Admin bypass. When true, the middleware skips the scope-access
4829
+ * check entirely. There is no other axis of privilege; the legacy
4830
+ * role enum collapsed onto this boolean in v2.
4831
+ */
4832
+ isAdmin: z.boolean().default(false),
4520
4833
  allowedProviders: AllowedProviderSchema,
4521
4834
  allowedDevices: AllowedDevicesSchema,
4522
4835
  /**
4523
- * Scopes granted to this user. Admins bypass; their `scopes` is ignored.
4524
- * Non-admins (`viewer`, `agent`, `scoped`) without scopes are locked out
4525
- * of every protected call.
4836
+ * Scopes granted to this user. Admins bypass; their `scopes` is
4837
+ * ignored. Non-admins without scopes are locked out of every
4838
+ * protected call.
4526
4839
  */
4527
4840
  scopes: z.array(TokenScopeSchema).default([]),
4528
4841
  createdAt: z.number(),
@@ -4531,7 +4844,7 @@ z.object({
4531
4844
  z.object({
4532
4845
  id: z.string(),
4533
4846
  label: z.string(),
4534
- role: UserRoleSchema,
4847
+ isAdmin: z.boolean().default(false),
4535
4848
  allowedProviders: AllowedProviderSchema,
4536
4849
  allowedDevices: AllowedDevicesSchema,
4537
4850
  tokenHash: z.string(),
@@ -4553,7 +4866,7 @@ z.object({
4553
4866
  var UserSummarySchema = z.object({
4554
4867
  id: z.string(),
4555
4868
  username: z.string(),
4556
- role: UserRoleSchema,
4869
+ isAdmin: z.boolean().default(false),
4557
4870
  allowedProviders: z.union([z.array(z.string()), z.literal("*")]),
4558
4871
  allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal("*")])),
4559
4872
  scopes: z.array(TokenScopeSchema).default([]),
@@ -4563,14 +4876,14 @@ var UserSummarySchema = z.object({
4563
4876
  var CreateUserInputSchema = z.object({
4564
4877
  username: z.string(),
4565
4878
  password: z.string().min(6),
4566
- role: UserRoleSchema,
4879
+ isAdmin: z.boolean().default(false),
4567
4880
  allowedProviders: z.union([z.array(z.string()), z.literal("*")]).optional(),
4568
4881
  allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal("*")])).optional(),
4569
4882
  scopes: z.array(TokenScopeSchema).optional()
4570
4883
  });
4571
4884
  var UpdateUserInputSchema = z.object({
4572
4885
  id: z.string(),
4573
- role: UserRoleSchema.optional(),
4886
+ isAdmin: z.boolean().optional(),
4574
4887
  allowedProviders: z.union([z.array(z.string()), z.literal("*")]).optional(),
4575
4888
  allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal("*")])).optional(),
4576
4889
  scopes: z.array(TokenScopeSchema).optional()
@@ -4578,7 +4891,7 @@ var UpdateUserInputSchema = z.object({
4578
4891
  var ApiKeySummarySchema = z.object({
4579
4892
  id: z.string(),
4580
4893
  label: z.string(),
4581
- role: UserRoleSchema,
4894
+ isAdmin: z.boolean().default(false),
4582
4895
  allowedProviders: z.union([z.array(z.string()), z.literal("*")]).optional(),
4583
4896
  allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal("*")])).optional(),
4584
4897
  tokenPrefix: z.string(),
@@ -4587,7 +4900,7 @@ var ApiKeySummarySchema = z.object({
4587
4900
  });
4588
4901
  var CreateApiKeyInputSchema = z.object({
4589
4902
  label: z.string(),
4590
- role: UserRoleSchema,
4903
+ isAdmin: z.boolean().default(false),
4591
4904
  allowedProviders: z.union([z.array(z.string()), z.literal("*")]).optional(),
4592
4905
  allowedDevices: z.record(z.string(), z.union([z.array(z.string()), z.literal("*")])).optional()
4593
4906
  });
@@ -4615,43 +4928,89 @@ var CreateScopedTokenResultSchema = z.object({
4615
4928
  token: z.string(),
4616
4929
  record: ScopedTokenSummarySchema
4617
4930
  });
4931
+ var TotpSetupResultSchema = z.object({
4932
+ secret: z.string(),
4933
+ otpauthUrl: z.string()
4934
+ });
4935
+ var TotpStatusSchema = z.object({
4936
+ /** True iff `confirmedAt != null` — a pending half-enrollment is reported as `enabled: false`. */
4937
+ enabled: z.boolean(),
4938
+ /** Null when no row exists OR the row is still pending confirmation. */
4939
+ confirmedAt: z.number().nullable()
4940
+ });
4618
4941
  method(z.void(), z.array(UserSummarySchema), { auth: "admin" }), method(CreateUserInputSchema, UserSummarySchema, {
4619
4942
  kind: "mutation",
4620
- auth: "admin"
4943
+ auth: "admin",
4944
+ access: "create"
4621
4945
  }), method(UpdateUserInputSchema, z.object({ success: z.literal(true) }), {
4622
4946
  kind: "mutation",
4623
- auth: "admin"
4947
+ auth: "admin",
4948
+ access: "create"
4624
4949
  }), method(z.object({ id: z.string() }), z.object({ success: z.literal(true) }), {
4625
4950
  kind: "mutation",
4626
- auth: "admin"
4951
+ auth: "admin",
4952
+ access: "delete"
4627
4953
  }), method(z.object({
4628
4954
  id: z.string(),
4629
4955
  newPassword: z.string().min(6)
4630
4956
  }), z.object({ success: z.literal(true) }), {
4631
4957
  kind: "mutation",
4632
- auth: "admin"
4958
+ auth: "admin",
4959
+ access: "create"
4633
4960
  }), method(z.object({
4634
4961
  userId: z.string(),
4635
4962
  scopes: z.array(TokenScopeSchema)
4636
4963
  }), z.object({ success: z.literal(true) }), {
4637
4964
  kind: "mutation",
4638
- auth: "admin"
4965
+ auth: "admin",
4966
+ access: "create"
4639
4967
  }), method(z.object({
4640
4968
  username: z.string(),
4641
4969
  password: z.string()
4642
- }), UserSummarySchema.extend({ passwordHash: z.string() }).nullable(), { kind: "mutation" }), method(z.void(), z.array(ApiKeySummarySchema), { auth: "admin" }), method(CreateApiKeyInputSchema, CreateApiKeyResultSchema, {
4970
+ }), UserSummarySchema.extend({ passwordHash: z.string() }).nullable(), {
4643
4971
  kind: "mutation",
4644
- auth: "admin"
4972
+ access: "view"
4973
+ }), method(z.void(), z.array(ApiKeySummarySchema), { auth: "admin" }), method(CreateApiKeyInputSchema, CreateApiKeyResultSchema, {
4974
+ kind: "mutation",
4975
+ auth: "admin",
4976
+ access: "create"
4645
4977
  }), method(z.object({ id: z.string() }), z.object({ success: z.literal(true) }), {
4646
4978
  kind: "mutation",
4647
- auth: "admin"
4648
- }), method(z.object({ token: z.string() }), ApiKeySummarySchema.nullable(), { kind: "mutation" }), method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
4979
+ auth: "admin",
4980
+ access: "delete"
4981
+ }), method(z.object({ token: z.string() }), ApiKeySummarySchema.nullable(), {
4649
4982
  kind: "mutation",
4650
- auth: "admin"
4983
+ access: "view"
4984
+ }), method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
4985
+ kind: "mutation",
4986
+ auth: "admin",
4987
+ access: "create"
4651
4988
  }), method(z.object({ id: z.string() }), z.object({ success: z.literal(true) }), {
4652
4989
  kind: "mutation",
4653
- auth: "admin"
4654
- }), method(z.object({ token: z.string() }), ScopedTokenSummarySchema.nullable()), method(z.object({ userId: z.string() }), z.array(ScopedTokenSummarySchema), { auth: "admin" });
4990
+ auth: "admin",
4991
+ access: "delete"
4992
+ }), method(z.object({ token: z.string() }), ScopedTokenSummarySchema.nullable(), { access: "view" }), method(z.object({ userId: z.string() }), z.array(ScopedTokenSummarySchema), { auth: "admin" }), method(z.object({ userId: z.string() }), TotpSetupResultSchema, {
4993
+ kind: "mutation",
4994
+ auth: "admin",
4995
+ access: "create"
4996
+ }), method(z.object({
4997
+ userId: z.string(),
4998
+ code: z.string()
4999
+ }), z.object({ success: z.literal(true) }), {
5000
+ kind: "mutation",
5001
+ auth: "admin",
5002
+ access: "create"
5003
+ }), method(z.object({ userId: z.string() }), z.object({ success: z.literal(true) }), {
5004
+ kind: "mutation",
5005
+ auth: "admin",
5006
+ access: "delete"
5007
+ }), method(z.object({ userId: z.string() }), TotpStatusSchema, { auth: "admin" }), method(z.object({
5008
+ userId: z.string(),
5009
+ code: z.string()
5010
+ }), z.object({ valid: z.boolean() }), {
5011
+ kind: "mutation",
5012
+ access: "view"
5013
+ });
4655
5014
  var FeatureManifestSchema = z.object({
4656
5015
  streaming: z.boolean(),
4657
5016
  notifications: z.boolean(),