@bli-cockpit/telemetry-core 0.1.6 → 0.1.8
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/evidence-completeness.d.ts +32 -0
- package/dist/evidence-completeness.js +46 -1
- package/dist/evidence-upload.d.ts +78 -0
- package/dist/evidence-upload.js +2 -0
- package/dist/ingest-dto.d.ts +108 -0
- package/dist/ingest-dto.js +28 -0
- package/dist/privacy.d.ts +26 -0
- package/dist/privacy.js +2 -0
- package/dist/secret-guards.d.ts +55 -0
- package/dist/secret-guards.js +205 -9
- package/dist/source-adapter.d.ts +52 -0
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ export declare const EvidenceCompletenessStatusSchema: z.ZodEnum<{
|
|
|
5
5
|
complete: "complete";
|
|
6
6
|
partial: "partial";
|
|
7
7
|
empty: "empty";
|
|
8
|
+
unavailable: "unavailable";
|
|
8
9
|
}>;
|
|
9
10
|
export type EvidenceCompletenessStatus = z.infer<typeof EvidenceCompletenessStatusSchema>;
|
|
10
11
|
export declare const EvidenceCompletenessSourceCountSchema: z.ZodObject<{
|
|
@@ -15,6 +16,7 @@ export declare const EvidenceCompletenessSourceCountSchema: z.ZodObject<{
|
|
|
15
16
|
truncated_count: z.ZodNumber;
|
|
16
17
|
deferred_count: z.ZodNumber;
|
|
17
18
|
reused_count: z.ZodNumber;
|
|
19
|
+
failed_count: z.ZodDefault<z.ZodNumber>;
|
|
18
20
|
}, z.core.$strict>;
|
|
19
21
|
export type EvidenceCompletenessSourceCount = z.infer<typeof EvidenceCompletenessSourceCountSchema>;
|
|
20
22
|
export declare const EvidenceCompletenessTotalsSchema: z.ZodObject<{
|
|
@@ -24,6 +26,7 @@ export declare const EvidenceCompletenessTotalsSchema: z.ZodObject<{
|
|
|
24
26
|
truncated_count: z.ZodNumber;
|
|
25
27
|
deferred_count: z.ZodNumber;
|
|
26
28
|
reused_count: z.ZodNumber;
|
|
29
|
+
failed_count: z.ZodDefault<z.ZodNumber>;
|
|
27
30
|
}, z.core.$strict>;
|
|
28
31
|
export type EvidenceCompletenessTotals = z.infer<typeof EvidenceCompletenessTotalsSchema>;
|
|
29
32
|
export declare const EvidenceCompletenessCapSchema: z.ZodObject<{
|
|
@@ -40,6 +43,12 @@ export declare const EvidenceCompletenessSkipReasonSchema: z.ZodObject<{
|
|
|
40
43
|
count: z.ZodNumber;
|
|
41
44
|
}, z.core.$strict>;
|
|
42
45
|
export type EvidenceCompletenessSkipReason = z.infer<typeof EvidenceCompletenessSkipReasonSchema>;
|
|
46
|
+
export declare const EvidenceCompletenessFailureReasonSchema: z.ZodObject<{
|
|
47
|
+
source: z.ZodString;
|
|
48
|
+
reason: z.ZodString;
|
|
49
|
+
count: z.ZodNumber;
|
|
50
|
+
}, z.core.$strict>;
|
|
51
|
+
export type EvidenceCompletenessFailureReason = z.infer<typeof EvidenceCompletenessFailureReasonSchema>;
|
|
43
52
|
export declare const EvidenceCompletenessTruncationMarkerSchema: z.ZodObject<{
|
|
44
53
|
source: z.ZodString;
|
|
45
54
|
reason: z.ZodString;
|
|
@@ -49,6 +58,14 @@ export declare const EvidenceCompletenessTruncationMarkerSchema: z.ZodObject<{
|
|
|
49
58
|
included_bytes: z.ZodOptional<z.ZodNumber>;
|
|
50
59
|
}, z.core.$strict>;
|
|
51
60
|
export type EvidenceCompletenessTruncationMarker = z.infer<typeof EvidenceCompletenessTruncationMarkerSchema>;
|
|
61
|
+
export declare const EvidenceCompletenessRedactionMarkerSchema: z.ZodObject<{
|
|
62
|
+
source: z.ZodString;
|
|
63
|
+
status: z.ZodLiteral<"sanitized">;
|
|
64
|
+
mode: z.ZodString;
|
|
65
|
+
count: z.ZodNumber;
|
|
66
|
+
rule_ids: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
67
|
+
}, z.core.$strict>;
|
|
68
|
+
export type EvidenceCompletenessRedactionMarker = z.infer<typeof EvidenceCompletenessRedactionMarkerSchema>;
|
|
52
69
|
export declare const EvidenceCompletenessPayloadSchema: z.ZodObject<{
|
|
53
70
|
schema_version: z.ZodLiteral<"evidence-completeness.v1">;
|
|
54
71
|
status: z.ZodEnum<{
|
|
@@ -57,6 +74,7 @@ export declare const EvidenceCompletenessPayloadSchema: z.ZodObject<{
|
|
|
57
74
|
complete: "complete";
|
|
58
75
|
partial: "partial";
|
|
59
76
|
empty: "empty";
|
|
77
|
+
unavailable: "unavailable";
|
|
60
78
|
}>;
|
|
61
79
|
generated_at: z.ZodString;
|
|
62
80
|
scan_window: z.ZodObject<{
|
|
@@ -72,6 +90,7 @@ export declare const EvidenceCompletenessPayloadSchema: z.ZodObject<{
|
|
|
72
90
|
truncated_count: z.ZodNumber;
|
|
73
91
|
deferred_count: z.ZodNumber;
|
|
74
92
|
reused_count: z.ZodNumber;
|
|
93
|
+
failed_count: z.ZodDefault<z.ZodNumber>;
|
|
75
94
|
}, z.core.$strict>>>;
|
|
76
95
|
totals: z.ZodObject<{
|
|
77
96
|
scanned_count: z.ZodNumber;
|
|
@@ -80,6 +99,7 @@ export declare const EvidenceCompletenessPayloadSchema: z.ZodObject<{
|
|
|
80
99
|
truncated_count: z.ZodNumber;
|
|
81
100
|
deferred_count: z.ZodNumber;
|
|
82
101
|
reused_count: z.ZodNumber;
|
|
102
|
+
failed_count: z.ZodDefault<z.ZodNumber>;
|
|
83
103
|
}, z.core.$strict>;
|
|
84
104
|
caps: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
85
105
|
source: z.ZodString;
|
|
@@ -93,6 +113,11 @@ export declare const EvidenceCompletenessPayloadSchema: z.ZodObject<{
|
|
|
93
113
|
reason: z.ZodString;
|
|
94
114
|
count: z.ZodNumber;
|
|
95
115
|
}, z.core.$strict>>>;
|
|
116
|
+
failure_reasons: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
117
|
+
source: z.ZodString;
|
|
118
|
+
reason: z.ZodString;
|
|
119
|
+
count: z.ZodNumber;
|
|
120
|
+
}, z.core.$strict>>>;
|
|
96
121
|
truncation_markers: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
97
122
|
source: z.ZodString;
|
|
98
123
|
reason: z.ZodString;
|
|
@@ -101,6 +126,13 @@ export declare const EvidenceCompletenessPayloadSchema: z.ZodObject<{
|
|
|
101
126
|
observed_bytes: z.ZodOptional<z.ZodNumber>;
|
|
102
127
|
included_bytes: z.ZodOptional<z.ZodNumber>;
|
|
103
128
|
}, z.core.$strict>>>;
|
|
129
|
+
redaction_markers: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
130
|
+
source: z.ZodString;
|
|
131
|
+
status: z.ZodLiteral<"sanitized">;
|
|
132
|
+
mode: z.ZodString;
|
|
133
|
+
count: z.ZodNumber;
|
|
134
|
+
rule_ids: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
135
|
+
}, z.core.$strict>>>;
|
|
104
136
|
notes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
105
137
|
}, z.core.$strict>;
|
|
106
138
|
export type EvidenceCompletenessPayload = z.infer<typeof EvidenceCompletenessPayloadSchema>;
|
|
@@ -6,6 +6,7 @@ export const EvidenceCompletenessStatusSchema = z.enum([
|
|
|
6
6
|
"partial",
|
|
7
7
|
"empty",
|
|
8
8
|
"failed",
|
|
9
|
+
"unavailable",
|
|
9
10
|
"unknown",
|
|
10
11
|
]);
|
|
11
12
|
export const EvidenceCompletenessSourceCountSchema = z
|
|
@@ -17,6 +18,7 @@ export const EvidenceCompletenessSourceCountSchema = z
|
|
|
17
18
|
truncated_count: EvidenceCountSchema,
|
|
18
19
|
deferred_count: EvidenceCountSchema,
|
|
19
20
|
reused_count: EvidenceCountSchema,
|
|
21
|
+
failed_count: EvidenceCountSchema.default(0),
|
|
20
22
|
})
|
|
21
23
|
.strict();
|
|
22
24
|
export const EvidenceCompletenessTotalsSchema = EvidenceCompletenessSourceCountSchema.omit({ source: true }).strict();
|
|
@@ -36,6 +38,7 @@ export const EvidenceCompletenessSkipReasonSchema = z
|
|
|
36
38
|
count: EvidenceCountSchema,
|
|
37
39
|
})
|
|
38
40
|
.strict();
|
|
41
|
+
export const EvidenceCompletenessFailureReasonSchema = EvidenceCompletenessSkipReasonSchema;
|
|
39
42
|
export const EvidenceCompletenessTruncationMarkerSchema = z
|
|
40
43
|
.object({
|
|
41
44
|
source: NonEmptyStringSchema,
|
|
@@ -46,6 +49,15 @@ export const EvidenceCompletenessTruncationMarkerSchema = z
|
|
|
46
49
|
included_bytes: EvidenceCountSchema.optional(),
|
|
47
50
|
})
|
|
48
51
|
.strict();
|
|
52
|
+
export const EvidenceCompletenessRedactionMarkerSchema = z
|
|
53
|
+
.object({
|
|
54
|
+
source: NonEmptyStringSchema,
|
|
55
|
+
status: z.literal("sanitized"),
|
|
56
|
+
mode: NonEmptyStringSchema,
|
|
57
|
+
count: EvidenceCountSchema,
|
|
58
|
+
rule_ids: z.array(NonEmptyStringSchema).default([]),
|
|
59
|
+
})
|
|
60
|
+
.strict();
|
|
49
61
|
export const EvidenceCompletenessPayloadSchema = z
|
|
50
62
|
.object({
|
|
51
63
|
schema_version: z.literal("evidence-completeness.v1"),
|
|
@@ -62,9 +74,42 @@ export const EvidenceCompletenessPayloadSchema = z
|
|
|
62
74
|
totals: EvidenceCompletenessTotalsSchema,
|
|
63
75
|
caps: z.array(EvidenceCompletenessCapSchema).default([]),
|
|
64
76
|
skip_reasons: z.array(EvidenceCompletenessSkipReasonSchema).default([]),
|
|
77
|
+
failure_reasons: z
|
|
78
|
+
.array(EvidenceCompletenessFailureReasonSchema)
|
|
79
|
+
.default([]),
|
|
65
80
|
truncation_markers: z
|
|
66
81
|
.array(EvidenceCompletenessTruncationMarkerSchema)
|
|
67
82
|
.default([]),
|
|
83
|
+
redaction_markers: z
|
|
84
|
+
.array(EvidenceCompletenessRedactionMarkerSchema)
|
|
85
|
+
.default([]),
|
|
68
86
|
notes: z.array(NonEmptyStringSchema.max(160)).default([]),
|
|
69
87
|
})
|
|
70
|
-
.strict()
|
|
88
|
+
.strict()
|
|
89
|
+
.superRefine((payload, context) => {
|
|
90
|
+
const hasGap = payload.totals.skipped_count > 0 ||
|
|
91
|
+
payload.totals.truncated_count > 0 ||
|
|
92
|
+
payload.totals.deferred_count > 0 ||
|
|
93
|
+
payload.totals.failed_count > 0 ||
|
|
94
|
+
payload.caps.some((cap) => cap.applied) ||
|
|
95
|
+
payload.skip_reasons.length > 0 ||
|
|
96
|
+
payload.failure_reasons.length > 0 ||
|
|
97
|
+
payload.truncation_markers.length > 0 ||
|
|
98
|
+
payload.redaction_markers.length > 0;
|
|
99
|
+
if (payload.status === "complete" && hasGap) {
|
|
100
|
+
context.addIssue({
|
|
101
|
+
code: "custom",
|
|
102
|
+
message: "complete evidence completeness cannot include skips, caps, truncations, deferrals, failures, or redactions",
|
|
103
|
+
path: ["status"],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (payload.status === "failed" &&
|
|
107
|
+
payload.totals.failed_count === 0 &&
|
|
108
|
+
payload.failure_reasons.length === 0) {
|
|
109
|
+
context.addIssue({
|
|
110
|
+
code: "custom",
|
|
111
|
+
message: "failed evidence completeness must include a failed count or failure reason",
|
|
112
|
+
path: ["failure_reasons"],
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
@@ -46,6 +46,32 @@ export declare const RawEvidenceUploadBeginObjectSchema: z.ZodObject<{
|
|
|
46
46
|
byte_size: z.ZodOptional<z.ZodNumber>;
|
|
47
47
|
media_type: z.ZodOptional<z.ZodString>;
|
|
48
48
|
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
49
|
+
redaction: z.ZodOptional<z.ZodObject<{
|
|
50
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
51
|
+
status: z.ZodLiteral<"sanitized">;
|
|
52
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
53
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
54
|
+
local_collector: "local_collector";
|
|
55
|
+
server_commit: "server_commit";
|
|
56
|
+
legacy_upload: "legacy_upload";
|
|
57
|
+
}>>;
|
|
58
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
59
|
+
rule_id: z.ZodString;
|
|
60
|
+
match_count: z.ZodNumber;
|
|
61
|
+
redacted_char_count: z.ZodNumber;
|
|
62
|
+
}, z.core.$strict>>;
|
|
63
|
+
secret_like_match_count: z.ZodNumber;
|
|
64
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
65
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
66
|
+
start: z.ZodNumber;
|
|
67
|
+
end: z.ZodNumber;
|
|
68
|
+
rule_id: z.ZodString;
|
|
69
|
+
}, z.core.$strict>>>;
|
|
70
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
71
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
72
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
73
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
74
|
+
}, z.core.$strict>>;
|
|
49
75
|
}, z.core.$strict>;
|
|
50
76
|
chunk_size_bytes: z.ZodNumber;
|
|
51
77
|
chunk_count: z.ZodNumber;
|
|
@@ -116,6 +142,32 @@ export declare const RawEvidenceUploadBeginRequestSchema: z.ZodObject<{
|
|
|
116
142
|
byte_size: z.ZodOptional<z.ZodNumber>;
|
|
117
143
|
media_type: z.ZodOptional<z.ZodString>;
|
|
118
144
|
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
145
|
+
redaction: z.ZodOptional<z.ZodObject<{
|
|
146
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
147
|
+
status: z.ZodLiteral<"sanitized">;
|
|
148
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
149
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
150
|
+
local_collector: "local_collector";
|
|
151
|
+
server_commit: "server_commit";
|
|
152
|
+
legacy_upload: "legacy_upload";
|
|
153
|
+
}>>;
|
|
154
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
155
|
+
rule_id: z.ZodString;
|
|
156
|
+
match_count: z.ZodNumber;
|
|
157
|
+
redacted_char_count: z.ZodNumber;
|
|
158
|
+
}, z.core.$strict>>;
|
|
159
|
+
secret_like_match_count: z.ZodNumber;
|
|
160
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
161
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
162
|
+
start: z.ZodNumber;
|
|
163
|
+
end: z.ZodNumber;
|
|
164
|
+
rule_id: z.ZodString;
|
|
165
|
+
}, z.core.$strict>>>;
|
|
166
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
167
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
168
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
169
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
170
|
+
}, z.core.$strict>>;
|
|
119
171
|
}, z.core.$strict>;
|
|
120
172
|
chunk_size_bytes: z.ZodNumber;
|
|
121
173
|
chunk_count: z.ZodNumber;
|
|
@@ -253,6 +305,32 @@ export declare const RawEvidenceUploadCommitResponseSchema: z.ZodObject<{
|
|
|
253
305
|
content_hash_sha256: z.ZodString;
|
|
254
306
|
byte_size: z.ZodNumber;
|
|
255
307
|
chunk_count: z.ZodNumber;
|
|
308
|
+
redaction: z.ZodOptional<z.ZodObject<{
|
|
309
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
310
|
+
status: z.ZodLiteral<"sanitized">;
|
|
311
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
312
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
313
|
+
local_collector: "local_collector";
|
|
314
|
+
server_commit: "server_commit";
|
|
315
|
+
legacy_upload: "legacy_upload";
|
|
316
|
+
}>>;
|
|
317
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
318
|
+
rule_id: z.ZodString;
|
|
319
|
+
match_count: z.ZodNumber;
|
|
320
|
+
redacted_char_count: z.ZodNumber;
|
|
321
|
+
}, z.core.$strict>>;
|
|
322
|
+
secret_like_match_count: z.ZodNumber;
|
|
323
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
324
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
325
|
+
start: z.ZodNumber;
|
|
326
|
+
end: z.ZodNumber;
|
|
327
|
+
rule_id: z.ZodString;
|
|
328
|
+
}, z.core.$strict>>>;
|
|
329
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
330
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
331
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
332
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
333
|
+
}, z.core.$strict>>;
|
|
256
334
|
}, z.core.$strict>;
|
|
257
335
|
export type RawEvidenceUploadCommitResponse = z.infer<typeof RawEvidenceUploadCommitResponseSchema>;
|
|
258
336
|
/**
|
package/dist/evidence-upload.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { CaptureProvenanceSchema, IsoDateTimeSchema, NonEmptyStringSchema, Sha256Schema, } from "./common.js";
|
|
3
3
|
import { RawEvidencePointerSchema } from "./privacy.js";
|
|
4
|
+
import { RawEvidenceRedactionMetadataSchema } from "./secret-guards.js";
|
|
4
5
|
/**
|
|
5
6
|
* Chunked raw-evidence upload wire contract.
|
|
6
7
|
*
|
|
@@ -117,6 +118,7 @@ export const RawEvidenceUploadCommitResponseSchema = z
|
|
|
117
118
|
content_hash_sha256: Sha256Schema,
|
|
118
119
|
byte_size: z.number().int().nonnegative(),
|
|
119
120
|
chunk_count: z.number().int().nonnegative(),
|
|
121
|
+
redaction: RawEvidenceRedactionMetadataSchema.optional(),
|
|
120
122
|
})
|
|
121
123
|
.strict();
|
|
122
124
|
/**
|
package/dist/ingest-dto.d.ts
CHANGED
|
@@ -96,6 +96,7 @@ export declare const TelemetryIngestEventDtoSchema: z.ZodObject<{
|
|
|
96
96
|
complete: "complete";
|
|
97
97
|
partial: "partial";
|
|
98
98
|
empty: "empty";
|
|
99
|
+
unavailable: "unavailable";
|
|
99
100
|
}>;
|
|
100
101
|
generated_at: z.ZodString;
|
|
101
102
|
scan_window: z.ZodObject<{
|
|
@@ -111,6 +112,7 @@ export declare const TelemetryIngestEventDtoSchema: z.ZodObject<{
|
|
|
111
112
|
truncated_count: z.ZodNumber;
|
|
112
113
|
deferred_count: z.ZodNumber;
|
|
113
114
|
reused_count: z.ZodNumber;
|
|
115
|
+
failed_count: z.ZodDefault<z.ZodNumber>;
|
|
114
116
|
}, z.core.$strict>>>;
|
|
115
117
|
totals: z.ZodObject<{
|
|
116
118
|
scanned_count: z.ZodNumber;
|
|
@@ -119,6 +121,7 @@ export declare const TelemetryIngestEventDtoSchema: z.ZodObject<{
|
|
|
119
121
|
truncated_count: z.ZodNumber;
|
|
120
122
|
deferred_count: z.ZodNumber;
|
|
121
123
|
reused_count: z.ZodNumber;
|
|
124
|
+
failed_count: z.ZodDefault<z.ZodNumber>;
|
|
122
125
|
}, z.core.$strict>;
|
|
123
126
|
caps: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
124
127
|
source: z.ZodString;
|
|
@@ -132,6 +135,11 @@ export declare const TelemetryIngestEventDtoSchema: z.ZodObject<{
|
|
|
132
135
|
reason: z.ZodString;
|
|
133
136
|
count: z.ZodNumber;
|
|
134
137
|
}, z.core.$strict>>>;
|
|
138
|
+
failure_reasons: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
139
|
+
source: z.ZodString;
|
|
140
|
+
reason: z.ZodString;
|
|
141
|
+
count: z.ZodNumber;
|
|
142
|
+
}, z.core.$strict>>>;
|
|
135
143
|
truncation_markers: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
136
144
|
source: z.ZodString;
|
|
137
145
|
reason: z.ZodString;
|
|
@@ -140,6 +148,13 @@ export declare const TelemetryIngestEventDtoSchema: z.ZodObject<{
|
|
|
140
148
|
observed_bytes: z.ZodOptional<z.ZodNumber>;
|
|
141
149
|
included_bytes: z.ZodOptional<z.ZodNumber>;
|
|
142
150
|
}, z.core.$strict>>>;
|
|
151
|
+
redaction_markers: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
152
|
+
source: z.ZodString;
|
|
153
|
+
status: z.ZodLiteral<"sanitized">;
|
|
154
|
+
mode: z.ZodString;
|
|
155
|
+
count: z.ZodNumber;
|
|
156
|
+
rule_ids: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
157
|
+
}, z.core.$strict>>>;
|
|
143
158
|
notes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
144
159
|
}, z.core.$strict>>;
|
|
145
160
|
ticket_binding: z.ZodOptional<z.ZodObject<{
|
|
@@ -261,6 +276,32 @@ export declare const TelemetryIngestEventDtoSchema: z.ZodObject<{
|
|
|
261
276
|
byte_size: z.ZodOptional<z.ZodNumber>;
|
|
262
277
|
media_type: z.ZodOptional<z.ZodString>;
|
|
263
278
|
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
279
|
+
redaction: z.ZodOptional<z.ZodObject<{
|
|
280
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
281
|
+
status: z.ZodLiteral<"sanitized">;
|
|
282
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
283
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
284
|
+
local_collector: "local_collector";
|
|
285
|
+
server_commit: "server_commit";
|
|
286
|
+
legacy_upload: "legacy_upload";
|
|
287
|
+
}>>;
|
|
288
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
289
|
+
rule_id: z.ZodString;
|
|
290
|
+
match_count: z.ZodNumber;
|
|
291
|
+
redacted_char_count: z.ZodNumber;
|
|
292
|
+
}, z.core.$strict>>;
|
|
293
|
+
secret_like_match_count: z.ZodNumber;
|
|
294
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
295
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
296
|
+
start: z.ZodNumber;
|
|
297
|
+
end: z.ZodNumber;
|
|
298
|
+
rule_id: z.ZodString;
|
|
299
|
+
}, z.core.$strict>>>;
|
|
300
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
301
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
302
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
303
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
304
|
+
}, z.core.$strict>>;
|
|
264
305
|
}, z.core.$strict>>>;
|
|
265
306
|
otel: z.ZodOptional<z.ZodObject<{
|
|
266
307
|
trace_id: z.ZodOptional<z.ZodString>;
|
|
@@ -517,6 +558,7 @@ export declare const TelemetryIngestEnvelopeSchema: z.ZodObject<{
|
|
|
517
558
|
complete: "complete";
|
|
518
559
|
partial: "partial";
|
|
519
560
|
empty: "empty";
|
|
561
|
+
unavailable: "unavailable";
|
|
520
562
|
}>;
|
|
521
563
|
generated_at: z.ZodString;
|
|
522
564
|
scan_window: z.ZodObject<{
|
|
@@ -532,6 +574,7 @@ export declare const TelemetryIngestEnvelopeSchema: z.ZodObject<{
|
|
|
532
574
|
truncated_count: z.ZodNumber;
|
|
533
575
|
deferred_count: z.ZodNumber;
|
|
534
576
|
reused_count: z.ZodNumber;
|
|
577
|
+
failed_count: z.ZodDefault<z.ZodNumber>;
|
|
535
578
|
}, z.core.$strict>>>;
|
|
536
579
|
totals: z.ZodObject<{
|
|
537
580
|
scanned_count: z.ZodNumber;
|
|
@@ -540,6 +583,7 @@ export declare const TelemetryIngestEnvelopeSchema: z.ZodObject<{
|
|
|
540
583
|
truncated_count: z.ZodNumber;
|
|
541
584
|
deferred_count: z.ZodNumber;
|
|
542
585
|
reused_count: z.ZodNumber;
|
|
586
|
+
failed_count: z.ZodDefault<z.ZodNumber>;
|
|
543
587
|
}, z.core.$strict>;
|
|
544
588
|
caps: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
545
589
|
source: z.ZodString;
|
|
@@ -553,6 +597,11 @@ export declare const TelemetryIngestEnvelopeSchema: z.ZodObject<{
|
|
|
553
597
|
reason: z.ZodString;
|
|
554
598
|
count: z.ZodNumber;
|
|
555
599
|
}, z.core.$strict>>>;
|
|
600
|
+
failure_reasons: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
601
|
+
source: z.ZodString;
|
|
602
|
+
reason: z.ZodString;
|
|
603
|
+
count: z.ZodNumber;
|
|
604
|
+
}, z.core.$strict>>>;
|
|
556
605
|
truncation_markers: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
557
606
|
source: z.ZodString;
|
|
558
607
|
reason: z.ZodString;
|
|
@@ -561,6 +610,13 @@ export declare const TelemetryIngestEnvelopeSchema: z.ZodObject<{
|
|
|
561
610
|
observed_bytes: z.ZodOptional<z.ZodNumber>;
|
|
562
611
|
included_bytes: z.ZodOptional<z.ZodNumber>;
|
|
563
612
|
}, z.core.$strict>>>;
|
|
613
|
+
redaction_markers: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
614
|
+
source: z.ZodString;
|
|
615
|
+
status: z.ZodLiteral<"sanitized">;
|
|
616
|
+
mode: z.ZodString;
|
|
617
|
+
count: z.ZodNumber;
|
|
618
|
+
rule_ids: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
619
|
+
}, z.core.$strict>>>;
|
|
564
620
|
notes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
565
621
|
}, z.core.$strict>>;
|
|
566
622
|
ticket_binding: z.ZodOptional<z.ZodObject<{
|
|
@@ -682,6 +738,32 @@ export declare const TelemetryIngestEnvelopeSchema: z.ZodObject<{
|
|
|
682
738
|
byte_size: z.ZodOptional<z.ZodNumber>;
|
|
683
739
|
media_type: z.ZodOptional<z.ZodString>;
|
|
684
740
|
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
741
|
+
redaction: z.ZodOptional<z.ZodObject<{
|
|
742
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
743
|
+
status: z.ZodLiteral<"sanitized">;
|
|
744
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
745
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
746
|
+
local_collector: "local_collector";
|
|
747
|
+
server_commit: "server_commit";
|
|
748
|
+
legacy_upload: "legacy_upload";
|
|
749
|
+
}>>;
|
|
750
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
751
|
+
rule_id: z.ZodString;
|
|
752
|
+
match_count: z.ZodNumber;
|
|
753
|
+
redacted_char_count: z.ZodNumber;
|
|
754
|
+
}, z.core.$strict>>;
|
|
755
|
+
secret_like_match_count: z.ZodNumber;
|
|
756
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
757
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
758
|
+
start: z.ZodNumber;
|
|
759
|
+
end: z.ZodNumber;
|
|
760
|
+
rule_id: z.ZodString;
|
|
761
|
+
}, z.core.$strict>>>;
|
|
762
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
763
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
764
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
765
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
766
|
+
}, z.core.$strict>>;
|
|
685
767
|
}, z.core.$strict>>>;
|
|
686
768
|
otel: z.ZodOptional<z.ZodObject<{
|
|
687
769
|
trace_id: z.ZodOptional<z.ZodString>;
|
|
@@ -806,6 +888,32 @@ export declare const TelemetryIngestEnvelopeSchema: z.ZodObject<{
|
|
|
806
888
|
byte_size: z.ZodOptional<z.ZodNumber>;
|
|
807
889
|
media_type: z.ZodOptional<z.ZodString>;
|
|
808
890
|
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
891
|
+
redaction: z.ZodOptional<z.ZodObject<{
|
|
892
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
893
|
+
status: z.ZodLiteral<"sanitized">;
|
|
894
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
895
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
896
|
+
local_collector: "local_collector";
|
|
897
|
+
server_commit: "server_commit";
|
|
898
|
+
legacy_upload: "legacy_upload";
|
|
899
|
+
}>>;
|
|
900
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
901
|
+
rule_id: z.ZodString;
|
|
902
|
+
match_count: z.ZodNumber;
|
|
903
|
+
redacted_char_count: z.ZodNumber;
|
|
904
|
+
}, z.core.$strict>>;
|
|
905
|
+
secret_like_match_count: z.ZodNumber;
|
|
906
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
907
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
908
|
+
start: z.ZodNumber;
|
|
909
|
+
end: z.ZodNumber;
|
|
910
|
+
rule_id: z.ZodString;
|
|
911
|
+
}, z.core.$strict>>>;
|
|
912
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
913
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
914
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
915
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
916
|
+
}, z.core.$strict>>;
|
|
809
917
|
}, z.core.$strict>>>;
|
|
810
918
|
}, z.core.$strict>>>;
|
|
811
919
|
ticket_binding_candidates: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
package/dist/ingest-dto.js
CHANGED
|
@@ -47,6 +47,34 @@ export const TelemetryIngestEventDtoSchema = z
|
|
|
47
47
|
path: ["redaction", "privacy_classification"],
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
+
const summaryStatus = event.attributes["evidence_completeness_status"];
|
|
51
|
+
const summarySchemaVersion = event.attributes["evidence_completeness_schema_version"];
|
|
52
|
+
if (event.evidence_completeness) {
|
|
53
|
+
if (summaryStatus !== undefined &&
|
|
54
|
+
summaryStatus !== event.evidence_completeness.status) {
|
|
55
|
+
context.addIssue({
|
|
56
|
+
code: "custom",
|
|
57
|
+
message: "evidence completeness status attribute must match payload",
|
|
58
|
+
path: ["attributes", "evidence_completeness_status"],
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (summarySchemaVersion !== undefined &&
|
|
62
|
+
summarySchemaVersion !== event.evidence_completeness.schema_version) {
|
|
63
|
+
context.addIssue({
|
|
64
|
+
code: "custom",
|
|
65
|
+
message: "evidence completeness schema version attribute must match payload",
|
|
66
|
+
path: ["attributes", "evidence_completeness_schema_version"],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (typeof summaryStatus === "string" &&
|
|
71
|
+
summaryStatus !== "unknown") {
|
|
72
|
+
context.addIssue({
|
|
73
|
+
code: "custom",
|
|
74
|
+
message: "typed evidence completeness payload is required when status is known",
|
|
75
|
+
path: ["evidence_completeness"],
|
|
76
|
+
});
|
|
77
|
+
}
|
|
50
78
|
});
|
|
51
79
|
export const TelemetryIngestEnvelopeSchema = z
|
|
52
80
|
.object({
|
package/dist/privacy.d.ts
CHANGED
|
@@ -66,6 +66,32 @@ export declare const RawEvidencePointerSchema: z.ZodObject<{
|
|
|
66
66
|
byte_size: z.ZodOptional<z.ZodNumber>;
|
|
67
67
|
media_type: z.ZodOptional<z.ZodString>;
|
|
68
68
|
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
69
|
+
redaction: z.ZodOptional<z.ZodObject<{
|
|
70
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
71
|
+
status: z.ZodLiteral<"sanitized">;
|
|
72
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
73
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
74
|
+
local_collector: "local_collector";
|
|
75
|
+
server_commit: "server_commit";
|
|
76
|
+
legacy_upload: "legacy_upload";
|
|
77
|
+
}>>;
|
|
78
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
79
|
+
rule_id: z.ZodString;
|
|
80
|
+
match_count: z.ZodNumber;
|
|
81
|
+
redacted_char_count: z.ZodNumber;
|
|
82
|
+
}, z.core.$strict>>;
|
|
83
|
+
secret_like_match_count: z.ZodNumber;
|
|
84
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
85
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
86
|
+
start: z.ZodNumber;
|
|
87
|
+
end: z.ZodNumber;
|
|
88
|
+
rule_id: z.ZodString;
|
|
89
|
+
}, z.core.$strict>>>;
|
|
90
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
91
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
92
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
93
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
94
|
+
}, z.core.$strict>>;
|
|
69
95
|
}, z.core.$strict>;
|
|
70
96
|
export type RawEvidencePointer = z.infer<typeof RawEvidencePointerSchema>;
|
|
71
97
|
export declare const RedactionMetadataSchema: z.ZodObject<{
|
package/dist/privacy.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { IsoDateTimeSchema, NonEmptyStringSchema, Sha256Schema, } from "./common.js";
|
|
3
|
+
import { RawEvidenceRedactionMetadataSchema } from "./secret-guards.js";
|
|
3
4
|
export const PrivacyClassificationSchema = z.enum([
|
|
4
5
|
"metadata",
|
|
5
6
|
"redacted_summary",
|
|
@@ -93,6 +94,7 @@ export const RawEvidencePointerSchema = z
|
|
|
93
94
|
byte_size: z.number().int().nonnegative().optional(),
|
|
94
95
|
media_type: NonEmptyStringSchema.optional(),
|
|
95
96
|
redacted_summary: z.string().trim().min(1).max(4000).optional(),
|
|
97
|
+
redaction: RawEvidenceRedactionMetadataSchema.optional(),
|
|
96
98
|
})
|
|
97
99
|
.strict()
|
|
98
100
|
.superRefine((pointer, context) => {
|
package/dist/secret-guards.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
/**
|
|
2
3
|
* Secret-like content + file-name guards shared by the local collector
|
|
3
4
|
* (attribution, collection) and the dashboard commit-time guard. Keeping a
|
|
@@ -24,3 +25,57 @@
|
|
|
24
25
|
export declare const SECRET_FILE_SEGMENT_PATTERN: RegExp;
|
|
25
26
|
export declare function isSecretLikePathSegment(value: string): boolean;
|
|
26
27
|
export declare function containsSecretLikeContent(value: string): boolean;
|
|
28
|
+
export declare const RawEvidenceRedactionSourceSchema: z.ZodEnum<{
|
|
29
|
+
local_collector: "local_collector";
|
|
30
|
+
server_commit: "server_commit";
|
|
31
|
+
legacy_upload: "legacy_upload";
|
|
32
|
+
}>;
|
|
33
|
+
export type RawEvidenceRedactionSource = z.infer<typeof RawEvidenceRedactionSourceSchema>;
|
|
34
|
+
export declare const RawEvidenceRedactionRuleCountSchema: z.ZodObject<{
|
|
35
|
+
rule_id: z.ZodString;
|
|
36
|
+
match_count: z.ZodNumber;
|
|
37
|
+
redacted_char_count: z.ZodNumber;
|
|
38
|
+
}, z.core.$strict>;
|
|
39
|
+
export type RawEvidenceRedactionRuleCount = z.infer<typeof RawEvidenceRedactionRuleCountSchema>;
|
|
40
|
+
export declare const RawEvidenceRedactionRangeSchema: z.ZodObject<{
|
|
41
|
+
start: z.ZodNumber;
|
|
42
|
+
end: z.ZodNumber;
|
|
43
|
+
rule_id: z.ZodString;
|
|
44
|
+
}, z.core.$strict>;
|
|
45
|
+
export type RawEvidenceRedactionRange = z.infer<typeof RawEvidenceRedactionRangeSchema>;
|
|
46
|
+
export declare const RawEvidenceRedactionMetadataSchema: z.ZodObject<{
|
|
47
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
48
|
+
status: z.ZodLiteral<"sanitized">;
|
|
49
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
50
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
51
|
+
local_collector: "local_collector";
|
|
52
|
+
server_commit: "server_commit";
|
|
53
|
+
legacy_upload: "legacy_upload";
|
|
54
|
+
}>>;
|
|
55
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
56
|
+
rule_id: z.ZodString;
|
|
57
|
+
match_count: z.ZodNumber;
|
|
58
|
+
redacted_char_count: z.ZodNumber;
|
|
59
|
+
}, z.core.$strict>>;
|
|
60
|
+
secret_like_match_count: z.ZodNumber;
|
|
61
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
62
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
63
|
+
start: z.ZodNumber;
|
|
64
|
+
end: z.ZodNumber;
|
|
65
|
+
rule_id: z.ZodString;
|
|
66
|
+
}, z.core.$strict>>>;
|
|
67
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
68
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
69
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
70
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
71
|
+
}, z.core.$strict>;
|
|
72
|
+
export type RawEvidenceRedactionMetadata = z.infer<typeof RawEvidenceRedactionMetadataSchema>;
|
|
73
|
+
export interface SecretRedactionResult {
|
|
74
|
+
redacted: boolean;
|
|
75
|
+
text: string;
|
|
76
|
+
metadata: RawEvidenceRedactionMetadata | null;
|
|
77
|
+
}
|
|
78
|
+
export declare function redactSecretLikeContent(value: string, options?: {
|
|
79
|
+
appliedBy?: RawEvidenceRedactionSource;
|
|
80
|
+
redactedFields?: string[];
|
|
81
|
+
}): SecretRedactionResult;
|
package/dist/secret-guards.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
/**
|
|
2
3
|
* Secret-like content + file-name guards shared by the local collector
|
|
3
4
|
* (attribution, collection) and the dashboard commit-time guard. Keeping a
|
|
@@ -29,16 +30,15 @@ export function isSecretLikePathSegment(value) {
|
|
|
29
30
|
// this source file (the public-package pack scanner bans it as a content
|
|
30
31
|
// pattern, just as the original guard did).
|
|
31
32
|
const PRIVILEGED_SUPABASE_KEY_NAME = ["SUPABASE", "SERVICE", "ROLE", "KEY"].join("_");
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* `GRANT ... TO service_role` (no assignment) do not match; the same name with
|
|
37
|
-
* an assigned value does.
|
|
38
|
-
*/
|
|
39
|
-
const SECRET_NAME_WITH_VALUE_PATTERN = new RegExp(`\\b(?:${[
|
|
33
|
+
const SUPABASE_SERVICE_ROLE_NAME = ["SUPABASE", "SERVICE", "ROLE"].join("_");
|
|
34
|
+
const OPENAI_KEY_NAME = ["OPENAI", "API", "KEY"].join("_");
|
|
35
|
+
const MEM0_KEY_NAME = ["MEM0", "API", "KEY"].join("_");
|
|
36
|
+
const SECRET_NAME_PATTERN_SOURCE = [
|
|
40
37
|
"(?:NEXT_PUBLIC_)?SUPABASE_ANON_KEY",
|
|
41
38
|
PRIVILEGED_SUPABASE_KEY_NAME,
|
|
39
|
+
SUPABASE_SERVICE_ROLE_NAME,
|
|
40
|
+
OPENAI_KEY_NAME,
|
|
41
|
+
MEM0_KEY_NAME,
|
|
42
42
|
"SERVICE[_\\s-]?ROLE(?:[_\\s-]?KEY)?",
|
|
43
43
|
"LANGFUSE_(?:PUBLIC|SECRET)_KEY",
|
|
44
44
|
"api[_-]?key",
|
|
@@ -47,7 +47,15 @@ const SECRET_NAME_WITH_VALUE_PATTERN = new RegExp(`\\b(?:${[
|
|
|
47
47
|
"private[_-]?key",
|
|
48
48
|
"client[_-]?secret",
|
|
49
49
|
"secret[_-]?access[_-]?key",
|
|
50
|
-
].join("|")
|
|
50
|
+
].join("|");
|
|
51
|
+
/**
|
|
52
|
+
* Credential names that are only a leak when assigned a value (D13). The value
|
|
53
|
+
* shape mirrors the long-standing generic pattern: an assignment operator
|
|
54
|
+
* followed by a 12+ char opaque value. A bare env var reference (name only) and
|
|
55
|
+
* `GRANT ... TO service_role` (no assignment) do not match; the same name with
|
|
56
|
+
* an assigned value does.
|
|
57
|
+
*/
|
|
58
|
+
const SECRET_NAME_WITH_VALUE_PATTERN = new RegExp(`\\b(?:${SECRET_NAME_PATTERN_SOURCE})\\b\\s*[:=]\\s*["']?[A-Za-z0-9_./+=-]{12,}`, "i");
|
|
51
59
|
/**
|
|
52
60
|
* Self-identifying secret values — blocked regardless of context because the
|
|
53
61
|
* token shape itself is the credential, with no benign reading.
|
|
@@ -65,6 +73,7 @@ const SECRET_VALUE_PATTERNS = [
|
|
|
65
73
|
/\bxox[baprs]-[A-Za-z0-9-]{16,}/,
|
|
66
74
|
/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/,
|
|
67
75
|
/\b(?:pk|sk)-lf-[A-Za-z0-9_-]{16,}\b/i,
|
|
76
|
+
/\bm0[-_][A-Za-z0-9_-]{16,}\b/i,
|
|
68
77
|
];
|
|
69
78
|
const SECRET_LIKE_CONTENT_PATTERNS = [
|
|
70
79
|
SECRET_NAME_WITH_VALUE_PATTERN,
|
|
@@ -73,3 +82,190 @@ const SECRET_LIKE_CONTENT_PATTERNS = [
|
|
|
73
82
|
export function containsSecretLikeContent(value) {
|
|
74
83
|
return SECRET_LIKE_CONTENT_PATTERNS.some((pattern) => pattern.test(value));
|
|
75
84
|
}
|
|
85
|
+
export const RawEvidenceRedactionSourceSchema = z.enum([
|
|
86
|
+
"local_collector",
|
|
87
|
+
"server_commit",
|
|
88
|
+
"legacy_upload",
|
|
89
|
+
]);
|
|
90
|
+
export const RawEvidenceRedactionRuleCountSchema = z
|
|
91
|
+
.object({
|
|
92
|
+
rule_id: z.string().trim().min(1).max(80),
|
|
93
|
+
match_count: z.number().int().nonnegative(),
|
|
94
|
+
redacted_char_count: z.number().int().nonnegative(),
|
|
95
|
+
})
|
|
96
|
+
.strict();
|
|
97
|
+
export const RawEvidenceRedactionRangeSchema = z
|
|
98
|
+
.object({
|
|
99
|
+
start: z.number().int().nonnegative(),
|
|
100
|
+
end: z.number().int().positive(),
|
|
101
|
+
rule_id: z.string().trim().min(1).max(80),
|
|
102
|
+
})
|
|
103
|
+
.strict()
|
|
104
|
+
.superRefine((range, context) => {
|
|
105
|
+
if (range.end <= range.start) {
|
|
106
|
+
context.addIssue({
|
|
107
|
+
code: "custom",
|
|
108
|
+
message: "redaction range end must be greater than start",
|
|
109
|
+
path: ["end"],
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
export const RawEvidenceRedactionMetadataSchema = z
|
|
114
|
+
.object({
|
|
115
|
+
schema_version: z.literal("raw-evidence-redaction.v1"),
|
|
116
|
+
status: z.literal("sanitized"),
|
|
117
|
+
mode: z.literal("deterministic_text_replacement"),
|
|
118
|
+
applied_by: z.array(RawEvidenceRedactionSourceSchema).min(1),
|
|
119
|
+
rule_counts: z.array(RawEvidenceRedactionRuleCountSchema).min(1),
|
|
120
|
+
secret_like_match_count: z.number().int().positive(),
|
|
121
|
+
redacted_fields: z.array(z.string().trim().min(1).max(160)).default([]),
|
|
122
|
+
redacted_ranges: z.array(RawEvidenceRedactionRangeSchema).max(200).default([]),
|
|
123
|
+
original_content_hash_sha256: z.string().regex(/^[a-f0-9]{64}$/).optional(),
|
|
124
|
+
sanitized_content_hash_sha256: z.string().regex(/^[a-f0-9]{64}$/).optional(),
|
|
125
|
+
original_byte_size: z.number().int().nonnegative().optional(),
|
|
126
|
+
sanitized_byte_size: z.number().int().nonnegative().optional(),
|
|
127
|
+
})
|
|
128
|
+
.strict();
|
|
129
|
+
const SECRET_ASSIGNMENT_REDACTION_PATTERN = new RegExp(`(\\b(?:${SECRET_NAME_PATTERN_SOURCE})\\b\\s*[:=]\\s*["']?)([A-Za-z0-9_./+=-]{12,})`, "gi");
|
|
130
|
+
const SECRET_REDACTION_RULES = [
|
|
131
|
+
{
|
|
132
|
+
ruleId: "credential_assignment",
|
|
133
|
+
pattern: SECRET_ASSIGNMENT_REDACTION_PATTERN,
|
|
134
|
+
secretGroup: 2,
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
ruleId: "private_key_block",
|
|
138
|
+
pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
ruleId: "private_key_header",
|
|
142
|
+
pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----/g,
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
ruleId: "bearer_token",
|
|
146
|
+
pattern: /\b(Bearer\s+)([A-Za-z0-9._~+/=-]{16,})/gi,
|
|
147
|
+
secretGroup: 2,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
ruleId: "jwt",
|
|
151
|
+
pattern: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
ruleId: "stripe_token",
|
|
155
|
+
pattern: /\b(?:sk|pk)_(?:live|test)_[A-Za-z0-9]{16,}/g,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
ruleId: "openai_token",
|
|
159
|
+
pattern: /\bsk-[A-Za-z0-9_-]{16,}/g,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
ruleId: "github_token",
|
|
163
|
+
pattern: /\b(?:gh[pousr]_[A-Za-z0-9_]{16,}|github_pat_[A-Za-z0-9_]{20,})/g,
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
ruleId: "linear_token",
|
|
167
|
+
pattern: /\blin_api_[A-Za-z0-9]{16,}/g,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
ruleId: "supabase_secret_token",
|
|
171
|
+
pattern: /\bsb_secret_[A-Za-z0-9_]{16,}/g,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
ruleId: "slack_token",
|
|
175
|
+
pattern: /\bxox[baprs]-[A-Za-z0-9-]{16,}/g,
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
ruleId: "aws_access_key_id",
|
|
179
|
+
pattern: /\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
ruleId: "langfuse_token",
|
|
183
|
+
pattern: /\b(?:pk|sk)-lf-[A-Za-z0-9_-]{16,}\b/gi,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
ruleId: "mem0_token",
|
|
187
|
+
pattern: /\bm0[-_][A-Za-z0-9_-]{16,}\b/gi,
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
export function redactSecretLikeContent(value, options = {}) {
|
|
191
|
+
const matches = findSecretRedactionMatches(value);
|
|
192
|
+
if (matches.length === 0) {
|
|
193
|
+
return { redacted: false, text: value, metadata: null };
|
|
194
|
+
}
|
|
195
|
+
let text = "";
|
|
196
|
+
let cursor = 0;
|
|
197
|
+
const ruleCounts = new Map();
|
|
198
|
+
for (const match of matches) {
|
|
199
|
+
text += value.slice(cursor, match.start);
|
|
200
|
+
text += `[REDACTED:${match.ruleId}]`;
|
|
201
|
+
cursor = match.end;
|
|
202
|
+
const existing = ruleCounts.get(match.ruleId) ?? {
|
|
203
|
+
rule_id: match.ruleId,
|
|
204
|
+
match_count: 0,
|
|
205
|
+
redacted_char_count: 0,
|
|
206
|
+
};
|
|
207
|
+
existing.match_count += 1;
|
|
208
|
+
existing.redacted_char_count += match.end - match.start;
|
|
209
|
+
ruleCounts.set(match.ruleId, existing);
|
|
210
|
+
}
|
|
211
|
+
text += value.slice(cursor);
|
|
212
|
+
const metadata = RawEvidenceRedactionMetadataSchema.parse({
|
|
213
|
+
schema_version: "raw-evidence-redaction.v1",
|
|
214
|
+
status: "sanitized",
|
|
215
|
+
mode: "deterministic_text_replacement",
|
|
216
|
+
applied_by: [options.appliedBy ?? "local_collector"],
|
|
217
|
+
rule_counts: [...ruleCounts.values()].sort((a, b) => a.rule_id.localeCompare(b.rule_id)),
|
|
218
|
+
secret_like_match_count: matches.length,
|
|
219
|
+
redacted_fields: options.redactedFields ?? [],
|
|
220
|
+
redacted_ranges: matches.slice(0, 200).map((match) => ({
|
|
221
|
+
start: match.start,
|
|
222
|
+
end: match.end,
|
|
223
|
+
rule_id: match.ruleId,
|
|
224
|
+
})),
|
|
225
|
+
});
|
|
226
|
+
return { redacted: true, text, metadata };
|
|
227
|
+
}
|
|
228
|
+
function findSecretRedactionMatches(value) {
|
|
229
|
+
const candidates = [];
|
|
230
|
+
SECRET_REDACTION_RULES.forEach((rule, priority) => {
|
|
231
|
+
const pattern = cloneGlobalPattern(rule.pattern);
|
|
232
|
+
for (const match of value.matchAll(pattern)) {
|
|
233
|
+
const fullMatch = match[0];
|
|
234
|
+
const matchIndex = match.index;
|
|
235
|
+
if (!fullMatch || matchIndex === undefined)
|
|
236
|
+
continue;
|
|
237
|
+
const secret = rule.secretGroup ? match[rule.secretGroup] : fullMatch;
|
|
238
|
+
if (!secret)
|
|
239
|
+
continue;
|
|
240
|
+
const relativeStart = fullMatch.indexOf(secret);
|
|
241
|
+
if (relativeStart < 0)
|
|
242
|
+
continue;
|
|
243
|
+
candidates.push({
|
|
244
|
+
start: matchIndex + relativeStart,
|
|
245
|
+
end: matchIndex + relativeStart + secret.length,
|
|
246
|
+
ruleId: rule.ruleId,
|
|
247
|
+
priority,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
candidates.sort((a, b) => {
|
|
252
|
+
if (a.start !== b.start)
|
|
253
|
+
return a.start - b.start;
|
|
254
|
+
if (a.priority !== b.priority)
|
|
255
|
+
return a.priority - b.priority;
|
|
256
|
+
return b.end - b.start - (a.end - a.start);
|
|
257
|
+
});
|
|
258
|
+
const accepted = [];
|
|
259
|
+
let lastEnd = -1;
|
|
260
|
+
for (const candidate of candidates) {
|
|
261
|
+
if (candidate.start < lastEnd)
|
|
262
|
+
continue;
|
|
263
|
+
accepted.push(candidate);
|
|
264
|
+
lastEnd = candidate.end;
|
|
265
|
+
}
|
|
266
|
+
return accepted;
|
|
267
|
+
}
|
|
268
|
+
function cloneGlobalPattern(pattern) {
|
|
269
|
+
const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
|
|
270
|
+
return new RegExp(pattern.source, flags);
|
|
271
|
+
}
|
package/dist/source-adapter.d.ts
CHANGED
|
@@ -74,6 +74,32 @@ export declare const SourceScanEventSummarySchema: z.ZodObject<{
|
|
|
74
74
|
byte_size: z.ZodOptional<z.ZodNumber>;
|
|
75
75
|
media_type: z.ZodOptional<z.ZodString>;
|
|
76
76
|
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
77
|
+
redaction: z.ZodOptional<z.ZodObject<{
|
|
78
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
79
|
+
status: z.ZodLiteral<"sanitized">;
|
|
80
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
81
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
82
|
+
local_collector: "local_collector";
|
|
83
|
+
server_commit: "server_commit";
|
|
84
|
+
legacy_upload: "legacy_upload";
|
|
85
|
+
}>>;
|
|
86
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
87
|
+
rule_id: z.ZodString;
|
|
88
|
+
match_count: z.ZodNumber;
|
|
89
|
+
redacted_char_count: z.ZodNumber;
|
|
90
|
+
}, z.core.$strict>>;
|
|
91
|
+
secret_like_match_count: z.ZodNumber;
|
|
92
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
93
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
94
|
+
start: z.ZodNumber;
|
|
95
|
+
end: z.ZodNumber;
|
|
96
|
+
rule_id: z.ZodString;
|
|
97
|
+
}, z.core.$strict>>>;
|
|
98
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
99
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
100
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
101
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
102
|
+
}, z.core.$strict>>;
|
|
77
103
|
}, z.core.$strict>>>;
|
|
78
104
|
}, z.core.$strict>;
|
|
79
105
|
export type SourceScanEventSummary = z.infer<typeof SourceScanEventSummarySchema>;
|
|
@@ -162,6 +188,32 @@ export declare const SourceScanResultSchema: z.ZodObject<{
|
|
|
162
188
|
byte_size: z.ZodOptional<z.ZodNumber>;
|
|
163
189
|
media_type: z.ZodOptional<z.ZodString>;
|
|
164
190
|
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
191
|
+
redaction: z.ZodOptional<z.ZodObject<{
|
|
192
|
+
schema_version: z.ZodLiteral<"raw-evidence-redaction.v1">;
|
|
193
|
+
status: z.ZodLiteral<"sanitized">;
|
|
194
|
+
mode: z.ZodLiteral<"deterministic_text_replacement">;
|
|
195
|
+
applied_by: z.ZodArray<z.ZodEnum<{
|
|
196
|
+
local_collector: "local_collector";
|
|
197
|
+
server_commit: "server_commit";
|
|
198
|
+
legacy_upload: "legacy_upload";
|
|
199
|
+
}>>;
|
|
200
|
+
rule_counts: z.ZodArray<z.ZodObject<{
|
|
201
|
+
rule_id: z.ZodString;
|
|
202
|
+
match_count: z.ZodNumber;
|
|
203
|
+
redacted_char_count: z.ZodNumber;
|
|
204
|
+
}, z.core.$strict>>;
|
|
205
|
+
secret_like_match_count: z.ZodNumber;
|
|
206
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
207
|
+
redacted_ranges: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
208
|
+
start: z.ZodNumber;
|
|
209
|
+
end: z.ZodNumber;
|
|
210
|
+
rule_id: z.ZodString;
|
|
211
|
+
}, z.core.$strict>>>;
|
|
212
|
+
original_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
213
|
+
sanitized_content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
214
|
+
original_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
215
|
+
sanitized_byte_size: z.ZodOptional<z.ZodNumber>;
|
|
216
|
+
}, z.core.$strict>>;
|
|
165
217
|
}, z.core.$strict>>>;
|
|
166
218
|
}, z.core.$strict>>>;
|
|
167
219
|
ticket_binding_candidates: z.ZodDefault<z.ZodArray<z.ZodObject<{
|