@camstack/types 1.2.332 → 1.2.333

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 (51) 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/notification-output.cap.d.ts +4 -4
  20. package/dist/capabilities/notification-rules.cap.d.ts +6 -6
  21. package/dist/capabilities/osd-manager.cap.d.ts +5 -5
  22. package/dist/capabilities/pipeline-analytics.cap.d.ts +39 -8
  23. package/dist/capabilities/recording.cap.d.ts +3 -3
  24. package/dist/capabilities/server-management.cap.d.ts +5 -5
  25. package/dist/capabilities/snapshot.cap.d.ts +2 -2
  26. package/dist/capabilities/sso-bridge.cap.d.ts +5 -2
  27. package/dist/capabilities/training-provider.cap.d.ts +373 -0
  28. package/dist/capabilities/training.cap.d.ts +1896 -0
  29. package/dist/capabilities/user-management.cap.d.ts +1 -64
  30. package/dist/capabilities/videoclips.cap.d.ts +3 -3
  31. package/dist/client.js +26 -4
  32. package/dist/client.mjs +26 -4
  33. package/dist/generated/addon-api.d.ts +842 -173
  34. package/dist/generated/cap-input-defaults.d.ts +1 -1
  35. package/dist/generated/capability-router-map.d.ts +10 -4
  36. package/dist/generated/collection-array-methods.d.ts +1 -1
  37. package/dist/generated/method-access-map.d.ts +1 -1
  38. package/dist/generated/method-device-selectors.d.ts +2 -2
  39. package/dist/generated/system-proxy.d.ts +5 -3
  40. package/dist/index.d.ts +3 -0
  41. package/dist/index.js +1462 -93
  42. package/dist/index.mjs +1413 -92
  43. package/dist/interfaces/addon-routes.d.ts +7 -0
  44. package/dist/interfaces/addon.d.ts +8 -0
  45. package/dist/interfaces/auth.d.ts +6 -3
  46. package/dist/schemas/auth-records.d.ts +1 -2
  47. package/dist/{sleep-ClNXPpWR.js → sleep-DiQYrfm9.js} +425 -75
  48. package/dist/{sleep-DujUvOcb.mjs → sleep-r3RWkGVx.mjs} +425 -75
  49. package/dist/training/index.d.ts +1 -0
  50. package/dist/training/trainer-contract.d.ts +468 -0
  51. 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
  */
@@ -48309,16 +48884,6 @@ var ApiKeySummarySchema = zod.z.object({
48309
48884
  createdAt: zod.z.number(),
48310
48885
  lastUsedAt: zod.z.number().optional()
48311
48886
  });
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
48887
  var ScopedTokenSummarySchema = zod.z.object({
48323
48888
  id: zod.z.string(),
48324
48889
  userId: zod.z.string(),
@@ -48430,20 +48995,11 @@ var userManagementCapability = {
48430
48995
  access: "view"
48431
48996
  }),
48432
48997
  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
48998
  revokeApiKey: require_sleep.method(zod.z.object({ id: zod.z.string() }), zod.z.object({ success: zod.z.literal(true) }), {
48439
48999
  kind: "mutation",
48440
49000
  auth: "admin",
48441
49001
  access: "delete"
48442
49002
  }),
48443
- validateApiKey: require_sleep.method(zod.z.object({ token: zod.z.string() }), ApiKeySummarySchema.nullable(), {
48444
- kind: "mutation",
48445
- access: "view"
48446
- }),
48447
49003
  createScopedToken: require_sleep.method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
48448
49004
  kind: "mutation",
48449
49005
  auth: "admin",
@@ -48533,20 +49089,6 @@ var userManagementCapability = {
48533
49089
  userId: zod.z.string(),
48534
49090
  issuer: zod.z.string()
48535
49091
  }).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
49092
  /** Remove one link of `userId`. `success: false` when it was not linked to that user. */
