@camstack/types 1.2.396 → 1.2.398

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 (37) hide show
  1. package/dist/addon.js +17 -2
  2. package/dist/addon.mjs +15 -3
  3. package/dist/capabilities/dishwasher.cap.d.ts +9 -0
  4. package/dist/capabilities/index.d.ts +2 -2
  5. package/dist/capabilities/notification-rules.cap.d.ts +138 -0
  6. package/dist/capabilities/osd-manager.cap.d.ts +36 -0
  7. package/dist/capabilities/records.cap.d.ts +67 -3
  8. package/dist/capabilities/storage-admin.cap.d.ts +0 -2
  9. package/dist/capabilities/user-management.cap.d.ts +2 -28
  10. package/dist/client.d.ts +1 -1
  11. package/dist/client.js +324 -13
  12. package/dist/client.mjs +320 -14
  13. package/dist/enums/event-category.d.ts +17 -0
  14. package/dist/enums.js +1 -1
  15. package/dist/enums.mjs +1 -1
  16. package/dist/{event-category-eSqkye-K.js → event-category-7AwNbPjm.js} +17 -0
  17. package/dist/{event-category-DOl51-Ij.mjs → event-category-BfJwUd2S.mjs} +17 -0
  18. package/dist/generated/addon-api.d.ts +7 -14
  19. package/dist/generated/addon-cap-facts.d.ts +1 -1
  20. package/dist/generated/method-access-map.d.ts +1 -1
  21. package/dist/generated/system-proxy.d.ts +1 -1
  22. package/dist/index.d.ts +3 -2
  23. package/dist/index.js +426 -62
  24. package/dist/index.mjs +415 -61
  25. package/dist/interfaces/auth.d.ts +1 -1
  26. package/dist/interfaces/event-bus.d.ts +43 -5
  27. package/dist/notification/alert-episode.d.ts +7 -0
  28. package/dist/notification/system-event-classes.d.ts +73 -0
  29. package/dist/records/errors.d.ts +9 -1
  30. package/dist/records/index.d.ts +1 -0
  31. package/dist/records/record-kind.d.ts +62 -2
  32. package/dist/records/records-access.d.ts +36 -1
  33. package/dist/records/transact-rules.d.ts +7 -0
  34. package/dist/schemas/auth-records.d.ts +0 -12
  35. package/dist/{sleep-Re8daN0Y.js → sleep-CD18m9HF.js} +478 -311
  36. package/dist/{sleep-_sV1BE2f.mjs → sleep-DJFUfKvA.mjs} +461 -312
  37. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- export { type UserRecord, type ApiKeyRecord, type TokenScope } from '../schemas/auth-records.js';
1
+ export { type UserRecord, type TokenScope } from '../schemas/auth-records.js';
2
2
  import type { TokenScope } from '../schemas/auth-records.js';
