@camstack/addon-export-alexa 1.2.145 → 1.2.146

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.
@@ -5,7 +5,7 @@ import "node:fs";
5
5
  import "node:path";
6
6
  import "node:child_process";
7
7
  import "node:zlib";
8
- //#region ../types/dist/event-category-C4hVnRo8.mjs
8
+ //#region ../types/dist/event-category-BvOFi6PY.mjs
9
9
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
10
10
  EventCategory["SystemBoot"] = "system.boot";
11
11
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -69,6 +69,24 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
69
69
  * consumes this category and maps it to the `addon-crash-loop` kind.
70
70
  */
71
71
  EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
72
+ /**
73
+ * A runner whose addon refused to start with a typed reason (D877) - parked
74
+ * in `refused`, never counted by the crash breaker, retried on operator
75
+ * action. One event per refusal.
76
+ */
77
+ EventCategory["AddonRunnerRefused"] = "addon.runner-refused";
78
+ /**
79
+ * A runner settled on a state (D877): `running` (READY), `crashed`, `failed` or
80
+ * `refused`. In-process telemetry for the boot check (re-evaluate while any
81
+ * runner is still pending) and the alert centre (close a recovered runner).
82
+ */
83
+ EventCategory["ProcessStateChanged"] = "process.state-changed";
84
+ /**
85
+ * The node's one-shot runner boot check (D877): planned runners against the
86
+ * process service, `degraded` when any is failed, refused or missing. The
87
+ * alert centre turns it into one alert and a direct critical push.
88
+ */
89
+ EventCategory["SystemRunnerCheck"] = "system.runner-check";
72
90
  EventCategory["AddonError"] = "addon.error";
73
91
  EventCategory["AddonPageReady"] = "addon.page-ready";
74
92
  EventCategory["AddonWidgetReady"] = "addon.widget-ready";
