@camstack/addon-notifiers 1.2.49 → 1.2.50

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.
package/dist/addon.js CHANGED
@@ -8136,6 +8136,21 @@ var RelocateJobSchema = object({
8136
8136
  bytesMoved: number().int(),
8137
8137
  /** Total files discovered up front; null while (or when) unknown. */
8138
8138
  filesTotal: number().int().nullable(),
8139
+ /**
8140
+ * Rows this run CORRECTED while moving them — a durable mutation the move
8141
+ * made that nobody asked for, so it is reported where the operator reads the
8142
+ * job rather than only in a log line.
8143
+ *
8144
+ * A footage segment records its byte count in its own NAME, and the durable
8145
+ * hour row derives its aggregates from those names. A file that does not
8146
+ * match its name therefore makes the ledger's sums — and with them quota and
8147
+ * pressure eviction — wrong by the difference, and only a rename can fix it.
8148
+ * On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
8149
+ *
8150
+ * Absent on lanes where the question has no meaning: a media blob's size is
8151
+ * in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
8152
+ */
8153
+ rowsReconciled: number().int().nonnegative().optional(),
8139
8154
  startedAt: number(),
8140
8155
  finishedAt: number().nullable(),
8141
8156
  error: string().nullable()
@@ -8204,14 +8219,42 @@ var RelocateMediaInputSchema = object({
8204
8219
  /** Omitted = `move`, the pre-existing behaviour. */
8205
8220
  mode: MediaRelocateModeSchema.optional()
8206
8221
  });
8207
- /** How many rows still carry NO `locationId` — the population a repoint would
8208
- * silently re-aim at a disk that does not hold their bytes. Zero is the only
8209
- * value that permits a non-blocking `eventMedia` cutover. */
8210
- var UnstampedEventMediaCountSchema = object({
8211
- media: number().int().nonnegative(),
8212
- retrainFrames: number().int().nonnegative(),
8213
- total: number().int().nonnegative()
8222
+ /**
8223
+ * The unstamped population of ONE collection — split, because the gate and the
8224
+ * operator ask two different questions and only one of them has to be cheap.
8225
+ *
8226
+ * `present` is the GATE: "is there at least one row that would be orphaned by a
8227
+ * repoint". It is a single indexed seek to the first matching row, so it stays
8228
+ * answerable on a saturated disk and answers in O(log n) precisely in the state
8229
+ * that matters — after a seal, when the population is empty.
8230
+ *
8231
+ * `rows` is the NUMBER, for the refusal message and the operator's sense of
8232
+ * scale. It is a second, indexed `COUNT(*)`, and `null` means **not
8233
+ * measurable** — never zero. `{ present: true, rows: null }` is a legitimate
8234
+ * and useful answer: "there are some, and this read could not say how many"
8235
+ * still refuses the cutover, which is the whole job.
8236
+ */
8237
+ var UnstampedRowsSchema = object({
8238
+ present: boolean(),
8239
+ rows: number().int().nonnegative().nullable()
8214
8240
  });
8241
+ /**
8242
+ * How many rows still carry NO `locationId` — the population a repoint would
8243
+ * silently re-aim at a disk that does not hold their bytes.
8244
+ *
8245
+ * **`null` = the count could not be taken**, and it is NOT permission to cut
8246
+ * over. The gate opens on a measured absence and on nothing else; an unread
8247
+ * collection and an empty one are different facts, and this repo has already
8248
+ * paid for conflating them (`RelocateResidueSchema`, D295).
8249
+ */
8250
+ var UnstampedEventMediaCountSchema = object({
8251
+ media: UnstampedRowsSchema,
8252
+ retrainFrames: UnstampedRowsSchema,
8253
+ /** True when EITHER collection holds one. The refusal reads this. */
8254
+ anyPresent: boolean(),
8255
+ /** Sum across both, or `null` when either lane could not be counted. */
8256
+ total: number().int().nonnegative().nullable()
8257
+ }).nullable();
8215
8258
  var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
8216
8259
  /** The independently selectable logical storage classes — every class
8217
8260
  * `storage.listLocationDeclarations` reports, so an operator never meets a
@@ -8322,6 +8365,10 @@ var StorageMigrationMoveProgressSchema = object({
8322
8365
  /** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
8323
8366
  filesTotal: number().int().nonnegative().nullable(),
8324
8367
  bytesMoved: number().int().nonnegative(),
8368
+ /** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
8369
+ * a lane that cannot reconcile. A migration that silently rewrote durable
8370
+ * rows would be the same failure as one that silently skipped them. */
8371
+ rowsReconciled: number().int().nonnegative().optional(),
8325
8372
  /** The MOVER's start, not the migration's: a drain restarted after an addon
8326
8373
  * crash gets a new mover, and a rate computed from the migration's start
8327
8374
  * would silently average in the time nothing was running. */
package/dist/addon.mjs CHANGED
@@ -8109,6 +8109,21 @@ var RelocateJobSchema = object({
8109
8109
  bytesMoved: number().int(),
8110
8110
  /** Total files discovered up front; null while (or when) unknown. */
8111
8111
  filesTotal: number().int().nullable(),
8112
+ /**
8113
+ * Rows this run CORRECTED while moving them — a durable mutation the move
8114
+ * made that nobody asked for, so it is reported where the operator reads the
8115
+ * job rather than only in a log line.
8116
+ *
8117
+ * A footage segment records its byte count in its own NAME, and the durable
8118
+ * hour row derives its aggregates from those names. A file that does not
8119
+ * match its name therefore makes the ledger's sums — and with them quota and
8120
+ * pressure eviction — wrong by the difference, and only a rename can fix it.
8121
+ * On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
8122
+ *
8123
+ * Absent on lanes where the question has no meaning: a media blob's size is
8124
+ * in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
8125
+ */
8126
+ rowsReconciled: number().int().nonnegative().optional(),
8112
8127
  startedAt: number(),
8113
8128
  finishedAt: number().nullable(),
8114
8129
  error: string().nullable()
@@ -8177,14 +8192,42 @@ var RelocateMediaInputSchema = object({
8177
8192
  /** Omitted = `move`, the pre-existing behaviour. */
8178
8193
  mode: MediaRelocateModeSchema.optional()
8179
8194
  });
8180
- /** How many rows still carry NO `locationId` — the population a repoint would
8181
- * silently re-aim at a disk that does not hold their bytes. Zero is the only
8182
- * value that permits a non-blocking `eventMedia` cutover. */
8183
- var UnstampedEventMediaCountSchema = object({
8184
- media: number().int().nonnegative(),
8185
- retrainFrames: number().int().nonnegative(),
8186
- total: number().int().nonnegative()
8195
+ /**
8196
+ * The unstamped population of ONE collection — split, because the gate and the
8197
+ * operator ask two different questions and only one of them has to be cheap.
8198
+ *
8199
+ * `present` is the GATE: "is there at least one row that would be orphaned by a
8200
+ * repoint". It is a single indexed seek to the first matching row, so it stays
8201
+ * answerable on a saturated disk and answers in O(log n) precisely in the state
8202
+ * that matters — after a seal, when the population is empty.
8203
+ *
8204
+ * `rows` is the NUMBER, for the refusal message and the operator's sense of
8205
+ * scale. It is a second, indexed `COUNT(*)`, and `null` means **not
8206
+ * measurable** — never zero. `{ present: true, rows: null }` is a legitimate
8207
+ * and useful answer: "there are some, and this read could not say how many"
8208
+ * still refuses the cutover, which is the whole job.
8209
+ */
8210
+ var UnstampedRowsSchema = object({
8211
+ present: boolean(),
8212
+ rows: number().int().nonnegative().nullable()
8187
8213
  });
8214
+ /**
8215
+ * How many rows still carry NO `locationId` — the population a repoint would
8216
+ * silently re-aim at a disk that does not hold their bytes.
8217
+ *
8218
+ * **`null` = the count could not be taken**, and it is NOT permission to cut
8219
+ * over. The gate opens on a measured absence and on nothing else; an unread
8220
+ * collection and an empty one are different facts, and this repo has already
8221
+ * paid for conflating them (`RelocateResidueSchema`, D295).
8222
+ */
8223
+ var UnstampedEventMediaCountSchema = object({
8224
+ media: UnstampedRowsSchema,
8225
+ retrainFrames: UnstampedRowsSchema,
8226
+ /** True when EITHER collection holds one. The refusal reads this. */
8227
+ anyPresent: boolean(),
8228
+ /** Sum across both, or `null` when either lane could not be counted. */
8229
+ total: number().int().nonnegative().nullable()
8230
+ }).nullable();
8188
8231
  var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
8189
8232
  /** The independently selectable logical storage classes — every class
8190
8233
  * `storage.listLocationDeclarations` reports, so an operator never meets a
@@ -8295,6 +8338,10 @@ var StorageMigrationMoveProgressSchema = object({
8295
8338
  /** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
8296
8339
  filesTotal: number().int().nonnegative().nullable(),
8297
8340
  bytesMoved: number().int().nonnegative(),
8341
+ /** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
8342
+ * a lane that cannot reconcile. A migration that silently rewrote durable
8343
+ * rows would be the same failure as one that silently skipped them. */
8344
+ rowsReconciled: number().int().nonnegative().optional(),
8298
8345
  /** The MOVER's start, not the migration's: a drain restarted after an addon
8299
8346
  * crash gets a new mover, and a rate computed from the migration's start
8300
8347
  * would silently average in the time nothing was running. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-notifiers",
3
- "version": "1.2.49",
3
+ "version": "1.2.50",
4
4
  "description": "System notifiers addon for CamStack — a `notification-output` collection provider hosting per-kind notifier adapters (ntfy, pushover, gotify, telegram, discord, webhook, zentik).",
5
5
  "keywords": [
6
6
  "camstack",