@camstack/addon-smtp-nodemailer 1.2.44 → 1.2.45

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.
@@ -8024,6 +8024,21 @@ var RelocateJobSchema = object({
8024
8024
  bytesMoved: number().int(),
8025
8025
  /** Total files discovered up front; null while (or when) unknown. */
8026
8026
  filesTotal: number().int().nullable(),
8027
+ /**
8028
+ * Rows this run CORRECTED while moving them — a durable mutation the move
8029
+ * made that nobody asked for, so it is reported where the operator reads the
8030
+ * job rather than only in a log line.
8031
+ *
8032
+ * A footage segment records its byte count in its own NAME, and the durable
8033
+ * hour row derives its aggregates from those names. A file that does not
8034
+ * match its name therefore makes the ledger's sums — and with them quota and
8035
+ * pressure eviction — wrong by the difference, and only a rename can fix it.
8036
+ * On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
8037
+ *
8038
+ * Absent on lanes where the question has no meaning: a media blob's size is
8039
+ * in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
8040
+ */
8041
+ rowsReconciled: number().int().nonnegative().optional(),
8027
8042
  startedAt: number(),
8028
8043
  finishedAt: number().nullable(),
8029
8044
  error: string().nullable()
@@ -8092,14 +8107,42 @@ var RelocateMediaInputSchema = object({
8092
8107
  /** Omitted = `move`, the pre-existing behaviour. */
8093
8108
  mode: MediaRelocateModeSchema.optional()
8094
8109
  });
8095
- /** How many rows still carry NO `locationId` — the population a repoint would
8096
- * silently re-aim at a disk that does not hold their bytes. Zero is the only
8097
- * value that permits a non-blocking `eventMedia` cutover. */
8098
- var UnstampedEventMediaCountSchema = object({
8099
- media: number().int().nonnegative(),
8100
- retrainFrames: number().int().nonnegative(),
8101
- total: number().int().nonnegative()
8110
+ /**
8111
+ * The unstamped population of ONE collection split, because the gate and the
8112
+ * operator ask two different questions and only one of them has to be cheap.
8113
+ *
8114
+ * `present` is the GATE: "is there at least one row that would be orphaned by a
8115
+ * repoint". It is a single indexed seek to the first matching row, so it stays
8116
+ * answerable on a saturated disk and answers in O(log n) precisely in the state
8117
+ * that matters — after a seal, when the population is empty.
8118
+ *
8119
+ * `rows` is the NUMBER, for the refusal message and the operator's sense of
8120
+ * scale. It is a second, indexed `COUNT(*)`, and `null` means **not
8121
+ * measurable** — never zero. `{ present: true, rows: null }` is a legitimate
8122
+ * and useful answer: "there are some, and this read could not say how many"
8123
+ * still refuses the cutover, which is the whole job.
8124
+ */
8125
+ var UnstampedRowsSchema = object({
8126
+ present: boolean(),
8127
+ rows: number().int().nonnegative().nullable()
8102
8128
  });
8129
+ /**
8130
+ * How many rows still carry NO `locationId` — the population a repoint would
8131
+ * silently re-aim at a disk that does not hold their bytes.
8132
+ *
8133
+ * **`null` = the count could not be taken**, and it is NOT permission to cut
8134
+ * over. The gate opens on a measured absence and on nothing else; an unread
8135
+ * collection and an empty one are different facts, and this repo has already
8136
+ * paid for conflating them (`RelocateResidueSchema`, D295).
8137
+ */
8138
+ var UnstampedEventMediaCountSchema = object({
8139
+ media: UnstampedRowsSchema,
8140
+ retrainFrames: UnstampedRowsSchema,
8141
+ /** True when EITHER collection holds one. The refusal reads this. */
8142
+ anyPresent: boolean(),
8143
+ /** Sum across both, or `null` when either lane could not be counted. */
8144
+ total: number().int().nonnegative().nullable()
8145
+ }).nullable();
8103
8146
  var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
8104
8147
  /** The independently selectable logical storage classes — every class
8105
8148
  * `storage.listLocationDeclarations` reports, so an operator never meets a
@@ -8210,6 +8253,10 @@ var StorageMigrationMoveProgressSchema = object({
8210
8253
  /** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
8211
8254
  filesTotal: number().int().nonnegative().nullable(),
8212
8255
  bytesMoved: number().int().nonnegative(),
8256
+ /** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
8257
+ * a lane that cannot reconcile. A migration that silently rewrote durable
8258
+ * rows would be the same failure as one that silently skipped them. */
8259
+ rowsReconciled: number().int().nonnegative().optional(),
8213
8260
  /** The MOVER's start, not the migration's: a drain restarted after an addon
8214
8261
  * crash gets a new mover, and a rate computed from the migration's start
8215
8262
  * would silently average in the time nothing was running. */
@@ -8022,6 +8022,21 @@ var RelocateJobSchema = object({
8022
8022
  bytesMoved: number().int(),
8023
8023
  /** Total files discovered up front; null while (or when) unknown. */
8024
8024
  filesTotal: number().int().nullable(),
8025
+ /**
8026
+ * Rows this run CORRECTED while moving them — a durable mutation the move
8027
+ * made that nobody asked for, so it is reported where the operator reads the
8028
+ * job rather than only in a log line.
8029
+ *
8030
+ * A footage segment records its byte count in its own NAME, and the durable
8031
+ * hour row derives its aggregates from those names. A file that does not
8032
+ * match its name therefore makes the ledger's sums — and with them quota and
8033
+ * pressure eviction — wrong by the difference, and only a rename can fix it.
8034
+ * On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
8035
+ *
8036
+ * Absent on lanes where the question has no meaning: a media blob's size is
8037
+ * in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
8038
+ */
8039
+ rowsReconciled: number().int().nonnegative().optional(),
8025
8040
  startedAt: number(),
8026
8041
  finishedAt: number().nullable(),
8027
8042
  error: string().nullable()
@@ -8090,14 +8105,42 @@ var RelocateMediaInputSchema = object({
8090
8105
  /** Omitted = `move`, the pre-existing behaviour. */
8091
8106
  mode: MediaRelocateModeSchema.optional()
8092
8107
  });
8093
- /** How many rows still carry NO `locationId` — the population a repoint would
8094
- * silently re-aim at a disk that does not hold their bytes. Zero is the only
8095
- * value that permits a non-blocking `eventMedia` cutover. */
8096
- var UnstampedEventMediaCountSchema = object({
8097
- media: number().int().nonnegative(),
8098
- retrainFrames: number().int().nonnegative(),
8099
- total: number().int().nonnegative()
8108
+ /**
8109
+ * The unstamped population of ONE collection split, because the gate and the
8110
+ * operator ask two different questions and only one of them has to be cheap.
8111
+ *
8112
+ * `present` is the GATE: "is there at least one row that would be orphaned by a
8113
+ * repoint". It is a single indexed seek to the first matching row, so it stays
8114
+ * answerable on a saturated disk and answers in O(log n) precisely in the state
8115
+ * that matters — after a seal, when the population is empty.
8116
+ *
8117
+ * `rows` is the NUMBER, for the refusal message and the operator's sense of
8118
+ * scale. It is a second, indexed `COUNT(*)`, and `null` means **not
8119
+ * measurable** — never zero. `{ present: true, rows: null }` is a legitimate
8120
+ * and useful answer: "there are some, and this read could not say how many"
8121
+ * still refuses the cutover, which is the whole job.
8122
+ */
8123
+ var UnstampedRowsSchema = object({
8124
+ present: boolean(),
8125
+ rows: number().int().nonnegative().nullable()
8100
8126
  });
8127
+ /**
8128
+ * How many rows still carry NO `locationId` — the population a repoint would
8129
+ * silently re-aim at a disk that does not hold their bytes.
8130
+ *
8131
+ * **`null` = the count could not be taken**, and it is NOT permission to cut
8132
+ * over. The gate opens on a measured absence and on nothing else; an unread
8133
+ * collection and an empty one are different facts, and this repo has already
8134
+ * paid for conflating them (`RelocateResidueSchema`, D295).
8135
+ */
8136
+ var UnstampedEventMediaCountSchema = object({
8137
+ media: UnstampedRowsSchema,
8138
+ retrainFrames: UnstampedRowsSchema,
8139
+ /** True when EITHER collection holds one. The refusal reads this. */
8140
+ anyPresent: boolean(),
8141
+ /** Sum across both, or `null` when either lane could not be counted. */
8142
+ total: number().int().nonnegative().nullable()
8143
+ }).nullable();
8101
8144
  var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
8102
8145
  /** The independently selectable logical storage classes — every class
8103
8146
  * `storage.listLocationDeclarations` reports, so an operator never meets a
@@ -8208,6 +8251,10 @@ var StorageMigrationMoveProgressSchema = object({
8208
8251
  /** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
8209
8252
  filesTotal: number().int().nonnegative().nullable(),
8210
8253
  bytesMoved: number().int().nonnegative(),
8254
+ /** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
8255
+ * a lane that cannot reconcile. A migration that silently rewrote durable
8256
+ * rows would be the same failure as one that silently skipped them. */
8257
+ rowsReconciled: number().int().nonnegative().optional(),
8211
8258
  /** The MOVER's start, not the migration's: a drain restarted after an addon
8212
8259
  * crash gets a new mover, and a rate computed from the migration's start
8213
8260
  * would silently average in the time nothing was running. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-smtp-nodemailer",
3
- "version": "1.2.44",
3
+ "version": "1.2.45",
4
4
  "description": "SMTP email provider addon for CamStack — wraps `nodemailer` and registers a `smtp-provider` cap collection entry. Used by magic-link login + notifier addons.",
5
5
  "keywords": [
6
6
  "camstack",