@@ -5393,7 +5411,7 @@ var ZodIssueCode = {
5393
5411
  var ZodFirstPartyTypeKind;
5394
5412
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5395
5413
  //#endregion
5396
- //#region ../types/dist/sleep-bwsTj221.mjs
5414
+ //#region ../types/dist/sleep-bZIhUvjd.mjs
5397
5415
  /**
5398
5416
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5399
5417
  * window to float samples (D455).
@@ -5510,7 +5528,7 @@ function isKeychainStoredField(field) {
5510
5528
  var SECRET_CLEAR = { $secretClear: true };
5511
5529
  /** The `'***'` token D634 redaction writes for non-admins. */
5512
5530
  var LEGACY_DEVICE_REDACTION = "***";
5513
- function isRecord$2(value) {
5531
+ function isRecord$5(value) {
5514
5532
  return typeof value === "object" && value !== null && !Array.isArray(value);
5515
5533
  }
5516
5534
  function makeSecretMarker(ref) {
@@ -5521,12 +5539,12 @@ function makeSecretMarker(ref) {
5521
5539
  }
5522
5540
  /** A stored marker: an object whose `$secret` is a non-empty string. */
5523
5541
  function isSecretMarker(value) {
5524
- if (!isRecord$2(value)) return false;
5542
+ if (!isRecord$5(value)) return false;
5525
5543
  const ref = value["$secret"];
5526
5544
  return typeof ref === "string" && ref.length > 0;
5527
5545
  }
5528
5546
  function isSecretClear(value) {
5529
- return isRecord$2(value) && value["$secretClear"] === true;
5547
+ return isRecord$5(value) && value["$secretClear"] === true;
5530
5548
  }
5531
5549
  /**
5532
5550
  * The UI view of a stored secret field value: a marker becomes "set", inline
@@ -6136,7 +6154,7 @@ var KeychainWriteRefusedError = class extends Error {
6136
6154
  }
6137
6155
  };
6138
6156
  var KEEP = { kind: "keep" };
6139
- function isRecord$1(value) {
6157
+ function isRecord$4(value) {
6140
6158
  return typeof value === "object" && value !== null && !Array.isArray(value);
6141
6159
  }
6142
6160
  function defaultMintId() {
@@ -6149,7 +6167,7 @@ function collectSecretMarkerRefs(value, out = []) {
6149
6167
  return out;
6150
6168
  }
6151
6169
  if (Array.isArray(value)) for (const item of value) collectSecretMarkerRefs(item, out);
6152
- else if (isRecord$1(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
6170
+ else if (isRecord$4(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
6153
6171
  return out;
6154
6172
  }
6155
6173
  async function storedValueEquals(secrets, marker, candidate) {
@@ -6204,7 +6222,7 @@ function rowId(row, idKey) {
6204
6222
  return null;
6205
6223
  }
6206
6224
  async function writeArray(ctx, node, incoming, stored, fieldPath) {
6207
- const storedRows = Array.isArray(stored) ? stored.filter(isRecord$1) : [];
6225
+ const storedRows = Array.isArray(stored) ? stored.filter(isRecord$4) : [];
6208
6226
  if (!Array.isArray(incoming)) {
6209
6227
  ctx.deletes.push(...collectSecretMarkerRefs(storedRows));
6210
6228
  return {
@@ -6220,7 +6238,7 @@ async function writeArray(ctx, node, incoming, stored, fieldPath) {
6220
6238
  const kept = /* @__PURE__ */ new Set();
6221
6239
  const rows = [];
6222
6240
  for (const row of incoming) {
6223
- if (!isRecord$1(row)) {
6241
+ if (!isRecord$4(row)) {
6224
6242
  rows.push(row);
6225
6243
  continue;
6226
6244
  }
@@ -6245,7 +6263,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
6245
6263
  case "leaf": return writeLeaf(ctx, incoming, stored, fieldPath);
6246
6264
  case "array": return writeArray(ctx, node, incoming, stored, fieldPath);
6247
6265
  case "object": {
6248
- if (!isRecord$1(incoming)) {
6266
+ if (!isRecord$4(incoming)) {
6249
6267
  if (incoming === void 0) return KEEP;
6250
6268
  ctx.deletes.push(...collectSecretMarkerRefs(stored));
6251
6269
  return {
@@ -6253,7 +6271,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
6253
6271
  value: incoming
6254
6272
  };
6255
6273
  }
6256
- const storedObj = isRecord$1(stored) ? stored : {};
6274
+ const storedObj = isRecord$4(stored) ? stored : {};
6257
6275
  return {
6258
6276
  kind: "value",
6259
6277
  value: await writeMembers(ctx, node.children, incoming, storedObj, (m) => `${fieldPath}.${m}`)
@@ -6376,7 +6394,7 @@ async function resolveSecretMarkers(value, secrets, options = {}) {
6376
6394
  value: items
6377
6395
  };
6378
6396
  }
6379
- if (isRecord$1(v)) {
6397
+ if (isRecord$4(v)) {
6380
6398
  const out = {};
6381
6399
  for (const [k, child] of Object.entries(v)) {
6382
6400
  const s = substitute(child);
@@ -7299,7 +7317,7 @@ var BaseAddon = class {
7299
7317
  if (!ctx) return;
7300
7318
  const addonId = ctx.id;
7301
7319
  setImmediate(() => {
7302
- ctx.api.addons?.restartAddon?.mutate({ addonId }).then(() => {
7320
+ ctx.api.addons.restartAddon.mutate({ addonId }).then(() => {
7303
7321
  ctx.logger.info("addon auto-restart triggered by restart-required setting change", { meta: { changedFields: patchKeys.filter((k) => restartKeys.has(k)) } });
7304
7322
  }).catch((err) => {
7305
7323
  ctx.logger.error("addon auto-restart failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
@@ -7793,6 +7811,89 @@ var PeerBytesTicketSchema = object({
7793
7811
  */
7794
7812
  declaredBytes: number().int().nonnegative().nullable()
7795
7813
  });
7814
+ /** Limits and names of `ctx.records` (D881). One authority; the engine and the facade read it. */
7815
+ /** The files a kind may live in. `history` is device-history's (D850), never records. */
7816
+ var RECORD_DATABASES = ["settings", "events"];
7817
+ /** The classes of a kind: the `@durable` vocabulary, one authority (replaces the annotation). */
7818
+ var RECORD_CLASSES = [
7819
+ "config",
7820
+ "ledger",
7821
+ "audit",
7822
+ "mirror",
7823
+ "ephemeral"
7824
+ ];
7825
+ var RECORD_DEFAULT_MAX_DATA_BYTES = 64 * 1024;
7826
+ var RECORD_MAX_DATA_BYTES = 1024 * 1024;
7827
+ var RECORD_BATCH_MAX = 1e3;
7828
+ var RECORD_QUERY_MAX = 1e3;
7829
+ /**
7830
+ * Record kinds (D881): the declaration an addon makes of one kind of fact, the
7831
+ * Zod row schema that describes it, and the helper that turns the two into the
7832
+ * JSON the engine stores.
7833
+ *
7834
+ * A kind is declared ONCE, next to the code that owns it, and the engine's
7835
+ * reconciler creates its indexes - nothing creates DDL at runtime from a write.
7836
+ * Everything the generic machinery needs (secret fields, the entry descriptor)
7837
+ * is DERIVED from the Zod schema: `.meta({ secret: true })` marks a credential,
7838
+ * never a field name (D879).
7839
+ */
7840
+ /** A JSON field path: `trackId`, `auth.accessToken`. Charset-restricted: it is rendered into DDL. */
7841
+ var RecordFieldPathSchema = string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,63}(\.[A-Za-z_][A-Za-z0-9_]{0,63}){0,3}$/);
7842
+ var RecordIndexSchema = object({
7843
+ name: string().regex(/^[a-z][a-z0-9_]{0,31}$/),
7844
+ fields: array(RecordFieldPathSchema).min(1).max(4),
7845
+ unique: boolean().optional()
7846
+ }).strict();
7847
+ var RecordRetentionSchema = union([
7848
+ object({
7849
+ ttlMs: number().int().positive(),
7850
+ from: _enum(["at", "write"])
7851
+ }).strict(),
7852
+ object({
7853
+ maxRows: number().int().positive().optional(),
7854
+ maxRowsPerDevice: number().int().positive().optional()
7855
+ }).strict().refine((r) => r.maxRows !== void 0 || r.maxRowsPerDevice !== void 0, { message: "name maxRows, maxRowsPerDevice or both" }),
7856
+ object({
7857
+ owner: string().min(1),
7858
+ reason: string().min(1)
7859
+ }).strict(),
7860
+ object({ none: string().min(1) }).strict()
7861
+ ]);
7862
+ /** The descriptor a generic entries UI reads (D881 "generic entries"). */
7863
+ var EntryDescriptorSchema = object({
7864
+ title: string().min(1),
7865
+ /** The record body field shown as the entry's name. */
7866
+ nameField: string().min(1),
7867
+ /** JSON Schema of the entry body; `secret: true` marks a password field. */
7868
+ fields: record(string(), unknown())
7869
+ }).strict();
7870
+ /** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
7871
+ var RecordKindDeclarationSchema = object({
7872
+ database: _enum(RECORD_DATABASES).default("settings"),
7873
+ class: _enum(RECORD_CLASSES),
7874
+ writeTrigger: string().min(1),
7875
+ device: _enum([
7876
+ "required",
7877
+ "optional",
7878
+ "none"
7879
+ ]).default("none"),
7880
+ at: _enum(["required", "none"]).default("none"),
7881
+ indexes: array(RecordIndexSchema).max(8).default([]),
7882
+ retention: RecordRetentionSchema,
7883
+ deviceRemoval: _enum(["delete", "none"]).default("none"),
7884
+ maxDataBytes: number().int().positive().max(RECORD_MAX_DATA_BYTES).default(RECORD_DEFAULT_MAX_DATA_BYTES),
7885
+ /** Derived from the Zod schema; never written by hand. */
7886
+ secretPaths: array(string().min(1)).default([]),
7887
+ /** The id key of each array that carries a secret (`{ headers: 'name' }`). */
7888
+ secretArrayKeys: record(string(), string()).default({}),
7889
+ /** The legacy table this kind adopts from; the boot guard reads it (D853: no migration code). */
7890
+ adoptsFrom: string().min(1).optional(),
7891
+ /** Kinds that must agree through `transact` sit in one file under one family name. */
7892
+ transactFamily: string().min(1).optional(),
7893
+ entry: EntryDescriptorSchema.optional()
7894
+ }).strict();
7895
+ /** The kind names: lower-case, dash separated, short enough for an index name. */
7896
+ var RecordKindNameSchema = string().regex(/^[a-z][a-z0-9-]{0,47}$/);
7796
7897
  /** Shared Zod schemas used across streaming capabilities. */
7797
7898
  var CamProfileSchema = _enum([
7798
7899
  "high",
@@ -15746,6 +15847,41 @@ var ComposableCapabilitiesSchema = object({ caps: array(object({
15746
15847
  keyField: string()
15747
15848
  }).optional()
15748
15849
  })) });
15850
+ /**
15851
+ * The report of a one-shot "move this owner's plaintext secrets into the
15852
+ * keychain" run (D878). COUNTS only - never a value, never a ref.
15853
+ *
15854
+ * The owner runs it on its own rows, through its own write path; an operator
15855
+ * script (`scripts/hub/migrate-raw-secrets.ts`) calls the owner's cap method.
15856
+ * Dry run (`apply: false`) reports what WOULD move and changes nothing.
15857
+ */
15858
+ var RawSecretMigrationInputSchema = object({
15859
+ /** `false` (the default of the script) = report only. */
15860
+ apply: boolean() });
15861
+ var RawSecretMigrationReportSchema = object({
15862
+ apply: boolean(),
15863
+ /** Rows that can carry a secret (a profile, an enrolment). */
15864
+ rows: number().int(),
15865
+ /** Rows whose secret was plaintext when the run started. */
15866
+ raw: number().int(),
15867
+ /** Rows that already held a keychain marker when the run started. */
15868
+ markers: number().int(),
15869
+ /** Plaintext rows moved by THIS run (always 0 on a dry run). */
15870
+ migrated: number().int(),
15871
+ /** Plaintext rows left in place because the move or its read-back failed. */
15872
+ failed: number().int(),
15873
+ /** After the run: rows still holding plaintext. */
15874
+ remainingRaw: number().int(),
15875
+ /** After the run: markers the keychain could not resolve right now. */
15876
+ unresolvedMarkers: number().int(),
15877
+ /**
15878
+ * A second, redundant copy of the secrets' rows that the run found (and, on
15879
+ * `apply`, deleted after verifying the first). Owners with a single copy omit it.
15880
+ */
15881
+ redundantCopies: number().int().optional(),
15882
+ /** True when nothing is raw and every marker resolves. */
15883
+ verified: boolean()
15884
+ });
15749
15885
  /** Where a block runs. The operator chooses — a block driving a device on an
15750
15886
  * agent is the reason placement is not fixed to the hub. */
15751
15887
  var CoreBlockPlacementSchema = union([literal("hub"), string().min(1)]);
@@ -15972,6 +16108,9 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
15972
16108
  }), SettingsUpdateResultSchema, {
15973
16109
  kind: "mutation",
15974
16110
  auth: "admin"
16111
+ }), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
16112
+ kind: "mutation",
16113
+ auth: "admin"
15975
16114
  }), method(object({}), object({ libs: array(object({
15976
16115
  filePath: string(),
15977
16116
  content: string()
@@ -16234,6 +16373,222 @@ id: union([string(), number()]) }), {
16234
16373
  kind: "mutation",
16235
16374
  auth: "admin"
16236
16375
  });
16376
+ /**
16377
+ * records - an addon's own facts and documents (D881): ledgers, audit rows,
16378
+ * config documents, mirrors. The third storage API next to `ctx.settings`
16379
+ * (operator intent, D870) and device-history (numbers over time, D850).
16380
+ *
16381
+ * Who the OWNER is: `callerAddonId`, stamped by the transport on a call that
16382
+ * crossed a process and stated by a hub in-process caller (`ctx.records` does
16383
+ * that with the addon id closed over). It is deliberately NOT in any input
16384
+ * schema, so a session can never supply it, and a call with no stamp is refused
16385
+ * `records/no-caller`. A kind is readable and writable only by its owner; other
16386
+ * addons go through the owner's capability.
16387
+ *
16388
+ * Every read is three-way: a row, `null`, or the call THROWS. A failed read is
16389
+ * never `[]`. Secret fields are never on the wire: a read shows the
16390
+ * redaction token, `secretRefs` hands the owner's `ctx.secrets` the refs it
16391
+ * resolves itself, and a write may carry only a keychain marker bound to the
16392
+ * row's own ref.
16393
+ *
16394
+ * Internal: addons reach it through `ctx.records`, never directly.
16395
+ */
16396
+ var RecordIdSchema = string().min(1).max(256);
16397
+ /** A JSON object body. Size is the engine's check (`maxDataBytes`), not a schema's. */
16398
+ var RecordBodySchema = record(string(), unknown());
16399
+ var RecordInputSchema = object({
16400
+ id: RecordIdSchema,
16401
+ /** The device this row belongs to (D865 removal, per-device reads). */
16402
+ deviceId: number().int().optional(),
16403
+ /** The domain clock, ms: observed / created / opened. */
16404
+ at: number().int().optional(),
16405
+ /** Producer-set expiry, ms. Refused on a kind whose retention is an engine TTL. */
16406
+ expiresAt: number().int().optional(),
16407
+ data: RecordBodySchema
16408
+ });
16409
+ var RecordViewSchema = object({
16410
+ id: string(),
16411
+ deviceId: number().int().nullable(),
16412
+ at: number().nullable(),
16413
+ expiresAt: number().nullable(),
16414
+ rev: number().int(),
16415
+ updatedAt: number(),
16416
+ data: RecordBodySchema
16417
+ });
16418
+ /** Declared index fields only. Anything else does not compile, by design. */
16419
+ var RecordWhereSchema = record(RecordFieldPathSchema, union([
16420
+ string(),
16421
+ number(),
16422
+ boolean(),
16423
+ object({ in: array(union([
16424
+ string(),
16425
+ number(),
16426
+ boolean()
16427
+ ])).min(1).max(RECORD_BATCH_MAX) }),
16428
+ object({
16429
+ gt: union([string(), number()]).optional(),
16430
+ gte: union([string(), number()]).optional(),
16431
+ lt: union([string(), number()]).optional(),
16432
+ lte: union([string(), number()]).optional()
16433
+ }).refine((r) => Object.keys(r).length > 0, { message: "name at least one bound" })
16434
+ ]));
16435
+ var KindShape = { kind: RecordKindNameSchema };
16436
+ var TimeWindowShape = {
16437
+ deviceId: number().int().optional(),
16438
+ atFrom: number().optional(),
16439
+ atTo: number().optional()
16440
+ };
16441
+ var RecordQueryInputSchema = object({
16442
+ ...KindShape,
16443
+ ...TimeWindowShape,
16444
+ where: RecordWhereSchema.optional(),
16445
+ /** Without `where`: `at` (default for a kind with a clock) or `id`. With `where` the order is the index's. */
16446
+ order: _enum(["at", "id"]).optional(),
16447
+ desc: boolean().optional(),
16448
+ limit: number().int().min(1).max(RECORD_QUERY_MAX).default(100),
16449
+ /** Opaque keyset cursor from a previous answer. There is no offset. */
16450
+ cursor: string().min(1).optional()
16451
+ });
16452
+ var RecordQueryResultSchema = object({
16453
+ records: array(RecordViewSchema),
16454
+ nextCursor: string().nullable()
16455
+ });
16456
+ var RecordKindStateSchema = _enum([
16457
+ "created",
16458
+ "unchanged",
16459
+ "updated"
16460
+ ]);
16461
+ var DeclareKindResultSchema = object({
16462
+ kindId: number().int(),
16463
+ state: RecordKindStateSchema,
16464
+ createdIndexes: array(string()),
16465
+ /** The boot guard: the kind is empty while its legacy table still holds rows. */
16466
+ adoptionPending: object({
16467
+ legacyTable: string(),
16468
+ legacyRows: number().int()
16469
+ }).nullable()
16470
+ });
16471
+ /** Keychain refs a write released (the old marker is gone from the row): the owner deletes the values. */
16472
+ var SecretRefsList = array(string());
16473
+ var RecordSecretRefsSchema = record(string(), record(string(), string()));
16474
+ method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema) }), object({ kinds: record(string(), DeclareKindResultSchema) }), {
16475
+ kind: "mutation",
16476
+ auth: "admin"
16477
+ }), method(object({
16478
+ ...KindShape,
16479
+ id: RecordIdSchema
16480
+ }), RecordViewSchema.nullable(), { auth: "admin" }), method(object({
16481
+ ...KindShape,
16482
+ ids: array(RecordIdSchema).min(1).max(RECORD_BATCH_MAX)
16483
+ }), array(RecordViewSchema), { auth: "admin" }), method(object({
16484
+ ...KindShape,
16485
+ ids: array(RecordIdSchema).min(1).max(RECORD_BATCH_MAX)
16486
+ }), RecordSecretRefsSchema, { auth: "admin" }), method(object({
16487
+ ...KindShape,
16488
+ record: RecordInputSchema,
16489
+ /** Compare-and-set. `0` means "the row must not exist". */
16490
+ ifRev: number().int().min(0).optional()
16491
+ }), object({
16492
+ rev: number().int(),
16493
+ releasedRefs: SecretRefsList
16494
+ }), {
16495
+ kind: "mutation",
16496
+ auth: "admin"
16497
+ }), method(object({
16498
+ ...KindShape,
16499
+ records: array(RecordInputSchema).min(1).max(RECORD_BATCH_MAX)
16500
+ }), object({
16501
+ count: number().int(),
16502
+ releasedRefs: SecretRefsList
16503
+ }), {
16504
+ kind: "mutation",
16505
+ auth: "admin"
16506
+ }), method(object({
16507
+ ...KindShape,
16508
+ id: RecordIdSchema,
16509
+ data: RecordBodySchema,
16510
+ at: number().int().nullable().optional(),
16511
+ expiresAt: number().int().nullable().optional(),
16512
+ ifRev: number().int().min(1).optional()
16513
+ }), object({
16514
+ rev: number().int(),
16515
+ releasedRefs: SecretRefsList
16516
+ }), {
16517
+ kind: "mutation",
16518
+ auth: "admin"
16519
+ }), method(object({
16520
+ ...KindShape,
16521
+ id: RecordIdSchema
16522
+ }), object({
16523
+ deleted: boolean(),
16524
+ secretRefs: SecretRefsList
16525
+ }), {
16526
+ kind: "mutation",
16527
+ auth: "admin"
16528
+ }), method(object({
16529
+ ...KindShape,
16530
+ ids: array(RecordIdSchema).min(1).max(RECORD_BATCH_MAX)
16531
+ }), object({
16532
+ deleted: number().int(),
16533
+ secretRefs: SecretRefsList
16534
+ }), {
16535
+ kind: "mutation",
16536
+ auth: "admin"
16537
+ }), method(RecordQueryInputSchema, RecordQueryResultSchema, { auth: "admin" }), method(object({
16538
+ ...KindShape,
16539
+ ...TimeWindowShape,
16540
+ where: RecordWhereSchema.optional()
16541
+ }), object({ count: number().int() }), { auth: "admin" }), method(object({
16542
+ ...KindShape,
16543
+ deviceId: number().int().optional(),
16544
+ from: number(),
16545
+ to: number(),
16546
+ bucketMs: number().int().positive()
16547
+ }), object({ buckets: array(object({
16548
+ bucketStart: number(),
16549
+ count: number().int()
16550
+ })) }), { auth: "admin" }), method(object({
16551
+ ...KindShape,
16552
+ op: _enum([
16553
+ "sum",
16554
+ "min",
16555
+ "max",
16556
+ "count"
16557
+ ]),
16558
+ field: RecordFieldPathSchema.optional(),
16559
+ groupBy: RecordFieldPathSchema.optional(),
16560
+ where: RecordWhereSchema.optional()
16561
+ }), object({ rows: array(object({
16562
+ group: union([
16563
+ string(),
16564
+ number(),
16565
+ _null()
16566
+ ]),
16567
+ value: number().nullable()
16568
+ })) }), { auth: "admin" }), method(object({
16569
+ ...KindShape,
16570
+ deviceId: number().int().optional(),
16571
+ atBefore: number().optional(),
16572
+ where: RecordWhereSchema.optional()
16573
+ }), object({
16574
+ deleted: number().int(),
16575
+ secretRefs: SecretRefsList
16576
+ }), {
16577
+ kind: "mutation",
16578
+ auth: "admin"
16579
+ }), method(object({
16580
+ deviceId: number().int(),
16581
+ kinds: array(RecordKindNameSchema).optional()
16582
+ }), object({
16583
+ deleted: record(string(), number().int()),
16584
+ secretRefs: SecretRefsList
16585
+ }), {
16586
+ kind: "mutation",
16587
+ auth: "admin"
16588
+ }), method(object(KindShape), object({ id: number().int() }), {
16589
+ kind: "mutation",
16590
+ auth: "admin"
16591
+ });
16237
16592
  /** One table of the settings database. */
16238
16593
  var StorageTableSchema = object({
16239
16594
  /** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
@@ -16246,6 +16601,28 @@ var StorageTableSchema = object({
16246
16601
  /** Declared by an addon since this engine process started (a running addon claims it). */
16247
16602
  declaredThisBoot: boolean()
16248
16603
  });
16604
+ /** One declared record kind (D881) as System -> Data shows it. */
16605
+ var StorageKindSchema = object({
16606
+ owner: string(),
16607
+ kind: string(),
16608
+ database: _enum(["settings", "events"]),
16609
+ class: string(),
16610
+ state: _enum([
16611
+ "declared",
16612
+ "orphaned",
16613
+ "dropped"
16614
+ ]),
16615
+ /** `null` when the caller asked for no counts (`counts: false`). */
16616
+ rows: number().int().nonnegative().nullable(),
16617
+ /** Rows x the average size of a sample; null for an empty kind. */
16618
+ bytesEstimate: number().int().nonnegative().nullable(),
16619
+ writeTrigger: string(),
16620
+ retention: RecordRetentionSchema,
16621
+ /** `true` when the kind is an entry kind (the generic entries UI lists it). */
16622
+ entry: boolean(),
16623
+ /** The whole declaration, secret paths and entry descriptor included (the entries service builds its handle from it). */
16624
+ declaration: RecordKindDeclarationSchema
16625
+ });
16249
16626
  method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: array(StorageTableSchema) }), { auth: "admin" }), method(object({
16250
16627
  collection: string().min(1),
16251
16628
  expectRows: number().int().nonnegative()
@@ -16255,6 +16632,87 @@ method(object({ ownerPrefix: string().min(1).optional() }), object({ tables: arr
16255
16632
  }), {
16256
16633
  kind: "mutation",
16257
16634
  auth: "admin"
16635
+ }), method(object({
16636
+ owner: string().min(1).optional(),
16637
+ /** `false` skips the per-kind row count (a catalog read only). Default true. */
16638
+ counts: boolean().optional()
16639
+ }), object({ kinds: array(StorageKindSchema) }), { auth: "admin" }), method(RecordQueryInputSchema.extend({
16640
+ owner: string().min(1),
16641
+ kind: RecordKindNameSchema
16642
+ }), RecordQueryResultSchema, { auth: "admin" }), method(object({
16643
+ owner: string().min(1),
16644
+ kind: RecordKindNameSchema,
16645
+ records: array(RecordInputSchema).max(RECORD_BATCH_MAX),
16646
+ /** The LAST batch: the copy is complete, the boot guard stops asking. */
16647
+ complete: boolean().optional()
16648
+ }).refine((input) => input.records.length > 0 || input.complete === true, { message: "records must be non-empty unless complete is true" }), object({ adopted: number().int() }), {
16649
+ kind: "mutation",
16650
+ auth: "admin"
16651
+ }), method(object({
16652
+ collection: string().min(1),
16653
+ cursor: string().optional(),
16654
+ limit: number().int().min(1).max(1e3).optional()
16655
+ }), object({
16656
+ rows: array(object({
16657
+ id: string(),
16658
+ data: record(string(), unknown())
16659
+ })),
16660
+ nextCursor: string().nullable()
16661
+ }), { auth: "admin" }), method(object({ collection: string().min(1) }), object({ adopted: boolean() }), { auth: "admin" });
16662
+ /**
16663
+ * record-entries - the ONE admin surface for every list of user-created entries
16664
+ * (D881): notification targets, brokers, LLM profiles, anything an addon
16665
+ * declares as an ENTRY kind (`entry: { title }` in `defineRecordKinds`).
16666
+ *
16667
+ * The UI is generic. `listEntryKinds` hands it, per kind, the JSON Schema of
16668
+ * the entry body with `secret: true` on every credential field, so a password
16669
+ * field is derived from the schema and never from a name. `putEntry` takes the
16670
+ * redaction token for an untouched secret (the stored value is kept), a string
16671
+ * for a new one, and the clear instruction to remove one. A read never carries
16672
+ * a secret value, and a locked keychain refuses the write with
16673
+ * `records/secret-unavailable` instead of storing plaintext.
16674
+ *
16675
+ * Hub-only, served in-process (it acts for each entry's owner on the keychain).
16676
+ */
16677
+ var EntryKindInfoSchema = object({
16678
+ owner: string(),
16679
+ kind: RecordKindNameSchema,
16680
+ title: string(),
16681
+ nameField: string(),
16682
+ /** JSON Schema of the body; `secret: true` marks a password field. */
16683
+ fields: record(string(), unknown()),
16684
+ secretPaths: array(string()),
16685
+ rows: number().int().nonnegative()
16686
+ });
16687
+ var EntryViewSchema = object({
16688
+ id: RecordIdSchema,
16689
+ name: string(),
16690
+ rev: number().int(),
16691
+ updatedAt: number(),
16692
+ /** Secret fields hold the redaction token. */
16693
+ data: RecordBodySchema
16694
+ });
16695
+ var EntryAddress = {
16696
+ owner: string().min(1),
16697
+ kind: RecordKindNameSchema
16698
+ };
16699
+ method(object({}), object({ kinds: array(EntryKindInfoSchema) }), { auth: "admin" }), method(object({ ...EntryAddress }), object({ entries: array(EntryViewSchema) }), { auth: "admin" }), method(object({
16700
+ ...EntryAddress,
16701
+ id: RecordIdSchema.optional(),
16702
+ data: RecordBodySchema,
16703
+ ifRev: number().int().min(1).optional()
16704
+ }), object({
16705
+ id: string(),
16706
+ rev: number().int()
16707
+ }), {
16708
+ kind: "mutation",
16709
+ auth: "admin"
16710
+ }), method(object({
16711
+ ...EntryAddress,
16712
+ id: RecordIdSchema
16713
+ }), object({ deleted: boolean() }), {
16714
+ kind: "mutation",
16715
+ auth: "admin"
16258
16716
  });
16259
16717
  /**
16260
16718
  * `keychain` — the hub's encrypted store of secret values (D787).
@@ -39301,6 +39759,9 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
39301
39759
  }), _void(), { kind: "mutation" }), method(object({}), array(LlmProfileKindDescriptorSchema)), method(object({}), array(LlmProfileSchema)), method(object({ profile: LlmProfileSchema }), LlmProfileSchema, {
39302
39760
  kind: "mutation",
39303
39761
  auth: "admin"
39762
+ }), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
39763
+ kind: "mutation",
39764
+ auth: "admin"
39304
39765
  }), method(ProfileRefInputSchema, _void(), {
39305
39766
  kind: "mutation",
39306
39767
  auth: "admin"
@@ -49740,6 +50201,41 @@ var ServerRollbackInfoSchema = object({
49740
50201
  atMs: number(),
49741
50202
  reason: string()
49742
50203
  });
50204
+ /**
50205
+ * The runner boot check (D877): the runners this node PLANNED (hub: one per
50206
+ * `resolveRunnerId` over its forked addons; agent: the runners its process
50207
+ * service holds, because only the hub plans) against the states the process
50208
+ * service reports. Kept in memory, recomputed by the same one-shot check after
50209
+ * every boot, served on `getServerPackageStatus`.
50210
+ *
50211
+ * `failed` is the D6 breaker's terminal state, `refused` a deterministic Init
50212
+ * refusal (an addon that said "I will not start, and here is why"), `missing` a
50213
+ * planned runner the process service has no entry for.
50214
+ */
50215
+ var RunnerRefusalSchema = object({
50216
+ runnerId: string(),
50217
+ addonIds: array(string()),
50218
+ reason: string()
50219
+ });
50220
+ var RunnerBootCheckSchema = object({
50221
+ checkedAtMs: number(),
50222
+ /** Runners planned for this node. */
50223
+ expected: number(),
50224
+ /** Planned runners whose process is `running`. */
50225
+ running: number(),
50226
+ failed: array(string()),
50227
+ refused: array(RunnerRefusalSchema),
50228
+ missing: array(string()),
50229
+ /**
50230
+ * Runners still on their way: `starting`, or `crashed` waiting on a backoff
50231
+ * respawn. The check is FINAL only when this is empty; until then nothing is
50232
+ * pushed and the verdict is re-evaluated on the next runner state change.
50233
+ * Optional for version skew (absent = settled).
50234
+ */
50235
+ pending: array(string()).optional(),
50236
+ /** True when the plan is the hub's (`missing` is then meaningful); false on an agent. */
50237
+ planKnown: boolean()
50238
+ });
49743
50239
  var ServerPackageStatusSchema = object({
49744
50240
  /** Root package name (`@camstack/server` on the hub). */
49745
50241
  packageName: string(),
@@ -49802,7 +50298,14 @@ var ServerPackageStatusSchema = object({
49802
50298
  * for version skew: an older provider's payload simply omits it, and an
49803
50299
  * absent wrapper is unknown — never `native`.
49804
50300
  */
49805
- wrapper: WrapperIdentitySchema.optional()
50301
+ wrapper: WrapperIdentitySchema.optional(),
50302
+ /**
50303
+ * What this node PLANNED to run against what its process service reports
50304
+ * (D877). Absent until the one-shot boot check has run (~60 s after boot) and
50305
+ * on a provider that predates it. Absent is "not checked yet", never "all
50306
+ * well": a consumer that needs the answer treats it as pending.
50307
+ */
50308
+ runners: RunnerBootCheckSchema.optional()
49806
50309
  });
49807
50310
  var ServerUpdateCheckResultSchema = object({
49808
50311
  packageName: string(),
@@ -49853,6 +50356,13 @@ var ServerUpdateOutcomeSchema = _enum([
49853
50356
  "refused",
49854
50357
  "failed"
49855
50358
  ]);
50359
+ /** One addon the pre-flight found the target version would refuse (D877). */
50360
+ var UpdateBlockerSchema = object({
50361
+ addonId: string(),
50362
+ reason: string(),
50363
+ /** What the operator does about it. */
50364
+ remedy: string()
50365
+ });
49856
50366
  var ServerUpdateActionResultSchema = object({
49857
50367
  accepted: boolean(),
49858
50368
  targetVersion: string().nullable(),
@@ -49870,14 +50380,27 @@ var ServerUpdateActionResultSchema = object({
49870
50380
  * The failure itself, verbatim enough to act on (the npm output for a
49871
50381
  * staging install). Non-null only for `failed`.
49872
50382
  */
49873
- error: string().nullable().optional()
50383
+ error: string().nullable().optional(),
50384
+ /**
50385
+ * The addons the target version would refuse to start on this node's live
50386
+ * store (D877), present when the pre-flight refused the update
50387
+ * (`reason: 'addon-would-refuse'`). Optional for version skew.
50388
+ */
50389
+ blockers: array(UpdateBlockerSchema).optional()
49874
50390
  });
49875
50391
  method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), ServerUpdateCheckResultSchema, {
49876
50392
  kind: "mutation",
49877
50393
  auth: "admin"
49878
- }), method(object({
49879
- /** Explicit target version; omitted = latest from the registry. */
49880
- version: string().optional() }), ServerUpdateActionResultSchema, {
50394
+ }), method(object({
50395
+ /** Explicit target version; omitted = latest from the registry. */
50396
+ version: string().optional(),
50397
+ /**
50398
+ * Apply even though the pre-flight (D877) found addons the target would
50399
+ * refuse to start. Off by default: those addons stay down until the
50400
+ * remedy is run, which is the incident this gate exists to prevent.
50401
+ */
50402
+ acknowledgeRefusals: boolean().optional()
50403
+ }), ServerUpdateActionResultSchema, {
49881
50404
  kind: "mutation",
49882
50405
  auth: "admin",
49883
50406
  timeoutMs: 16 * 6e4
@@ -52290,7 +52813,9 @@ var ManifestShapeSchema = object({
52290
52813
  var AddonProcessSchema = object({
52291
52814
  pid: number().optional(),
52292
52815
  mode: string(),
52293
- state: string()
52816
+ state: string(),
52817
+ /** Why the runner is `refused` (an addon's own words), when it is (D877). */
52818
+ reason: string().optional()
52294
52819
  });
52295
52820
  /**
52296
52821
  * Per-addon health snapshot from the kernel's AddonHealthMonitor.
@@ -60374,7 +60899,11 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
60374
60899
  kind: "mutation",
60375
60900
  auth: "admin",
60376
60901
  access: "delete"
60377
- }), method(object({ userId: string() }), TotpStatusSchema, { auth: "admin" }), method(object({
60902
+ }), method(object({ userId: string() }), TotpStatusSchema, { auth: "admin" }), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
60903
+ kind: "mutation",
60904
+ auth: "admin",
60905
+ access: "create"
60906
+ }), method(object({
60378
60907
  userId: string(),
60379
60908
  code: string()
60380
60909
  }), object({ valid: boolean() }), {
@@ -62575,6 +63104,12 @@ Object.freeze({
62575
63104
  addonId: null,
62576
63105
  access: "view"
62577
63106
  },
63107
+ "coreBlocks.migrateRawSecrets": {
63108
+ capName: "core-blocks",
63109
+ capScope: "system",
63110
+ addonId: null,
63111
+ access: "create"
63112
+ },
62578
63113
  "coreBlocks.restart": {
62579
63114
  capName: "core-blocks",
62580
63115
  capScope: "system",
@@ -64435,6 +64970,12 @@ Object.freeze({
64435
64970
  addonId: null,
64436
64971
  access: "view"
64437
64972
  },
64973
+ "llm.migrateRawSecrets": {
64974
+ capName: "llm",
64975
+ capScope: "system",
64976
+ addonId: null,
64977
+ access: "create"
64978
+ },
64438
64979
  "llm.resolveModelRef": {
64439
64980
  capName: "llm",
64440
64981
  capScope: "system",
@@ -67321,6 +67862,30 @@ Object.freeze({
67321
67862
  addonId: null,
67322
67863
  access: "create"
67323
67864
  },
67865
+ "recordEntries.deleteEntry": {
67866
+ capName: "record-entries",
67867
+ capScope: "system",
67868
+ addonId: null,
67869
+ access: "delete"
67870
+ },
67871
+ "recordEntries.listEntries": {
67872
+ capName: "record-entries",
67873
+ capScope: "system",
67874
+ addonId: null,
67875
+ access: "view"
67876
+ },
67877
+ "recordEntries.listEntryKinds": {
67878
+ capName: "record-entries",
67879
+ capScope: "system",
67880
+ addonId: null,
67881
+ access: "view"
67882
+ },
67883
+ "recordEntries.putEntry": {
67884
+ capName: "record-entries",
67885
+ capScope: "system",
67886
+ addonId: null,
67887
+ access: "create"
67888
+ },
67324
67889
  "recording.getAvailability": {
67325
67890
  capName: "recording",
67326
67891
  capScope: "device",
@@ -67621,6 +68186,102 @@ Object.freeze({
67621
68186
  addonId: null,
67622
68187
  access: "view"
67623
68188
  },
68189
+ "records.aggregate": {
68190
+ capName: "records",
68191
+ capScope: "system",
68192
+ addonId: null,
68193
+ access: "view"
68194
+ },
68195
+ "records.allocateId": {
68196
+ capName: "records",
68197
+ capScope: "system",
68198
+ addonId: null,
68199
+ access: "create"
68200
+ },
68201
+ "records.count": {
68202
+ capName: "records",
68203
+ capScope: "system",
68204
+ addonId: null,
68205
+ access: "view"
68206
+ },
68207
+ "records.declareKinds": {
68208
+ capName: "records",
68209
+ capScope: "system",
68210
+ addonId: null,
68211
+ access: "create"
68212
+ },
68213
+ "records.delete": {
68214
+ capName: "records",
68215
+ capScope: "system",
68216
+ addonId: null,
68217
+ access: "delete"
68218
+ },
68219
+ "records.deleteDevice": {
68220
+ capName: "records",
68221
+ capScope: "system",
68222
+ addonId: null,
68223
+ access: "delete"
68224
+ },
68225
+ "records.deleteMany": {
68226
+ capName: "records",
68227
+ capScope: "system",
68228
+ addonId: null,
68229
+ access: "delete"
68230
+ },
68231
+ "records.deleteWhere": {
68232
+ capName: "records",
68233
+ capScope: "system",
68234
+ addonId: null,
68235
+ access: "delete"
68236
+ },
68237
+ "records.get": {
68238
+ capName: "records",
68239
+ capScope: "system",
68240
+ addonId: null,
68241
+ access: "view"
68242
+ },
68243
+ "records.getMany": {
68244
+ capName: "records",
68245
+ capScope: "system",
68246
+ addonId: null,
68247
+ access: "view"
68248
+ },
68249
+ "records.histogram": {
68250
+ capName: "records",
68251
+ capScope: "system",
68252
+ addonId: null,
68253
+ access: "view"
68254
+ },
68255
+ "records.patch": {
68256
+ capName: "records",
68257
+ capScope: "system",
68258
+ addonId: null,
68259
+ access: "create"
68260
+ },
68261
+ "records.put": {
68262
+ capName: "records",
68263
+ capScope: "system",
68264
+ addonId: null,
68265
+ access: "create"
68266
+ },
68267
+ "records.putMany": {
68268
+ capName: "records",
68269
+ capScope: "system",
68270
+ addonId: null,
68271
+ access: "create"
68272
+ },
68273
+ "records.query": {
68274
+ capName: "records",
68275
+ capScope: "system",
68276
+ addonId: null,
68277
+ access: "view"
68278
+ },
68279
+ "records.secretRefs": {
68280
+ capName: "records",
68281
+ capScope: "system",
68282
+ addonId: null,
68283
+ access: "view"
68284
+ },
67624
68285
  "sceneMonitor.captureReference": {
67625
68286
  capName: "scene-monitor",
67626
68287
  capScope: "device",
@@ -68053,18 +68714,48 @@ Object.freeze({
68053
68714
  addonId: null,
68054
68715
  access: "create"
68055
68716
  },
68717
+ "storageAdmin.adoptRecords": {
68718
+ capName: "storage-admin",
68719
+ capScope: "system",
68720
+ addonId: null,
68721
+ access: "create"
68722
+ },
68056
68723
  "storageAdmin.dropCollection": {
68057
68724
  capName: "storage-admin",
68058
68725
  capScope: "system",
68059
68726
  addonId: null,
68060
68727
  access: "delete"
68061
68728
  },
68729
+ "storageAdmin.isAdoptedLegacyTable": {
68730
+ capName: "storage-admin",
68731
+ capScope: "system",
68732
+ addonId: null,
68733
+ access: "view"
68734
+ },
68735
+ "storageAdmin.listKinds": {
68736
+ capName: "storage-admin",
68737
+ capScope: "system",
68738
+ addonId: null,
68739
+ access: "view"
68740
+ },
68062
68741
  "storageAdmin.listTables": {
68063
68742
  capName: "storage-admin",
68064
68743
  capScope: "system",
68065
68744
  addonId: null,
68066
68745
  access: "view"
68067
68746
  },
68747
+ "storageAdmin.readLegacyCollection": {
68748
+ capName: "storage-admin",
68749
+ capScope: "system",
68750
+ addonId: null,
68751
+ access: "view"
68752
+ },
68753
+ "storageAdmin.readRecords": {
68754
+ capName: "storage-admin",
68755
+ capScope: "system",
68756
+ addonId: null,
68757
+ access: "view"
68758
+ },
68068
68759
  "storageEvictable.evict": {
68069
68760
  capName: "storage-evictable",
68070
68761
  capScope: "system",
@@ -68977,6 +69668,12 @@ Object.freeze({
68977
69668
  addonId: null,
68978
69669
  access: "view"
68979
69670
  },
69671
+ "userManagement.migrateRawSecrets": {
69672
+ capName: "user-management",
69673
+ capScope: "system",
69674
+ addonId: null,
69675
+ access: "create"
69676
+ },
68980
69677
  "userManagement.oauthExchangeCode": {
68981
69678
  capName: "user-management",
68982
69679
  capScope: "system",
@@ -71653,6 +72350,37 @@ Object.freeze({
71653
72350
  form: "single",
71654
72351
  optional: false
71655
72352
  }],
72353
+ "records.count": [{
72354
+ name: "deviceId",
72355
+ form: "single",
72356
+ optional: true
72357
+ }],
72358
+ "records.deleteDevice": [{
72359
+ name: "deviceId",
72360
+ form: "single",
72361
+ optional: false
72362
+ }],
72363
+ "records.deleteWhere": [{
72364
+ name: "deviceId",
72365
+ form: "single",
72366
+ optional: true
72367
+ }],
72368
+ "records.histogram": [{
72369
+ name: "deviceId",
72370
+ form: "single",
72371
+ optional: true
72372
+ }],
72373
+ "records.putMany": [{
72374
+ name: "records",
72375
+ form: "object-array",
72376
+ optional: false,
72377
+ itemField: "deviceId"
72378
+ }],
72379
+ "records.query": [{
72380
+ name: "deviceId",
72381
+ form: "single",
72382
+ optional: true
72383
+ }],
71656
72384
  "sceneMonitor.captureReference": [{
71657
72385
  name: "deviceId",
71658
72386
  form: "single",
@@ -71769,6 +72497,17 @@ Object.freeze({
71769
72497
  form: "single",
71770
72498
  optional: false
71771
72499
  }],
72500
+ "storageAdmin.adoptRecords": [{
72501
+ name: "records",
72502
+ form: "object-array",
72503
+ optional: false,
72504
+ itemField: "deviceId"
72505
+ }],
72506
+ "storageAdmin.readRecords": [{
72507
+ name: "deviceId",
72508
+ form: "single",
72509
+ optional: true
72510
+ }],
71772
72511
  "streamBroker.acquireEgressTranscode": [{
71773
72512
  name: "deviceId",
71774
72513
  form: "single",