3
3
  export interface UserPermissions {
4
4
  isAdmin: boolean;
@@ -484,6 +484,15 @@ export interface StorageLocationsChangedPayload {
484
484
  * when a camera is assigned to or unassigned from an agent runner. Used by
485
485
  * the UI / metrics dashboard. No frame data.
486
486
  */
487
+ export type PipelineMotionNoisePayload = {
488
+ readonly deviceId: number;
489
+ /** The rolling window the figures are over, in ms. */
490
+ readonly windowMs: number;
491
+ /** Share of the window with a detection session open, whole percent. */
492
+ readonly dutyPct: number;
493
+ /** Sessions opened in the window. */
494
+ readonly sessions: number;
495
+ };
487
496
  export interface PipelineCameraAssignmentPayload {
488
497
  readonly deviceId: number;
489
498
  readonly agentNodeId: string;
@@ -1122,6 +1131,25 @@ export interface EventCatalog {
1122
1131
  nodeId?: string;
1123
1132
  locationName?: string;
1124
1133
  };
1134
+ 'notification.rule-broken': {
1135
+ ruleId: string;
1136
+ /** `null` when the row was too broken to say. */
1137
+ ruleName: string | null;
1138
+ /** The first reason; `reasons` carries them all. */
1139
+ reason: 'unparseable' | 'device-deleted' | 'target-deleted';
1140
+ reasons: readonly {
1141
+ code: 'unparseable' | 'device-deleted' | 'target-deleted';
1142
+ /** Device ids (decimal) or target ids; empty for `unparseable`. */
1143
+ ids: readonly string[];
1144
+ /** The first schema issue, for `unparseable`. */
1145
+ detail?: string;
1146
+ }[];
1147
+ offendingIds: readonly string[];
1148
+ };
1149
+ 'notification.rule-repaired': {
1150
+ ruleId: string;
1151
+ ruleName: string | null;
1152
+ };
1125
1153
  'recording.segment.written': {
1126
1154
  deviceId: number;
1127
1155
  path?: string;
@@ -1251,15 +1279,25 @@ export interface EventCatalog {
1251
1279
  /** The enabled device keys the live probe did not report. */
1252
1280
  readonly unavailableDeviceKeys: readonly string[];
1253
1281
  };
1254
- /** A camera with an open detection session that has detected nothing for
1255
- * longer than the blind threshold. */
1282
+ /** A camera that MOVED (enough session time over enough sessions), was
1283
+ * analysed, and whose detector produced no raw output at all (D907). */
1256
1284
  'pipeline.detection-blind': {
1257
1285
  readonly deviceId: number;
1258
- /** How long it has been blind, in ms. */
1286
+ /** Wall time since its last detection, in ms — context, not the gate. */
1259
1287
  readonly blindForMs: number;
1260
- /** The threshold that was crossed, in ms. */
1288
+ /** The motion bar that was crossed, in ms. */
1261
1289
  readonly thresholdMs: number;
1262
- };
1290
+ /** Session-open time since the detector last produced anything, in ms. */
1291
+ readonly motionMs: number;
1292
+ /** Sessions opened in that time. */
1293
+ readonly sessions: number;
1294
+ /** Frames since the last detection where candidates fell under the floor. */
1295
+ readonly belowFloor: number;
1296
+ };
1297
+ /** A camera whose motion has been constant with no detection (D907). */
1298
+ 'pipeline.motion-noisy': PipelineMotionNoisePayload;
1299
+ /** The camera's motion fell back, or a detection arrived (D907). */
1300
+ 'pipeline.motion-calm': PipelineMotionNoisePayload;
1263
1301
  /** Per-camera pipeline config changed — orchestrator hot-reloads the assigned runner. */
1264
1302
  'pipeline.camera-updated': {
1265
1303
  readonly deviceId: number;
@@ -59,4 +59,11 @@ export declare function alertNodeId(alert: Pick<Alert, 'source' | 'metadata'>):
59
59
  * (an `error` episode announces its opening only).
60
60
  */
61
61
  export declare function alertEpisodeKind(severity: AlertSeverity, phase: AlertEpisodePhase): NcSystemEventKind | null;
62
+ /**
63
+ * The kind of a CRITICAL episode edge about a DEVICE (D911): the alert's source
64
+ * is `device`, so it is announced in the devices family as
65
+ * `device-attention-required` / `-resolved` INSTEAD of `alert-critical`. One
66
+ * alert notifies once, through one family. `null` for any other severity.
67
+ */
68
+ export declare function deviceAttentionKind(severity: AlertSeverity, phase: AlertEpisodePhase): NcSystemEventKind | null;
62
69
  export declare function alertEpisodePayload(alert: Alert, phase: AlertEpisodePhase, at: number): AlertEpisodePayload;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * D906 — system events that come in PAIRS are one CLASS: a "went bad" edge and
3
+ * a "came back" edge of the same condition (a stream offline / back online, a
4
+ * recording stalled / writing again, a rule broken / repaired).
5
+ *
6
+ * Nothing new is STORED: a rule keeps listing edge kinds, and a class is the
7
+ * set of its edges. What the class decides:
8
+ *
9
+ * - an IMMEDIATE system rule that selects a class is told about BOTH edges.
10
+ * A stored instant rule listing only one edge of a class is read as the
11
+ * whole class (`withSystemEventClasses`) — the operator asked for both
12
+ * fronts, and a rule that heard "offline" and never "back online" left
13
+ * every outage open-ended on the phone.
14
+ * - a SCHEDULED STATE SUMMARY (`systemEventDelivery.mode: 'summary'`) reads a
15
+ * class as a SNAPSHOT of the bad state at the scheduled time — never edges,
16
+ * never recoveries — so it is NOT widened. The summary already reports a
17
+ * state per kind group regardless of which edge was selected (D647).
18
+ *
19
+ * One-edge kinds (a node restarting, an update available, a backup done, the
20
+ * alarm's transitions) stay single. Pure.
21
+ */
22
+ import type { NcSystemEventCondition, NcSystemEventDelivery, NcSystemEventKind } from '../capabilities/notification-rules.cap.js';
23
+ import { type NcSystemEventFamily } from './system-event-families.js';
24
+ export interface NcSystemEventClassSpec {
25
+ readonly id: string;
26
+ readonly family: NcSystemEventFamily;
27
+ /** The editor's one checkbox. */
28
+ readonly label: string;
29
+ /** The edges into the bad state. */
30
+ readonly bad: readonly NcSystemEventKind[];
31
+ /** The edges out of it. */
32
+ readonly recovery: readonly NcSystemEventKind[];
33
+ /** What the class means on a SCHEDULED summary: the bad state, as a list. */
34
+ readonly snapshotLabel: string;
35
+ /**
36
+ * The state-summary section that snapshots the bad state, or `null` when the
37
+ * summary has no source for this class (it then reports nothing for it).
38
+ */
39
+ readonly snapshotSection: string | null;
40
+ }
41
+ export declare const NC_SYSTEM_EVENT_CLASS_SPECS: readonly NcSystemEventClassSpec[];
42
+ /** Every edge of a class: what an instant rule selecting it listens to. */
43
+ export declare function systemEventClassKinds(spec: NcSystemEventClassSpec): readonly NcSystemEventKind[];
44
+ /** The class a kind belongs to, or `undefined` for a one-edge kind. */
45
+ export declare function systemEventClassOf(kind: string): NcSystemEventClassSpec | undefined;
46
+ /** Is this kind a RECOVERY edge of some class? */
47
+ export declare function isSystemEventRecoveryKind(kind: string): boolean;
48
+ /** The classes of ONE family, for that family's editor. */
49
+ export declare function systemEventClassesFor(family: NcSystemEventFamily): readonly NcSystemEventClassSpec[];
50
+ /**
51
+ * A kind list with the OTHER front of every class it touches: a bad edge
52
+ * brings the class's recovery, a recovery brings the class's bad edges. A
53
+ * sibling bad edge is never added by a bad edge — a rule on
54
+ * `storage-location-critical` does not start hearing `storage-location-low`.
55
+ * Input order is kept, each added edge right after the kind that brought it.
56
+ * Kinds of no class (and legacy names) pass through.
57
+ */
58
+ export declare function expandSystemEventClasses(kinds: readonly NcSystemEventKind[]): NcSystemEventKind[];
59
+ /** The part of a rule {@link withSystemEventClasses} reads. */
60
+ export interface NcSystemEventClassSubject {
61
+ readonly delivery: string;
62
+ readonly conditions: {
63
+ readonly systemEvent?: NcSystemEventCondition;
64
+ };
65
+ readonly systemEventDelivery?: NcSystemEventDelivery;
66
+ }
67
+ /**
68
+ * An INSTANT system rule with each class it touches completed with both edges;
69
+ * the rule itself (same object) when there is nothing to add, a summary rule,
70
+ * or a rule spanning families (`mixed` stays read-only, D637). A copy, never a
71
+ * mutation.
72
+ */
73
+ export declare function withSystemEventClasses<T extends NcSystemEventClassSubject>(rule: T): T;
@@ -8,7 +8,7 @@
8
8
  * A failed read is never `[]` or `undefined`: it throws one of these.
9
9
  */
10
10
  /** Every code a records failure carries. */
11
- export declare const RECORDS_ERROR_CODES: readonly ['rev-conflict', 'too-large', 'unindexed-filter', 'filter-required', 'unknown-kind', 'not-found', 'unique-violation', 'plaintext-secret', 'foreign-marker', 'secret-unavailable', 'invalid-record', 'declaration-refused', 'no-caller', 'batch-too-large'];
11
+ export declare const RECORDS_ERROR_CODES: readonly ['rev-conflict', 'too-large', 'unindexed-filter', 'filter-required', 'unknown-kind', 'not-found', 'unique-violation', 'plaintext-secret', 'foreign-marker', 'secret-unavailable', 'invalid-record', 'declaration-refused', 'no-caller', 'batch-too-large', 'transact-refused'];
12
12
  export type RecordsErrorCode = (typeof RECORDS_ERROR_CODES)[number];
13
13
  /** The base of every records failure. `detail` is the human part of the message. */
14
14
  export declare class RecordsError extends Error {
@@ -68,6 +68,14 @@ export declare class NoCallerError extends RecordsError {
68
68
  export declare class BatchTooLargeError extends RecordsError {
69
69
  constructor(detail: string);
70
70
  }
71
+ /**
72
+ * A `transact` the engine refuses before touching a row: an op on a kind the
73
+ * caller did not declare in ONE file and ONE `transactFamily`. The detail names
74
+ * which rule (`cross-file`, `cross-family`, `no-family`); it is never a silent split.
75
+ */
76
+ export declare class TransactRefusedError extends RecordsError {
77
+ constructor(detail: string);
78
+ }
71
79
  /**
72
80
  * Rebuild the typed error from a message that crossed a wire; `null` when the
73
81
  * message is not a records failure.
@@ -2,6 +2,7 @@ export * from './constants.js';
2
2
  export * from './errors.js';
3
3
  export * from './record-kind.js';
4
4
  export * from './secret-paths.js';
5
+ export * from './transact-rules.js';
5
6
  export * from './records-access.js';
6
7
  export * from './entry-kind.js';
7
8
  export { makeInMemoryRecords, type InMemoryRecords, type InMemoryRecordsOptions, type InMemorySeedRow, type InMemoryStoredRow, } from './in-memory-records.js';
@@ -42,7 +42,7 @@ export declare const EntryDescriptorSchema: z.ZodObject<{
42
42
  fields: z.ZodRecord<z.ZodString, z.ZodUnknown>;
43
43
  }, z.core.$strict>;
44
44
  export type EntryDescriptor = z.infer<typeof EntryDescriptorSchema>;
45
- /** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
45
+ /** What crosses the wire from an addon: JSON only, no Zod. An unknown key is refused. */
46
46
  export declare const RecordKindDeclarationSchema: z.ZodObject<{
47
47
  database: z.ZodDefault<z.ZodEnum<{
48
48
  events: "events";
@@ -92,7 +92,6 @@ export declare const RecordKindDeclarationSchema: z.ZodObject<{
92
92
  maxDataBytes: z.ZodDefault<z.ZodNumber>;
93
93
  secretPaths: z.ZodDefault<z.ZodArray<z.ZodString>>;
94
94
  secretArrayKeys: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
95
- adoptsFrom: z.ZodOptional<z.ZodString>;
96
95
  transactFamily: z.ZodOptional<z.ZodString>;
97
96
  entry: z.ZodOptional<z.ZodObject<{
98
97
  title: z.ZodString;
@@ -100,6 +99,67 @@ export declare const RecordKindDeclarationSchema: z.ZodObject<{
100
99
  fields: z.ZodRecord<z.ZodString, z.ZodUnknown>;
101
100
  }, z.core.$strict>>;
102
101
  }, z.core.$strict>;
102
+ /**
103
+ * A declaration as the engine's catalog stored it: an unknown key is DROPPED,
104
+ * because a row written by an older engine must never stop records from
105
+ * starting. Only for rows read back from the catalog, never for input.
106
+ */
107
+ export declare const StoredRecordKindDeclarationSchema: z.ZodObject<{
108
+ database: z.ZodDefault<z.ZodEnum<{
109
+ events: "events";
110
+ settings: "settings";
111
+ }>>;
112
+ class: z.ZodEnum<{
113
+ audit: "audit";
114
+ config: "config";
115
+ ephemeral: "ephemeral";
116
+ ledger: "ledger";
117
+ mirror: "mirror";
118
+ }>;
119
+ writeTrigger: z.ZodString;
120
+ device: z.ZodDefault<z.ZodEnum<{
121
+ none: "none";
122
+ optional: "optional";
123
+ required: "required";
124
+ }>>;
125
+ at: z.ZodDefault<z.ZodEnum<{
126
+ none: "none";
127
+ required: "required";
128
+ }>>;
129
+ indexes: z.ZodDefault<z.ZodArray<z.ZodObject<{
130
+ name: z.ZodString;
131
+ fields: z.ZodArray<z.ZodString>;
132
+ unique: z.ZodOptional<z.ZodBoolean>;
133
+ }, z.core.$strict>>>;
134
+ retention: z.ZodUnion<readonly [z.ZodObject<{
135
+ ttlMs: z.ZodNumber;
136
+ from: z.ZodEnum<{
137
+ at: "at";
138
+ write: "write";
139
+ }>;
140
+ }, z.core.$strict>, z.ZodObject<{
141
+ maxRows: z.ZodOptional<z.ZodNumber>;
142
+ maxRowsPerDevice: z.ZodOptional<z.ZodNumber>;
143
+ }, z.core.$strict>, z.ZodObject<{
144
+ owner: z.ZodString;
145
+ reason: z.ZodString;
146
+ }, z.core.$strict>, z.ZodObject<{
147
+ none: z.ZodString;
148
+ }, z.core.$strict>]>;
149
+ deviceRemoval: z.ZodDefault<z.ZodEnum<{
150
+ delete: "delete";
151
+ none: "none";
152
+ }>>;
153
+ maxDataBytes: z.ZodDefault<z.ZodNumber>;
154
+ secretPaths: z.ZodDefault<z.ZodArray<z.ZodString>>;
155
+ secretArrayKeys: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
156
+ transactFamily: z.ZodOptional<z.ZodString>;
157
+ entry: z.ZodOptional<z.ZodObject<{
158
+ title: z.ZodString;
159
+ nameField: z.ZodString;
160
+ fields: z.ZodRecord<z.ZodString, z.ZodUnknown>;
161
+ }, z.core.$strict>>;
162
+ }, z.core.$strip>;
103
163
  export type RecordKindDeclaration = z.infer<typeof RecordKindDeclarationSchema>;
104
164
  /** The kind names: lower-case, dash separated, short enough for an index name. */
105
165
  export declare const RecordKindNameSchema: z.ZodString;
@@ -24,7 +24,7 @@
24
24
  * - **delete**: the keychain values of the removed rows go with them.
25
25
  */
26
26
  import type { z } from 'zod';
27
- import type { DeclareKindResult, IRecordsProvider, RecordQueryInput, RecordWhere } from '../capabilities/records.cap.js';
27
+ import type { DeclareKindResult, IRecordsProvider, RecordQueryInput, RecordTransactOp, RecordWhere } from '../capabilities/records.cap.js';
28
28
  import type { SecretsAccess } from '../keychain/secrets-access.js';
29
29
  import { type DefinedRecordKind } from './record-kind.js';
30
30
  /** The wire: the `records` provider's methods. The owner is never an argument. */
@@ -64,8 +64,36 @@ export interface RecordQueryOptions {
64
64
  /** Resolve the secret fields of the page in ONE keychain call. A failure throws. */
65
65
  readonly resolveSecrets?: boolean;
66
66
  }
67
+ /**
68
+ * One write prepared for {@link RecordsAccess.transact}: the wire op plus the
69
+ * undo of the keychain writes made for it (a refused transaction puts the
70
+ * previous secret values back). Build it with the kind handle's `txPut`,
71
+ * `txPatch` and `txDelete`, which run the same validation and secret handling
72
+ * as the single `put` / `patch` / `delete`.
73
+ */
74
+ export interface PreparedTransactOp {
75
+ readonly wire: RecordTransactOp;
76
+ readonly rollback: () => Promise<void>;
77
+ }
78
+ /** What one op of a transaction did, in op order. `rev` is `null` for a delete. */
79
+ export interface TransactOpResult {
80
+ readonly rev: number | null;
81
+ readonly deleted: boolean;
82
+ }
67
83
  export interface RecordKindHandle<T> {
68
84
  readonly name: string;
85
+ /** `put` as an op of {@link RecordsAccess.transact}. */
86
+ txPut(input: RecordPut<T>, opts?: {
87
+ readonly ifRev?: number;
88
+ }): Promise<PreparedTransactOp>;
89
+ /** `patch` as an op of {@link RecordsAccess.transact}. */
90
+ txPatch(id: string, partial: Readonly<Record<string, unknown>>, opts?: {
91
+ readonly ifRev?: number;
92
+ readonly at?: number | null;
93
+ readonly expiresAt?: number | null;
94
+ }): Promise<PreparedTransactOp>;
95
+ /** `delete` as an op of {@link RecordsAccess.transact}. */
96
+ txDelete(id: string): PreparedTransactOp;
69
97
  get(id: string): Promise<RecordRow<T> | null>;
70
98
  getMany(ids: readonly string[]): Promise<readonly RecordRow<T>[]>;
71
99
  /** `get` with the secret fields resolved from the keychain. */
@@ -133,6 +161,13 @@ export interface RecordsAccess {
133
161
  */
134
162
  declare(kinds: Readonly<Record<string, DefinedRecordKind>>): Promise<Readonly<Record<string, DeclareKindResult>>>;
135
163
  kind<S extends z.ZodType>(definition: DefinedRecordKind<S>): RecordKindHandle<z.infer<S>>;
164
+ /**
165
+ * Several writes in ONE transaction: all land or none does. Every op's kind
166
+ * must be declared by this owner in ONE database file under ONE
167
+ * `transactFamily`; anything else throws `records/transact-refused` before a
168
+ * row is touched. Results are in op order.
169
+ */
170
+ transact(ops: readonly PreparedTransactOp[]): Promise<readonly TransactOpResult[]>;
136
171
  /**
137
172
  * In-process SYSTEM builtins only (the entries service): act as the door of
138
173
  * another owner. `null` everywhere else - a forked addon has no way to state
@@ -0,0 +1,7 @@
1
+ import type { RecordKindDeclaration } from './record-kind.js';
2
+ export interface TransactMember {
3
+ readonly kind: string;
4
+ readonly declaration: Pick<RecordKindDeclaration, 'database' | 'transactFamily'>;
5
+ }
6
+ /** Throws {@link TransactRefusedError} unless the kinds may share one transaction. */
7
+ export declare function assertTransactScope(members: readonly TransactMember[]): void;
@@ -202,18 +202,6 @@ export declare const UserRecordSchema: z.ZodObject<{
202
202
  updatedAt: z.ZodNumber;
203
203
  }, z.core.$strip>;
204
204
  export type UserRecord = z.infer<typeof UserRecordSchema>;
205
- export declare const ApiKeyRecordSchema: z.ZodObject<{
206
- id: z.ZodString;
207
- label: z.ZodString;
208
- isAdmin: z.ZodDefault<z.ZodBoolean>;
209
- allowedProviders: z.ZodUnion<readonly [z.ZodLiteral<"*">, z.ZodArray<z.ZodString>]>;
210
- allowedDevices: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodLiteral<"*">, z.ZodArray<z.ZodString>]>>;
211
- tokenHash: z.ZodString;
212
- tokenPrefix: z.ZodString;
213
- createdAt: z.ZodNumber;
214
- lastUsedAt: z.ZodOptional<z.ZodNumber>;
215
- }, z.core.$strip>;
216
- export type ApiKeyRecord = z.infer<typeof ApiKeyRecordSchema>;
217
205
  export declare const ScopedTokenSchema: z.ZodObject<{
218
206
  id: z.ZodString;
219
207
  userId: z.ZodString;