@camstack/types 1.2.332 → 1.2.334

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 (53) hide show
  1. package/dist/addon/base-addon.d.ts +32 -0
  2. package/dist/addon/secret-aware-context.d.ts +49 -6
  3. package/dist/addon/secret-settings-view.d.ts +23 -1
  4. package/dist/addon/secret-write-back.d.ts +40 -0
  5. package/dist/addon.js +5 -7
  6. package/dist/addon.mjs +5 -7
  7. package/dist/auth/app-callback.d.ts +28 -0
  8. package/dist/auth/sso-state.d.ts +16 -0
  9. package/dist/capabilities/addon-routes.cap.d.ts +3 -0
  10. package/dist/capabilities/addons.cap.d.ts +4 -4
  11. package/dist/capabilities/backup.cap.d.ts +101 -1
  12. package/dist/capabilities/broker.cap.d.ts +4 -4
  13. package/dist/capabilities/custom-model-registry.cap.d.ts +520 -0
  14. package/dist/capabilities/device-manager.cap.d.ts +4 -4
  15. package/dist/capabilities/hub-address.d.ts +2 -2
  16. package/dist/capabilities/index.d.ts +12 -6
  17. package/dist/capabilities/keychain-admin.cap.d.ts +83 -0
  18. package/dist/capabilities/login-method.cap.d.ts +5 -6
  19. package/dist/capabilities/nodes.cap.d.ts +8 -0
  20. package/dist/capabilities/notification-output.cap.d.ts +4 -4
  21. package/dist/capabilities/notification-rules.cap.d.ts +6 -6
  22. package/dist/capabilities/osd-manager.cap.d.ts +5 -5
  23. package/dist/capabilities/pipeline-analytics.cap.d.ts +39 -8
  24. package/dist/capabilities/recording.cap.d.ts +3 -3
  25. package/dist/capabilities/server-management.cap.d.ts +5 -5
  26. package/dist/capabilities/snapshot.cap.d.ts +2 -2
  27. package/dist/capabilities/sso-bridge.cap.d.ts +5 -2
  28. package/dist/capabilities/training-provider.cap.d.ts +373 -0
  29. package/dist/capabilities/training.cap.d.ts +1896 -0
  30. package/dist/capabilities/user-management.cap.d.ts +1 -64
  31. package/dist/capabilities/videoclips.cap.d.ts +3 -3
  32. package/dist/client.js +33 -5
  33. package/dist/client.mjs +33 -5
  34. package/dist/generated/addon-api.d.ts +872 -173
  35. package/dist/generated/cap-input-defaults.d.ts +1 -1
  36. package/dist/generated/capability-router-map.d.ts +10 -4
  37. package/dist/generated/collection-array-methods.d.ts +1 -1
  38. package/dist/generated/method-access-map.d.ts +1 -1
  39. package/dist/generated/method-device-selectors.d.ts +2 -2
  40. package/dist/generated/system-proxy.d.ts +5 -3
  41. package/dist/index.d.ts +3 -0
  42. package/dist/index.js +1469 -94
  43. package/dist/index.mjs +1420 -93
  44. package/dist/interfaces/addon-routes.d.ts +7 -0
  45. package/dist/interfaces/addon.d.ts +8 -0
  46. package/dist/interfaces/auth.d.ts +6 -3
  47. package/dist/interfaces/event-bus.d.ts +5 -0
  48. package/dist/schemas/auth-records.d.ts +1 -2
  49. package/dist/{sleep-ClNXPpWR.js → sleep-DiQYrfm9.js} +425 -75
  50. package/dist/{sleep-DujUvOcb.mjs → sleep-r3RWkGVx.mjs} +425 -75
  51. package/dist/training/index.d.ts +1 -0
  52. package/dist/training/trainer-contract.d.ts +468 -0
  53. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sleep = require("./sleep-ClNXPpWR.js");
2
+ const require_sleep = require("./sleep-DiQYrfm9.js");
3
3
  const require_event_category = require("./event-category-CHduMGvg.js");
4
4
  const require_composition = require("./composition-BLWAivB2.js");
5
5
  const require_err_msg = require("./err-msg-Dx2Kor0g.js");
@@ -1632,6 +1632,298 @@ function composeSwitchedOff(input) {
1632
1632
  };
1633
1633
  }
1634
1634
  //#endregion
1635
+ //#region src/training/trainer-contract.ts
1636
+ /**
1637
+ * The trainer contract — what the hub hands the cloud trainer and what it
1638
+ * gets back (cloud training, D805+).
1639
+ *
1640
+ * The trainer (`hf/camstack-trainer`, published as the Hugging Face repo
1641
+ * `camstack/camstack-trainer`) is a separate AGPL program the hub never
1642
+ * imports: `job.json` goes in, files come out, and progress is `CAMSTACK_EVENT`
1643
+ * lines on stdout. These schemas are the hub's half of that boundary; the
1644
+ * trainer's pydantic models (and the JSON Schemas generated from them under
1645
+ * `hf/camstack-trainer/schemas/`) are the other half. A change here is a
1646
+ * change there, in the same piece of work.
1647
+ *
1648
+ * No `.default()` anywhere: defaults do not run on the addon cap path, so the
1649
+ * orchestrator fills every field of a job spec explicitly.
1650
+ */
1651
+ var TRAINING_JOB_SCHEMA = "camstack.training/v1";
1652
+ var TRAINING_RESULT_SCHEMA = "camstack.training-result/v1";
1653
+ /** The stdout prefix of a progress line. Anything else on stdout is log text. */
1654
+ var CAMSTACK_EVENT_PREFIX = "CAMSTACK_EVENT ";
1655
+ /** What the trainer can export. Edge TPU is a later, separate image. */
1656
+ var TrainingExportSchema = zod.z.enum([
1657
+ "onnx",
1658
+ "openvino-fp16",
1659
+ "openvino-int8",
1660
+ "coreml-fp16"
1661
+ ]);
1662
+ var FloorsSchema = zod.z.record(zod.z.string(), zod.z.number().min(0).max(1));
1663
+ var TrainingJobSpecSchema = zod.z.object({
1664
+ schema: zod.z.literal(TRAINING_JOB_SCHEMA),
1665
+ jobKey: zod.z.string().uuid(),
1666
+ target: zod.z.object({
1667
+ kind: zod.z.literal("detector"),
1668
+ step: zod.z.literal("object-detection")
1669
+ }),
1670
+ base: zod.z.object({
1671
+ modelId: zod.z.string().min(1),
1672
+ /** Ultralytics weights id, e.g. `yolov9m.pt`. */
1673
+ weights: zod.z.string().min(1),
1674
+ imgsz: zod.z.number().int().positive()
1675
+ }),
1676
+ baseline: zod.z.object({
1677
+ modelId: zod.z.string().min(1),
1678
+ /** The baseline ONNX the holdout comparison runs; public mirror URL. */
1679
+ onnxUrl: zod.z.string().url(),
1680
+ imgsz: zod.z.number().int().positive(),
1681
+ floors: FloorsSchema
1682
+ }),
1683
+ dataset: zod.z.object({
1684
+ versionId: zod.z.string().min(1),
1685
+ annotationHash: zod.z.string(),
1686
+ /** sha256 of the uploaded archive; the trainer refuses a mismatch (exit 65). */
1687
+ sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
1688
+ }),
1689
+ split: zod.z.object({
1690
+ holdoutCameras: zod.z.array(zod.z.number().int()),
1691
+ /** When no camera is held out: the last N days of every camera. */
1692
+ holdoutLastDays: zod.z.number().int().nonnegative(),
1693
+ valFraction: zod.z.number().min(0).max(.5),
1694
+ seed: zod.z.number().int()
1695
+ }),
1696
+ hyper: zod.z.object({
1697
+ epochs: zod.z.number().int().positive(),
1698
+ batch: zod.z.number().int().positive(),
1699
+ lr0: zod.z.number().positive(),
1700
+ /** Layers frozen from the start of the backbone; 0 = none. */
1701
+ freeze: zod.z.number().int().nonnegative(),
1702
+ patience: zod.z.number().int().nonnegative(),
1703
+ seed: zod.z.number().int()
1704
+ }),
1705
+ replay: zod.z.object({
1706
+ source: zod.z.literal("coco2017"),
1707
+ count: zod.z.number().int().nonnegative()
1708
+ }),
1709
+ exports: zod.z.array(TrainingExportSchema).min(1),
1710
+ calibration: zod.z.object({ maxFrames: zod.z.number().int().positive() }),
1711
+ floors: zod.z.object({
1712
+ minSupport: zod.z.number().int().positive(),
1713
+ clamp: zod.z.number().min(0).max(1)
1714
+ }),
1715
+ int8Gate: zod.z.object({ maxMap50Drop: zod.z.number().min(0).max(1) }),
1716
+ catalog: zod.z.object({
1717
+ id: zod.z.string().regex(/^[a-z0-9][a-z0-9-]{2,80}$/),
1718
+ name: zod.z.string().min(1).max(160)
1719
+ })
1720
+ });
1721
+ /** One regular file of the bundle. An mlpackage contributes one row per member. */
1722
+ var TrainingResultFileSchema = zod.z.object({
1723
+ path: zod.z.string().min(1),
1724
+ bytes: zod.z.number().int().nonnegative(),
1725
+ sha256: zod.z.string().regex(/^[0-9a-f]{64}$/),
1726
+ format: zod.z.enum([
1727
+ "onnx",
1728
+ "openvino",
1729
+ "coreml",
1730
+ "pt"
1731
+ ]),
1732
+ variant: zod.z.enum(["base", "int8"])
1733
+ });
1734
+ var DraftFormatSchema = zod.z.object({
1735
+ /** RELATIVE path inside the bundle; the hub rewrites it to `camstack-local://`. */
1736
+ url: zod.z.string().min(1),
1737
+ sizeMB: zod.z.number().nonnegative(),
1738
+ isDirectory: zod.z.boolean().optional(),
1739
+ files: zod.z.array(zod.z.string()).optional(),
1740
+ runtimes: zod.z.array(zod.z.literal("python")).optional(),
1741
+ revision: zod.z.string().min(1)
1742
+ });
1743
+ /** The trainer's half of a catalog entry; the hub completes it (labels, licence, group). */
1744
+ var TrainingCatalogDraftSchema = zod.z.object({
1745
+ id: zod.z.string().min(1),
1746
+ name: zod.z.string().min(1),
1747
+ description: zod.z.string(),
1748
+ labels: zod.z.array(zod.z.unknown()),
1749
+ inputSize: zod.z.object({
1750
+ width: zod.z.number().int().positive(),
1751
+ height: zod.z.number().int().positive()
1752
+ }),
1753
+ preprocessMode: zod.z.literal("letterbox"),
1754
+ defaultClassFloors: FloorsSchema,
1755
+ formats: zod.z.object({
1756
+ onnx: DraftFormatSchema.optional(),
1757
+ openvino: DraftFormatSchema.optional(),
1758
+ coreml: DraftFormatSchema.optional()
1759
+ })
1760
+ });
1761
+ /** One class of one model's holdout report (the eval harness's summary). */
1762
+ var TrainingEvalClassSchema = zod.z.object({
1763
+ positives: zod.z.number().int(),
1764
+ floor: zod.z.number().nullable(),
1765
+ tp: zod.z.number().int(),
1766
+ fp: zod.z.number().int(),
1767
+ fn: zod.z.number().int(),
1768
+ precision: zod.z.number().nullable(),
1769
+ recall: zod.z.number().nullable(),
1770
+ ap50: zod.z.number().nullable(),
1771
+ recallByCamera: zod.z.record(zod.z.string(), zod.z.number().nullable()).optional(),
1772
+ recallByLight: zod.z.record(zod.z.string(), zod.z.number().nullable()).optional(),
1773
+ fpByCamera: zod.z.record(zod.z.string(), zod.z.number()).optional(),
1774
+ smallFound: zod.z.number().int().optional(),
1775
+ smallTotal: zod.z.number().int().optional()
1776
+ }).passthrough();
1777
+ var TrainingEvalReportSchema = zod.z.object({
1778
+ frames: zod.z.number().int(),
1779
+ classes: zod.z.record(zod.z.string(), TrainingEvalClassSchema)
1780
+ }).passthrough();
1781
+ /**
1782
+ * A succeeded result carries every block; a failed one carries the error and
1783
+ * whatever was known by then — the other blocks are ABSENT, not null. The
1784
+ * orchestrator checks the blocks it needs before it trusts a success.
1785
+ */
1786
+ var TrainingResultSchema = zod.z.object({
1787
+ schema: zod.z.literal(TRAINING_RESULT_SCHEMA),
1788
+ jobKey: zod.z.string(),
1789
+ status: zod.z.enum(["succeeded", "failed"]),
1790
+ error: zod.z.object({
1791
+ stage: zod.z.string(),
1792
+ code: zod.z.string(),
1793
+ message: zod.z.string()
1794
+ }).nullable(),
1795
+ trainer: zod.z.object({
1796
+ version: zod.z.string(),
1797
+ revision: zod.z.string()
1798
+ }),
1799
+ toolchain: zod.z.record(zod.z.string(), zod.z.string().nullable()),
1800
+ dataset: zod.z.object({
1801
+ versionId: zod.z.string(),
1802
+ annotationHash: zod.z.string(),
1803
+ sha256: zod.z.string(),
1804
+ frames: zod.z.object({
1805
+ train: zod.z.number().int(),
1806
+ val: zod.z.number().int(),
1807
+ holdout: zod.z.number().int()
1808
+ }),
1809
+ holdoutCameras: zod.z.array(zod.z.number().int()),
1810
+ replayImages: zod.z.number().int()
1811
+ }).optional(),
1812
+ training: zod.z.object({
1813
+ epochsRun: zod.z.number().int(),
1814
+ bestEpoch: zod.z.number().int(),
1815
+ bestMap50: zod.z.number(),
1816
+ bestMap50_95: zod.z.number(),
1817
+ seconds: zod.z.number()
1818
+ }).optional(),
1819
+ evaluation: zod.z.object({
1820
+ holdoutFrames: zod.z.number().int(),
1821
+ baseline: TrainingEvalReportSchema.nullable(),
1822
+ candidate: TrainingEvalReportSchema.nullable(),
1823
+ candidateInt8: TrainingEvalReportSchema.nullable(),
1824
+ recallDeltaByCamera: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.number())).nullable(),
1825
+ map50: zod.z.record(zod.z.string(), zod.z.number().nullable())
1826
+ }).optional(),
1827
+ floors: zod.z.object({
1828
+ baseline: FloorsSchema,
1829
+ candidate: FloorsSchema,
1830
+ candidateInt8: FloorsSchema.nullable(),
1831
+ notes: zod.z.array(zod.z.string())
1832
+ }).optional(),
1833
+ int8: zod.z.object({
1834
+ kept: zod.z.boolean(),
1835
+ map50Fp16: zod.z.number().nullable(),
1836
+ map50Int8: zod.z.number().nullable(),
1837
+ reason: zod.z.string().nullable()
1838
+ }).optional(),
1839
+ exportsDropped: zod.z.array(zod.z.object({
1840
+ export: zod.z.string(),
1841
+ reason: zod.z.string()
1842
+ })).optional(),
1843
+ files: zod.z.array(TrainingResultFileSchema).optional(),
1844
+ bundle: zod.z.object({
1845
+ path: zod.z.literal("bundle.tar"),
1846
+ bytes: zod.z.number().int().nonnegative(),
1847
+ sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
1848
+ }).nullable().optional(),
1849
+ catalogDraft: zod.z.object({
1850
+ base: TrainingCatalogDraftSchema,
1851
+ int8: TrainingCatalogDraftSchema.nullable()
1852
+ }).nullable().optional(),
1853
+ licence: zod.z.string()
1854
+ });
1855
+ var TrainingStageSchema = zod.z.enum([
1856
+ "prepare",
1857
+ "replay",
1858
+ "train",
1859
+ "eval",
1860
+ "export",
1861
+ "package"
1862
+ ]);
1863
+ var EventBase = {
1864
+ v: zod.z.literal(1),
1865
+ ts: zod.z.number()
1866
+ };
1867
+ var TrainingEventSchema = zod.z.discriminatedUnion("type", [
1868
+ zod.z.object({
1869
+ ...EventBase,
1870
+ type: zod.z.literal("stage"),
1871
+ stage: TrainingStageSchema
1872
+ }),
1873
+ zod.z.object({
1874
+ ...EventBase,
1875
+ type: zod.z.literal("epoch"),
1876
+ epoch: zod.z.number().int(),
1877
+ epochs: zod.z.number().int(),
1878
+ boxLoss: zod.z.number().nullable().optional(),
1879
+ map50: zod.z.number().nullable().optional(),
1880
+ map50_95: zod.z.number().nullable().optional(),
1881
+ etaSec: zod.z.number().nullable().optional()
1882
+ }),
1883
+ zod.z.object({
1884
+ ...EventBase,
1885
+ type: zod.z.literal("metric"),
1886
+ name: zod.z.string(),
1887
+ value: zod.z.number()
1888
+ }),
1889
+ zod.z.object({
1890
+ ...EventBase,
1891
+ type: zod.z.literal("artifact"),
1892
+ path: zod.z.string(),
1893
+ bytes: zod.z.number(),
1894
+ sha256: zod.z.string()
1895
+ }),
1896
+ zod.z.object({
1897
+ ...EventBase,
1898
+ type: zod.z.literal("done"),
1899
+ status: zod.z.enum(["succeeded", "failed"]),
1900
+ resultSha256: zod.z.string().nullable().optional()
1901
+ }),
1902
+ zod.z.object({
1903
+ ...EventBase,
1904
+ type: zod.z.literal("error"),
1905
+ stage: zod.z.string(),
1906
+ code: zod.z.string(),
1907
+ message: zod.z.string()
1908
+ })
1909
+ ]);
1910
+ /**
1911
+ * Parse one stdout line. `null` = not an event (plain log text, or an event
1912
+ * line this hub does not understand — a newer trainer may add types).
1913
+ */
1914
+ function parseTrainingEventLine(line) {
1915
+ const start = line.indexOf(CAMSTACK_EVENT_PREFIX);
1916
+ if (start < 0) return null;
1917
+ let raw;
1918
+ try {
1919
+ raw = JSON.parse(line.slice(start + 15));
1920
+ } catch {
1921
+ return null;
1922
+ }
1923
+ const parsed = TrainingEventSchema.safeParse(raw);
1924
+ return parsed.success ? parsed.data : null;
1925
+ }
1926
+ //#endregion
1635
1927
  //#region src/interfaces/birth-decision-ledger.ts