48551
49093
  unlinkExternalIdentity: require_sleep.method(ExternalIdentityKeySchema.extend({ userId: zod.z.string() }), zod.z.object({ success: zod.z.boolean() }), {
48552
49094
  kind: "mutation",
@@ -49290,6 +49832,535 @@ var zoneRulesCapability = {
49290
49832
  durability: "restored"
49291
49833
  };
49292
49834
  //#endregion
49835
+ //#region src/capabilities/training-provider.cap.ts
49836
+ /**
49837
+ * `training-provider` — ONE cloud that can run the CamStack trainer.
49838
+ *
49839
+ * A thin, mockable translation layer: it knows how to run a container with a
49840
+ * GPU, move a dataset in, read the job's stdout and hand artefacts back. It
49841
+ * knows nothing about datasets, splits, floors, cost policy or Model Studio —
49842
+ * those are the `training` orchestrator's (D805). Every rule written there
49843
+ * once is what makes a second provider (RunPod, a local NVIDIA node) a new
49844
+ * manifest entry and nothing else.
49845
+ *
49846
+ * Collection, routed by the `addonId` in every single-row input (the `llm` /
49847
+ * `notification-output` posture); `describe` concat-fans across providers.
49848
+ * Every method is `admin`: these spend money.
49849
+ *
49850
+ * Every cloud object a provider creates is tagged with the orchestrator's
49851
+ * `jobKey`, so a retried submit finds the job it already started instead of
49852
+ * starting a second GPU, and `listJobs` can find orphans.
49853
+ *
49854
+ * Bytes never ride a cap field: the dataset arrives as a `ctx.peerBytes`
49855
+ * ticket the producer (pipeline-analytics) minted, and artefacts leave as a
49856
+ * ticket the provider mints (D613).
49857
+ */
49858
+ var TrainingGpuOptionSchema = zod.z.object({
49859
+ id: zod.z.string(),
49860
+ label: zod.z.string(),
49861
+ /** List price, USD per GPU-hour, before any region multiplier. */
49862
+ usdPerHour: zod.z.number().nonnegative(),
49863
+ vramGb: zod.z.number().nonnegative()
49864
+ });
49865
+ var TrainingRegionOptionSchema = zod.z.object({
49866
+ /** `''` = any region (the provider's choice). */
49867
+ id: zod.z.string(),
49868
+ label: zod.z.string(),
49869
+ priceMultiplier: zod.z.number().positive()
49870
+ });
49871
+ /**
49872
+ * The provider's per-account settings, as the orchestrator reads them. They
49873
+ * live in the PROVIDER addon's settings (operator decision 2026-10-08: they
49874
+ * depend on the user's account), never hard-coded in the orchestrator.
49875
+ */
49876
+ var TrainingProviderDefaultsSchema = zod.z.object({
49877
+ gpuType: zod.z.string(),
49878
+ region: zod.z.string(),
49879
+ costCapUsd: zod.z.number().nonnegative(),
49880
+ maxRuntimeSec: zod.z.number().int().positive(),
49881
+ /** Hours a FAILED job's cloud dataset is kept for debugging; 0 = delete at once. */
49882
+ failedDatasetGraceHours: zod.z.number().nonnegative()
49883
+ });
49884
+ var TrainingProviderDescriptorSchema = zod.z.object({
49885
+ addonId: zod.z.string(),
49886
+ /** `modal`, `runpod`, `fake`, … */
49887
+ kind: zod.z.string(),
49888
+ label: zod.z.string(),
49889
+ gpuTypes: zod.z.array(TrainingGpuOptionSchema).readonly(),
49890
+ regions: zod.z.array(TrainingRegionOptionSchema).readonly(),
49891
+ maxDatasetBytes: zod.z.number().int().positive(),
49892
+ maxRuntimeSec: zod.z.number().int().positive(),
49893
+ freeTierNote: zod.z.string().optional(),
49894
+ /** Where the data goes, in one sentence the confirm dialog repeats. */
49895
+ dataResidencyNote: zod.z.string(),
49896
+ /** Credentials are present — never the values. */
49897
+ configured: zod.z.boolean(),
49898
+ defaults: TrainingProviderDefaultsSchema
49899
+ });
49900
+ var TrainingCredentialCheckSchema = zod.z.object({
49901
+ ok: zod.z.boolean(),
49902
+ /** Workspace / account name, when the provider says. */
49903
+ account: zod.z.string().optional(),
49904
+ reason: zod.z.enum([
49905
+ "missing",
49906
+ "invalid",
49907
+ "forbidden",
49908
+ "network",
49909
+ "quota"
49910
+ ]).optional(),
49911
+ detail: zod.z.string().optional()
49912
+ });
49913
+ var ProviderJobStateSchema = zod.z.enum([
49914
+ "pending",
49915
+ "starting",
49916
+ "running",
49917
+ "succeeded",
49918
+ "failed",
49919
+ "cancelled",
49920
+ "lost"
49921
+ ]);
49922
+ var ProviderJobStatusSchema = zod.z.object({
49923
+ jobKey: zod.z.string(),
49924
+ providerJobId: zod.z.string().optional(),
49925
+ state: ProviderJobStateSchema,
49926
+ startedAt: zod.z.number().optional(),
49927
+ endedAt: zod.z.number().optional(),
49928
+ exitCode: zod.z.number().int().optional(),
49929
+ failureReason: zod.z.string().optional(),
49930
+ gpuType: zod.z.string(),
49931
+ region: zod.z.string().optional(),
49932
+ billedSeconds: zod.z.number().nonnegative(),
49933
+ costUsd: zod.z.number().nonnegative(),
49934
+ /** True when `costUsd` is runtime × list price, not a billing answer. */
49935
+ costIsEstimate: zod.z.boolean(),
49936
+ lastFetchedAt: zod.z.number()
49937
+ });
49938
+ /**
49939
+ * The trainer the job runs, by SOURCE revision: the provider turns it into an
49940
+ * image its own way (Modal builds the published Dockerfile at that revision;
49941
+ * a registry-pull provider maps it to a tag). Recorded on the job and echoed
49942
+ * in `result.json`.
49943
+ */
49944
+ var TrainerSourceRefSchema = zod.z.object({
49945
+ /** Hugging Face repo id, e.g. `camstack/camstack-trainer`. */
49946
+ repo: zod.z.string().min(1),
49947
+ /** A commit sha (never a branch) — the job must be reproducible. */
49948
+ revision: zod.z.string().regex(/^[0-9a-f]{7,64}$/)
49949
+ });
49950
+ var JobRef = {
49951
+ addonId: zod.z.string(),
49952
+ jobKey: zod.z.string().uuid()
49953
+ };
49954
+ var TrainingLogLineSchema = zod.z.object({
49955
+ ts: zod.z.number(),
49956
+ text: zod.z.string()
49957
+ });
49958
+ var trainingProviderCapability = {
49959
+ name: "training-provider",
49960
+ scope: "system",
49961
+ mode: "collection",
49962
+ internal: true,
49963
+ methods: {
49964
+ /** Every provider's offer and settings. Concat-fans across providers. */
49965
+ describe: require_sleep.method(zod.z.object({}), zod.z.array(TrainingProviderDescriptorSchema).readonly(), { auth: "admin" }),
49966
+ /** Call the provider with the stored credentials. Never returns them. */
49967
+ validateCredentials: require_sleep.method(zod.z.object({ addonId: zod.z.string() }), TrainingCredentialCheckSchema, {
49968
+ kind: "mutation",
49969
+ auth: "admin",
49970
+ timeoutMs: 3e4
49971
+ }),
49972
+ /** USD range for a run of `gpuSeconds` on `gpuType` in `region`. */
49973
+ estimateJob: require_sleep.method(zod.z.object({
49974
+ addonId: zod.z.string(),
49975
+ gpuType: zod.z.string(),
49976
+ region: zod.z.string(),
49977
+ datasetBytes: zod.z.number().int().nonnegative(),
49978
+ gpuSecondsLow: zod.z.number().nonnegative(),
49979
+ gpuSecondsHigh: zod.z.number().nonnegative()
49980
+ }), zod.z.object({
49981
+ usdLow: zod.z.number().nonnegative(),
49982
+ usdHigh: zod.z.number().nonnegative(),
49983
+ notes: zod.z.array(zod.z.string()).readonly()
49984
+ }), { auth: "admin" }),
49985
+ /**
49986
+ * Take the dataset archive behind `ticket` (minted by pipeline-analytics,
49987
+ * same host) and land it as the job's dataset in the cloud, streamed —
49988
+ * nothing is staged on the hub's disk. Idempotent per `jobKey`: a second
49989
+ * call replaces a partial upload. Answers what actually landed.
49990
+ */
49991
+ uploadDataset: require_sleep.method(zod.z.object({
49992
+ ...JobRef,
49993
+ ticket: require_sleep.PeerBytesTicketSchema
49994
+ }), zod.z.object({
49995
+ bytes: zod.z.number().int().nonnegative(),
49996
+ sha256: zod.z.string()
49997
+ }), {
49998
+ kind: "mutation",
49999
+ auth: "admin",
50000
+ timeoutMs: 120 * 6e4
50001
+ }),
50002
+ /**
50003
+ * Start the trainer on a GPU. Looks the job up by `jobKey` first, so a
50004
+ * retried submit never starts a second GPU. `jobSpecJson` is written next
50005
+ * to the dataset as `job.json`; `maxRuntimeSec` is enforced by the
50006
+ * provider (a hard timeout), not by the hub.
50007
+ */
50008
+ submitJob: require_sleep.method(zod.z.object({
50009
+ ...JobRef,
50010
+ trainer: TrainerSourceRefSchema,
50011
+ jobSpecJson: zod.z.string().min(2).max(64e3),
50012
+ gpuType: zod.z.string(),
50013
+ region: zod.z.string(),
50014
+ maxRuntimeSec: zod.z.number().int().positive()
50015
+ }), ProviderJobStatusSchema, {
50016
+ kind: "mutation",
50017
+ auth: "admin",
50018
+ timeoutMs: 30 * 6e4
50019
+ }),
50020
+ getJob: require_sleep.method(zod.z.object(JobRef), ProviderJobStatusSchema, {
50021
+ auth: "admin",
50022
+ timeoutMs: 6e4
50023
+ }),
50024
+ /** Stdout/stderr since `cursor` (opaque), oldest first, at most `max` lines. */
50025
+ listJobEvents: require_sleep.method(zod.z.object({
50026
+ ...JobRef,
50027
+ cursor: zod.z.string().optional(),
50028
+ max: zod.z.number().int().min(1).max(500)
50029
+ }), zod.z.object({
50030
+ lines: zod.z.array(TrainingLogLineSchema).readonly(),
50031
+ cursor: zod.z.string()
50032
+ }), {
50033
+ auth: "admin",
50034
+ timeoutMs: 6e4
50035
+ }),
50036
+ /** Stop the job. Idempotent: an unknown or finished job is a no-op. */
50037
+ cancelJob: require_sleep.method(zod.z.object(JobRef), zod.z.object({ ok: zod.z.literal(true) }), {
50038
+ kind: "mutation",
50039
+ auth: "admin",
50040
+ timeoutMs: 6e4
50041
+ }),
50042
+ /** The job's `result.json`, as text (small, JSON). `found: false` before it exists. */
50043
+ readResult: require_sleep.method(zod.z.object(JobRef), zod.z.object({
50044
+ found: zod.z.boolean(),
50045
+ text: zod.z.string().optional()
50046
+ }), {
50047
+ kind: "mutation",
50048
+ auth: "admin",
50049
+ timeoutMs: 5 * 6e4
50050
+ }),
50051
+ /**
50052
+ * Offer one output file of the job (`bundle.tar`) to the caller as a
50053
+ * one-shot `ctx.peerBytes` ticket, streamed from the cloud — the provider
50054
+ * stages nothing on disk. The caller dials it at once.
50055
+ */
50056
+ offerArtifact: require_sleep.method(zod.z.object({
50057
+ ...JobRef,
50058
+ path: zod.z.enum(["bundle.tar"])
50059
+ }), zod.z.object({ ticket: require_sleep.PeerBytesTicketSchema }), {
50060
+ kind: "mutation",
50061
+ auth: "admin",
50062
+ timeoutMs: 5 * 6e4
50063
+ }),
50064
+ /** Delete every cloud object tagged with `jobKey` (the dataset first). Idempotent. */
50065
+ cleanupJob: require_sleep.method(zod.z.object(JobRef), zod.z.object({ deleted: zod.z.array(zod.z.string()).readonly() }), {
50066
+ kind: "mutation",
50067
+ auth: "admin",
50068
+ timeoutMs: 5 * 6e4
50069
+ }),
50070
+ /** Every job the provider can still see — the orphan sweep diffs it against our records. */
50071
+ listJobs: require_sleep.method(zod.z.object({ addonId: zod.z.string() }), zod.z.array(ProviderJobStatusSchema).readonly(), {
50072
+ auth: "admin",
50073
+ timeoutMs: 2 * 6e4
50074
+ })
50075
+ }
50076
+ };
50077
+ //#endregion
50078
+ //#region src/capabilities/training.cap.ts
50079
+ /**
50080
+ * `training` — the cloud-training orchestrator (D805). Hub-only singleton,
50081
+ * provided by `addon-training`.
50082
+ *
50083
+ * It owns what every provider must agree on, written once:
50084
+ *
50085
+ * - **Dataset versions.** Taken over from pipeline-analytics (D796): the rows
50086
+ * live here (D808); pipeline-analytics still CUTS a version (it owns the corpus and
50087
+ * the export plan) and reaches this store through the five row methods
50088
+ * below, so the Retrain page and the export did not change.
50089
+ * - **Jobs.** A persisted state machine, a reconcile loop against the
50090
+ * provider, a cost guard, a daily orphan sweep and the retention rules.
50091
+ * - **The return flow.** Verified artefacts → Model Studio
50092
+ * (`custom-model-registry.importModelBundle`) → canary on cameras →
50093
+ * rollback. Nothing is ever registered automatically.
50094
+ *
50095
+ * Every method is `admin`.
50096
+ */
50097
+ /** A version WITH its frame list — what the export and a job read. */
50098
+ var TrainingDatasetVersionRowSchema = RetrainDatasetVersionSchema.omit({ frameCount: true }).extend({ frameIds: zod.z.array(zod.z.string()).max(2e4).readonly() });
50099
+ /** A base model a detector job can fine-tune, and the baseline it is judged against. */
50100
+ var TrainingBaseModelSchema = zod.z.object({
50101
+ modelId: zod.z.string(),
50102
+ label: zod.z.string(),
50103
+ weights: zod.z.string(),
50104
+ imgsz: zod.z.number().int(),
50105
+ baselineOnnxUrl: zod.z.string(),
50106
+ baselineFloors: zod.z.record(zod.z.string(), zod.z.number()),
50107
+ /** The base the fleet runs most — the UI's default. */
50108
+ recommended: zod.z.boolean()
50109
+ });
50110
+ var TrainingPresetSchema = zod.z.enum([
50111
+ "quick",
50112
+ "standard",
50113
+ "thorough"
50114
+ ]);
50115
+ var TrainingJobRequestSchema = zod.z.object({
50116
+ datasetVersionId: zod.z.string().min(1),
50117
+ /** The `training-provider` addon that runs it. */
50118
+ addonId: zod.z.string().min(1),
50119
+ gpuType: zod.z.string().min(1),
50120
+ region: zod.z.string(),
50121
+ baseModelId: zod.z.string().min(1),
50122
+ preset: TrainingPresetSchema,
50123
+ /** Freeze the backbone's first N layers; `null` = the preset's choice. */
50124
+ freeze: zod.z.number().int().nonnegative().nullable(),
50125
+ /** Cameras held out whole for evaluation; `null` = the orchestrator's default. */
50126
+ holdoutCameras: zod.z.array(zod.z.number().int()).nullable()
50127
+ });
50128
+ var TrainingSplitPlanSchema = zod.z.object({
50129
+ holdoutCameras: zod.z.array(zod.z.number().int()).readonly(),
50130
+ /** Used when no camera is held out: the last N days of every camera. */
50131
+ holdoutLastDays: zod.z.number().int().nonnegative(),
50132
+ /** Holdout subjects per class (camera holdout only; `null` = known only after the split). */
50133
+ holdoutSupport: zod.z.record(zod.z.string(), zod.z.number().int()).nullable(),
50134
+ trainSubjects: zod.z.number().int()
50135
+ });
50136
+ var TrainingRefusalReasonSchema = zod.z.enum([
50137
+ "unknown-dataset",
50138
+ "unknown-provider",
50139
+ "provider-not-configured",
50140
+ "unknown-base-model",
50141
+ "unknown-gpu",
50142
+ "dataset-too-large",
50143
+ "no-training-subjects",
50144
+ "job-already-running"
50145
+ ]);
50146
+ var TrainingJobPlanSchema = zod.z.object({
50147
+ refusal: zod.z.object({
50148
+ reason: TrainingRefusalReasonSchema,
50149
+ detail: zod.z.string()
50150
+ }).nullable(),
50151
+ warnings: zod.z.array(zod.z.string()).readonly(),
50152
+ split: TrainingSplitPlanSchema.nullable(),
50153
+ estimate: zod.z.object({
50154
+ datasetBytes: zod.z.number().int(),
50155
+ uploadMinutesAt20Mbps: zod.z.number(),
50156
+ gpuSecondsLow: zod.z.number(),
50157
+ gpuSecondsHigh: zod.z.number(),
50158
+ usdLow: zod.z.number(),
50159
+ usdHigh: zod.z.number(),
50160
+ notes: zod.z.array(zod.z.string()).readonly()
50161
+ }).nullable(),
50162
+ /** Pre-filled from the provider's settings; the operator may lower or raise them. */
50163
+ defaults: zod.z.object({
50164
+ maxCostUsd: zod.z.number(),
50165
+ maxRuntimeSec: zod.z.number().int()
50166
+ }).nullable(),
50167
+ /** The sentence the confirm dialog repeats: where the frames go and when they are deleted. */
50168
+ dataNotice: zod.z.string()
50169
+ });
50170
+ /**
50171
+ * Orchestrator-owned states, persisted. `uploading` covers exporting the
50172
+ * archive (it is streamed, never staged). Terminal: `failed`, `cancelled`,
50173
+ * `lost`, `expired`, `discarded`. `registered` and `canary` are where a
50174
+ * result lives after the operator acted on it.
50175
+ */
50176
+ var TrainingJobStateSchema = zod.z.enum([
50177
+ "uploading",
50178
+ "submitted",
50179
+ "starting",
50180
+ "running",
50181
+ "collecting",
50182
+ "ready",
50183
+ "registered",
50184
+ "canary",
50185
+ "failed",
50186
+ "cancelling",
50187
+ "cancelled",
50188
+ "lost",
50189
+ "expired",
50190
+ "discarded"
50191
+ ]);
50192
+ var TrainingFailureReasonSchema = zod.z.enum([
50193
+ "cost-cap",
50194
+ "runtime-cap",
50195
+ "upload-failed",
50196
+ "submit-failed",
50197
+ "trainer-failed",
50198
+ "result-invalid",
50199
+ "checksum-mismatch",
50200
+ "fetch-failed",
50201
+ "provider-error",
50202
+ "hub-restart-during-upload"
50203
+ ]);
50204
+ var TrainingProgressPointSchema = zod.z.object({
50205
+ epoch: zod.z.number().int(),
50206
+ map50: zod.z.number().nullable(),
50207
+ map50_95: zod.z.number().nullable()
50208
+ });
50209
+ var TrainingCanarySchema = zod.z.object({
50210
+ deviceIds: zod.z.array(zod.z.number().int()).readonly(),
50211
+ since: zod.z.number(),
50212
+ /** Every override the canary replaced, exactly, so rollback restores it. */
50213
+ previous: zod.z.array(zod.z.object({
50214
+ deviceId: zod.z.number().int(),
50215
+ nodeId: zod.z.string(),
50216
+ deviceKey: zod.z.string(),
50217
+ patch: zod.z.object({
50218
+ modelId: zod.z.string().optional(),
50219
+ settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly().optional()
50220
+ }).nullable()
50221
+ })).readonly()
50222
+ });
50223
+ var TrainingJobSchema = zod.z.object({
50224
+ id: zod.z.string(),
50225
+ idempotencyKey: zod.z.string(),
50226
+ name: zod.z.string(),
50227
+ createdAt: zod.z.number(),
50228
+ updatedAt: zod.z.number(),
50229
+ state: TrainingJobStateSchema,
50230
+ stage: TrainingStageSchema.nullable(),
50231
+ failure: zod.z.object({
50232
+ reason: TrainingFailureReasonSchema,
50233
+ stage: zod.z.string().nullable(),
50234
+ detail: zod.z.string()
50235
+ }).nullable(),
50236
+ request: TrainingJobRequestSchema,
50237
+ maxCostUsd: zod.z.number().nonnegative(),
50238
+ maxRuntimeSec: zod.z.number().int().positive(),
50239
+ trainer: TrainerSourceRefSchema,
50240
+ datasetLayout: RetrainExportLayoutSchema,
50241
+ dataset: zod.z.object({
50242
+ bytes: zod.z.number().int(),
50243
+ sha256: zod.z.string(),
50244
+ uploadedAt: zod.z.number()
50245
+ }).nullable(),
50246
+ split: TrainingSplitPlanSchema,
50247
+ provider: zod.z.object({
50248
+ state: ProviderJobStateSchema.nullable(),
50249
+ providerJobId: zod.z.string().nullable(),
50250
+ startedAt: zod.z.number().nullable(),
50251
+ endedAt: zod.z.number().nullable(),
50252
+ billedSeconds: zod.z.number(),
50253
+ costUsd: zod.z.number(),
50254
+ costIsEstimate: zod.z.boolean(),
50255
+ lastPolledAt: zod.z.number().nullable()
50256
+ }),
50257
+ progress: zod.z.object({
50258
+ epoch: zod.z.number().int().nullable(),
50259
+ epochs: zod.z.number().int().nullable(),
50260
+ etaSec: zod.z.number().nullable(),
50261
+ series: zod.z.array(TrainingProgressPointSchema).readonly()
50262
+ }),
50263
+ /** The last lines of the job's output (≤ 200), newest last. Never frame paths. */
50264
+ logTail: zod.z.array(zod.z.string()).readonly(),
50265
+ logCursor: zod.z.string().nullable(),
50266
+ artifacts: zod.z.object({
50267
+ bundleBytes: zod.z.number().int(),
50268
+ bundleSha256: zod.z.string(),
50269
+ fetchedAt: zod.z.number(),
50270
+ /** When the staged artefacts are deleted from the hub. */
50271
+ expiresAt: zod.z.number()
50272
+ }).nullable(),
50273
+ /** When the provider-side copy of the frames was deleted; null while it exists. */
50274
+ cloudDatasetDeletedAt: zod.z.number().nullable(),
50275
+ /** A failed job's dataset is kept until then (the provider's grace), then deleted. */
50276
+ cloudCleanupDueAt: zod.z.number().nullable(),
50277
+ /** Model ids registered from this job (base, and int8 when kept). */
50278
+ registeredModelIds: zod.z.array(zod.z.string()).readonly(),
50279
+ canary: TrainingCanarySchema.nullable()
50280
+ });
50281
+ var IdInput = zod.z.object({ id: zod.z.string().min(1) });
50282
+ var trainingCapability = {
50283
+ name: "training",
50284
+ scope: "system",
50285
+ mode: "singleton",
50286
+ mount: { kind: "hub-only" },
50287
+ methods: {
50288
+ /** Store a version once. `stored: false` = that id already exists (immutable). */
50289
+ putDatasetVersion: require_sleep.method(TrainingDatasetVersionRowSchema, zod.z.object({ stored: zod.z.boolean() }), {
50290
+ kind: "mutation",
50291
+ auth: "admin"
50292
+ }),
50293
+ getDatasetVersion: require_sleep.method(IdInput, TrainingDatasetVersionRowSchema.nullable(), { auth: "admin" }),
50294
+ /** Every version without its frame list, newest first. */
50295
+ listDatasetVersions: require_sleep.method(zod.z.object({}), zod.z.array(RetrainDatasetVersionSchema).readonly(), { auth: "admin" }),
50296
+ findDatasetVersionIdByName: require_sleep.method(zod.z.object({ name: zod.z.string() }), zod.z.object({ id: zod.z.string().nullable() }), { auth: "admin" }),
50297
+ removeDatasetVersion: require_sleep.method(IdInput, zod.z.object({ removed: zod.z.boolean() }), {
50298
+ kind: "mutation",
50299
+ auth: "admin"
50300
+ }),
50301
+ listBaseModels: require_sleep.method(zod.z.object({}), zod.z.array(TrainingBaseModelSchema).readonly(), { auth: "admin" }),
50302
+ /** Split, estimate, defaults and any named refusal — nothing is started. */
50303
+ planJob: require_sleep.method(TrainingJobRequestSchema, TrainingJobPlanSchema, {
50304
+ auth: "admin",
50305
+ timeoutMs: 6e4
50306
+ }),
50307
+ /**
50308
+ * Start a job. The same `idempotencyKey` returns the job it already
50309
+ * started. Answers at once (`uploading`); the upload and the submit run in
50310
+ * the background and the job record says how far they got.
50311
+ */
50312
+ startJob: require_sleep.method(TrainingJobRequestSchema.extend({
50313
+ name: zod.z.string().min(1).max(120),
50314
+ maxCostUsd: zod.z.number().positive(),
50315
+ maxRuntimeSec: zod.z.number().int().positive(),
50316
+ idempotencyKey: zod.z.string().min(8).max(80)
50317
+ }), zod.z.discriminatedUnion("kind", [zod.z.object({
50318
+ kind: zod.z.literal("started"),
50319
+ job: TrainingJobSchema
50320
+ }), zod.z.object({
50321
+ kind: zod.z.literal("refused"),
50322
+ reason: TrainingRefusalReasonSchema,
50323
+ detail: zod.z.string()
50324
+ })]), {
50325
+ kind: "mutation",
50326
+ auth: "admin",
50327
+ timeoutMs: 12e4
50328
+ }),
50329
+ listJobs: require_sleep.method(zod.z.object({}), zod.z.array(TrainingJobSchema).readonly(), { auth: "admin" }),
50330
+ getJob: require_sleep.method(IdInput, TrainingJobSchema.nullable(), { auth: "admin" }),
50331
+ cancelJob: require_sleep.method(IdInput, TrainingJobSchema, {
50332
+ kind: "mutation",
50333
+ auth: "admin",
50334
+ timeoutMs: 12e4
50335
+ }),
50336
+ /** The verified `result.json` of a job in `ready` or later; null before. */
50337
+ getJobResult: require_sleep.method(IdInput, TrainingResultSchema.nullable(), { auth: "admin" }),
50338
+ /** Hand the verified bundle to Model Studio; optionally canary right after. */
50339
+ registerResult: require_sleep.method(IdInput.extend({ canaryDeviceIds: zod.z.array(zod.z.number().int()).readonly() }), TrainingJobSchema, {
50340
+ kind: "mutation",
50341
+ auth: "admin",
50342
+ timeoutMs: 30 * 6e4
50343
+ }),
50344
+ /** Pin the registered model on these cameras, remembering what it replaced. */
50345
+ canaryResult: require_sleep.method(IdInput.extend({ deviceIds: zod.z.array(zod.z.number().int()).min(1).readonly() }), TrainingJobSchema, {
50346
+ kind: "mutation",
50347
+ auth: "admin",
50348
+ timeoutMs: 12e4
50349
+ }),
50350
+ /** Put every canary camera back exactly as it was. */
50351
+ rollbackCanary: require_sleep.method(IdInput, TrainingJobSchema, {
50352
+ kind: "mutation",
50353
+ auth: "admin",
50354
+ timeoutMs: 12e4
50355
+ }),
50356
+ /** Delete the staged artefacts of an unregistered result. */
50357
+ discardResult: require_sleep.method(IdInput, TrainingJobSchema, {
50358
+ kind: "mutation",
50359
+ auth: "admin"
50360
+ })
50361
+ }
50362
+ };
50363
+ //#endregion
49293
50364
  //#region src/capabilities/index.ts
49294
50365
  /**
49295
50366
  * Capability definitions — Zod-schema-first, single source of truth.
@@ -53462,6 +54533,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
53462
54533
  addonId: null,
53463
54534
  access: "create"
53464
54535
  },
54536
+ "backup.checkBackupKey": {
54537
+ capName: "backup",
54538
+ capScope: "system",
54539
+ addonId: null,
54540
+ access: "create"
54541
+ },
53465
54542
  "backup.delete": {
53466
54543
  capName: "backup",
53467
54544
  capScope: "system",
@@ -53474,6 +54551,18 @@ var METHOD_ACCESS_MAP = Object.freeze({
53474
54551
  addonId: null,
53475
54552
  access: "delete"
53476
54553
  },
54554
+ "backup.disableEncryption": {
54555
+ capName: "backup",
54556
+ capScope: "system",
54557
+ addonId: null,
54558
+ access: "create"
54559
+ },
54560
+ "backup.getEncryption": {
54561
+ capName: "backup",
54562
+ capScope: "system",
54563
+ addonId: null,
54564
+ access: "view"
54565
+ },
53477
54566
  "backup.getEntries": {
53478
54567
  capName: "backup",
53479
54568
  capScope: "system",
@@ -53528,6 +54617,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
53528
54617
  addonId: null,
53529
54618
  access: "create"
53530
54619
  },
54620
+ "backup.setupEncryption": {
54621
+ capName: "backup",
54622
+ capScope: "system",
54623
+ addonId: null,
54624
+ access: "create"
54625
+ },
53531
54626
  "backup.trigger": {
53532
54627
  capName: "backup",
53533
54628
  capScope: "system",
@@ -54080,6 +55175,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
54080
55175
  addonId: null,
54081
55176
  access: "create"
54082
55177
  },
55178
+ "customModelRegistry.importModelBundle": {
55179
+ capName: "custom-model-registry",
55180
+ capScope: "system",
55181
+ addonId: null,
55182
+ access: "create"
55183
+ },
54083
55184
  "customModelRegistry.listModels": {
54084
55185
  capName: "custom-model-registry",
54085
55186
  capScope: "system",
@@ -55520,6 +56621,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
55520
56621
  addonId: null,
55521
56622
  access: "view"
55522
56623
  },
56624
+ "keychainAdmin.acknowledgeReset": {
56625
+ capName: "keychain-admin",
56626
+ capScope: "system",
56627
+ addonId: null,
56628
+ access: "create"
56629
+ },
55523
56630
  "keychainAdmin.deleteOrphans": {
55524
56631
  capName: "keychain-admin",
55525
56632
  capScope: "system",
@@ -55556,6 +56663,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
55556
56663
  addonId: null,
55557
56664
  access: "delete"
55558
56665
  },
56666
+ "keychainAdmin.resetReport": {
56667
+ capName: "keychain-admin",
56668
+ capScope: "system",
56669
+ addonId: null,
56670
+ access: "delete"
56671
+ },
55559
56672
  "keychainAdmin.reveal": {
55560
56673
  capName: "keychain-admin",
55561
56674
  capScope: "system",
@@ -57302,6 +58415,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
57302
58415
  addonId: null,
57303
58416
  access: "view"
57304
58417
  },
58418
+ "pipelineAnalytics.offerRetrainArchive": {
58419
+ capName: "pipeline-analytics",
58420
+ capScope: "device",
58421
+ addonId: null,
58422
+ access: "create"
58423
+ },
57305
58424
  "pipelineAnalytics.ownersWithMedia": {
57306
58425
  capName: "pipeline-analytics",
57307
58426
  capScope: "device",
@@ -59840,6 +60959,174 @@ var METHOD_ACCESS_MAP = Object.freeze({
59840
60959
  addonId: null,
59841
60960
  access: "view"
59842
60961
  },
60962
+ "training.canaryResult": {
60963
+ capName: "training",
60964
+ capScope: "system",
60965
+ addonId: null,
60966
+ access: "create"
60967
+ },
60968
+ "training.cancelJob": {
60969
+ capName: "training",
60970
+ capScope: "system",
60971
+ addonId: null,
60972
+ access: "create"
60973
+ },
60974
+ "training.discardResult": {
60975
+ capName: "training",
60976
+ capScope: "system",
60977
+ addonId: null,
60978
+ access: "create"
60979
+ },
60980
+ "training.findDatasetVersionIdByName": {
60981
+ capName: "training",
60982
+ capScope: "system",
60983
+ addonId: null,
60984
+ access: "view"
60985
+ },
60986
+ "training.getDatasetVersion": {
60987
+ capName: "training",
60988
+ capScope: "system",
60989
+ addonId: null,
60990
+ access: "view"
60991
+ },
60992
+ "training.getJob": {
60993
+ capName: "training",
60994
+ capScope: "system",
60995
+ addonId: null,
60996
+ access: "view"
60997
+ },
60998
+ "training.getJobResult": {
60999
+ capName: "training",
61000
+ capScope: "system",
61001
+ addonId: null,
61002
+ access: "view"
61003
+ },
61004
+ "training.listBaseModels": {
61005
+ capName: "training",
61006
+ capScope: "system",
61007
+ addonId: null,
61008
+ access: "view"
61009
+ },
61010
+ "training.listDatasetVersions": {
61011
+ capName: "training",
61012
+ capScope: "system",
61013
+ addonId: null,
61014
+ access: "view"
61015
+ },
61016
+ "training.listJobs": {
61017
+ capName: "training",
61018
+ capScope: "system",
61019
+ addonId: null,
61020
+ access: "view"
61021
+ },
61022
+ "training.planJob": {
61023
+ capName: "training",
61024
+ capScope: "system",
61025
+ addonId: null,
61026
+ access: "view"
61027
+ },
61028
+ "training.putDatasetVersion": {
61029
+ capName: "training",
61030
+ capScope: "system",
61031
+ addonId: null,
61032
+ access: "create"
61033
+ },
61034
+ "training.registerResult": {
61035
+ capName: "training",
61036
+ capScope: "system",
61037
+ addonId: null,
61038
+ access: "create"
61039
+ },
61040
+ "training.removeDatasetVersion": {
61041
+ capName: "training",
61042
+ capScope: "system",
61043
+ addonId: null,
61044
+ access: "delete"
61045
+ },
61046
+ "training.rollbackCanary": {
61047
+ capName: "training",
61048
+ capScope: "system",
61049
+ addonId: null,
61050
+ access: "create"
61051
+ },
61052
+ "training.startJob": {
61053
+ capName: "training",
61054
+ capScope: "system",
61055
+ addonId: null,
61056
+ access: "create"
61057
+ },
61058
+ "trainingProvider.cancelJob": {
61059
+ capName: "training-provider",
61060
+ capScope: "system",
61061
+ addonId: null,
61062
+ access: "create"
61063
+ },
61064
+ "trainingProvider.cleanupJob": {
61065
+ capName: "training-provider",
61066
+ capScope: "system",
61067
+ addonId: null,
61068
+ access: "create"
61069
+ },
61070
+ "trainingProvider.describe": {
61071
+ capName: "training-provider",
61072
+ capScope: "system",
61073
+ addonId: null,
61074
+ access: "view"
61075
+ },
61076
+ "trainingProvider.estimateJob": {
61077
+ capName: "training-provider",
61078
+ capScope: "system",
61079
+ addonId: null,
61080
+ access: "view"
61081
+ },
61082
+ "trainingProvider.getJob": {
61083
+ capName: "training-provider",
61084
+ capScope: "system",
61085
+ addonId: null,
61086
+ access: "view"
61087
+ },
61088
+ "trainingProvider.listJobEvents": {
61089
+ capName: "training-provider",
61090
+ capScope: "system",
61091
+ addonId: null,
61092
+ access: "view"
61093
+ },
61094
+ "trainingProvider.listJobs": {
61095
+ capName: "training-provider",
61096
+ capScope: "system",
61097
+ addonId: null,
61098
+ access: "view"
61099
+ },
61100
+ "trainingProvider.offerArtifact": {
61101
+ capName: "training-provider",
61102
+ capScope: "system",
61103
+ addonId: null,
61104
+ access: "create"
61105
+ },
61106
+ "trainingProvider.readResult": {
61107
+ capName: "training-provider",
61108
+ capScope: "system",
61109
+ addonId: null,
61110
+ access: "create"
61111
+ },
61112
+ "trainingProvider.submitJob": {
61113
+ capName: "training-provider",
61114
+ capScope: "system",
61115
+ addonId: null,
61116
+ access: "create"
61117
+ },
61118
+ "trainingProvider.uploadDataset": {
61119
+ capName: "training-provider",
61120
+ capScope: "system",
61121
+ addonId: null,
61122
+ access: "create"
61123
+ },
61124
+ "trainingProvider.validateCredentials": {
61125
+ capName: "training-provider",
61126
+ capScope: "system",
61127
+ addonId: null,
61128
+ access: "create"
61129
+ },
59843
61130
  "turnProvider.getTurnServers": {
59844
61131
  capName: "turn-provider",
59845
61132
  capScope: "system",
@@ -59864,12 +61151,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
59864
61151
  addonId: null,
59865
61152
  access: "create"
59866
61153
  },
59867
- "userManagement.createApiKey": {
59868
- capName: "user-management",
59869
- capScope: "system",
59870
- addonId: null,
59871
- access: "create"
59872
- },
59873
61154
  "userManagement.createScopedToken": {
59874
61155
  capName: "user-management",
59875
61156
  capScope: "system",
@@ -59906,12 +61187,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
59906
61187
  addonId: null,
59907
61188
  access: "view"
59908
61189
  },
59909
- "userManagement.linkExternalIdentity": {
59910
- capName: "user-management",
59911
- capScope: "system",
59912
- addonId: null,
59913
- access: "create"
59914
- },
59915
61190
  "userManagement.listApiKeys": {
59916
61191
  capName: "user-management",
59917
61192
  capScope: "system",
@@ -60014,12 +61289,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
60014
61289
  addonId: null,
60015
61290
  access: "create"
60016
61291
  },
60017
- "userManagement.validateApiKey": {
60018
- capName: "user-management",
60019
- capScope: "system",
60020
- addonId: null,
60021
- access: "view"
60022
- },
60023
61292
  "userManagement.validateCredentials": {
60024
61293
  capName: "user-management",
60025
61294
  capScope: "system",
@@ -60600,6 +61869,8 @@ var KNOWN_CAP_NAMES = [
60600
61869
  "temperature-sensor",
60601
61870
  "terminal-session",
60602
61871
  "toast",
61872
+ "training",
61873
+ "training-provider",
60603
61874
  "turn-provider",
60604
61875
  "update",
60605
61876
  "user-management",
@@ -60784,6 +62055,8 @@ var SYSTEM_CAP_NAMES = [
60784
62055
  "system",
60785
62056
  "terminal-session",
60786
62057
  "toast",
62058
+ "training",
62059
+ "training-provider",
60787
62060
  "turn-provider",
60788
62061
  "user-management",
60789
62062
  "user-passkeys",
@@ -64290,6 +65563,8 @@ var CAPABILITY_NAMES = {
64290
65563
  temperatureSensor: "temperature-sensor",
64291
65564
  terminalSession: "terminal-session",
64292
65565
  toast: "toast",
65566
+ training: "training",
65567
+ trainingProvider: "training-provider",
64293
65568
  turnProvider: "turn-provider",
64294
65569
  update: "update",
64295
65570
  userManagement: "user-management",
@@ -64913,6 +66188,14 @@ var CAPABILITY_ROUTER_KEYS = [
64913
66188
  key: "toast",
64914
66189
  name: "toast"
64915
66190
  },
66191
+ {
66192
+ key: "training",
66193
+ name: "training"
66194
+ },
66195
+ {
66196
+ key: "trainingProvider",
66197
+ name: "training-provider"
66198
+ },
64916
66199
  {
64917
66200
  key: "turnProvider",
64918
66201
  name: "turn-provider"
@@ -65139,6 +66422,8 @@ var ALL_CAPABILITY_DEFINITIONS = [
65139
66422
  temperatureSensorCapability,
65140
66423
  terminalSessionCapability,
65141
66424
  toastCapability,
66425
+ trainingCapability,
66426
+ trainingProviderCapability,
65142
66427
  turnProviderCapability,
65143
66428
  updateCapability,
65144
66429
  userManagementCapability,
@@ -67519,6 +68804,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
67519
68804
  form: "single",
67520
68805
  optional: false
67521
68806
  }],
68807
+ "training.canaryResult": [{
68808
+ name: "deviceIds",
68809
+ form: "array",
68810
+ optional: false
68811
+ }],
67522
68812
  "update.getStatus": [{
67523
68813
  name: "deviceId",
67524
68814
  form: "single",
@@ -67923,7 +69213,8 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
67923
69213
  "streamBroker.restartProfile",
67924
69214
  "streamBroker.retractCameraStream",
67925
69215
  "streamBroker.setDeviceAudioMute",
67926
- "streamBroker.unassignProfile"
69216
+ "streamBroker.unassignProfile",
69217
+ "training.canaryResult"
67927
69218
  ];
67928
69219
  //#endregion
67929
69220
  //#region src/generated/provider-kind-map.ts
@@ -68481,6 +69772,10 @@ function createSystemProxy(api) {
68481
69772
  listLocations: (input) => dispatch("backup", "listLocations", "query", input),
68482
69773
  getEntries: (input) => dispatch("backup", "getEntries", "query", input),
68483
69774
  restore: (input) => dispatch("backup", "restore", "mutation", input),
69775
+ getEncryption: (input) => dispatch("backup", "getEncryption", "query", input),
69776
+ setupEncryption: (input) => dispatch("backup", "setupEncryption", "mutation", input),
69777
+ disableEncryption: (input) => dispatch("backup", "disableEncryption", "mutation", input),
69778
+ checkBackupKey: (input) => dispatch("backup", "checkBackupKey", "mutation", input),
68484
69779
  delete: (input) => dispatch("backup", "delete", "mutation", input),
68485
69780
  listArchives: (input) => dispatch("backup", "listArchives", "query", input),
68486
69781
  upsertDestinationPolicy: (input) => dispatch("backup", "upsertDestinationPolicy", "mutation", input),
@@ -68668,7 +69963,9 @@ function createSystemProxy(api) {
68668
69963
  rotateMasterKey: (input) => dispatch("keychainAdmin", "rotateMasterKey", "mutation", input),
68669
69964
  purgeRetiredKeys: (input) => dispatch("keychainAdmin", "purgeRetiredKeys", "mutation", input),
68670
69965
  downloadRecoveryKey: (input) => dispatch("keychainAdmin", "downloadRecoveryKey", "mutation", input),
68671
- resetKeychain: (input) => dispatch("keychainAdmin", "resetKeychain", "mutation", input)
69966
+ resetKeychain: (input) => dispatch("keychainAdmin", "resetKeychain", "mutation", input),
69967
+ resetReport: (input) => dispatch("keychainAdmin", "resetReport", "query", input),
69968
+ acknowledgeReset: (input) => dispatch("keychainAdmin", "acknowledgeReset", "mutation", input)
68672
69969
  },
68673
69970
  llm: {
68674
69971
  generate: (input) => dispatch("llm", "generate", "mutation", input),
@@ -69080,6 +70377,24 @@ function createSystemProxy(api) {
69080
70377
  close: (input) => dispatch("terminalSession", "close", "mutation", input)
69081
70378
  },
69082
70379
  toast: { onToast: (input, push) => dispatch("toast", "onToast", "subscription", input, push) },
70380
+ training: {
70381
+ putDatasetVersion: (input) => dispatch("training", "putDatasetVersion", "mutation", input),
70382
+ getDatasetVersion: (input) => dispatch("training", "getDatasetVersion", "query", input),
70383
+ listDatasetVersions: (input) => dispatch("training", "listDatasetVersions", "query", input),
70384
+ findDatasetVersionIdByName: (input) => dispatch("training", "findDatasetVersionIdByName", "query", input),
70385
+ removeDatasetVersion: (input) => dispatch("training", "removeDatasetVersion", "mutation", input),
70386
+ listBaseModels: (input) => dispatch("training", "listBaseModels", "query", input),
70387
+ planJob: (input) => dispatch("training", "planJob", "query", input),
70388
+ startJob: (input) => dispatch("training", "startJob", "mutation", input),
70389
+ listJobs: (input) => dispatch("training", "listJobs", "query", input),
70390
+ getJob: (input) => dispatch("training", "getJob", "query", input),
70391
+ cancelJob: (input) => dispatch("training", "cancelJob", "mutation", input),
70392
+ getJobResult: (input) => dispatch("training", "getJobResult", "query", input),
70393
+ registerResult: (input) => dispatch("training", "registerResult", "mutation", input),
70394
+ canaryResult: (input) => dispatch("training", "canaryResult", "mutation", input),
70395
+ rollbackCanary: (input) => dispatch("training", "rollbackCanary", "mutation", input),
70396
+ discardResult: (input) => dispatch("training", "discardResult", "mutation", input)
70397
+ },
69083
70398
  turnProvider: { getTurnServers: (input) => dispatch("turnProvider", "getTurnServers", "query", input) },
69084
70399
  userManagement: {
69085
70400
  listUsers: (input) => dispatch("userManagement", "listUsers", "query", input),
@@ -69090,9 +70405,7 @@ function createSystemProxy(api) {
69090
70405
  setUserScopes: (input) => dispatch("userManagement", "setUserScopes", "mutation", input),
69091
70406
  validateCredentials: (input) => dispatch("userManagement", "validateCredentials", "mutation", input),
69092
70407
  listApiKeys: (input) => dispatch("userManagement", "listApiKeys", "query", input),
69093
- createApiKey: (input) => dispatch("userManagement", "createApiKey", "mutation", input),
69094
70408
  revokeApiKey: (input) => dispatch("userManagement", "revokeApiKey", "mutation", input),
69095
- validateApiKey: (input) => dispatch("userManagement", "validateApiKey", "mutation", input),
69096
70409
  createScopedToken: (input) => dispatch("userManagement", "createScopedToken", "mutation", input),
69097
70410
  revokeScopedToken: (input) => dispatch("userManagement", "revokeScopedToken", "mutation", input),
69098
70411
  validateScopedToken: (input) => dispatch("userManagement", "validateScopedToken", "query", input),
@@ -69108,7 +70421,6 @@ function createSystemProxy(api) {
69108
70421
  oauthVerifyAccessToken: (input) => dispatch("userManagement", "oauthVerifyAccessToken", "query", input),
69109
70422
  listExternalIdentities: (input) => dispatch("userManagement", "listExternalIdentities", "query", input),
69110
70423
  findUserByExternalIdentity: (input) => dispatch("userManagement", "findUserByExternalIdentity", "query", input),
69111
- linkExternalIdentity: (input) => dispatch("userManagement", "linkExternalIdentity", "mutation", input),
69112
70424
  unlinkExternalIdentity: (input) => dispatch("userManagement", "unlinkExternalIdentity", "mutation", input),
69113
70425
  listOauthSessions: (input) => dispatch("userManagement", "listOauthSessions", "query", input),
69114
70426
  revokeOauthSession: (input) => dispatch("userManagement", "revokeOauthSession", "mutation", input)
@@ -76447,7 +77759,12 @@ var CREDENTIAL_PARAM_PATTERNS = [
76447
77759
  /^bearer$/i,
76448
77760
  /^api[_-]?key$/i,
76449
77761
  /^access[_-]?token$/i,
76450
- /^refresh[_-]?token$/i
77762
+ /^refresh[_-]?token$/i,
77763
+ /^bridge$/i,
77764
+ /^code$/i,
77765
+ /^state$/i,
77766
+ /^challenge$/i,
77767
+ /^link$/i
76451
77768
  ];
76452
77769
  function isCredentialParam(name) {
76453
77770
  return CREDENTIAL_PARAM_PATTERNS.some((re) => re.test(name));
@@ -76469,6 +77786,10 @@ function isCredentialParam(name) {
76469
77786
  * are NOT masked (those are entity references, not credentials).
76470
77787
  */
76471
77788
  function maskUrlCredentials(rawUrl) {
77789
+ if (rawUrl.startsWith("/") && !rawUrl.startsWith("//")) {
77790
+ const masked = maskUrlCredentials(`http://relative.invalid${rawUrl}`);
77791
+ return masked.startsWith("http://relative.invalid") ? masked.slice(23) : rawUrl;
77792
+ }
76472
77793
  try {
76473
77794
  const u = new URL(rawUrl);
76474
77795
  let touched = false;
@@ -77407,6 +78728,8 @@ exports.APPEARANCE_BLOCKS = APPEARANCE_BLOCKS;
77407
78728
  exports.APPEARANCE_DESCRIPTOR_VERSION = APPEARANCE_DESCRIPTOR_VERSION;
77408
78729
  exports.APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT = APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT;
77409
78730
  exports.APPLE_SA_TO_MACRO = APPLE_SA_TO_MACRO;
78731
+ exports.APP_AUTH_CALLBACK_MAX_LENGTH = APP_AUTH_CALLBACK_MAX_LENGTH;
78732
+ exports.APP_AUTH_CALLBACK_URLS = APP_AUTH_CALLBACK_URLS;
77410
78733
  exports.ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT = ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT;
77411
78734
  exports.AUDIO_ANALYSIS_CAP_NAME = AUDIO_ANALYSIS_CAP_NAME;
77412
78735
  exports.AUDIO_BACKEND_CHOICES = AUDIO_BACKEND_CHOICES;
@@ -77511,7 +78834,9 @@ exports.BOOT_RECOVERY_BACKOFF_MS = require_sleep.BOOT_RECOVERY_BACKOFF_MS;
77511
78834
  exports.BUILTIN_RESULT_KINDS = BUILTIN_RESULT_KINDS;
77512
78835
  exports.BackgroundRunRegistry = BackgroundRunRegistry;
77513
78836
  exports.BacklightModeSchema = BacklightModeSchema;
78837
+ exports.BackupArchiveEncryptionSchema = BackupArchiveEncryptionSchema;
77514
78838
  exports.BackupDestinationInfoSchema = BackupDestinationInfoSchema;
78839
+ exports.BackupEncryptionStatusSchema = BackupEncryptionStatusSchema;
77515
78840
  exports.BackupEntrySchema = BackupEntrySchema;
77516
78841
  exports.BackupRunPhaseSchema = BackupRunPhaseSchema;
77517
78842
  exports.BackupRunSchema = BackupRunSchema;
@@ -77554,6 +78879,7 @@ exports.CAMERA_SWITCH_CATALOG = CAMERA_SWITCH_CATALOG;
77554
78879
  exports.CAMERA_SWITCH_ORDER = CAMERA_SWITCH_ORDER;
77555
78880
  exports.CAMERA_TRIGGER = CAMERA_TRIGGER;
77556
78881
  exports.CAMSTACK_APP_LINK_ORIGIN = CAMSTACK_APP_LINK_ORIGIN;
78882
+ exports.CAMSTACK_EVENT_PREFIX = CAMSTACK_EVENT_PREFIX;
77557
78883
  exports.CAM_PROFILE_ORDER = require_sleep.CAM_PROFILE_ORDER;
77558
78884
  exports.CAPABILITY_NAMES = CAPABILITY_NAMES;
77559
78885
  exports.CAPABILITY_ROUTER_KEYS = CAPABILITY_ROUTER_KEYS;
@@ -77758,8 +79084,6 @@ exports.CoreBlockSourceSchema = CoreBlockSourceSchema;
77758
79084
  exports.CoreBlockStatusSchema = CoreBlockStatusSchema;
77759
79085
  exports.CoverStateSchema = CoverStateSchema;
77760
79086
  exports.CoverStatusSchema = CoverStatusSchema;
77761
- exports.CreateApiKeyInputSchema = CreateApiKeyInputSchema;
77762
- exports.CreateApiKeyResultSchema = CreateApiKeyResultSchema;
77763
79087
  exports.CreateIntegrationInputSchema = CreateIntegrationInputSchema;
77764
79088
  exports.CreateRetrainDatasetVersionResultSchema = CreateRetrainDatasetVersionResultSchema;
77765
79089
  exports.CreateScopedTokenInputSchema = CreateScopedTokenInputSchema;
@@ -78031,6 +79355,8 @@ exports.ImageSettingsOptionsSchema = ImageSettingsOptionsSchema;
78031
79355
  exports.ImageSettingsPatchSchema = ImageSettingsPatchSchema;
78032
79356
  exports.ImageSettingsStatusSchema = ImageSettingsStatusSchema;
78033
79357
  exports.ImageStatusSchema = ImageStatusSchema;
79358
+ exports.ImportModelBundleInputSchema = ImportModelBundleInputSchema;
79359
+ exports.ImportModelBundleResultSchema = ImportModelBundleResultSchema;
78034
79360
  exports.InferenceDeviceExclusionReasonSchema = InferenceDeviceExclusionReasonSchema;
78035
79361
  exports.IngestOwnerSchema = IngestOwnerSchema;
78036
79362
  exports.InstalledPackageSchema = InstalledPackageSchema;
@@ -78040,6 +79366,7 @@ exports.IntercomAbilitySchema = IntercomAbilitySchema;
78040
79366
  exports.IntercomStatusSchema = IntercomStatusSchema;
78041
79367
  exports.KEYCHAIN_MAX_REFS_PER_CALL = KEYCHAIN_MAX_REFS_PER_CALL;
78042
79368
  exports.KEYCHAIN_RESET_CONFIRMATION = KEYCHAIN_RESET_CONFIRMATION;
79369
+ exports.KEYCHAIN_RESET_TRIGGER_ACTOR = KEYCHAIN_RESET_TRIGGER_ACTOR;
78043
79370
  exports.KNOWN_CAP_NAMES = KNOWN_CAP_NAMES;
78044
79371
  exports.KeptReasonSchema = KeptReasonSchema;
78045
79372
  exports.KeyEventSchema = KeyEventSchema;
@@ -78048,6 +79375,7 @@ exports.KeychainAuditActionSchema = KeychainAuditActionSchema;
78048
79375
  exports.KeychainAuditEntrySchema = KeychainAuditEntrySchema;
78049
79376
  exports.KeychainKeySourceKindSchema = KeychainKeySourceKindSchema;
78050
79377
  exports.KeychainKeySourceSchema = KeychainKeySourceSchema;
79378
+ exports.KeychainResetRecordSchema = KeychainResetRecordSchema;
78051
79379
  exports.KeychainResolveEntrySchema = KeychainResolveEntrySchema;
78052
79380
  exports.KeychainResolveResultSchema = KeychainResolveResultSchema;
78053
79381
  exports.KeychainSecretMetaSchema = KeychainSecretMetaSchema;
@@ -78210,6 +79538,7 @@ exports.MethodAccessSchema = MethodAccessSchema;
78210
79538
  exports.MigrateDeviceResultSchema = MigrateDeviceResultSchema;
78211
79539
  exports.MigrateSwitchOutcomeSchema = MigrateSwitchOutcomeSchema;
78212
79540
  exports.MigrateSwitchReportSchema = MigrateSwitchReportSchema;
79541
+ exports.ModelBundleFileSchema = ModelBundleFileSchema;
78213
79542
  exports.ModelCatalogEntrySchema = ModelCatalogEntrySchema;
78214
79543
  exports.ModelConvertInputSchema = ModelConvertInputSchema;
78215
79544
  exports.ModelConvertMetadataSchema = ModelConvertMetadataSchema;
@@ -78597,6 +79926,8 @@ exports.ProbeTargetConfigResultSchema = ProbeTargetConfigResultSchema;
78597
79926
  exports.ProfileRtspEntrySchema = require_sleep.ProfileRtspEntrySchema;
78598
79927
  exports.ProfileSlotSchema = require_sleep.ProfileSlotSchema;
78599
79928
  exports.ProfileSlotStatusSchema = require_sleep.ProfileSlotStatusSchema;
79929
+ exports.ProviderJobStateSchema = ProviderJobStateSchema;
79930
+ exports.ProviderJobStatusSchema = ProviderJobStatusSchema;
78600
79931
  exports.ProviderMotionDataSchema = ProviderMotionDataSchema;
78601
79932
  exports.ProviderStatusSchema = ProviderStatusSchema;
78602
79933
  exports.PtzAutotrackRuntimeStateSchema = PtzAutotrackRuntimeStateSchema;
@@ -78774,6 +80105,8 @@ exports.SOURCE_CAP_ACTIVE_FIELD = require_composition.SOURCE_CAP_ACTIVE_FIELD;
78774
80105
  exports.SOURCE_CAP_CHANGED_AT_FIELD = require_composition.SOURCE_CAP_CHANGED_AT_FIELD;
78775
80106
  exports.SOURCE_DEVICE_TYPES = require_composition.SOURCE_DEVICE_TYPES;
78776
80107
  exports.SOURCE_INFO_METADATA_KEY = SOURCE_INFO_METADATA_KEY;
80108
+ exports.SSO_STATE_COOKIE = SSO_STATE_COOKIE;
80109
+ exports.SSO_STATE_COOKIE_MAX_AGE_SEC = SSO_STATE_COOKIE_MAX_AGE_SEC;
78777
80110
  exports.STATE_LABELS = STATE_LABELS;
78778
80111
  exports.STATE_LABEL_KEYS = STATE_LABEL_KEYS;
78779
80112
  exports.STATIONARY_OVERLAY_STYLE = STATIONARY_OVERLAY_STYLE;
@@ -78912,6 +80245,8 @@ exports.TAXONOMY_COLORS = TAXONOMY_COLORS;
78912
80245
  exports.TIMELAPSE_DENSE_FLOOR_SEC = TIMELAPSE_DENSE_FLOOR_SEC;
78913
80246
  exports.TIMEZONES = TIMEZONES;
78914
80247
  exports.TRACK_RELATIONS_DEFAULT_LIMIT = TRACK_RELATIONS_DEFAULT_LIMIT;
80248
+ exports.TRAINING_JOB_SCHEMA = TRAINING_JOB_SCHEMA;
80249
+ exports.TRAINING_RESULT_SCHEMA = TRAINING_RESULT_SCHEMA;
78915
80250
  exports.TRANSCODE_DOWN_MAX_BITRATE_KBPS = TRANSCODE_DOWN_MAX_BITRATE_KBPS;
78916
80251
  exports.TRANSCODE_DOWN_MAX_HEIGHT = TRANSCODE_DOWN_MAX_HEIGHT;
78917
80252
  exports.TamperStatusSchema = TamperStatusSchema;
@@ -78955,8 +80290,36 @@ exports.TrackSourceSchema = TrackSourceSchema;
78955
80290
  exports.TrackStateSchema = TrackStateSchema;
78956
80291
  exports.TrackZoneFilterSchema = TrackZoneFilterSchema;
78957
80292
  exports.TrackedDetectionSchema = TrackedDetectionSchema;
80293
+ exports.TrainerSourceRefSchema = TrainerSourceRefSchema;
80294
+ exports.TrainingBaseModelSchema = TrainingBaseModelSchema;
80295
+ exports.TrainingCanarySchema = TrainingCanarySchema;
80296
+ exports.TrainingCatalogDraftSchema = TrainingCatalogDraftSchema;
80297
+ exports.TrainingCredentialCheckSchema = TrainingCredentialCheckSchema;
80298
+ exports.TrainingDatasetVersionRowSchema = TrainingDatasetVersionRowSchema;
80299
+ exports.TrainingEvalClassSchema = TrainingEvalClassSchema;
80300
+ exports.TrainingEvalReportSchema = TrainingEvalReportSchema;
80301
+ exports.TrainingEventSchema = TrainingEventSchema;
78958
80302
  exports.TrainingExportDeviceTotalsSchema = TrainingExportDeviceTotalsSchema;
80303
+ exports.TrainingExportSchema = TrainingExportSchema;
78959
80304
  exports.TrainingExportSummarySchema = TrainingExportSummarySchema;
80305
+ exports.TrainingFailureReasonSchema = TrainingFailureReasonSchema;
80306
+ exports.TrainingGpuOptionSchema = TrainingGpuOptionSchema;
80307
+ exports.TrainingJobPlanSchema = TrainingJobPlanSchema;
80308
+ exports.TrainingJobRequestSchema = TrainingJobRequestSchema;
80309
+ exports.TrainingJobSchema = TrainingJobSchema;
80310
+ exports.TrainingJobSpecSchema = TrainingJobSpecSchema;
80311
+ exports.TrainingJobStateSchema = TrainingJobStateSchema;
80312
+ exports.TrainingLogLineSchema = TrainingLogLineSchema;
80313
+ exports.TrainingPresetSchema = TrainingPresetSchema;
80314
+ exports.TrainingProgressPointSchema = TrainingProgressPointSchema;
80315
+ exports.TrainingProviderDefaultsSchema = TrainingProviderDefaultsSchema;
80316
+ exports.TrainingProviderDescriptorSchema = TrainingProviderDescriptorSchema;
80317
+ exports.TrainingRefusalReasonSchema = TrainingRefusalReasonSchema;
80318
+ exports.TrainingRegionOptionSchema = TrainingRegionOptionSchema;
80319
+ exports.TrainingResultFileSchema = TrainingResultFileSchema;
80320
+ exports.TrainingResultSchema = TrainingResultSchema;
80321
+ exports.TrainingSplitPlanSchema = TrainingSplitPlanSchema;
80322
+ exports.TrainingStageSchema = TrainingStageSchema;
78960
80323
  exports.TransportPlaneCountsSchema = TransportPlaneCountsSchema;
78961
80324
  exports.TransportPlaneSchema = TransportPlaneSchema;
78962
80325
  exports.TurnServerSchema = TurnServerSchema;
@@ -79129,6 +80492,7 @@ exports.cameraSensorRefKey = cameraSensorRefKey;
79129
80492
  exports.cameraStreamsCapability = cameraStreamsCapability;
79130
80493
  exports.canConvertUnit = canConvertUnit;
79131
80494
  exports.canonicalEgressPlan = canonicalEgressPlan;
80495
+ exports.canonicalizeAppCallback = canonicalizeAppCallback;
79132
80496
  exports.capacitySessionsOf = capacitySessionsOf;
79133
80497
  exports.carbonMonoxideCapability = carbonMonoxideCapability;
79134
80498
  exports.cellsToRects = cellsToRects;
@@ -79362,6 +80726,7 @@ exports.gifFromMp4Args = gifFromMp4Args;
79362
80726
  exports.globalSecretScope = require_sleep.globalSecretScope;
79363
80727
  exports.hasModelBoundOverrides = hasModelBoundOverrides;
79364
80728
  exports.hasMotionTrigger = hasMotionTrigger;
80729
+ exports.hasUrlScheme = hasUrlScheme;
79365
80730
  exports.hfModelUrl = hfModelUrl;
79366
80731
  exports.htmlToText = htmlToText;
79367
80732
  exports.hubAddressHostname = hubAddressHostname;
@@ -79542,6 +80907,7 @@ exports.osdManagerCapability = osdManagerCapability;
79542
80907
  exports.overlayClusterStepSettings = overlayClusterStepSettings;
79543
80908
  exports.packagePickerItems = packagePickerItems;
79544
80909
  exports.parseAdminBase = parseAdminBase;
80910
+ exports.parseAppAuthCallback = parseAppAuthCallback;
79545
80911
  exports.parseCameraStreamConfig = parseCameraStreamConfig;
79546
80912
  exports.parseExpression = require_composition.parseExpression;
79547
80913
  exports.parseJsonArray = require_sleep.parseJsonArray;
@@ -79557,6 +80923,7 @@ exports.parseSecretStatePath = require_sleep.parseSecretStatePath;
79557
80923
  exports.parseSessionPlacementPolicy = parseSessionPlacementPolicy;
79558
80924
  exports.parseShareSource = parseShareSource;
79559
80925
  exports.parseStreamParamsFormPatch = parseStreamParamsFormPatch;
80926
+ exports.parseTrainingEventLine = parseTrainingEventLine;
79560
80927
  exports.patchAudio = patchAudio;
79561
80928
  exports.petFeederCapability = petFeederCapability;
79562
80929
  exports.pickAccessoryControl = pickAccessoryControl;
@@ -79788,6 +81155,8 @@ exports.toStreamSourceEntry = toStreamSourceEntry;
79788
81155
  exports.toastCapability = toastCapability;
79789
81156
  exports.toggleAudioLabel = toggleAudioLabel;
79790
81157
  exports.tokenize = require_composition.tokenize;
81158
+ exports.trainingCapability = trainingCapability;
81159
+ exports.trainingProviderCapability = trainingProviderCapability;
79791
81160
  exports.transcodeBody = transcodeBody;
79792
81161
  exports.transformSecretWrite = require_sleep.transformSecretWrite;
79793
81162
  exports.tryConvertUnit = tryConvertUnit;