@bli-cockpit/telemetry-core 0.1.23 → 0.1.25
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.
|
@@ -54,6 +54,7 @@ export declare const RawEvidenceLegacyUploadResponseSchema: z.ZodObject<{
|
|
|
54
54
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
55
55
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
56
56
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
57
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
57
58
|
}, z.core.$strict>>;
|
|
58
59
|
}, z.core.$strict>>;
|
|
59
60
|
}, z.core.$strict>;
|
|
@@ -119,6 +120,7 @@ export declare const RawEvidenceUploadBeginObjectSchema: z.ZodObject<{
|
|
|
119
120
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
120
121
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
121
122
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
123
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
122
124
|
}, z.core.$strict>>;
|
|
123
125
|
}, z.core.$strict>;
|
|
124
126
|
chunk_size_bytes: z.ZodNumber;
|
|
@@ -218,6 +220,7 @@ export declare const RawEvidenceUploadBeginRequestSchema: z.ZodObject<{
|
|
|
218
220
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
219
221
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
220
222
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
223
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
221
224
|
}, z.core.$strict>>;
|
|
222
225
|
}, z.core.$strict>;
|
|
223
226
|
chunk_size_bytes: z.ZodNumber;
|
|
@@ -386,6 +389,7 @@ export declare const RawEvidenceUploadCommitResponseSchema: z.ZodObject<{
|
|
|
386
389
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
387
390
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
388
391
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
392
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
389
393
|
}, z.core.$strict>>;
|
|
390
394
|
}, z.core.$strict>;
|
|
391
395
|
export type RawEvidenceUploadCommitResponse = z.infer<typeof RawEvidenceUploadCommitResponseSchema>;
|
package/dist/ingest-dto.d.ts
CHANGED
|
@@ -316,6 +316,7 @@ export declare const TelemetryIngestEventDtoSchema: z.ZodObject<{
|
|
|
316
316
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
317
317
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
318
318
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
319
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
319
320
|
}, z.core.$strict>>;
|
|
320
321
|
}, z.core.$strict>>>;
|
|
321
322
|
otel: z.ZodOptional<z.ZodObject<{
|
|
@@ -792,6 +793,7 @@ export declare const TelemetryIngestEnvelopeSchema: z.ZodObject<{
|
|
|
792
793
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
793
794
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
794
795
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
796
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
795
797
|
}, z.core.$strict>>;
|
|
796
798
|
}, z.core.$strict>>>;
|
|
797
799
|
otel: z.ZodOptional<z.ZodObject<{
|
|
@@ -945,6 +947,7 @@ export declare const TelemetryIngestEnvelopeSchema: z.ZodObject<{
|
|
|
945
947
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
946
948
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
947
949
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
950
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
948
951
|
}, z.core.$strict>>;
|
|
949
952
|
}, z.core.$strict>>>;
|
|
950
953
|
}, z.core.$strict>>>;
|
package/dist/privacy.d.ts
CHANGED
|
@@ -94,6 +94,7 @@ export declare const RawEvidencePointerSchema: z.ZodObject<{
|
|
|
94
94
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
95
95
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
96
96
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
97
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
97
98
|
}, z.core.$strict>>;
|
|
98
99
|
}, z.core.$strict>;
|
|
99
100
|
export type RawEvidencePointer = z.infer<typeof RawEvidencePointerSchema>;
|
package/dist/secret-guards.d.ts
CHANGED
|
@@ -86,8 +86,35 @@ export declare const RawEvidenceRedactionMetadataSchema: z.ZodObject<{
|
|
|
86
86
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
87
87
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
88
88
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
89
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
89
90
|
}, z.core.$strict>;
|
|
90
91
|
export type RawEvidenceRedactionMetadata = z.infer<typeof RawEvidenceRedactionMetadataSchema>;
|
|
92
|
+
/**
|
|
93
|
+
* The receipt for a file the scan cleared (BLI-3277, moved here by BLI-3280).
|
|
94
|
+
*
|
|
95
|
+
* Same schema, same `mode` — the deterministic ruleset is what ran — with the
|
|
96
|
+
* verdict `scanned_clean` and zero of everything else. The content fields are
|
|
97
|
+
* the point: an evidence ref is only readable downstream when its redaction
|
|
98
|
+
* record hashes the bytes that are actually in the bucket, and for a clean file
|
|
99
|
+
* those are the original bytes, so both halves carry the same digest and size.
|
|
100
|
+
*
|
|
101
|
+
* It lives in telemetry-core rather than in the collector because two callers
|
|
102
|
+
* now build this exact record and they must never drift: the collector writes
|
|
103
|
+
* it at upload time, and the BLI-3280 operator backfill writes it onto refs
|
|
104
|
+
* that were stored before the receipt existed. Both must satisfy the same
|
|
105
|
+
* `sanitized_content_hash_sha256 === content_hash_sha256` /
|
|
106
|
+
* `sanitized_byte_size === byte_size` equality the digest reader checks, and a
|
|
107
|
+
* second copy of this function is a second chance to get that wrong.
|
|
108
|
+
*
|
|
109
|
+
* `appliedBy` is who ran the scan, and it is not decoration: a backfill passes
|
|
110
|
+
* `legacy_upload` so a reader can tell "the collector scanned this before it
|
|
111
|
+
* uploaded" apart from "an operator scanned the stored bytes afterwards".
|
|
112
|
+
*/
|
|
113
|
+
export declare function scannedCleanRedactionMetadata(bytes: Uint8Array, options?: {
|
|
114
|
+
appliedBy?: RawEvidenceRedactionSource;
|
|
115
|
+
/** ISO-8601 with offset. Omitted entirely when absent (BLI-3290). */
|
|
116
|
+
appliedAt?: string;
|
|
117
|
+
}): RawEvidenceRedactionMetadata;
|
|
91
118
|
export interface SecretRedactionResult {
|
|
92
119
|
redacted: boolean;
|
|
93
120
|
text: string;
|
package/dist/secret-guards.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { z } from "zod";
|
|
3
|
+
import { IsoDateTimeSchema } from "./common.js";
|
|
2
4
|
/**
|
|
3
5
|
* Secret-like content + file-name guards shared by the local collector
|
|
4
6
|
* (attribution, collection) and the dashboard commit-time guard. Keeping a
|
|
@@ -181,6 +183,17 @@ export const RawEvidenceRedactionMetadataSchema = z
|
|
|
181
183
|
sanitized_content_hash_sha256: z.string().regex(/^[a-f0-9]{64}$/).optional(),
|
|
182
184
|
original_byte_size: z.number().int().nonnegative().optional(),
|
|
183
185
|
sanitized_byte_size: z.number().int().nonnegative().optional(),
|
|
186
|
+
/**
|
|
187
|
+
* When the scan ran, ISO-8601 with an offset (BLI-3290).
|
|
188
|
+
*
|
|
189
|
+
* Optional, and it stays optional: every receipt written before this field
|
|
190
|
+
* existed is still valid, and the collector does not stamp it — at upload
|
|
191
|
+
* time the ref's own `received_at` already answers "when". It exists for
|
|
192
|
+
* receipts written over bytes that were stored long ago, where the ref's
|
|
193
|
+
* timestamps describe the ORIGINAL upload and nothing in the record would
|
|
194
|
+
* otherwise say when an operator re-scanned or re-masked the object.
|
|
195
|
+
*/
|
|
196
|
+
applied_at: IsoDateTimeSchema.optional(),
|
|
184
197
|
})
|
|
185
198
|
.strict()
|
|
186
199
|
// The per-status invariants the old `z.literal("sanitized")` + `.min(1)` +
|
|
@@ -253,6 +266,45 @@ export const RawEvidenceRedactionMetadataSchema = z
|
|
|
253
266
|
});
|
|
254
267
|
}
|
|
255
268
|
});
|
|
269
|
+
/**
|
|
270
|
+
* The receipt for a file the scan cleared (BLI-3277, moved here by BLI-3280).
|
|
271
|
+
*
|
|
272
|
+
* Same schema, same `mode` — the deterministic ruleset is what ran — with the
|
|
273
|
+
* verdict `scanned_clean` and zero of everything else. The content fields are
|
|
274
|
+
* the point: an evidence ref is only readable downstream when its redaction
|
|
275
|
+
* record hashes the bytes that are actually in the bucket, and for a clean file
|
|
276
|
+
* those are the original bytes, so both halves carry the same digest and size.
|
|
277
|
+
*
|
|
278
|
+
* It lives in telemetry-core rather than in the collector because two callers
|
|
279
|
+
* now build this exact record and they must never drift: the collector writes
|
|
280
|
+
* it at upload time, and the BLI-3280 operator backfill writes it onto refs
|
|
281
|
+
* that were stored before the receipt existed. Both must satisfy the same
|
|
282
|
+
* `sanitized_content_hash_sha256 === content_hash_sha256` /
|
|
283
|
+
* `sanitized_byte_size === byte_size` equality the digest reader checks, and a
|
|
284
|
+
* second copy of this function is a second chance to get that wrong.
|
|
285
|
+
*
|
|
286
|
+
* `appliedBy` is who ran the scan, and it is not decoration: a backfill passes
|
|
287
|
+
* `legacy_upload` so a reader can tell "the collector scanned this before it
|
|
288
|
+
* uploaded" apart from "an operator scanned the stored bytes afterwards".
|
|
289
|
+
*/
|
|
290
|
+
export function scannedCleanRedactionMetadata(bytes, options = {}) {
|
|
291
|
+
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
292
|
+
return {
|
|
293
|
+
schema_version: "raw-evidence-redaction.v1",
|
|
294
|
+
status: "scanned_clean",
|
|
295
|
+
mode: "deterministic_text_replacement",
|
|
296
|
+
applied_by: [options.appliedBy ?? "local_collector"],
|
|
297
|
+
rule_counts: [],
|
|
298
|
+
secret_like_match_count: 0,
|
|
299
|
+
redacted_fields: [],
|
|
300
|
+
redacted_ranges: [],
|
|
301
|
+
original_content_hash_sha256: digest,
|
|
302
|
+
sanitized_content_hash_sha256: digest,
|
|
303
|
+
original_byte_size: bytes.byteLength,
|
|
304
|
+
sanitized_byte_size: bytes.byteLength,
|
|
305
|
+
...(options.appliedAt === undefined ? {} : { applied_at: options.appliedAt }),
|
|
306
|
+
};
|
|
307
|
+
}
|
|
256
308
|
// Same fence as the detector (BLI-3116) — the two must agree or a prefixed
|
|
257
309
|
// name would be detected and then left unredacted, which costs whole sessions
|
|
258
310
|
// (see findSecretRedactionMatches).
|
package/dist/source-adapter.d.ts
CHANGED
|
@@ -102,6 +102,7 @@ export declare const SourceScanEventSummarySchema: z.ZodObject<{
|
|
|
102
102
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
103
103
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
104
104
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
105
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
105
106
|
}, z.core.$strict>>;
|
|
106
107
|
}, z.core.$strict>>>;
|
|
107
108
|
}, z.core.$strict>;
|
|
@@ -219,6 +220,7 @@ export declare const SourceScanResultSchema: z.ZodObject<{
|
|
|
219
220
|
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
220
221
|
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
221
222
|
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
223
|
+
applied_at: z.ZodOptional<z.ZodString>;
|
|
222
224
|
}, z.core.$strict>>;
|
|
223
225
|
}, z.core.$strict>>>;
|
|
224
226
|
}, z.core.$strict>>>;
|
|
@@ -149,6 +149,17 @@ const UPLOAD_FAILURE_CLASSES = {
|
|
|
149
149
|
// The file itself is the problem, and it will be the same size and the same
|
|
150
150
|
// shape on the next pass. Retrying is a promise nobody can keep.
|
|
151
151
|
file_too_large: "deterministic",
|
|
152
|
+
// A declared image above IMAGE_EVIDENCE_MAX_VALIDATION_BYTES (BLI-3067). The
|
|
153
|
+
// commit route deliberately KEEPS the staged chunks for these so that raising
|
|
154
|
+
// the bound turns the identical row into a commit that works — and
|
|
155
|
+
// `docs/runbooks/cockpit-stuck-evidence-uploads.md` has always documented it
|
|
156
|
+
// as deterministic. The entry was missing here, so it classified `unknown`,
|
|
157
|
+
// `isPermanentUploadFailure` answered false, and `begin`'s terminal-failure
|
|
158
|
+
// guard fell through to the reset that deletes those very chunk receipts —
|
|
159
|
+
// destroying the retained staging on the next sync and re-uploading the same
|
|
160
|
+
// oversized image forever. That is the BLI-2528 loop reappearing inside the
|
|
161
|
+
// code written to end it (BLI-3408).
|
|
162
|
+
image_too_large_to_validate: "deterministic",
|
|
152
163
|
// Storage looked at the finished object and said no. The bytes are already
|
|
153
164
|
// final and content-addressed, so the next attempt presents the identical
|
|
154
165
|
// object to the identical rule (BLI-2528). Retrying these is what let 76
|