1636
1928
  /**
1637
1929
  * Birth-decision ledger — one durable row per track-birth VERDICT (D409).
@@ -6110,6 +6402,62 @@ function principalMayReachAddon(input) {
6110
6402
  };
6111
6403
  }
6112
6404
  //#endregion
6405
+ //#region src/auth/app-callback.ts
6406
+ /**
6407
+ * The viewer app's custom-scheme callback — the ONE list of URLs a hub flow
6408
+ * may hand a browser back to the native app at.
6409
+ *
6410
+ * Two readers, one answer: the admin-ui login page (`redirect=` for the
6411
+ * native sign-in handoff) and the hub itself (`auth.beginExternalLink`'s
6412
+ * `returnTo` for a native account link, D801). Both validate against this
6413
+ * list, so a scheme added for one flow can never be accepted by one side and
6414
+ * refused by the other.
6415
+ *
6416
+ * `camstack` is the production app; `camstack.dev` the dev client
6417
+ * (`APP_VARIANT=development`). Exact match after canonicalisation — no
6418
+ * query or fragment riders, no http(s).
6419
+ */
6420
+ var APP_AUTH_CALLBACK_URLS = ["camstack://auth-callback", "camstack.dev://auth-callback"];
6421
+ /** Longest raw callback value considered at all. */
6422
+ var APP_AUTH_CALLBACK_MAX_LENGTH = 512;
6423
+ /**
6424
+ * The variants the OS / linking layer produces for the same callback:
6425
+ * `scheme:///auth-callback` (expo-linking's empty-host standalone form — three
6426
+ * slashes) and a trailing `/` both mean `scheme://auth-callback`. Nothing else
6427
+ * is normalised: riders keep failing the exact match.
6428
+ */
6429
+ function canonicalizeAppCallback(raw) {
6430
+ return raw.replace(/^([a-z][a-z0-9.+-]*):\/\/\/(?!\/)/i, "$1://").replace(/\/$/, "");
6431
+ }
6432
+ /** The canonical allowlisted callback `raw` names, or `null`. */
6433
+ function parseAppAuthCallback(raw) {
6434
+ if (typeof raw !== "string" || raw.length === 0 || raw.length > 512) return null;
6435
+ const canonical = canonicalizeAppCallback(raw);
6436
+ return APP_AUTH_CALLBACK_URLS.includes(canonical) ? canonical : null;
6437
+ }
6438
+ /** True for a URL with a scheme (`camstack://…`, `https://…`) — not a hub-relative path. */
6439
+ function hasUrlScheme(url) {
6440
+ return /^[a-z][a-z0-9+.-]*:/i.test(url);
6441
+ }
6442
+ //#endregion
6443
+ //#region src/auth/sso-state.ts
6444
+ /**
6445
+ * The cookie that binds an SSO sign-in to the browser that started it.
6446
+ *
6447
+ * An IdP `/start` sets it to a random value and keeps only its SHA-256 in the
6448
+ * server-side pending state; the login bridge carries that hash. The hub's
6449
+ * `/api/auth/sso/finish` swaps a bridge for a session only when the request
6450
+ * presents the cookie whose hash the bridge names — so a bridge copied out of
6451
+ * a URL (history, a proxy log, a screenshot) is useless in any other browser.
6452
+ * The finish clears the cookie, and records the bridge's `jti` so the same
6453
+ * bridge never finishes twice.
6454
+ *
6455
+ * One name, two readers (the OIDC addon that sets it, the hub that checks it).
6456
+ */
6457
+ var SSO_STATE_COOKIE = "camstack_sso_state";
6458
+ /** Seconds the state cookie lives — the pending IdP state lasts 5 minutes, the bridge 5 more. */
6459
+ var SSO_STATE_COOKIE_MAX_AGE_SEC = 600;
6460
+ //#endregion
6113
6461
  //#region src/expression/binding-source.ts
6114
6462
  /**
6115
6463
  * What an expression's named bindings READ from.
@@ -6933,7 +7281,9 @@ var AddonHttpRouteSchema = zod.z.object({
6933
7281
  "authenticated",
6934
7282
  "admin"
6935
7283
  ]).optional(),
6936
- description: zod.z.string().optional()
7284
+ description: zod.z.string().optional(),
7285
+ /** The hub limits this route per client address before the handler runs. */
7286
+ rateLimit: zod.z.enum(["auth"]).optional()
6937
7287
  });
6938
7288
  /**
6939
7289
  * Cross-process route invocation envelope. The hub captures the
@@ -7960,6 +8310,37 @@ var BackupDestinationInfoSchema = zod.z.object({
7960
8310
  lastError: zod.z.string().optional()
7961
8311
  });
7962
8312
  /**
8313
+ * How an archive is encrypted (operator decision 2026-10-09): to a backup
8314
+ * PUBLIC key the hub holds, so only the operator's secret key opens it.
8315
+ * Absent on a plain `.tar.gz` — every archive made before encryption, or
8316
+ * with it off — which restores without a key.
8317
+ */
8318
+ var BackupArchiveEncryptionSchema = zod.z.object({
8319
+ /** `x25519-hkdf-aes256gcm-stream-v1`. */
8320
+ scheme: zod.z.string(),
8321
+ /** 16 hex — the backup key whose secret restores this archive. */
8322
+ keyId: zod.z.string()
8323
+ });
8324
+ /**
8325
+ * The backup encryption setting. The hub keeps PUBLIC keys only: the active
8326
+ * one new archives are encrypted to, and the retired ones older archives
8327
+ * still need. The secret key is shown once, at `setupEncryption`.
8328
+ */
8329
+ var BackupEncryptionStatusSchema = zod.z.object({
8330
+ enabled: zod.z.boolean(),
8331
+ active: zod.z.object({
8332
+ keyId: zod.z.string(),
8333
+ publicKey: zod.z.string(),
8334
+ createdAt: zod.z.number()
8335
+ }).nullable(),
8336
+ /** Every key ever set up, newest first. */
8337
+ keys: zod.z.array(zod.z.object({
8338
+ keyId: zod.z.string(),
8339
+ createdAt: zod.z.number(),
8340
+ retiredAt: zod.z.number().nullable()
8341
+ })).readonly()
8342
+ });
8343
+ /**
7963
8344
  * Per-archive entry returned by `backup.listArchives({ destinationId })`.
7964
8345
  * Same shape the destination drill-in renders. Sourced from the per-
7965
8346
  * location `manifests.json` (no per-archive tarball read required).
@@ -7971,7 +8352,9 @@ var BackupArchiveEntrySchema = zod.z.object({
7971
8352
  sizeBytes: zod.z.number(),
7972
8353
  label: zod.z.string().optional(),
7973
8354
  /** Top-level locations included in the archive (db, addons, tls, …). */
7974
- locations: zod.z.array(zod.z.string()).readonly()
8355
+ locations: zod.z.array(zod.z.string()).readonly(),
8356
+ /** Present when the archive is encrypted; restore then needs that key. */
8357
+ encryption: BackupArchiveEncryptionSchema.optional()
7975
8358
  });
7976
8359
  var BackupEntrySchema = zod.z.object({
7977
8360
  id: zod.z.string(),
@@ -7980,7 +8363,8 @@ var BackupEntrySchema = zod.z.object({
7980
8363
  label: zod.z.string().optional(),
7981
8364
  createdAt: zod.z.number(),
7982
8365
  sizeBytes: zod.z.number(),
7983
- locations: zod.z.array(zod.z.string()).optional()
8366
+ locations: zod.z.array(zod.z.string()).optional(),
8367
+ encryption: BackupArchiveEncryptionSchema.optional()
7984
8368
  });
7985
8369
  var ArchiveEntrySchema = zod.z.object({
7986
8370
  path: zod.z.string(),
@@ -8235,11 +8619,58 @@ var backupCapability = {
8235
8619
  * this list and skips entries whose path doesn't start with
8236
8620
  * any of them.
8237
8621
  */
8238
- locations: zod.z.array(zod.z.string()).optional()
8622
+ locations: zod.z.array(zod.z.string()).optional(),
8623
+ /**
8624
+ * The backup SECRET key, for an encrypted archive (ignored for a plain
8625
+ * one). The archive is decrypted into the hub's private staging
8626
+ * before the restart; the key is not stored. A wrong or missing key
8627
+ * is refused before the archive is downloaded.
8628
+ */
8629
+ backupSecretKey: zod.z.string().optional()
8239
8630
  }), zod.z.void(), {
8240
8631
  kind: "mutation",
8241
8632
  auth: "admin"
8242
8633
  }),
8634
+ /** The encryption setting — public keys only. */
8635
+ getEncryption: require_sleep.method(zod.z.void(), BackupEncryptionStatusSchema, { auth: "admin" }),
8636
+ /**
8637
+ * Turn encryption on, or replace the key: generates a new key pair, keeps
8638
+ * the PUBLIC key, and returns the SECRET key — once. It is never stored
8639
+ * on the hub and cannot be shown again; archives made from now on need
8640
+ * it to be restored. A previous key is retired: archives made with it
8641
+ * still need IT.
8642
+ */
8643
+ setupEncryption: require_sleep.method(zod.z.object({}), zod.z.object({
8644
+ keyId: zod.z.string(),
8645
+ secretKey: zod.z.string(),
8646
+ publicKey: zod.z.string(),
8647
+ createdAt: zod.z.number(),
8648
+ replacedKeyId: zod.z.string().nullable()
8649
+ }), {
8650
+ kind: "mutation",
8651
+ auth: "admin"
8652
+ }),
8653
+ /** New archives are plain again. Existing encrypted archives keep needing their key. */
8654
+ disableEncryption: require_sleep.method(zod.z.object({}), zod.z.object({ disabledKeyId: zod.z.string().nullable() }), {
8655
+ kind: "mutation",
8656
+ auth: "admin"
8657
+ }),
8658
+ /**
8659
+ * Does this secret key parse, and which backup key is it? A mutation so
8660
+ * the key never travels in a URL. Nothing is stored.
8661
+ */
8662
+ checkBackupKey: require_sleep.method(zod.z.object({ backupSecretKey: zod.z.string() }), zod.z.object({
8663
+ valid: zod.z.boolean(),
8664
+ keyId: zod.z.string().nullable(),
8665
+ /** The hub knows this key (active or retired). */
8666
+ known: zod.z.boolean(),
8667
+ /** It is the key new archives are encrypted to. */
8668
+ active: zod.z.boolean(),
8669
+ error: zod.z.string().optional()
8670
+ }), {
8671
+ kind: "mutation",
8672
+ auth: "admin"
8673
+ }),
8243
8674
  delete: require_sleep.method(zod.z.object({
8244
8675
  destinationId: zod.z.string(),
8245
8676
  backupId: zod.z.string()
@@ -11833,22 +12264,87 @@ var CustomModelDescriptorSchema = zod.z.object({
11833
12264
  stepId: zod.z.string(),
11834
12265
  entry: ModelCatalogEntrySchema
11835
12266
  });
12267
+ /** One regular file of an imported bundle, as the producer measured it. */
12268
+ var ModelBundleFileSchema = zod.z.object({
12269
+ /** Relative path inside the bundle tar; an mlpackage member is `<x>.mlpackage/<member>`. */
12270
+ path: zod.z.string().min(1),
12271
+ bytes: zod.z.number().int().nonnegative(),
12272
+ sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
12273
+ });
12274
+ var ImportModelBundleInputSchema = zod.z.object({
12275
+ /** The registry provider that keeps the model (Model Studio). */
12276
+ addonId: zod.z.string(),
12277
+ stepId: zod.z.string().min(1),
12278
+ /**
12279
+ * The catalog rows to register, complete, every format URL already
12280
+ * `camstack-local://<modelId>/<file>` naming a file of the bundle. One
12281
+ * bundle may carry several rows (a base and its INT8 variant).
12282
+ */
12283
+ entries: zod.z.array(ModelCatalogEntrySchema).min(1).max(4),
12284
+ /** The bundle tar, offered by the producer over `ctx.peerBytes` (same host). */
12285
+ bundle: zod.z.object({
12286
+ ticket: require_sleep.PeerBytesTicketSchema,
12287
+ bytes: zod.z.number().int().positive(),
12288
+ sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
12289
+ }),
12290
+ /** Every file the tar must hold; anything missing, extra or different is refused. */
12291
+ files: zod.z.array(ModelBundleFileSchema).min(1).max(64),
12292
+ /** Convert missing engine formats and push the model to every agent afterwards. */
12293
+ distribute: zod.z.boolean()
12294
+ });
12295
+ var ImportModelBundleResultSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
12296
+ kind: zod.z.literal("imported"),
12297
+ modelIds: zod.z.array(zod.z.string()).readonly(),
12298
+ distributed: zod.z.array(zod.z.object({
12299
+ modelId: zod.z.string(),
12300
+ nodeId: zod.z.string(),
12301
+ format: zod.z.enum(MODEL_FORMATS),
12302
+ ok: zod.z.boolean(),
12303
+ error: zod.z.string().optional()
12304
+ })).readonly()
12305
+ }), zod.z.object({
12306
+ kind: zod.z.literal("refused"),
12307
+ reason: zod.z.enum([
12308
+ "transfer-failed",
12309
+ "checksum-mismatch",
12310
+ "bundle-mismatch",
12311
+ "invalid-entry",
12312
+ "id-taken"
12313
+ ]),
12314
+ detail: zod.z.string()
12315
+ })]);
11836
12316
  var customModelRegistryCapability = {
11837
12317
  name: "custom-model-registry",
11838
12318
  scope: "system",
11839
12319
  mode: "collection",
11840
12320
  internal: true,
11841
- methods: {
11842
- /**
11843
- * `internal: true` did not gate the mount (see the 2026-08-26 note on
11844
- * `data-store-provider`) — this was reachable on the AppRouter by ANY
11845
- * authenticated session at the default `auth: 'protected'`. The only
11846
- * consumer, the detection-pipeline's model resolution
11847
- * (`addon-pipeline/src/detection-pipeline/provider.ts`), calls
11848
- * `ctx.api.customModelRegistry.listModels.query()` — UDS/Moleculer,
11849
- * never tRPC — so `auth: 'admin'` costs it nothing.
11850
- */
11851
- listModels: require_sleep.method(zod.z.void(), zod.z.array(CustomModelDescriptorSchema).readonly(), { auth: "admin" }) }
12321
+ methods: {
12322
+ /**
12323
+ * `internal: true` did not gate the mount (see the 2026-08-26 note on
12324
+ * `data-store-provider`) — this was reachable on the AppRouter by ANY
12325
+ * authenticated session at the default `auth: 'protected'`. The only
12326
+ * consumer, the detection-pipeline's model resolution
12327
+ * (`addon-pipeline/src/detection-pipeline/provider.ts`), calls
12328
+ * `ctx.api.customModelRegistry.listModels.query()` — UDS/Moleculer,
12329
+ * never tRPC — so `auth: 'admin'` costs it nothing.
12330
+ */
12331
+ listModels: require_sleep.method(zod.z.void(), zod.z.array(CustomModelDescriptorSchema).readonly(), { auth: "admin" }),
12332
+ /**
12333
+ * Register a model whose files arrive as ONE bundle tar (D806): the tar
12334
+ * is taken over `ctx.peerBytes`, checked against `bundle.sha256` and
12335
+ * every row of `files`, unpacked into the hub's flat modelsDir (directory
12336
+ * formats included), each format's `.revision` record written, the rows
12337
+ * upserted under the operator's name, the hub marked available and —
12338
+ * when asked — engine formats converted and the model distributed. A
12339
+ * model id already registered by another source is refused, never
12340
+ * overwritten.
12341
+ */
12342
+ importModelBundle: require_sleep.method(ImportModelBundleInputSchema, ImportModelBundleResultSchema, {
12343
+ kind: "mutation",
12344
+ auth: "admin",
12345
+ timeoutMs: 30 * 6e4
12346
+ })
12347
+ }
11852
12348
  };
11853
12349
  //#endregion
11854
12350
  //#region src/capabilities/settings-store.cap.ts
@@ -12665,6 +13161,42 @@ var KeychainKeySourceSchema = zod.z.object({
12665
13161
  */
12666
13162
  sharesBackupWithDatabase: zod.z.boolean()
12667
13163
  });
13164
+ /**
13165
+ * Who reset the keychain: an operator from System → Secrets (`user:<id>`), or
13166
+ * the one-shot `<dataDir>/.keychain/RESET_KEYCHAIN` trigger file at boot
13167
+ * (`trigger-file`) — the only way back into a hub whose master key is lost,
13168
+ * because a locked keychain leaves no session that could reach the page (D797).
13169
+ */
13170
+ var KEYCHAIN_RESET_TRIGGER_ACTOR = "trigger-file";
13171
+ /**
13172
+ * One keychain reset, as the Secrets page reports it until the operator
13173
+ * acknowledges it. Never a value: refs, counts and table names only.
13174
+ */
13175
+ var KeychainResetRecordSchema = zod.z.object({
13176
+ id: zod.z.string(),
13177
+ at: zod.z.number(),
13178
+ /** `user:<id>` or {@link KEYCHAIN_RESET_TRIGGER_ACTOR}. */
13179
+ actor: zod.z.string(),
13180
+ /** Why the keychain was locked when it was reset; `null` when it was not locked. */
13181
+ lockedReason: zod.z.string().nullable(),
13182
+ /** Values moved into the archive table (ciphertext under the lost key). */
13183
+ archived: zod.z.number().int(),
13184
+ /** `keychain:secrets-orphaned-<ts>`, or `null` when nothing was stored. */
13185
+ archivedCollection: zod.z.string().nullable(),
13186
+ /**
13187
+ * `keychain:keys-orphaned-<ts>`: the wrapped data keys of the archive, kept
13188
+ * so the archive can still be opened if the lost master key turns up.
13189
+ */
13190
+ archivedKeysCollection: zod.z.string().nullable(),
13191
+ /**
13192
+ * `system-settings` keys whose marker the reset cleared — the cluster
13193
+ * secret's: a marker left pointing at an archived value would refuse every
13194
+ * agent forever (D797).
13195
+ */
13196
+ clearedSettingsKeys: zod.z.array(zod.z.string()).readonly(),
13197
+ /** When an operator dismissed the notice on the Secrets page; `null` until then. */
13198
+ acknowledgedAt: zod.z.number().nullable()
13199
+ });
12668
13200
  var KeychainStatusSchema = zod.z.object({
12669
13201
  keychain: KeychainStateSchema,
12670
13202
  /** The source of the master key in use; `null` while locked. */
@@ -12682,7 +13214,9 @@ var KeychainStatusSchema = zod.z.object({
12682
13214
  /** Wrapped copies of the data key under a previous master key, kept until purged. */
12683
13215
  retiredWraps: zod.z.number().int(),
12684
13216
  recoveryKeyDownloadedAt: zod.z.number().nullable(),
12685
- secretCount: zod.z.number().int()
13217
+ secretCount: zod.z.number().int(),
13218
+ /** The most recent reset, acknowledged or not; `null` when the keychain was never reset. */
13219
+ lastReset: KeychainResetRecordSchema.nullable()
12686
13220
  });
12687
13221
  /**
12688
13222
  * Whether a stored value is still pointed at by its owner's settings.
@@ -12704,13 +13238,14 @@ var KeychainAuditActionSchema = zod.z.enum([
12704
13238
  "download-recovery-key",
12705
13239
  "delete-orphans",
12706
13240
  "reset",
13241
+ "acknowledge-reset",
12707
13242
  "initialize"
12708
13243
  ]);
12709
13244
  var KeychainAuditEntrySchema = zod.z.object({
12710
13245
  id: zod.z.string(),
12711
13246
  at: zod.z.number(),
12712
13247
  action: KeychainAuditActionSchema,
12713
- /** `addon:<id>` | `user:<id>` | `system`. */
13248
+ /** `addon:<id>` | `user:<id>` | `system` | `trigger-file`. */
12714
13249
  actor: zod.z.string(),
12715
13250
  ref: zod.z.string().nullable(),
12716
13251
  detail: zod.z.string().nullable()
@@ -12820,6 +13355,21 @@ var keychainAdminCapability = {
12820
13355
  kind: "mutation",
12821
13356
  auth: "admin",
12822
13357
  caller: "required"
13358
+ }),
13359
+ /**
13360
+ * What the last reset left to re-enter: the archived refs (owner, scope,
13361
+ * field — never a value) that hold no value again yet. Process-held refs
13362
+ * the hub regenerates itself (the session signing key) are not listed.
13363
+ */
13364
+ resetReport: require_sleep.method(zod.z.object({}), zod.z.object({
13365
+ reset: KeychainResetRecordSchema.nullable(),
13366
+ pendingReentry: zod.z.array(KeychainSecretMetaSchema).readonly()
13367
+ }), { auth: "admin" }),
13368
+ /** Dismiss the "keychain was reset" notice. Audited. */
13369
+ acknowledgeReset: require_sleep.method(zod.z.object({}), zod.z.object({ acknowledged: zod.z.boolean() }), {
13370
+ kind: "mutation",
13371
+ auth: "admin",
13372
+ caller: "required"
12823
13373
  })
12824
13374
  }
12825
13375
  };
@@ -16581,8 +17131,8 @@ var PUBLIC_ENDPOINT_HTTP_REASON = "The public endpoint needs an https:// address
16581
17131
  * May `baseUrl` carry `role`? The address check above, plus two role rules:
16582
17132
  * the app link carries `notificationTaps` only (it is not a hub address), and
16583
17133
  * a plain-http address carries `publicEndpoint` only when the operator
16584
- * explicitly accepted it (`acceptInsecureHttp`) — a LAN-only password or
16585
- * magic-link sign-in works over http, a passkey or an OIDC callback does not.
17134
+ * explicitly accepted it (`acceptInsecureHttp`) — a LAN-only password
17135
+ * sign-in works over http, a passkey or an OIDC callback does not.
16586
17136
  */
16587
17137
  function checkRoleAddress(role, baseUrl, options = {}) {
16588
17138
  if (isAppLinkBase(baseUrl)) return role === "notificationTaps" ? {
@@ -17732,7 +18282,7 @@ var logDestinationCapability = {
17732
18282
  * `login-method` — collection cap through which auth addons contribute
17733
18283
  * their pre-auth login surfaces to the login page. This is the SINGLE,
17734
18284
  * generic mechanism that supersedes the dead `auth.listProviders` reader:
17735
- * every auth addon (OIDC, magic-link, WebAuthn/passkey) registers a
18285
+ * every auth addon (OIDC, WebAuthn/passkey) registers a
17736
18286
  * `login-method` provider and the PUBLIC `auth.listLoginMethods`
17737
18287
  * procedure aggregates them for the unauthenticated login page.
17738
18288
  *
@@ -17740,8 +18290,7 @@ var logDestinationCapability = {
17740
18290
  *
17741
18291
  * - `redirect` — a declarative button. The login page renders a generic
17742
18292
  * button that navigates to `startUrl` (an addon-owned HTTP route).
17743
- * Covers OIDC (`/addon/auth-oidc/<id>/start`) and magic-link with
17744
- * ZERO shell-side JS. A future SSO addon plugs in the same way — the
18293
+ * Covers OIDC (`/addon/auth-oidc/<id>/start`) with ZERO shell-side JS. A future SSO addon plugs in the same way — the
17745
18294
  * login page needs NO change.
17746
18295
  *
17747
18296
  * - `widget` — a Module-Federation widget the login page mounts (via
@@ -17760,8 +18309,8 @@ var logDestinationCapability = {
17760
18309
  * decision.
17761
18310
  *
17762
18311
  * Every contribution carries a `stage`:
17763
- * - `primary` — shown on the first credentials screen (OIDC /
17764
- * magic-link buttons; a future usernameless passkey).
18312
+ * - `primary` — shown on the first credentials screen (OIDC
18313
+ * buttons; a usernameless passkey).
17765
18314
  * - `second-factor` — shown AFTER the password leg, gated on the
17766
18315
  * returned `factors` (passkey-as-2FA today).
17767
18316
  *
@@ -17773,7 +18322,7 @@ var logDestinationCapability = {
17773
18322
  var LoginStageEnum = zod.z.enum(["primary", "second-factor"]);
17774
18323
  /**
17775
18324
  * A declarative redirect button — the login page navigates to `startUrl`.
17776
- * OIDC and magic-link contribute this; a future SSO addon does too.
18325
+ * OIDC contributes this; a future SSO addon does too.
17777
18326
  */
17778
18327
  var RedirectLoginMethodSchema = zod.z.object({
17779
18328
  kind: zod.z.literal("redirect"),
@@ -17790,7 +18339,7 @@ var RedirectLoginMethodSchema = zod.z.object({
17790
18339
  * The provider names an external identity a signed-in user can link to
17791
18340
  * their own account (D782): `auth.listLinkableProviders` /
17792
18341
  * `beginExternalLink` offer exactly the redirect methods that set this,
17793
- * whatever their id. Absent / false — a login button only (magic-link).
18342
+ * whatever their id. Absent / false — a login button only.
17794
18343
  */
17795
18344
  linkable: zod.z.boolean().optional()
17796
18345
  });
@@ -23208,8 +23757,7 @@ var notificationRulesCapability = {
23208
23757
  * `super_admin` — collapsed onto the single boolean because every
23209
23758
  * non-admin caller is governed by the same scope-check rules; the
23210
23759
  * distinction was only ever used to route role-specific procedures
23211
- * which we no longer have. Agents are admin sessions issued via
23212
- * `createServiceToken`; CLI / webhook integrations are `cst_*` tokens
23760
+ * which we no longer have. CLI / webhook integrations are `cst_*` tokens
23213
23761
  * with `isAdmin: false` + an explicit scope list.
23214
23762
  */
23215
23763
  /** Per-method access flavour. Materialised on every cap method via codegen. */
@@ -26746,6 +27294,26 @@ var pipelineAnalyticsCapability = {
26746
27294
  auth: "admin",
26747
27295
  timeoutMs: 60 * 6e4
26748
27296
  }),
27297
+ /**
27298
+ * OFFER the annotated archive instead of pushing it (D805): the same tar
27299
+ * `writeRetrainArchive` streams, behind a one-shot `ctx.peerBytes` ticket
27300
+ * the caller dials at once (same host). For a consumer that cannot expose
27301
+ * an upload URL — a training provider streaming straight into its cloud.
27302
+ * The answer is the plan; the bytes and their sha256 are the consumer's
27303
+ * to measure as they arrive.
27304
+ */
27305
+ offerRetrainArchive: require_sleep.method(zod.z.object({
27306
+ filter: RetrainExportFilterSchema,
27307
+ layout: RetrainExportLayoutSchema
27308
+ }), zod.z.object({
27309
+ ticket: require_sleep.PeerBytesTicketSchema,
27310
+ frames: zod.z.number().int(),
27311
+ annotations: zod.z.number().int()
27312
+ }), {
27313
+ kind: "mutation",
27314
+ auth: "admin",
27315
+ timeoutMs: 12e4
27316
+ }),
26749
27317
  /** The counts a selection would freeze — class × camera × day/night,
26750
27318
  * completeness — without freezing anything. Index reads only. */
26751
27319
  previewRetrainDataset: require_sleep.method(zod.z.object({
@@ -31786,8 +32354,8 @@ version: zod.z.string().optional() }), ServerUpdateActionResultSchema, {
31786
32354
  * `smtp-provider` — pluggable email delivery surface.
31787
32355
  *
31788
32356
  * Collection cap: a deployment may install multiple SMTP relays (e.g.
31789
- * one for transactional / one for notifications). Consumers (magic-link,
31790
- * notifier addons, …) walk the collection and pick the first
32357
+ * one for transactional / one for notifications). Consumers (notifier
32358
+ * addons, …) walk the collection and pick the first
31791
32359
  * ready provider OR target a specific addonId.
31792
32360
  *
31793
32361
  * The shape stays small on purpose — `sendEmail` is enough for the
@@ -32087,7 +32655,7 @@ targets: zod.z.array(zod.z.object({
32087
32655
  //#region src/capabilities/sso-bridge.cap.ts
32088
32656
  /**
32089
32657
  * `sso-bridge` — internal hub-only cap that lets SSO-style auth
32090
- * providers (OIDC, SAML, magic-link, …) mint an HMAC-signed token
32658
+ * providers (OIDC, SAML, …) mint an HMAC-signed token
32091
32659
  * carrying the post-callback claims before redirecting back to
32092
32660
  * `/api/auth/sso/finish`.
32093
32661
  *
@@ -32150,7 +32718,14 @@ var SsoBridgeClaimsSchema = zod.z.object({
32150
32718
  * Verified `iss` of the id_token behind an OIDC login bridge (D782). A
32151
32719
  * subject is unique only per issuer, so a link is bound to it.
32152
32720
  */
32153
- issuer: zod.z.string().optional()
32721
+ issuer: zod.z.string().optional(),
32722
+ /**
32723
+ * SHA-256 (hex) of the `camstack_sso_state` cookie the IdP `/start` set in
32724
+ * the browser that began this sign-in. `/api/auth/sso/finish` requires the
32725
+ * request to present the matching cookie — a login bridge is useless in
32726
+ * any other browser.
32727
+ */
32728
+ browserBinding: zod.z.string().optional()
32154
32729
  });
32155
32730
  var ssoBridgeCapability = {
32156
32731
  name: "sso-bridge",
@@ -32168,7 +32743,7 @@ var ssoBridgeCapability = {
32168
32743
  * `/api/auth/sso/finish` to become admin — a full privilege escalation
32169
32744
  * through the exact surface this cap exists to close (see the module
32170
32745
  * docblock). Every real caller (`oauth-grants.ts`, `main.ts`
32171
- * registration, the OIDC/magic-link addons) reaches this through
32746
+ * registration, the OIDC addon) reaches this through
32172
32747
  * `ctx.api` / the in-process registry — never through tRPC — so
32173
32748
  * `auth: 'admin'` costs those callers nothing.
32174
32749
  */
@@ -41732,7 +42307,13 @@ var TopologyNodeSchema = zod.z.object({
41732
42307
  })).readonly(),
41733
42308
  processes: zod.z.array(TopologyProcessSchema).readonly(),
41734
42309
  categories: zod.z.array(TopologyCategorySchema).readonly(),
41735
- rootPackage: TopologyRootPackageSchema.nullable()
42310
+ rootPackage: TopologyRootPackageSchema.nullable(),
42311
+ /**
42312
+ * How an online AGENT reaches the hub (mesh mTLS Release A): `tls` once it has
42313
+ * completed a mutual-TLS handshake, `clear` otherwise. Absent for the hub,
42314
+ * for offline rows and when the hub cannot tell.
42315
+ */
42316
+ meshTransport: zod.z.enum(["tls", "clear"]).optional()
41736
42317
  });
41737
42318
  var CapUsageEdgeSchema = zod.z.object({
41738
42319
  callerAddonId: zod.z.string(),
@@ -48309,16 +48890,6 @@ var ApiKeySummarySchema = zod.z.object({
48309
48890
  createdAt: zod.z.number(),
48310
48891
  lastUsedAt: zod.z.number().optional()
48311
48892
  });
48312
- var CreateApiKeyInputSchema = zod.z.object({
48313
- label: zod.z.string(),
48314
- isAdmin: zod.z.boolean().default(false),
48315
- allowedProviders: zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")]).optional(),
48316
- allowedDevices: zod.z.record(zod.z.string(), zod.z.union([zod.z.array(zod.z.string()), zod.z.literal("*")])).optional()
48317
- });
48318
- var CreateApiKeyResultSchema = zod.z.object({
48319
- token: zod.z.string(),
48320
- record: ApiKeySummarySchema
48321
- });
48322
48893
  var ScopedTokenSummarySchema = zod.z.object({
48323
48894
  id: zod.z.string(),
48324
48895
  userId: zod.z.string(),
@@ -48430,20 +49001,11 @@ var userManagementCapability = {
48430
49001
  access: "view"
48431
49002
  }),
48432
49003
  listApiKeys: require_sleep.method(zod.z.void(), zod.z.array(ApiKeySummarySchema), { auth: "admin" }),
48433
- createApiKey: require_sleep.method(CreateApiKeyInputSchema, CreateApiKeyResultSchema, {
48434
- kind: "mutation",
48435
- auth: "admin",
48436
- access: "create"
48437
- }),
48438
49004
  revokeApiKey: require_sleep.method(zod.z.object({ id: zod.z.string() }), zod.z.object({ success: zod.z.literal(true) }), {
48439
49005
  kind: "mutation",
48440
49006
  auth: "admin",
48441
49007
  access: "delete"
48442
49008
  }),
48443
- validateApiKey: require_sleep.method(zod.z.object({ token: zod.z.string() }), ApiKeySummarySchema.nullable(), {
48444
- kind: "mutation",
48445
- access: "view"
48446
- }),
48447
49009
  createScopedToken: require_sleep.method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
48448
49010
  kind: "mutation",
48449
49011
  auth: "admin",
@@ -48533,20 +49095,6 @@ var userManagementCapability = {
48533
49095
  userId: zod.z.string(),
48534
49096
  issuer: zod.z.string()
48535
49097
  }).nullable(), { auth: "admin" }),
48536
- /**
48537
- * Link `(provider, subject)` to `userId`. Idempotent for the same user;
48538
- * REFUSES (throws) an identity already linked to another user, and a
48539
- * user that does not exist.
48540
- */
48541
- linkExternalIdentity: require_sleep.method(ExternalIdentityKeySchema.extend({
48542
- userId: zod.z.string(),
48543
- issuer: zod.z.string().min(1),
48544
- label: zod.z.string().optional()
48545
- }), zod.z.object({ success: zod.z.literal(true) }), {
48546
- kind: "mutation",
48547
- auth: "admin",
48548
- access: "create"
48549
- }),
48550
49098
  /** Remove one link of `userId`. `success: false` when it was not linked to that user. */
48551
49099
  unlinkExternalIdentity: require_sleep.method(ExternalIdentityKeySchema.extend({ userId: zod.z.string() }), zod.z.object({ success: zod.z.boolean() }), {
48552
49100
  kind: "mutation",
@@ -49290,6 +49838,535 @@ var zoneRulesCapability = {
49290
49838
  durability: "restored"
49291
49839
  };
49292
49840
  //#endregion
49841
+ //#region src/capabilities/training-provider.cap.ts
49842
+ /**
49843
+ * `training-provider` — ONE cloud that can run the CamStack trainer.
49844
+ *
49845
+ * A thin, mockable translation layer: it knows how to run a container with a
49846
+ * GPU, move a dataset in, read the job's stdout and hand artefacts back. It
49847
+ * knows nothing about datasets, splits, floors, cost policy or Model Studio —
49848
+ * those are the `training` orchestrator's (D805). Every rule written there
49849
+ * once is what makes a second provider (RunPod, a local NVIDIA node) a new
49850
+ * manifest entry and nothing else.
49851
+ *
49852
+ * Collection, routed by the `addonId` in every single-row input (the `llm` /
49853
+ * `notification-output` posture); `describe` concat-fans across providers.
49854
+ * Every method is `admin`: these spend money.
49855
+ *
49856
+ * Every cloud object a provider creates is tagged with the orchestrator's
49857
+ * `jobKey`, so a retried submit finds the job it already started instead of
49858
+ * starting a second GPU, and `listJobs` can find orphans.
49859
+ *
49860
+ * Bytes never ride a cap field: the dataset arrives as a `ctx.peerBytes`
49861
+ * ticket the producer (pipeline-analytics) minted, and artefacts leave as a
49862
+ * ticket the provider mints (D613).
49863
+ */
49864
+ var TrainingGpuOptionSchema = zod.z.object({
49865
+ id: zod.z.string(),
49866
+ label: zod.z.string(),
49867
+ /** List price, USD per GPU-hour, before any region multiplier. */
49868
+ usdPerHour: zod.z.number().nonnegative(),
49869
+ vramGb: zod.z.number().nonnegative()
49870
+ });
49871
+ var TrainingRegionOptionSchema = zod.z.object({
49872
+ /** `''` = any region (the provider's choice). */
49873
+ id: zod.z.string(),
49874
+ label: zod.z.string(),
49875
+ priceMultiplier: zod.z.number().positive()
49876
+ });
49877
+ /**
49878
+ * The provider's per-account settings, as the orchestrator reads them. They
49879
+ * live in the PROVIDER addon's settings (operator decision 2026-10-08: they
49880
+ * depend on the user's account), never hard-coded in the orchestrator.
49881
+ */
49882
+ var TrainingProviderDefaultsSchema = zod.z.object({
49883
+ gpuType: zod.z.string(),
49884
+ region: zod.z.string(),
49885
+ costCapUsd: zod.z.number().nonnegative(),
49886
+ maxRuntimeSec: zod.z.number().int().positive(),
49887
+ /** Hours a FAILED job's cloud dataset is kept for debugging; 0 = delete at once. */
49888
+ failedDatasetGraceHours: zod.z.number().nonnegative()
49889
+ });
49890
+ var TrainingProviderDescriptorSchema = zod.z.object({
49891
+ addonId: zod.z.string(),
49892
+ /** `modal`, `runpod`, `fake`, … */
49893
+ kind: zod.z.string(),
49894
+ label: zod.z.string(),
49895
+ gpuTypes: zod.z.array(TrainingGpuOptionSchema).readonly(),
49896
+ regions: zod.z.array(TrainingRegionOptionSchema).readonly(),
49897
+ maxDatasetBytes: zod.z.number().int().positive(),
49898
+ maxRuntimeSec: zod.z.number().int().positive(),
49899
+ freeTierNote: zod.z.string().optional(),
49900
+ /** Where the data goes, in one sentence the confirm dialog repeats. */
49901
+ dataResidencyNote: zod.z.string(),
49902
+ /** Credentials are present — never the values. */
49903
+ configured: zod.z.boolean(),
49904
+ defaults: TrainingProviderDefaultsSchema
49905
+ });
49906
+ var TrainingCredentialCheckSchema = zod.z.object({
49907
+ ok: zod.z.boolean(),
49908
+ /** Workspace / account name, when the provider says. */
49909
+ account: zod.z.string().optional(),
49910
+ reason: zod.z.enum([
49911
+ "missing",
49912
+ "invalid",
49913
+ "forbidden",
49914
+ "network",
49915
+ "quota"
49916
+ ]).optional(),
49917
+ detail: zod.z.string().optional()
49918
+ });
49919
+ var ProviderJobStateSchema = zod.z.enum([
49920
+ "pending",
49921
+ "starting",
49922
+ "running",
49923
+ "succeeded",
49924
+ "failed",
49925
+ "cancelled",
49926
+ "lost"
49927
+ ]);
49928
+ var ProviderJobStatusSchema = zod.z.object({
49929
+ jobKey: zod.z.string(),
49930
+ providerJobId: zod.z.string().optional(),
49931
+ state: ProviderJobStateSchema,
49932
+ startedAt: zod.z.number().optional(),
49933
+ endedAt: zod.z.number().optional(),
49934
+ exitCode: zod.z.number().int().optional(),
49935
+ failureReason: zod.z.string().optional(),
49936
+ gpuType: zod.z.string(),
49937
+ region: zod.z.string().optional(),
49938
+ billedSeconds: zod.z.number().nonnegative(),
49939
+ costUsd: zod.z.number().nonnegative(),
49940
+ /** True when `costUsd` is runtime × list price, not a billing answer. */
49941
+ costIsEstimate: zod.z.boolean(),
49942
+ lastFetchedAt: zod.z.number()
49943
+ });
49944
+ /**
49945
+ * The trainer the job runs, by SOURCE revision: the provider turns it into an
49946
+ * image its own way (Modal builds the published Dockerfile at that revision;
49947
+ * a registry-pull provider maps it to a tag). Recorded on the job and echoed
49948
+ * in `result.json`.
49949
+ */
49950
+ var TrainerSourceRefSchema = zod.z.object({
49951
+ /** Hugging Face repo id, e.g. `camstack/camstack-trainer`. */
49952
+ repo: zod.z.string().min(1),
49953
+ /** A commit sha (never a branch) — the job must be reproducible. */
49954
+ revision: zod.z.string().regex(/^[0-9a-f]{7,64}$/)
49955
+ });
49956
+ var JobRef = {
49957
+ addonId: zod.z.string(),
49958
+ jobKey: zod.z.string().uuid()
49959
+ };
49960
+ var TrainingLogLineSchema = zod.z.object({
49961
+ ts: zod.z.number(),
49962
+ text: zod.z.string()
49963
+ });
49964
+ var trainingProviderCapability = {
49965
+ name: "training-provider",
49966
+ scope: "system",
49967
+ mode: "collection",
49968
+ internal: true,
49969
+ methods: {
49970
+ /** Every provider's offer and settings. Concat-fans across providers. */
49971
+ describe: require_sleep.method(zod.z.object({}), zod.z.array(TrainingProviderDescriptorSchema).readonly(), { auth: "admin" }),
49972
+ /** Call the provider with the stored credentials. Never returns them. */
49973
+ validateCredentials: require_sleep.method(zod.z.object({ addonId: zod.z.string() }), TrainingCredentialCheckSchema, {
49974
+ kind: "mutation",
49975
+ auth: "admin",
49976
+ timeoutMs: 3e4
49977
+ }),
49978
+ /** USD range for a run of `gpuSeconds` on `gpuType` in `region`. */
49979
+ estimateJob: require_sleep.method(zod.z.object({
49980
+ addonId: zod.z.string(),
49981
+ gpuType: zod.z.string(),
49982
+ region: zod.z.string(),
49983
+ datasetBytes: zod.z.number().int().nonnegative(),
49984
+ gpuSecondsLow: zod.z.number().nonnegative(),
49985
+ gpuSecondsHigh: zod.z.number().nonnegative()
49986
+ }), zod.z.object({
49987
+ usdLow: zod.z.number().nonnegative(),
49988
+ usdHigh: zod.z.number().nonnegative(),
49989
+ notes: zod.z.array(zod.z.string()).readonly()
49990
+ }), { auth: "admin" }),
49991
+ /**
49992
+ * Take the dataset archive behind `ticket` (minted by pipeline-analytics,
49993
+ * same host) and land it as the job's dataset in the cloud, streamed —
49994
+ * nothing is staged on the hub's disk. Idempotent per `jobKey`: a second
49995
+ * call replaces a partial upload. Answers what actually landed.
49996
+ */
49997
+ uploadDataset: require_sleep.method(zod.z.object({
49998
+ ...JobRef,
49999
+ ticket: require_sleep.PeerBytesTicketSchema
50000
+ }), zod.z.object({
50001
+ bytes: zod.z.number().int().nonnegative(),
50002
+ sha256: zod.z.string()
50003
+ }), {
50004
+ kind: "mutation",
50005
+ auth: "admin",
50006
+ timeoutMs: 120 * 6e4
50007
+ }),
50008
+ /**
50009
+ * Start the trainer on a GPU. Looks the job up by `jobKey` first, so a
50010
+ * retried submit never starts a second GPU. `jobSpecJson` is written next
50011
+ * to the dataset as `job.json`; `maxRuntimeSec` is enforced by the
50012
+ * provider (a hard timeout), not by the hub.
50013
+ */
50014
+ submitJob: require_sleep.method(zod.z.object({
50015
+ ...JobRef,
50016
+ trainer: TrainerSourceRefSchema,
50017
+ jobSpecJson: zod.z.string().min(2).max(64e3),
50018
+ gpuType: zod.z.string(),
50019
+ region: zod.z.string(),
50020
+ maxRuntimeSec: zod.z.number().int().positive()
50021
+ }), ProviderJobStatusSchema, {
50022
+ kind: "mutation",
50023
+ auth: "admin",
50024
+ timeoutMs: 30 * 6e4
50025
+ }),
50026
+ getJob: require_sleep.method(zod.z.object(JobRef), ProviderJobStatusSchema, {
50027
+ auth: "admin",
50028
+ timeoutMs: 6e4
50029
+ }),
50030
+ /** Stdout/stderr since `cursor` (opaque), oldest first, at most `max` lines. */
50031
+ listJobEvents: require_sleep.method(zod.z.object({
50032
+ ...JobRef,
50033
+ cursor: zod.z.string().optional(),
50034
+ max: zod.z.number().int().min(1).max(500)
50035
+ }), zod.z.object({
50036
+ lines: zod.z.array(TrainingLogLineSchema).readonly(),
50037
+ cursor: zod.z.string()
50038
+ }), {
50039
+ auth: "admin",
50040
+ timeoutMs: 6e4
50041
+ }),
50042
+ /** Stop the job. Idempotent: an unknown or finished job is a no-op. */
50043
+ cancelJob: require_sleep.method(zod.z.object(JobRef), zod.z.object({ ok: zod.z.literal(true) }), {
50044
+ kind: "mutation",
50045
+ auth: "admin",
50046
+ timeoutMs: 6e4
50047
+ }),
50048
+ /** The job's `result.json`, as text (small, JSON). `found: false` before it exists. */
50049
+ readResult: require_sleep.method(zod.z.object(JobRef), zod.z.object({
50050
+ found: zod.z.boolean(),
50051
+ text: zod.z.string().optional()
50052
+ }), {
50053
+ kind: "mutation",
50054
+ auth: "admin",
50055
+ timeoutMs: 5 * 6e4
50056
+ }),
50057
+ /**
50058
+ * Offer one output file of the job (`bundle.tar`) to the caller as a
50059
+ * one-shot `ctx.peerBytes` ticket, streamed from the cloud — the provider
50060
+ * stages nothing on disk. The caller dials it at once.
50061
+ */
50062
+ offerArtifact: require_sleep.method(zod.z.object({
50063
+ ...JobRef,
50064
+ path: zod.z.enum(["bundle.tar"])
50065
+ }), zod.z.object({ ticket: require_sleep.PeerBytesTicketSchema }), {
50066
+ kind: "mutation",
50067
+ auth: "admin",
50068
+ timeoutMs: 5 * 6e4
50069
+ }),
50070
+ /** Delete every cloud object tagged with `jobKey` (the dataset first). Idempotent. */
50071
+ cleanupJob: require_sleep.method(zod.z.object(JobRef), zod.z.object({ deleted: zod.z.array(zod.z.string()).readonly() }), {
50072
+ kind: "mutation",
50073
+ auth: "admin",
50074
+ timeoutMs: 5 * 6e4
50075
+ }),
50076
+ /** Every job the provider can still see — the orphan sweep diffs it against our records. */
50077
+ listJobs: require_sleep.method(zod.z.object({ addonId: zod.z.string() }), zod.z.array(ProviderJobStatusSchema).readonly(), {
50078
+ auth: "admin",
50079
+ timeoutMs: 2 * 6e4
50080
+ })
50081
+ }
50082
+ };
50083
+ //#endregion
50084
+ //#region src/capabilities/training.cap.ts
50085
+ /**
50086
+ * `training` — the cloud-training orchestrator (D805). Hub-only singleton,
50087
+ * provided by `addon-training`.
50088
+ *
50089
+ * It owns what every provider must agree on, written once:
50090
+ *
50091
+ * - **Dataset versions.** Taken over from pipeline-analytics (D796): the rows
50092
+ * live here (D808); pipeline-analytics still CUTS a version (it owns the corpus and
50093
+ * the export plan) and reaches this store through the five row methods
50094
+ * below, so the Retrain page and the export did not change.
50095
+ * - **Jobs.** A persisted state machine, a reconcile loop against the
50096
+ * provider, a cost guard, a daily orphan sweep and the retention rules.
50097
+ * - **The return flow.** Verified artefacts → Model Studio
50098
+ * (`custom-model-registry.importModelBundle`) → canary on cameras →
50099
+ * rollback. Nothing is ever registered automatically.
50100
+ *
50101
+ * Every method is `admin`.
50102
+ */
50103
+ /** A version WITH its frame list — what the export and a job read. */
50104
+ var TrainingDatasetVersionRowSchema = RetrainDatasetVersionSchema.omit({ frameCount: true }).extend({ frameIds: zod.z.array(zod.z.string()).max(2e4).readonly() });
50105
+ /** A base model a detector job can fine-tune, and the baseline it is judged against. */
50106
+ var TrainingBaseModelSchema = zod.z.object({
50107
+ modelId: zod.z.string(),
50108
+ label: zod.z.string(),
50109
+ weights: zod.z.string(),
50110
+ imgsz: zod.z.number().int(),
50111
+ baselineOnnxUrl: zod.z.string(),
50112
+ baselineFloors: zod.z.record(zod.z.string(), zod.z.number()),
50113
+ /** The base the fleet runs most — the UI's default. */
50114
+ recommended: zod.z.boolean()
50115
+ });
50116
+ var TrainingPresetSchema = zod.z.enum([
50117
+ "quick",
50118
+ "standard",
50119
+ "thorough"
50120
+ ]);
50121
+ var TrainingJobRequestSchema = zod.z.object({
50122
+ datasetVersionId: zod.z.string().min(1),
50123
+ /** The `training-provider` addon that runs it. */
50124
+ addonId: zod.z.string().min(1),
50125
+ gpuType: zod.z.string().min(1),
50126
+ region: zod.z.string(),
50127
+ baseModelId: zod.z.string().min(1),
50128
+ preset: TrainingPresetSchema,
50129
+ /** Freeze the backbone's first N layers; `null` = the preset's choice. */
50130
+ freeze: zod.z.number().int().nonnegative().nullable(),
50131
+ /** Cameras held out whole for evaluation; `null` = the orchestrator's default. */
50132
+ holdoutCameras: zod.z.array(zod.z.number().int()).nullable()
50133
+ });
50134
+ var TrainingSplitPlanSchema = zod.z.object({
50135
+ holdoutCameras: zod.z.array(zod.z.number().int()).readonly(),
50136
+ /** Used when no camera is held out: the last N days of every camera. */
50137
+ holdoutLastDays: zod.z.number().int().nonnegative(),
50138
+ /** Holdout subjects per class (camera holdout only; `null` = known only after the split). */
50139
+ holdoutSupport: zod.z.record(zod.z.string(), zod.z.number().int()).nullable(),
50140
+ trainSubjects: zod.z.number().int()
50141
+ });
50142
+ var TrainingRefusalReasonSchema = zod.z.enum([
50143
+ "unknown-dataset",
50144
+ "unknown-provider",
50145
+ "provider-not-configured",
50146
+ "unknown-base-model",
50147
+ "unknown-gpu",
50148
+ "dataset-too-large",
50149
+ "no-training-subjects",
50150
+ "job-already-running"
50151
+ ]);
50152
+ var TrainingJobPlanSchema = zod.z.object({
50153
+ refusal: zod.z.object({
50154
+ reason: TrainingRefusalReasonSchema,
50155
+ detail: zod.z.string()
50156
+ }).nullable(),
50157
+ warnings: zod.z.array(zod.z.string()).readonly(),
50158
+ split: TrainingSplitPlanSchema.nullable(),
50159
+ estimate: zod.z.object({
50160
+ datasetBytes: zod.z.number().int(),
50161
+ uploadMinutesAt20Mbps: zod.z.number(),
50162
+ gpuSecondsLow: zod.z.number(),
50163
+ gpuSecondsHigh: zod.z.number(),
50164
+ usdLow: zod.z.number(),
50165
+ usdHigh: zod.z.number(),
50166
+ notes: zod.z.array(zod.z.string()).readonly()
50167
+ }).nullable(),
50168
+ /** Pre-filled from the provider's settings; the operator may lower or raise them. */
50169
+ defaults: zod.z.object({
50170
+ maxCostUsd: zod.z.number(),
50171
+ maxRuntimeSec: zod.z.number().int()
50172
+ }).nullable(),
50173
+ /** The sentence the confirm dialog repeats: where the frames go and when they are deleted. */
50174
+ dataNotice: zod.z.string()
50175
+ });
50176
+ /**
50177
+ * Orchestrator-owned states, persisted. `uploading` covers exporting the
50178
+ * archive (it is streamed, never staged). Terminal: `failed`, `cancelled`,
50179
+ * `lost`, `expired`, `discarded`. `registered` and `canary` are where a
50180
+ * result lives after the operator acted on it.
50181
+ */
50182
+ var TrainingJobStateSchema = zod.z.enum([
50183
+ "uploading",
50184
+ "submitted",
50185
+ "starting",
50186
+ "running",
50187
+ "collecting",
50188
+ "ready",
50189
+ "registered",
50190
+ "canary",
50191
+ "failed",
50192
+ "cancelling",
50193
+ "cancelled",
50194
+ "lost",
50195
+ "expired",
50196
+ "discarded"
50197
+ ]);
50198
+ var TrainingFailureReasonSchema = zod.z.enum([
50199
+ "cost-cap",
50200
+ "runtime-cap",
50201
+ "upload-failed",
50202
+ "submit-failed",
50203
+ "trainer-failed",
50204
+ "result-invalid",
50205
+ "checksum-mismatch",
50206
+ "fetch-failed",
50207
+ "provider-error",
50208
+ "hub-restart-during-upload"
50209
+ ]);
50210
+ var TrainingProgressPointSchema = zod.z.object({
50211
+ epoch: zod.z.number().int(),
50212
+ map50: zod.z.number().nullable(),
50213
+ map50_95: zod.z.number().nullable()
50214
+ });
50215
+ var TrainingCanarySchema = zod.z.object({
50216
+ deviceIds: zod.z.array(zod.z.number().int()).readonly(),
50217
+ since: zod.z.number(),
50218
+ /** Every override the canary replaced, exactly, so rollback restores it. */
50219
+ previous: zod.z.array(zod.z.object({
50220
+ deviceId: zod.z.number().int(),
50221
+ nodeId: zod.z.string(),
50222
+ deviceKey: zod.z.string(),
50223
+ patch: zod.z.object({
50224
+ modelId: zod.z.string().optional(),
50225
+ settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly().optional()
50226
+ }).nullable()
50227
+ })).readonly()
50228
+ });
50229
+ var TrainingJobSchema = zod.z.object({
50230
+ id: zod.z.string(),
50231
+ idempotencyKey: zod.z.string(),
50232
+ name: zod.z.string(),
50233
+ createdAt: zod.z.number(),
50234
+ updatedAt: zod.z.number(),
50235
+ state: TrainingJobStateSchema,
50236
+ stage: TrainingStageSchema.nullable(),
50237
+ failure: zod.z.object({
50238
+ reason: TrainingFailureReasonSchema,
50239
+ stage: zod.z.string().nullable(),
50240
+ detail: zod.z.string()
50241
+ }).nullable(),
50242
+ request: TrainingJobRequestSchema,
50243
+ maxCostUsd: zod.z.number().nonnegative(),
50244
+ maxRuntimeSec: zod.z.number().int().positive(),
50245
+ trainer: TrainerSourceRefSchema,
50246
+ datasetLayout: RetrainExportLayoutSchema,
50247
+ dataset: zod.z.object({
50248
+ bytes: zod.z.number().int(),
50249
+ sha256: zod.z.string(),
50250
+ uploadedAt: zod.z.number()
50251
+ }).nullable(),
50252
+ split: TrainingSplitPlanSchema,
50253
+ provider: zod.z.object({
50254
+ state: ProviderJobStateSchema.nullable(),
50255
+ providerJobId: zod.z.string().nullable(),
50256
+ startedAt: zod.z.number().nullable(),
50257
+ endedAt: zod.z.number().nullable(),
50258
+ billedSeconds: zod.z.number(),
50259
+ costUsd: zod.z.number(),
50260
+ costIsEstimate: zod.z.boolean(),
50261
+ lastPolledAt: zod.z.number().nullable()
50262
+ }),
50263
+ progress: zod.z.object({
50264
+ epoch: zod.z.number().int().nullable(),
50265
+ epochs: zod.z.number().int().nullable(),
50266
+ etaSec: zod.z.number().nullable(),
50267
+ series: zod.z.array(TrainingProgressPointSchema).readonly()
50268
+ }),
50269
+ /** The last lines of the job's output (≤ 200), newest last. Never frame paths. */
50270
+ logTail: zod.z.array(zod.z.string()).readonly(),
50271
+ logCursor: zod.z.string().nullable(),
50272
+ artifacts: zod.z.object({
50273
+ bundleBytes: zod.z.number().int(),
50274
+ bundleSha256: zod.z.string(),
50275
+ fetchedAt: zod.z.number(),
50276
+ /** When the staged artefacts are deleted from the hub. */
50277
+ expiresAt: zod.z.number()
50278
+ }).nullable(),
50279
+ /** When the provider-side copy of the frames was deleted; null while it exists. */
50280
+ cloudDatasetDeletedAt: zod.z.number().nullable(),
50281
+ /** A failed job's dataset is kept until then (the provider's grace), then deleted. */
50282
+ cloudCleanupDueAt: zod.z.number().nullable(),
50283
+ /** Model ids registered from this job (base, and int8 when kept). */
50284
+ registeredModelIds: zod.z.array(zod.z.string()).readonly(),
50285
+ canary: TrainingCanarySchema.nullable()
50286
+ });
50287
+ var IdInput = zod.z.object({ id: zod.z.string().min(1) });
50288
+ var trainingCapability = {
50289
+ name: "training",
50290
+ scope: "system",
50291
+ mode: "singleton",
50292
+ mount: { kind: "hub-only" },
50293
+ methods: {
50294
+ /** Store a version once. `stored: false` = that id already exists (immutable). */
50295
+ putDatasetVersion: require_sleep.method(TrainingDatasetVersionRowSchema, zod.z.object({ stored: zod.z.boolean() }), {
50296
+ kind: "mutation",
50297
+ auth: "admin"
50298
+ }),
50299
+ getDatasetVersion: require_sleep.method(IdInput, TrainingDatasetVersionRowSchema.nullable(), { auth: "admin" }),
50300
+ /** Every version without its frame list, newest first. */
50301
+ listDatasetVersions: require_sleep.method(zod.z.object({}), zod.z.array(RetrainDatasetVersionSchema).readonly(), { auth: "admin" }),
50302
+ findDatasetVersionIdByName: require_sleep.method(zod.z.object({ name: zod.z.string() }), zod.z.object({ id: zod.z.string().nullable() }), { auth: "admin" }),
50303
+ removeDatasetVersion: require_sleep.method(IdInput, zod.z.object({ removed: zod.z.boolean() }), {
50304
+ kind: "mutation",
50305
+ auth: "admin"
50306
+ }),
50307
+ listBaseModels: require_sleep.method(zod.z.object({}), zod.z.array(TrainingBaseModelSchema).readonly(), { auth: "admin" }),
50308
+ /** Split, estimate, defaults and any named refusal — nothing is started. */
50309
+ planJob: require_sleep.method(TrainingJobRequestSchema, TrainingJobPlanSchema, {
50310
+ auth: "admin",
50311
+ timeoutMs: 6e4
50312
+ }),
50313
+ /**
50314
+ * Start a job. The same `idempotencyKey` returns the job it already
50315
+ * started. Answers at once (`uploading`); the upload and the submit run in
50316
+ * the background and the job record says how far they got.
50317
+ */
50318
+ startJob: require_sleep.method(TrainingJobRequestSchema.extend({
50319
+ name: zod.z.string().min(1).max(120),
50320
+ maxCostUsd: zod.z.number().positive(),
50321
+ maxRuntimeSec: zod.z.number().int().positive(),
50322
+ idempotencyKey: zod.z.string().min(8).max(80)
50323
+ }), zod.z.discriminatedUnion("kind", [zod.z.object({
50324
+ kind: zod.z.literal("started"),
50325
+ job: TrainingJobSchema
50326
+ }), zod.z.object({
50327
+ kind: zod.z.literal("refused"),
50328
+ reason: TrainingRefusalReasonSchema,
50329
+ detail: zod.z.string()
50330
+ })]), {
50331
+ kind: "mutation",
50332
+ auth: "admin",
50333
+ timeoutMs: 12e4
50334
+ }),
50335
+ listJobs: require_sleep.method(zod.z.object({}), zod.z.array(TrainingJobSchema).readonly(), { auth: "admin" }),
50336
+ getJob: require_sleep.method(IdInput, TrainingJobSchema.nullable(), { auth: "admin" }),
50337
+ cancelJob: require_sleep.method(IdInput, TrainingJobSchema, {
50338
+ kind: "mutation",
50339
+ auth: "admin",
50340
+ timeoutMs: 12e4
50341
+ }),
50342
+ /** The verified `result.json` of a job in `ready` or later; null before. */
50343
+ getJobResult: require_sleep.method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }),
50344
+ /** Hand the verified bundle to Model Studio; optionally canary right after. */
50345
+ registerResult: require_sleep.method(IdInput.extend({ canaryDeviceIds: zod.z.array(zod.z.number().int()).readonly() }), TrainingJobSchema, {
50346
+ kind: "mutation",
50347
+ auth: "admin",
50348
+ timeoutMs: 30 * 6e4
50349
+ }),
50350
+ /** Pin the registered model on these cameras, remembering what it replaced. */
50351
+ canaryResult: require_sleep.method(IdInput.extend({ deviceIds: zod.z.array(zod.z.number().int()).min(1).readonly() }), TrainingJobSchema, {
50352
+ kind: "mutation",
50353
+ auth: "admin",
50354
+ timeoutMs: 12e4
50355
+ }),
50356
+ /** Put every canary camera back exactly as it was. */
50357
+ rollbackCanary: require_sleep.method(IdInput, TrainingJobSchema, {
50358
+ kind: "mutation",
50359
+ auth: "admin",
50360
+ timeoutMs: 12e4
50361
+ }),
50362
+ /** Delete the staged artefacts of an unregistered result. */
50363
+ discardResult: require_sleep.method(IdInput, TrainingJobSchema, {
50364
+ kind: "mutation",
50365
+ auth: "admin"
50366
+ })
50367
+ }
50368
+ };
50369
+ //#endregion
49293
50370
  //#region src/capabilities/index.ts
49294
50371
  /**
49295
50372
  * Capability definitions — Zod-schema-first, single source of truth.
@@ -53462,6 +54539,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
53462
54539
  addonId: null,
53463
54540
  access: "create"
53464
54541
  },
54542
+ "backup.checkBackupKey": {
54543
+ capName: "backup",
54544
+ capScope: "system",
54545
+ addonId: null,
54546
+ access: "create"
54547
+ },
53465
54548
  "backup.delete": {
53466
54549
  capName: "backup",
53467
54550
  capScope: "system",
@@ -53474,6 +54557,18 @@ var METHOD_ACCESS_MAP = Object.freeze({
53474
54557
  addonId: null,
53475
54558
  access: "delete"
53476
54559
  },
54560
+ "backup.disableEncryption": {
54561
+ capName: "backup",
54562
+ capScope: "system",
54563
+ addonId: null,
54564
+ access: "create"
54565
+ },
54566
+ "backup.getEncryption": {
54567
+ capName: "backup",
54568
+ capScope: "system",
54569
+ addonId: null,
54570
+ access: "view"
54571
+ },
53477
54572
  "backup.getEntries": {
53478
54573
  capName: "backup",
53479
54574
  capScope: "system",
@@ -53528,6 +54623,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
53528
54623
  addonId: null,
53529
54624
  access: "create"
53530
54625
  },
54626
+ "backup.setupEncryption": {
54627
+ capName: "backup",
54628
+ capScope: "system",
54629
+ addonId: null,
54630
+ access: "create"
54631
+ },
53531
54632
  "backup.trigger": {
53532
54633
  capName: "backup",
53533
54634
  capScope: "system",
@@ -54080,6 +55181,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
54080
55181
  addonId: null,
54081
55182
  access: "create"
54082
55183
  },
55184
+ "customModelRegistry.importModelBundle": {
55185
+ capName: "custom-model-registry",
55186
+ capScope: "system",
55187
+ addonId: null,
55188
+ access: "create"
55189
+ },
54083
55190
  "customModelRegistry.listModels": {
54084
55191
  capName: "custom-model-registry",
54085
55192
  capScope: "system",
@@ -55520,6 +56627,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
55520
56627
  addonId: null,
55521
56628
  access: "view"
55522
56629
  },
56630
+ "keychainAdmin.acknowledgeReset": {
56631
+ capName: "keychain-admin",
56632
+ capScope: "system",
56633
+ addonId: null,
56634
+ access: "create"
56635
+ },
55523
56636
  "keychainAdmin.deleteOrphans": {
55524
56637
  capName: "keychain-admin",
55525
56638
  capScope: "system",
@@ -55556,6 +56669,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
55556
56669
  addonId: null,
55557
56670
  access: "delete"
55558
56671
  },
56672
+ "keychainAdmin.resetReport": {
56673
+ capName: "keychain-admin",
56674
+ capScope: "system",
56675
+ addonId: null,
56676
+ access: "delete"
56677
+ },
55559
56678
  "keychainAdmin.reveal": {
55560
56679
  capName: "keychain-admin",
55561
56680
  capScope: "system",
@@ -57302,6 +58421,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
57302
58421
  addonId: null,
57303
58422
  access: "view"
57304
58423
  },
58424
+ "pipelineAnalytics.offerRetrainArchive": {
58425
+ capName: "pipeline-analytics",
58426
+ capScope: "device",
58427
+ addonId: null,
58428
+ access: "create"
58429
+ },
57305
58430
  "pipelineAnalytics.ownersWithMedia": {
57306
58431
  capName: "pipeline-analytics",
57307
58432
  capScope: "device",
@@ -59840,6 +60965,174 @@ var METHOD_ACCESS_MAP = Object.freeze({
59840
60965
  addonId: null,
59841
60966
  access: "view"
59842
60967
  },
60968
+ "training.canaryResult": {
60969
+ capName: "training",
60970
+ capScope: "system",
60971
+ addonId: null,
60972
+ access: "create"
60973
+ },
60974
+ "training.cancelJob": {
60975
+ capName: "training",
60976
+ capScope: "system",
60977
+ addonId: null,
60978
+ access: "create"
60979
+ },
60980
+ "training.discardResult": {
60981
+ capName: "training",
60982
+ capScope: "system",
60983
+ addonId: null,
60984
+ access: "create"
60985
+ },
60986
+ "training.findDatasetVersionIdByName": {
60987
+ capName: "training",
60988
+ capScope: "system",
60989
+ addonId: null,
60990
+ access: "view"
60991
+ },
60992
+ "training.getDatasetVersion": {
60993
+ capName: "training",
60994
+ capScope: "system",
60995
+ addonId: null,
60996
+ access: "view"
60997
+ },
60998
+ "training.getJob": {
60999
+ capName: "training",
61000
+ capScope: "system",
61001
+ addonId: null,
61002
+ access: "view"
61003
+ },
61004
+ "training.getJobResult": {
61005
+ capName: "training",
61006
+ capScope: "system",
61007
+ addonId: null,
61008
+ access: "view"
61009
+ },
61010
+ "training.listBaseModels": {
61011
+ capName: "training",
61012
+ capScope: "system",
61013
+ addonId: null,
61014
+ access: "view"
61015
+ },
61016
+ "training.listDatasetVersions": {
61017
+ capName: "training",
61018
+ capScope: "system",
61019
+ addonId: null,
61020
+ access: "view"
61021
+ },
61022
+ "training.listJobs": {
61023
+ capName: "training",
61024
+ capScope: "system",
61025
+ addonId: null,
61026
+ access: "view"
61027
+ },
61028
+ "training.planJob": {
61029
+ capName: "training",
61030
+ capScope: "system",
61031
+ addonId: null,
61032
+ access: "view"
61033
+ },
61034
+ "training.putDatasetVersion": {
61035
+ capName: "training",
61036
+ capScope: "system",
61037
+ addonId: null,
61038
+ access: "create"
61039
+ },
61040
+ "training.registerResult": {
61041
+ capName: "training",
61042
+ capScope: "system",
61043
+ addonId: null,
61044
+ access: "create"
61045
+ },
61046
+ "training.removeDatasetVersion": {
61047
+ capName: "training",
61048
+ capScope: "system",
61049
+ addonId: null,
61050
+ access: "delete"
61051
+ },
61052
+ "training.rollbackCanary": {
61053
+ capName: "training",
61054
+ capScope: "system",
61055
+ addonId: null,
61056
+ access: "create"
61057
+ },
61058
+ "training.startJob": {
61059
+ capName: "training",
61060
+ capScope: "system",
61061
+ addonId: null,
61062
+ access: "create"
61063
+ },
61064
+ "trainingProvider.cancelJob": {
61065
+ capName: "training-provider",
61066
+ capScope: "system",
61067
+ addonId: null,
61068
+ access: "create"
61069
+ },
61070
+ "trainingProvider.cleanupJob": {
61071
+ capName: "training-provider",
61072
+ capScope: "system",
61073
+ addonId: null,
61074
+ access: "create"
61075
+ },
61076
+ "trainingProvider.describe": {
61077
+ capName: "training-provider",
61078
+ capScope: "system",
61079
+ addonId: null,
61080
+ access: "view"
61081
+ },
61082
+ "trainingProvider.estimateJob": {
61083
+ capName: "training-provider",
61084
+ capScope: "system",
61085
+ addonId: null,
61086
+ access: "view"
61087
+ },
61088
+ "trainingProvider.getJob": {
61089
+ capName: "training-provider",
61090
+ capScope: "system",
61091
+ addonId: null,
61092
+ access: "view"
61093
+ },
61094
+ "trainingProvider.listJobEvents": {
61095
+ capName: "training-provider",
61096
+ capScope: "system",
61097
+ addonId: null,
61098
+ access: "view"
61099
+ },
61100
+ "trainingProvider.listJobs": {
61101
+ capName: "training-provider",
61102
+ capScope: "system",
61103
+ addonId: null,
61104
+ access: "view"
61105
+ },
61106
+ "trainingProvider.offerArtifact": {
61107
+ capName: "training-provider",
61108
+ capScope: "system",
61109
+ addonId: null,
61110
+ access: "create"
61111
+ },
61112
+ "trainingProvider.readResult": {
61113
+ capName: "training-provider",
61114
+ capScope: "system",
61115
+ addonId: null,
61116
+ access: "create"
61117
+ },
61118
+ "trainingProvider.submitJob": {
61119
+ capName: "training-provider",
61120
+ capScope: "system",
61121
+ addonId: null,
61122
+ access: "create"
61123
+ },
61124
+ "trainingProvider.uploadDataset": {
61125
+ capName: "training-provider",
61126
+ capScope: "system",
61127
+ addonId: null,
61128
+ access: "create"
61129
+ },
61130
+ "trainingProvider.validateCredentials": {
61131
+ capName: "training-provider",
61132
+ capScope: "system",
61133
+ addonId: null,
61134
+ access: "create"
61135
+ },
59843
61136
  "turnProvider.getTurnServers": {
59844
61137
  capName: "turn-provider",
59845
61138
  capScope: "system",
@@ -59864,12 +61157,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
59864
61157
  addonId: null,
59865
61158
  access: "create"
59866
61159
  },
59867
- "userManagement.createApiKey": {
59868
- capName: "user-management",
59869
- capScope: "system",
59870
- addonId: null,
59871
- access: "create"
59872
- },
59873
61160
  "userManagement.createScopedToken": {
59874
61161
  capName: "user-management",
59875
61162
  capScope: "system",
@@ -59906,12 +61193,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
59906
61193
  addonId: null,
59907
61194
  access: "view"
59908
61195
  },
59909
- "userManagement.linkExternalIdentity": {
59910
- capName: "user-management",
59911
- capScope: "system",
59912
- addonId: null,
59913
- access: "create"
59914
- },
59915
61196
  "userManagement.listApiKeys": {
59916
61197
  capName: "user-management",
59917
61198
  capScope: "system",
@@ -60014,12 +61295,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
60014
61295
  addonId: null,
60015
61296
  access: "create"
60016
61297
  },
60017
- "userManagement.validateApiKey": {
60018
- capName: "user-management",
60019
- capScope: "system",
60020
- addonId: null,
60021
- access: "view"
60022
- },
60023
61298
  "userManagement.validateCredentials": {
60024
61299
  capName: "user-management",
60025
61300
  capScope: "system",
@@ -60600,6 +61875,8 @@ var KNOWN_CAP_NAMES = [
60600
61875
  "temperature-sensor",
60601
61876
  "terminal-session",
60602
61877
  "toast",
61878
+ "training",
61879
+ "training-provider",
60603
61880
  "turn-provider",
60604
61881
  "update",
60605
61882
  "user-management",
@@ -60784,6 +62061,8 @@ var SYSTEM_CAP_NAMES = [
60784
62061
  "system",
60785
62062
  "terminal-session",
60786
62063
  "toast",
62064
+ "training",
62065
+ "training-provider",
60787
62066
  "turn-provider",
60788
62067
  "user-management",
60789
62068
  "user-passkeys",
@@ -64290,6 +65569,8 @@ var CAPABILITY_NAMES = {
64290
65569
  temperatureSensor: "temperature-sensor",
64291
65570
  terminalSession: "terminal-session",
64292
65571
  toast: "toast",
65572
+ training: "training",
65573
+ trainingProvider: "training-provider",
64293
65574
  turnProvider: "turn-provider",
64294
65575
  update: "update",
64295
65576
  userManagement: "user-management",
@@ -64913,6 +66194,14 @@ var CAPABILITY_ROUTER_KEYS = [
64913
66194
  key: "toast",
64914
66195
  name: "toast"
64915
66196
  },
66197
+ {
66198
+ key: "training",
66199
+ name: "training"
66200
+ },
66201
+ {
66202
+ key: "trainingProvider",
66203
+ name: "training-provider"
66204
+ },
64916
66205
  {
64917
66206
  key: "turnProvider",
64918
66207
  name: "turn-provider"
@@ -65139,6 +66428,8 @@ var ALL_CAPABILITY_DEFINITIONS = [
65139
66428
  temperatureSensorCapability,
65140
66429
  terminalSessionCapability,
65141
66430
  toastCapability,
66431
+ trainingCapability,
66432
+ trainingProviderCapability,
65142
66433
  turnProviderCapability,
65143
66434
  updateCapability,
65144
66435
  userManagementCapability,
@@ -67519,6 +68810,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
67519
68810
  form: "single",
67520
68811
  optional: false
67521
68812
  }],
68813
+ "training.canaryResult": [{
68814
+ name: "deviceIds",
68815
+ form: "array",
68816
+ optional: false
68817
+ }],
67522
68818
  "update.getStatus": [{
67523
68819
  name: "deviceId",
67524
68820
  form: "single",
@@ -67923,7 +69219,8 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
67923
69219
  "streamBroker.restartProfile",
67924
69220
  "streamBroker.retractCameraStream",
67925
69221
  "streamBroker.setDeviceAudioMute",
67926
- "streamBroker.unassignProfile"
69222
+ "streamBroker.unassignProfile",
69223
+ "training.canaryResult"
67927
69224
  ];
67928
69225
  //#endregion
67929
69226
  //#region src/generated/provider-kind-map.ts
@@ -68481,6 +69778,10 @@ function createSystemProxy(api) {
68481
69778
  listLocations: (input) => dispatch("backup", "listLocations", "query", input),
68482
69779
  getEntries: (input) => dispatch("backup", "getEntries", "query", input),
68483
69780
  restore: (input) => dispatch("backup", "restore", "mutation", input),
69781
+ getEncryption: (input) => dispatch("backup", "getEncryption", "query", input),
69782
+ setupEncryption: (input) => dispatch("backup", "setupEncryption", "mutation", input),
69783
+ disableEncryption: (input) => dispatch("backup", "disableEncryption", "mutation", input),
69784
+ checkBackupKey: (input) => dispatch("backup", "checkBackupKey", "mutation", input),
68484
69785
  delete: (input) => dispatch("backup", "delete", "mutation", input),
68485
69786
  listArchives: (input) => dispatch("backup", "listArchives", "query", input),
68486
69787
  upsertDestinationPolicy: (input) => dispatch("backup", "upsertDestinationPolicy", "mutation", input),
@@ -68668,7 +69969,9 @@ function createSystemProxy(api) {
68668
69969
  rotateMasterKey: (input) => dispatch("keychainAdmin", "rotateMasterKey", "mutation", input),
68669
69970
  purgeRetiredKeys: (input) => dispatch("keychainAdmin", "purgeRetiredKeys", "mutation", input),
68670
69971
  downloadRecoveryKey: (input) => dispatch("keychainAdmin", "downloadRecoveryKey", "mutation", input),
68671
- resetKeychain: (input) => dispatch("keychainAdmin", "resetKeychain", "mutation", input)
69972
+ resetKeychain: (input) => dispatch("keychainAdmin", "resetKeychain", "mutation", input),
69973
+ resetReport: (input) => dispatch("keychainAdmin", "resetReport", "query", input),
69974
+ acknowledgeReset: (input) => dispatch("keychainAdmin", "acknowledgeReset", "mutation", input)
68672
69975
  },
68673
69976
  llm: {
68674
69977
  generate: (input) => dispatch("llm", "generate", "mutation", input),
@@ -69080,6 +70383,24 @@ function createSystemProxy(api) {
69080
70383
  close: (input) => dispatch("terminalSession", "close", "mutation", input)
69081
70384
  },
69082
70385
  toast: { onToast: (input, push) => dispatch("toast", "onToast", "subscription", input, push) },
70386
+ training: {
70387
+ putDatasetVersion: (input) => dispatch("training", "putDatasetVersion", "mutation", input),
70388
+ getDatasetVersion: (input) => dispatch("training", "getDatasetVersion", "query", input),
70389
+ listDatasetVersions: (input) => dispatch("training", "listDatasetVersions", "query", input),
70390
+ findDatasetVersionIdByName: (input) => dispatch("training", "findDatasetVersionIdByName", "query", input),
70391
+ removeDatasetVersion: (input) => dispatch("training", "removeDatasetVersion", "mutation", input),
70392
+ listBaseModels: (input) => dispatch("training", "listBaseModels", "query", input),
70393
+ planJob: (input) => dispatch("training", "planJob", "query", input),
70394
+ startJob: (input) => dispatch("training", "startJob", "mutation", input),
70395
+ listJobs: (input) => dispatch("training", "listJobs", "query", input),
70396
+ getJob: (input) => dispatch("training", "getJob", "query", input),
70397
+ cancelJob: (input) => dispatch("training", "cancelJob", "mutation", input),
70398
+ getJobResult: (input) => dispatch("training", "getJobResult", "query", input),
70399
+ registerResult: (input) => dispatch("training", "registerResult", "mutation", input),
70400
+ canaryResult: (input) => dispatch("training", "canaryResult", "mutation", input),
70401
+ rollbackCanary: (input) => dispatch("training", "rollbackCanary", "mutation", input),
70402
+ discardResult: (input) => dispatch("training", "discardResult", "mutation", input)
70403
+ },
69083
70404
  turnProvider: { getTurnServers: (input) => dispatch("turnProvider", "getTurnServers", "query", input) },
69084
70405
  userManagement: {
69085
70406
  listUsers: (input) => dispatch("userManagement", "listUsers", "query", input),
@@ -69090,9 +70411,7 @@ function createSystemProxy(api) {
69090
70411
  setUserScopes: (input) => dispatch("userManagement", "setUserScopes", "mutation", input),
69091
70412
  validateCredentials: (input) => dispatch("userManagement", "validateCredentials", "mutation", input),
69092
70413
  listApiKeys: (input) => dispatch("userManagement", "listApiKeys", "query", input),
69093
- createApiKey: (input) => dispatch("userManagement", "createApiKey", "mutation", input),
69094
70414
  revokeApiKey: (input) => dispatch("userManagement", "revokeApiKey", "mutation", input),
69095
- validateApiKey: (input) => dispatch("userManagement", "validateApiKey", "mutation", input),
69096
70415
  createScopedToken: (input) => dispatch("userManagement", "createScopedToken", "mutation", input),
69097
70416
  revokeScopedToken: (input) => dispatch("userManagement", "revokeScopedToken", "mutation", input),
69098
70417
  validateScopedToken: (input) => dispatch("userManagement", "validateScopedToken", "query", input),
@@ -69108,7 +70427,6 @@ function createSystemProxy(api) {
69108
70427
  oauthVerifyAccessToken: (input) => dispatch("userManagement", "oauthVerifyAccessToken", "query", input),
69109
70428
  listExternalIdentities: (input) => dispatch("userManagement", "listExternalIdentities", "query", input),
69110
70429
  findUserByExternalIdentity: (input) => dispatch("userManagement", "findUserByExternalIdentity", "query", input),
69111
- linkExternalIdentity: (input) => dispatch("userManagement", "linkExternalIdentity", "mutation", input),
69112
70430
  unlinkExternalIdentity: (input) => dispatch("userManagement", "unlinkExternalIdentity", "mutation", input),
69113
70431
  listOauthSessions: (input) => dispatch("userManagement", "listOauthSessions", "query", input),
69114
70432
  revokeOauthSession: (input) => dispatch("userManagement", "revokeOauthSession", "mutation", input)
@@ -76447,7 +77765,12 @@ var CREDENTIAL_PARAM_PATTERNS = [
76447
77765
  /^bearer$/i,
76448
77766
  /^api[_-]?key$/i,
76449
77767
  /^access[_-]?token$/i,
76450
- /^refresh[_-]?token$/i
77768
+ /^refresh[_-]?token$/i,
77769
+ /^bridge$/i,
77770
+ /^code$/i,
77771
+ /^state$/i,
77772
+ /^challenge$/i,
77773
+ /^link$/i
76451
77774
  ];
76452
77775
  function isCredentialParam(name) {
76453
77776
  return CREDENTIAL_PARAM_PATTERNS.some((re) => re.test(name));
@@ -76469,6 +77792,10 @@ function isCredentialParam(name) {
76469
77792
  * are NOT masked (those are entity references, not credentials).
76470
77793
  */
76471
77794
  function maskUrlCredentials(rawUrl) {
77795
+ if (rawUrl.startsWith("/") && !rawUrl.startsWith("//")) {
77796
+ const masked = maskUrlCredentials(`http://relative.invalid${rawUrl}`);
77797
+ return masked.startsWith("http://relative.invalid") ? masked.slice(23) : rawUrl;
77798
+ }
76472
77799
  try {
76473
77800
  const u = new URL(rawUrl);
76474
77801
  let touched = false;
@@ -77407,6 +78734,8 @@ exports.APPEARANCE_BLOCKS = APPEARANCE_BLOCKS;
77407
78734
  exports.APPEARANCE_DESCRIPTOR_VERSION = APPEARANCE_DESCRIPTOR_VERSION;
77408
78735
  exports.APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT = APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT;
77409
78736
  exports.APPLE_SA_TO_MACRO = APPLE_SA_TO_MACRO;
78737
+ exports.APP_AUTH_CALLBACK_MAX_LENGTH = APP_AUTH_CALLBACK_MAX_LENGTH;
78738
+ exports.APP_AUTH_CALLBACK_URLS = APP_AUTH_CALLBACK_URLS;
77410
78739
  exports.ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT = ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT;
77411
78740
  exports.AUDIO_ANALYSIS_CAP_NAME = AUDIO_ANALYSIS_CAP_NAME;
77412
78741
  exports.AUDIO_BACKEND_CHOICES = AUDIO_BACKEND_CHOICES;
@@ -77511,7 +78840,9 @@ exports.BOOT_RECOVERY_BACKOFF_MS = require_sleep.BOOT_RECOVERY_BACKOFF_MS;
77511
78840
  exports.BUILTIN_RESULT_KINDS = BUILTIN_RESULT_KINDS;
77512
78841
  exports.BackgroundRunRegistry = BackgroundRunRegistry;
77513
78842
  exports.BacklightModeSchema = BacklightModeSchema;
78843
+ exports.BackupArchiveEncryptionSchema = BackupArchiveEncryptionSchema;
77514
78844
  exports.BackupDestinationInfoSchema = BackupDestinationInfoSchema;
78845
+ exports.BackupEncryptionStatusSchema = BackupEncryptionStatusSchema;
77515
78846
  exports.BackupEntrySchema = BackupEntrySchema;
77516
78847
  exports.BackupRunPhaseSchema = BackupRunPhaseSchema;
77517
78848
  exports.BackupRunSchema = BackupRunSchema;
@@ -77554,6 +78885,7 @@ exports.CAMERA_SWITCH_CATALOG = CAMERA_SWITCH_CATALOG;
77554
78885
  exports.CAMERA_SWITCH_ORDER = CAMERA_SWITCH_ORDER;
77555
78886
  exports.CAMERA_TRIGGER = CAMERA_TRIGGER;
77556
78887
  exports.CAMSTACK_APP_LINK_ORIGIN = CAMSTACK_APP_LINK_ORIGIN;
78888
+ exports.CAMSTACK_EVENT_PREFIX = CAMSTACK_EVENT_PREFIX;
77557
78889
  exports.CAM_PROFILE_ORDER = require_sleep.CAM_PROFILE_ORDER;
77558
78890
  exports.CAPABILITY_NAMES = CAPABILITY_NAMES;
77559
78891
  exports.CAPABILITY_ROUTER_KEYS = CAPABILITY_ROUTER_KEYS;
@@ -77758,8 +79090,6 @@ exports.CoreBlockSourceSchema = CoreBlockSourceSchema;
77758
79090
  exports.CoreBlockStatusSchema = CoreBlockStatusSchema;
77759
79091
  exports.CoverStateSchema = CoverStateSchema;
77760
79092
  exports.CoverStatusSchema = CoverStatusSchema;
77761
- exports.CreateApiKeyInputSchema = CreateApiKeyInputSchema;
77762
- exports.CreateApiKeyResultSchema = CreateApiKeyResultSchema;
77763
79093
  exports.CreateIntegrationInputSchema = CreateIntegrationInputSchema;
77764
79094
  exports.CreateRetrainDatasetVersionResultSchema = CreateRetrainDatasetVersionResultSchema;
77765
79095
  exports.CreateScopedTokenInputSchema = CreateScopedTokenInputSchema;
@@ -78031,6 +79361,8 @@ exports.ImageSettingsOptionsSchema = ImageSettingsOptionsSchema;
78031
79361
  exports.ImageSettingsPatchSchema = ImageSettingsPatchSchema;
78032
79362
  exports.ImageSettingsStatusSchema = ImageSettingsStatusSchema;
78033
79363
  exports.ImageStatusSchema = ImageStatusSchema;
79364
+ exports.ImportModelBundleInputSchema = ImportModelBundleInputSchema;
79365
+ exports.ImportModelBundleResultSchema = ImportModelBundleResultSchema;
78034
79366
  exports.InferenceDeviceExclusionReasonSchema = InferenceDeviceExclusionReasonSchema;
78035
79367
  exports.IngestOwnerSchema = IngestOwnerSchema;
78036
79368
  exports.InstalledPackageSchema = InstalledPackageSchema;
@@ -78040,6 +79372,7 @@ exports.IntercomAbilitySchema = IntercomAbilitySchema;
78040
79372
  exports.IntercomStatusSchema = IntercomStatusSchema;
78041
79373
  exports.KEYCHAIN_MAX_REFS_PER_CALL = KEYCHAIN_MAX_REFS_PER_CALL;
78042
79374
  exports.KEYCHAIN_RESET_CONFIRMATION = KEYCHAIN_RESET_CONFIRMATION;
79375
+ exports.KEYCHAIN_RESET_TRIGGER_ACTOR = KEYCHAIN_RESET_TRIGGER_ACTOR;
78043
79376
  exports.KNOWN_CAP_NAMES = KNOWN_CAP_NAMES;
78044
79377
  exports.KeptReasonSchema = KeptReasonSchema;
78045
79378
  exports.KeyEventSchema = KeyEventSchema;
@@ -78048,6 +79381,7 @@ exports.KeychainAuditActionSchema = KeychainAuditActionSchema;
78048
79381
  exports.KeychainAuditEntrySchema = KeychainAuditEntrySchema;
78049
79382
  exports.KeychainKeySourceKindSchema = KeychainKeySourceKindSchema;
78050
79383
  exports.KeychainKeySourceSchema = KeychainKeySourceSchema;
79384
+ exports.KeychainResetRecordSchema = KeychainResetRecordSchema;
78051
79385
  exports.KeychainResolveEntrySchema = KeychainResolveEntrySchema;
78052
79386
  exports.KeychainResolveResultSchema = KeychainResolveResultSchema;
78053
79387
  exports.KeychainSecretMetaSchema = KeychainSecretMetaSchema;
@@ -78210,6 +79544,7 @@ exports.MethodAccessSchema = MethodAccessSchema;
78210
79544
  exports.MigrateDeviceResultSchema = MigrateDeviceResultSchema;
78211
79545
  exports.MigrateSwitchOutcomeSchema = MigrateSwitchOutcomeSchema;
78212
79546
  exports.MigrateSwitchReportSchema = MigrateSwitchReportSchema;
79547
+ exports.ModelBundleFileSchema = ModelBundleFileSchema;
78213
79548
  exports.ModelCatalogEntrySchema = ModelCatalogEntrySchema;
78214
79549
  exports.ModelConvertInputSchema = ModelConvertInputSchema;
78215
79550
  exports.ModelConvertMetadataSchema = ModelConvertMetadataSchema;
@@ -78597,6 +79932,8 @@ exports.ProbeTargetConfigResultSchema = ProbeTargetConfigResultSchema;
78597
79932
  exports.ProfileRtspEntrySchema = require_sleep.ProfileRtspEntrySchema;
78598
79933
  exports.ProfileSlotSchema = require_sleep.ProfileSlotSchema;
78599
79934
  exports.ProfileSlotStatusSchema = require_sleep.ProfileSlotStatusSchema;
79935
+ exports.ProviderJobStateSchema = ProviderJobStateSchema;
79936
+ exports.ProviderJobStatusSchema = ProviderJobStatusSchema;
78600
79937
  exports.ProviderMotionDataSchema = ProviderMotionDataSchema;
78601
79938
  exports.ProviderStatusSchema = ProviderStatusSchema;
78602
79939
  exports.PtzAutotrackRuntimeStateSchema = PtzAutotrackRuntimeStateSchema;
@@ -78774,6 +80111,8 @@ exports.SOURCE_CAP_ACTIVE_FIELD = require_composition.SOURCE_CAP_ACTIVE_FIELD;
78774
80111
  exports.SOURCE_CAP_CHANGED_AT_FIELD = require_composition.SOURCE_CAP_CHANGED_AT_FIELD;
78775
80112
  exports.SOURCE_DEVICE_TYPES = require_composition.SOURCE_DEVICE_TYPES;
78776
80113
  exports.SOURCE_INFO_METADATA_KEY = SOURCE_INFO_METADATA_KEY;
80114
+ exports.SSO_STATE_COOKIE = SSO_STATE_COOKIE;
80115
+ exports.SSO_STATE_COOKIE_MAX_AGE_SEC = SSO_STATE_COOKIE_MAX_AGE_SEC;
78777
80116
  exports.STATE_LABELS = STATE_LABELS;
78778
80117
  exports.STATE_LABEL_KEYS = STATE_LABEL_KEYS;
78779
80118
  exports.STATIONARY_OVERLAY_STYLE = STATIONARY_OVERLAY_STYLE;
@@ -78912,6 +80251,8 @@ exports.TAXONOMY_COLORS = TAXONOMY_COLORS;
78912
80251
  exports.TIMELAPSE_DENSE_FLOOR_SEC = TIMELAPSE_DENSE_FLOOR_SEC;
78913
80252
  exports.TIMEZONES = TIMEZONES;
78914
80253
  exports.TRACK_RELATIONS_DEFAULT_LIMIT = TRACK_RELATIONS_DEFAULT_LIMIT;
80254
+ exports.TRAINING_JOB_SCHEMA = TRAINING_JOB_SCHEMA;
80255
+ exports.TRAINING_RESULT_SCHEMA = TRAINING_RESULT_SCHEMA;
78915
80256
  exports.TRANSCODE_DOWN_MAX_BITRATE_KBPS = TRANSCODE_DOWN_MAX_BITRATE_KBPS;
78916
80257
  exports.TRANSCODE_DOWN_MAX_HEIGHT = TRANSCODE_DOWN_MAX_HEIGHT;
78917
80258
  exports.TamperStatusSchema = TamperStatusSchema;
@@ -78955,8 +80296,36 @@ exports.TrackSourceSchema = TrackSourceSchema;
78955
80296
  exports.TrackStateSchema = TrackStateSchema;
78956
80297
  exports.TrackZoneFilterSchema = TrackZoneFilterSchema;
78957
80298
  exports.TrackedDetectionSchema = TrackedDetectionSchema;
80299
+ exports.TrainerSourceRefSchema = TrainerSourceRefSchema;
80300
+ exports.TrainingBaseModelSchema = TrainingBaseModelSchema;
80301
+ exports.TrainingCanarySchema = TrainingCanarySchema;
80302
+ exports.TrainingCatalogDraftSchema = TrainingCatalogDraftSchema;
80303
+ exports.TrainingCredentialCheckSchema = TrainingCredentialCheckSchema;
80304
+ exports.TrainingDatasetVersionRowSchema = TrainingDatasetVersionRowSchema;
80305
+ exports.TrainingEvalClassSchema = TrainingEvalClassSchema;
80306
+ exports.TrainingEvalReportSchema = TrainingEvalReportSchema;
80307
+ exports.TrainingEventSchema = TrainingEventSchema;
78958
80308
  exports.TrainingExportDeviceTotalsSchema = TrainingExportDeviceTotalsSchema;
80309
+ exports.TrainingExportSchema = TrainingExportSchema;
78959
80310
  exports.TrainingExportSummarySchema = TrainingExportSummarySchema;
80311
+ exports.TrainingFailureReasonSchema = TrainingFailureReasonSchema;
80312
+ exports.TrainingGpuOptionSchema = TrainingGpuOptionSchema;
80313
+ exports.TrainingJobPlanSchema = TrainingJobPlanSchema;
80314
+ exports.TrainingJobRequestSchema = TrainingJobRequestSchema;
80315
+ exports.TrainingJobSchema = TrainingJobSchema;
80316
+ exports.TrainingJobSpecSchema = TrainingJobSpecSchema;
80317
+ exports.TrainingJobStateSchema = TrainingJobStateSchema;
80318
+ exports.TrainingLogLineSchema = TrainingLogLineSchema;
80319
+ exports.TrainingPresetSchema = TrainingPresetSchema;
80320
+ exports.TrainingProgressPointSchema = TrainingProgressPointSchema;
80321
+ exports.TrainingProviderDefaultsSchema = TrainingProviderDefaultsSchema;
80322
+ exports.TrainingProviderDescriptorSchema = TrainingProviderDescriptorSchema;
80323
+ exports.TrainingRefusalReasonSchema = TrainingRefusalReasonSchema;
80324
+ exports.TrainingRegionOptionSchema = TrainingRegionOptionSchema;
80325
+ exports.TrainingResultFileSchema = TrainingResultFileSchema;
80326
+ exports.TrainingResultSchema = TrainingResultSchema;
80327
+ exports.TrainingSplitPlanSchema = TrainingSplitPlanSchema;
80328
+ exports.TrainingStageSchema = TrainingStageSchema;
78960
80329
  exports.TransportPlaneCountsSchema = TransportPlaneCountsSchema;
78961
80330
  exports.TransportPlaneSchema = TransportPlaneSchema;
78962
80331
  exports.TurnServerSchema = TurnServerSchema;
@@ -79129,6 +80498,7 @@ exports.cameraSensorRefKey = cameraSensorRefKey;
79129
80498
  exports.cameraStreamsCapability = cameraStreamsCapability;
79130
80499
  exports.canConvertUnit = canConvertUnit;
79131
80500
  exports.canonicalEgressPlan = canonicalEgressPlan;
80501
+ exports.canonicalizeAppCallback = canonicalizeAppCallback;
79132
80502
  exports.capacitySessionsOf = capacitySessionsOf;
79133
80503
  exports.carbonMonoxideCapability = carbonMonoxideCapability;
79134
80504
  exports.cellsToRects = cellsToRects;
@@ -79362,6 +80732,7 @@ exports.gifFromMp4Args = gifFromMp4Args;
79362
80732
  exports.globalSecretScope = require_sleep.globalSecretScope;
79363
80733
  exports.hasModelBoundOverrides = hasModelBoundOverrides;
79364
80734
  exports.hasMotionTrigger = hasMotionTrigger;
80735
+ exports.hasUrlScheme = hasUrlScheme;
79365
80736
  exports.hfModelUrl = hfModelUrl;
79366
80737
  exports.htmlToText = htmlToText;
79367
80738
  exports.hubAddressHostname = hubAddressHostname;
@@ -79542,6 +80913,7 @@ exports.osdManagerCapability = osdManagerCapability;
79542
80913
  exports.overlayClusterStepSettings = overlayClusterStepSettings;
79543
80914
  exports.packagePickerItems = packagePickerItems;
79544
80915
  exports.parseAdminBase = parseAdminBase;
80916
+ exports.parseAppAuthCallback = parseAppAuthCallback;
79545
80917
  exports.parseCameraStreamConfig = parseCameraStreamConfig;
79546
80918
  exports.parseExpression = require_composition.parseExpression;
79547
80919
  exports.parseJsonArray = require_sleep.parseJsonArray;
@@ -79557,6 +80929,7 @@ exports.parseSecretStatePath = require_sleep.parseSecretStatePath;
79557
80929
  exports.parseSessionPlacementPolicy = parseSessionPlacementPolicy;
79558
80930
  exports.parseShareSource = parseShareSource;
79559
80931
  exports.parseStreamParamsFormPatch = parseStreamParamsFormPatch;
80932
+ exports.parseTrainingEventLine = parseTrainingEventLine;
79560
80933
  exports.patchAudio = patchAudio;
79561
80934
  exports.petFeederCapability = petFeederCapability;
79562
80935
  exports.pickAccessoryControl = pickAccessoryControl;
@@ -79788,6 +81161,8 @@ exports.toStreamSourceEntry = toStreamSourceEntry;
79788
81161
  exports.toastCapability = toastCapability;
79789
81162
  exports.toggleAudioLabel = toggleAudioLabel;
79790
81163
  exports.tokenize = require_composition.tokenize;
81164
+ exports.trainingCapability = trainingCapability;
81165
+ exports.trainingProviderCapability = trainingProviderCapability;
79791
81166
  exports.transcodeBody = transcodeBody;
79792
81167
  exports.transformSecretWrite = require_sleep.transformSecretWrite;
79793
81168
  exports.tryConvertUnit = tryConvertUnit;