@bli-cockpit/telemetry-core 0.1.0
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/README.md +8 -0
- package/dist/common.d.ts +45 -0
- package/dist/common.js +41 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/ingest-dto.d.ts +677 -0
- package/dist/ingest-dto.js +59 -0
- package/dist/local-config.d.ts +72 -0
- package/dist/local-config.js +46 -0
- package/dist/paths.d.ts +22 -0
- package/dist/paths.js +66 -0
- package/dist/privacy.d.ts +80 -0
- package/dist/privacy.js +110 -0
- package/dist/risk-flags.d.ts +102 -0
- package/dist/risk-flags.js +46 -0
- package/dist/source-adapter.d.ts +235 -0
- package/dist/source-adapter.js +37 -0
- package/dist/trace-sink.d.ts +58 -0
- package/dist/trace-sink.js +35 -0
- package/dist/work-context.d.ts +76 -0
- package/dist/work-context.js +37 -0
- package/package.json +38 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CaptureProvenanceSchema, IsoDateTimeSchema, JsonAttributeRecordSchema, NonEmptyStringSchema, } from "./common.js";
|
|
3
|
+
import { LocalUserSessionReferenceSchema } from "./local-config.js";
|
|
4
|
+
import { PrivacyClassificationSchema, RawEvidencePointerSchema, RedactionMetadataSchema, } from "./privacy.js";
|
|
5
|
+
import { RiskFlagSchema } from "./risk-flags.js";
|
|
6
|
+
import { SourceScanResultSchema } from "./source-adapter.js";
|
|
7
|
+
import { ExternalTraceSinkPointerSchema, NormalizedOtelTelemetrySchema, } from "./trace-sink.js";
|
|
8
|
+
import { LocalWorkContextSchema, TicketBindingCandidateSchema, } from "./work-context.js";
|
|
9
|
+
export const TelemetryEventTypeSchema = z.enum([
|
|
10
|
+
"session_started",
|
|
11
|
+
"session_ended",
|
|
12
|
+
"work_context_updated",
|
|
13
|
+
"source_scan_completed",
|
|
14
|
+
"ticket_binding_detected",
|
|
15
|
+
"risk_flag_detected",
|
|
16
|
+
"review_signal_detected",
|
|
17
|
+
"pr_status_detected",
|
|
18
|
+
"command_signal_detected",
|
|
19
|
+
"otel_span_normalized",
|
|
20
|
+
"otel_log_normalized",
|
|
21
|
+
]);
|
|
22
|
+
export const TelemetryIngestEventDtoSchema = z
|
|
23
|
+
.object({
|
|
24
|
+
event_id: NonEmptyStringSchema,
|
|
25
|
+
event_type: TelemetryEventTypeSchema,
|
|
26
|
+
occurred_at: IsoDateTimeSchema,
|
|
27
|
+
provenance: CaptureProvenanceSchema,
|
|
28
|
+
privacy_classification: PrivacyClassificationSchema,
|
|
29
|
+
redaction: RedactionMetadataSchema,
|
|
30
|
+
redacted_summary: z.string().trim().min(1).max(4000).optional(),
|
|
31
|
+
metrics: z.record(z.string(), z.number()).default({}),
|
|
32
|
+
attributes: JsonAttributeRecordSchema.default({}),
|
|
33
|
+
ticket_binding: TicketBindingCandidateSchema.optional(),
|
|
34
|
+
risk_flags: z.array(RiskFlagSchema).default([]),
|
|
35
|
+
raw_evidence_pointers: z.array(RawEvidencePointerSchema).default([]),
|
|
36
|
+
otel: NormalizedOtelTelemetrySchema.optional(),
|
|
37
|
+
external_trace_sink_pointer: ExternalTraceSinkPointerSchema.optional(),
|
|
38
|
+
})
|
|
39
|
+
.strict()
|
|
40
|
+
.superRefine((event, context) => {
|
|
41
|
+
if (event.privacy_classification !== event.redaction.privacy_classification) {
|
|
42
|
+
context.addIssue({
|
|
43
|
+
code: "custom",
|
|
44
|
+
message: "event privacy must match redaction privacy",
|
|
45
|
+
path: ["redaction", "privacy_classification"],
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
export const TelemetryIngestEnvelopeSchema = z
|
|
50
|
+
.object({
|
|
51
|
+
envelope_version: z.literal("telemetry-ingest.v1"),
|
|
52
|
+
generated_at: IsoDateTimeSchema,
|
|
53
|
+
collector_version: NonEmptyStringSchema,
|
|
54
|
+
session_reference: LocalUserSessionReferenceSchema,
|
|
55
|
+
work_context: LocalWorkContextSchema,
|
|
56
|
+
events: z.array(TelemetryIngestEventDtoSchema).min(1),
|
|
57
|
+
source_scan_results: z.array(SourceScanResultSchema).default([]),
|
|
58
|
+
})
|
|
59
|
+
.strict();
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const LocalCollectorConfigSchema: z.ZodObject<{
|
|
3
|
+
schema_version: z.ZodLiteral<"telemetry-core.v1">;
|
|
4
|
+
dashboard_url: z.ZodString;
|
|
5
|
+
supabase_url: z.ZodOptional<z.ZodString>;
|
|
6
|
+
collector_version: z.ZodOptional<z.ZodString>;
|
|
7
|
+
device_id: z.ZodOptional<z.ZodString>;
|
|
8
|
+
device_name: z.ZodOptional<z.ZodString>;
|
|
9
|
+
claimed_owner_email: z.ZodOptional<z.ZodString>;
|
|
10
|
+
operator_id: z.ZodOptional<z.ZodString>;
|
|
11
|
+
default_repo_paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
12
|
+
raw_evidence_upload: z.ZodDefault<z.ZodEnum<{
|
|
13
|
+
disabled: "disabled";
|
|
14
|
+
remote_short_retention_opt_in: "remote_short_retention_opt_in";
|
|
15
|
+
}>>;
|
|
16
|
+
session_file_path: z.ZodOptional<z.ZodString>;
|
|
17
|
+
state_dir_path: z.ZodOptional<z.ZodString>;
|
|
18
|
+
}, z.core.$strict>;
|
|
19
|
+
export type LocalCollectorConfig = z.infer<typeof LocalCollectorConfigSchema>;
|
|
20
|
+
export declare const LocalUserSessionReferenceSchema: z.ZodObject<{
|
|
21
|
+
operator_id: z.ZodString;
|
|
22
|
+
auth_subject_id: z.ZodString;
|
|
23
|
+
email: z.ZodOptional<z.ZodString>;
|
|
24
|
+
team_id: z.ZodOptional<z.ZodString>;
|
|
25
|
+
device_id: z.ZodOptional<z.ZodString>;
|
|
26
|
+
device_name: z.ZodOptional<z.ZodString>;
|
|
27
|
+
session_id: z.ZodString;
|
|
28
|
+
session_file_path: z.ZodString;
|
|
29
|
+
session_state: z.ZodEnum<{
|
|
30
|
+
unknown: "unknown";
|
|
31
|
+
missing: "missing";
|
|
32
|
+
valid: "valid";
|
|
33
|
+
expired: "expired";
|
|
34
|
+
}>;
|
|
35
|
+
auth_method: z.ZodOptional<z.ZodEnum<{
|
|
36
|
+
unknown: "unknown";
|
|
37
|
+
ambient_device_token: "ambient_device_token";
|
|
38
|
+
supabase_bearer: "supabase_bearer";
|
|
39
|
+
}>>;
|
|
40
|
+
issued_at: z.ZodOptional<z.ZodString>;
|
|
41
|
+
expires_at: z.ZodOptional<z.ZodString>;
|
|
42
|
+
}, z.core.$strict>;
|
|
43
|
+
export type LocalUserSessionReference = z.infer<typeof LocalUserSessionReferenceSchema>;
|
|
44
|
+
export declare const LocalCollectorSessionFileSchema: z.ZodObject<{
|
|
45
|
+
operator_id: z.ZodString;
|
|
46
|
+
auth_subject_id: z.ZodString;
|
|
47
|
+
email: z.ZodOptional<z.ZodString>;
|
|
48
|
+
team_id: z.ZodOptional<z.ZodString>;
|
|
49
|
+
device_name: z.ZodOptional<z.ZodString>;
|
|
50
|
+
session_id: z.ZodString;
|
|
51
|
+
session_file_path: z.ZodString;
|
|
52
|
+
session_state: z.ZodEnum<{
|
|
53
|
+
unknown: "unknown";
|
|
54
|
+
missing: "missing";
|
|
55
|
+
valid: "valid";
|
|
56
|
+
expired: "expired";
|
|
57
|
+
}>;
|
|
58
|
+
auth_method: z.ZodOptional<z.ZodEnum<{
|
|
59
|
+
unknown: "unknown";
|
|
60
|
+
ambient_device_token: "ambient_device_token";
|
|
61
|
+
supabase_bearer: "supabase_bearer";
|
|
62
|
+
}>>;
|
|
63
|
+
issued_at: z.ZodOptional<z.ZodString>;
|
|
64
|
+
expires_at: z.ZodOptional<z.ZodString>;
|
|
65
|
+
schema_version: z.ZodLiteral<"telemetry-core.v1">;
|
|
66
|
+
dashboard_url: z.ZodString;
|
|
67
|
+
device_id: z.ZodString;
|
|
68
|
+
device_token: z.ZodString;
|
|
69
|
+
token_type: z.ZodLiteral<"ambient_device_token">;
|
|
70
|
+
paired_at: z.ZodString;
|
|
71
|
+
}, z.core.$strict>;
|
|
72
|
+
export type LocalCollectorSessionFile = z.infer<typeof LocalCollectorSessionFileSchema>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { IsoDateTimeSchema, NonEmptyStringSchema, VersionStringSchema, } from "./common.js";
|
|
3
|
+
export const LocalCollectorConfigSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
schema_version: z.literal("telemetry-core.v1"),
|
|
6
|
+
dashboard_url: z.string().url(),
|
|
7
|
+
supabase_url: z.string().url().optional(),
|
|
8
|
+
collector_version: VersionStringSchema.optional(),
|
|
9
|
+
device_id: NonEmptyStringSchema.optional(),
|
|
10
|
+
device_name: z.string().trim().min(1).max(120).optional(),
|
|
11
|
+
claimed_owner_email: z.string().email().optional(),
|
|
12
|
+
operator_id: NonEmptyStringSchema.optional(),
|
|
13
|
+
default_repo_paths: z.array(NonEmptyStringSchema).default([]),
|
|
14
|
+
raw_evidence_upload: z
|
|
15
|
+
.enum(["disabled", "remote_short_retention_opt_in"])
|
|
16
|
+
.default("disabled"),
|
|
17
|
+
session_file_path: NonEmptyStringSchema.optional(),
|
|
18
|
+
state_dir_path: NonEmptyStringSchema.optional(),
|
|
19
|
+
})
|
|
20
|
+
.strict();
|
|
21
|
+
export const LocalUserSessionReferenceSchema = z
|
|
22
|
+
.object({
|
|
23
|
+
operator_id: NonEmptyStringSchema,
|
|
24
|
+
auth_subject_id: NonEmptyStringSchema,
|
|
25
|
+
email: z.string().email().optional(),
|
|
26
|
+
team_id: NonEmptyStringSchema.optional(),
|
|
27
|
+
device_id: NonEmptyStringSchema.optional(),
|
|
28
|
+
device_name: z.string().trim().min(1).max(120).optional(),
|
|
29
|
+
session_id: NonEmptyStringSchema,
|
|
30
|
+
session_file_path: NonEmptyStringSchema,
|
|
31
|
+
session_state: z.enum(["missing", "valid", "expired", "unknown"]),
|
|
32
|
+
auth_method: z
|
|
33
|
+
.enum(["ambient_device_token", "supabase_bearer", "unknown"])
|
|
34
|
+
.optional(),
|
|
35
|
+
issued_at: IsoDateTimeSchema.optional(),
|
|
36
|
+
expires_at: IsoDateTimeSchema.optional(),
|
|
37
|
+
})
|
|
38
|
+
.strict();
|
|
39
|
+
export const LocalCollectorSessionFileSchema = LocalUserSessionReferenceSchema.extend({
|
|
40
|
+
schema_version: z.literal("telemetry-core.v1"),
|
|
41
|
+
dashboard_url: z.string().url(),
|
|
42
|
+
device_id: NonEmptyStringSchema,
|
|
43
|
+
device_token: NonEmptyStringSchema,
|
|
44
|
+
token_type: z.literal("ambient_device_token"),
|
|
45
|
+
paired_at: IsoDateTimeSchema,
|
|
46
|
+
}).strict();
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const RepoLocalContextPathsSchema: z.ZodObject<{
|
|
3
|
+
repo_root: z.ZodString;
|
|
4
|
+
car_root_dir: z.ZodString;
|
|
5
|
+
context_dir: z.ZodString;
|
|
6
|
+
active_context_file: z.ZodString;
|
|
7
|
+
tickets_dir: z.ZodString;
|
|
8
|
+
traces_dir: z.ZodString;
|
|
9
|
+
}, z.core.$strict>;
|
|
10
|
+
export type RepoLocalContextPaths = z.infer<typeof RepoLocalContextPathsSchema>;
|
|
11
|
+
export declare const UserLocalCockpitPathsSchema: z.ZodObject<{
|
|
12
|
+
home_dir: z.ZodString;
|
|
13
|
+
config_dir: z.ZodString;
|
|
14
|
+
config_file: z.ZodString;
|
|
15
|
+
session_file: z.ZodString;
|
|
16
|
+
state_dir: z.ZodString;
|
|
17
|
+
spool_dir: z.ZodString;
|
|
18
|
+
cursors_dir: z.ZodString;
|
|
19
|
+
}, z.core.$strict>;
|
|
20
|
+
export type UserLocalCockpitPaths = z.infer<typeof UserLocalCockpitPathsSchema>;
|
|
21
|
+
export declare function getRepoLocalContextPaths(repoRoot: string): RepoLocalContextPaths;
|
|
22
|
+
export declare function getUserLocalCockpitPaths(homeDir: string): UserLocalCockpitPaths;
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { NonEmptyStringSchema } from "./common.js";
|
|
3
|
+
export const RepoLocalContextPathsSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
repo_root: NonEmptyStringSchema,
|
|
6
|
+
car_root_dir: NonEmptyStringSchema,
|
|
7
|
+
context_dir: NonEmptyStringSchema,
|
|
8
|
+
active_context_file: NonEmptyStringSchema,
|
|
9
|
+
tickets_dir: NonEmptyStringSchema,
|
|
10
|
+
traces_dir: NonEmptyStringSchema,
|
|
11
|
+
})
|
|
12
|
+
.strict();
|
|
13
|
+
export const UserLocalCockpitPathsSchema = z
|
|
14
|
+
.object({
|
|
15
|
+
home_dir: NonEmptyStringSchema,
|
|
16
|
+
config_dir: NonEmptyStringSchema,
|
|
17
|
+
config_file: NonEmptyStringSchema,
|
|
18
|
+
session_file: NonEmptyStringSchema,
|
|
19
|
+
state_dir: NonEmptyStringSchema,
|
|
20
|
+
spool_dir: NonEmptyStringSchema,
|
|
21
|
+
cursors_dir: NonEmptyStringSchema,
|
|
22
|
+
})
|
|
23
|
+
.strict();
|
|
24
|
+
export function getRepoLocalContextPaths(repoRoot) {
|
|
25
|
+
const repo_root = normalizeBasePath(repoRoot);
|
|
26
|
+
const car_root_dir = joinPath(repo_root, ".codex-autorunner");
|
|
27
|
+
const context_dir = joinPath(car_root_dir, "contextspace");
|
|
28
|
+
return {
|
|
29
|
+
repo_root,
|
|
30
|
+
car_root_dir,
|
|
31
|
+
context_dir,
|
|
32
|
+
active_context_file: joinPath(context_dir, "active_context.md"),
|
|
33
|
+
tickets_dir: joinPath(car_root_dir, "tickets"),
|
|
34
|
+
traces_dir: joinPath(car_root_dir, "traces"),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function getUserLocalCockpitPaths(homeDir) {
|
|
38
|
+
const home_dir = normalizeBasePath(homeDir);
|
|
39
|
+
const config_dir = joinPath(home_dir, ".config", "bli-cockpit");
|
|
40
|
+
const state_dir = joinPath(home_dir, ".local", "state", "bli-cockpit");
|
|
41
|
+
return {
|
|
42
|
+
home_dir,
|
|
43
|
+
config_dir,
|
|
44
|
+
config_file: joinPath(config_dir, "config.json"),
|
|
45
|
+
session_file: joinPath(config_dir, "session.json"),
|
|
46
|
+
state_dir,
|
|
47
|
+
spool_dir: joinPath(state_dir, "spool"),
|
|
48
|
+
cursors_dir: joinPath(state_dir, "cursors"),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function normalizeBasePath(value) {
|
|
52
|
+
const trimmed = value.trim();
|
|
53
|
+
if (!trimmed) {
|
|
54
|
+
throw new Error("path base must be a non-empty string");
|
|
55
|
+
}
|
|
56
|
+
if (/^[A-Za-z]:[\\/]?$/.test(trimmed)) {
|
|
57
|
+
return trimmed.replace(/[\\/]?$/, "\\");
|
|
58
|
+
}
|
|
59
|
+
return trimmed.replace(/[\\/]+$/, "");
|
|
60
|
+
}
|
|
61
|
+
function joinPath(base, ...segments) {
|
|
62
|
+
const separator = base.includes("\\") ? "\\" : "/";
|
|
63
|
+
const normalizedBase = normalizeBasePath(base);
|
|
64
|
+
const cleanSegments = segments.map((segment) => segment.replace(/^[\\/]+|[\\/]+$/g, ""));
|
|
65
|
+
return [normalizedBase, ...cleanSegments].join(separator);
|
|
66
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const PrivacyClassificationSchema: z.ZodEnum<{
|
|
3
|
+
metadata: "metadata";
|
|
4
|
+
redacted_summary: "redacted_summary";
|
|
5
|
+
local_only_raw_evidence: "local_only_raw_evidence";
|
|
6
|
+
remote_short_retention_raw_evidence: "remote_short_retention_raw_evidence";
|
|
7
|
+
}>;
|
|
8
|
+
export type PrivacyClassification = z.infer<typeof PrivacyClassificationSchema>;
|
|
9
|
+
export declare const RawEvidencePrivacyClassificationSchema: z.ZodEnum<{
|
|
10
|
+
local_only_raw_evidence: "local_only_raw_evidence";
|
|
11
|
+
remote_short_retention_raw_evidence: "remote_short_retention_raw_evidence";
|
|
12
|
+
}>;
|
|
13
|
+
export type RawEvidencePrivacyClassification = z.infer<typeof RawEvidencePrivacyClassificationSchema>;
|
|
14
|
+
export declare const RawEvidenceRetentionModeSchema: z.ZodEnum<{
|
|
15
|
+
local_only: "local_only";
|
|
16
|
+
remote_short_retention: "remote_short_retention";
|
|
17
|
+
}>;
|
|
18
|
+
export type RawEvidenceRetentionMode = z.infer<typeof RawEvidenceRetentionModeSchema>;
|
|
19
|
+
export declare const RawEvidenceRetentionPolicySchema: z.ZodObject<{
|
|
20
|
+
mode: z.ZodEnum<{
|
|
21
|
+
local_only: "local_only";
|
|
22
|
+
remote_short_retention: "remote_short_retention";
|
|
23
|
+
}>;
|
|
24
|
+
privacy_classification: z.ZodEnum<{
|
|
25
|
+
local_only_raw_evidence: "local_only_raw_evidence";
|
|
26
|
+
remote_short_retention_raw_evidence: "remote_short_retention_raw_evidence";
|
|
27
|
+
}>;
|
|
28
|
+
remote_retention_days: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
expires_at: z.ZodOptional<z.ZodString>;
|
|
30
|
+
}, z.core.$strict>;
|
|
31
|
+
export type RawEvidenceRetentionPolicy = z.infer<typeof RawEvidenceRetentionPolicySchema>;
|
|
32
|
+
export declare const RawEvidencePointerSchema: z.ZodObject<{
|
|
33
|
+
raw_evidence_pointer_id: z.ZodString;
|
|
34
|
+
privacy_classification: z.ZodEnum<{
|
|
35
|
+
local_only_raw_evidence: "local_only_raw_evidence";
|
|
36
|
+
remote_short_retention_raw_evidence: "remote_short_retention_raw_evidence";
|
|
37
|
+
}>;
|
|
38
|
+
retention_policy: z.ZodObject<{
|
|
39
|
+
mode: z.ZodEnum<{
|
|
40
|
+
local_only: "local_only";
|
|
41
|
+
remote_short_retention: "remote_short_retention";
|
|
42
|
+
}>;
|
|
43
|
+
privacy_classification: z.ZodEnum<{
|
|
44
|
+
local_only_raw_evidence: "local_only_raw_evidence";
|
|
45
|
+
remote_short_retention_raw_evidence: "remote_short_retention_raw_evidence";
|
|
46
|
+
}>;
|
|
47
|
+
remote_retention_days: z.ZodOptional<z.ZodNumber>;
|
|
48
|
+
expires_at: z.ZodOptional<z.ZodString>;
|
|
49
|
+
}, z.core.$strict>;
|
|
50
|
+
storage_scope: z.ZodEnum<{
|
|
51
|
+
local_file: "local_file";
|
|
52
|
+
remote_object: "remote_object";
|
|
53
|
+
}>;
|
|
54
|
+
local_path: z.ZodOptional<z.ZodString>;
|
|
55
|
+
object_key: z.ZodOptional<z.ZodString>;
|
|
56
|
+
content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
57
|
+
byte_size: z.ZodOptional<z.ZodNumber>;
|
|
58
|
+
media_type: z.ZodOptional<z.ZodString>;
|
|
59
|
+
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
60
|
+
}, z.core.$strict>;
|
|
61
|
+
export type RawEvidencePointer = z.infer<typeof RawEvidencePointerSchema>;
|
|
62
|
+
export declare const RedactionMetadataSchema: z.ZodObject<{
|
|
63
|
+
privacy_classification: z.ZodEnum<{
|
|
64
|
+
metadata: "metadata";
|
|
65
|
+
redacted_summary: "redacted_summary";
|
|
66
|
+
local_only_raw_evidence: "local_only_raw_evidence";
|
|
67
|
+
remote_short_retention_raw_evidence: "remote_short_retention_raw_evidence";
|
|
68
|
+
}>;
|
|
69
|
+
redaction_status: z.ZodEnum<{
|
|
70
|
+
metadata_only: "metadata_only";
|
|
71
|
+
redacted: "redacted";
|
|
72
|
+
raw_local_only: "raw_local_only";
|
|
73
|
+
raw_remote_short_retention: "raw_remote_short_retention";
|
|
74
|
+
}>;
|
|
75
|
+
redacted_fields: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
76
|
+
raw_evidence_pointer_ids: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
77
|
+
content_hash_sha256: z.ZodOptional<z.ZodString>;
|
|
78
|
+
redacted_summary: z.ZodOptional<z.ZodString>;
|
|
79
|
+
}, z.core.$strict>;
|
|
80
|
+
export type RedactionMetadata = z.infer<typeof RedactionMetadataSchema>;
|
package/dist/privacy.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { IsoDateTimeSchema, NonEmptyStringSchema, Sha256Schema, } from "./common.js";
|
|
3
|
+
export const PrivacyClassificationSchema = z.enum([
|
|
4
|
+
"metadata",
|
|
5
|
+
"redacted_summary",
|
|
6
|
+
"local_only_raw_evidence",
|
|
7
|
+
"remote_short_retention_raw_evidence",
|
|
8
|
+
]);
|
|
9
|
+
export const RawEvidencePrivacyClassificationSchema = z.enum([
|
|
10
|
+
"local_only_raw_evidence",
|
|
11
|
+
"remote_short_retention_raw_evidence",
|
|
12
|
+
]);
|
|
13
|
+
export const RawEvidenceRetentionModeSchema = z.enum([
|
|
14
|
+
"local_only",
|
|
15
|
+
"remote_short_retention",
|
|
16
|
+
]);
|
|
17
|
+
export const RawEvidenceRetentionPolicySchema = z
|
|
18
|
+
.object({
|
|
19
|
+
mode: RawEvidenceRetentionModeSchema,
|
|
20
|
+
privacy_classification: RawEvidencePrivacyClassificationSchema,
|
|
21
|
+
remote_retention_days: z.number().int().min(1).max(30).optional(),
|
|
22
|
+
expires_at: IsoDateTimeSchema.optional(),
|
|
23
|
+
})
|
|
24
|
+
.strict()
|
|
25
|
+
.superRefine((policy, context) => {
|
|
26
|
+
if (policy.mode === "local_only" &&
|
|
27
|
+
policy.privacy_classification !== "local_only_raw_evidence") {
|
|
28
|
+
context.addIssue({
|
|
29
|
+
code: "custom",
|
|
30
|
+
message: "local_only retention must use local_only_raw_evidence",
|
|
31
|
+
path: ["privacy_classification"],
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (policy.mode === "remote_short_retention" &&
|
|
35
|
+
policy.privacy_classification !== "remote_short_retention_raw_evidence") {
|
|
36
|
+
context.addIssue({
|
|
37
|
+
code: "custom",
|
|
38
|
+
message: "remote_short_retention must use remote_short_retention_raw_evidence",
|
|
39
|
+
path: ["privacy_classification"],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (policy.mode === "local_only" && policy.remote_retention_days) {
|
|
43
|
+
context.addIssue({
|
|
44
|
+
code: "custom",
|
|
45
|
+
message: "local-only evidence cannot set remote_retention_days",
|
|
46
|
+
path: ["remote_retention_days"],
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (policy.mode === "remote_short_retention" &&
|
|
50
|
+
!policy.remote_retention_days) {
|
|
51
|
+
context.addIssue({
|
|
52
|
+
code: "custom",
|
|
53
|
+
message: "remote evidence must set remote_retention_days",
|
|
54
|
+
path: ["remote_retention_days"],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
export const RawEvidencePointerSchema = z
|
|
59
|
+
.object({
|
|
60
|
+
raw_evidence_pointer_id: NonEmptyStringSchema,
|
|
61
|
+
privacy_classification: RawEvidencePrivacyClassificationSchema,
|
|
62
|
+
retention_policy: RawEvidenceRetentionPolicySchema,
|
|
63
|
+
storage_scope: z.enum(["local_file", "remote_object"]),
|
|
64
|
+
local_path: NonEmptyStringSchema.optional(),
|
|
65
|
+
object_key: NonEmptyStringSchema.optional(),
|
|
66
|
+
content_hash_sha256: Sha256Schema.optional(),
|
|
67
|
+
byte_size: z.number().int().nonnegative().optional(),
|
|
68
|
+
media_type: NonEmptyStringSchema.optional(),
|
|
69
|
+
redacted_summary: z.string().trim().min(1).max(4000).optional(),
|
|
70
|
+
})
|
|
71
|
+
.strict()
|
|
72
|
+
.superRefine((pointer, context) => {
|
|
73
|
+
if (pointer.privacy_classification !==
|
|
74
|
+
pointer.retention_policy.privacy_classification) {
|
|
75
|
+
context.addIssue({
|
|
76
|
+
code: "custom",
|
|
77
|
+
message: "pointer privacy must match its retention policy",
|
|
78
|
+
path: ["retention_policy", "privacy_classification"],
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
if (pointer.storage_scope === "local_file" && !pointer.local_path) {
|
|
82
|
+
context.addIssue({
|
|
83
|
+
code: "custom",
|
|
84
|
+
message: "local evidence pointers require local_path",
|
|
85
|
+
path: ["local_path"],
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (pointer.storage_scope === "remote_object" && !pointer.object_key) {
|
|
89
|
+
context.addIssue({
|
|
90
|
+
code: "custom",
|
|
91
|
+
message: "remote evidence pointers require object_key",
|
|
92
|
+
path: ["object_key"],
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
export const RedactionMetadataSchema = z
|
|
97
|
+
.object({
|
|
98
|
+
privacy_classification: PrivacyClassificationSchema,
|
|
99
|
+
redaction_status: z.enum([
|
|
100
|
+
"metadata_only",
|
|
101
|
+
"redacted",
|
|
102
|
+
"raw_local_only",
|
|
103
|
+
"raw_remote_short_retention",
|
|
104
|
+
]),
|
|
105
|
+
redacted_fields: z.array(NonEmptyStringSchema).default([]),
|
|
106
|
+
raw_evidence_pointer_ids: z.array(NonEmptyStringSchema).default([]),
|
|
107
|
+
content_hash_sha256: Sha256Schema.optional(),
|
|
108
|
+
redacted_summary: z.string().trim().min(1).max(4000).optional(),
|
|
109
|
+
})
|
|
110
|
+
.strict();
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const RiskFlagTypeSchema: z.ZodEnum<{
|
|
3
|
+
no_plan_signal_before_large_edit: "no_plan_signal_before_large_edit";
|
|
4
|
+
p1_or_p2_review_finding: "p1_or_p2_review_finding";
|
|
5
|
+
many_add_revert_loops: "many_add_revert_loops";
|
|
6
|
+
repeated_same_tool_input_shape: "repeated_same_tool_input_shape";
|
|
7
|
+
tool_call_loop: "tool_call_loop";
|
|
8
|
+
file_thrash_same_path: "file_thrash_same_path";
|
|
9
|
+
context_window_pressure: "context_window_pressure";
|
|
10
|
+
permission_denied_spike: "permission_denied_spike";
|
|
11
|
+
high_token_or_time_burn_no_pr: "high_token_or_time_burn_no_pr";
|
|
12
|
+
stuck_for_30_minutes: "stuck_for_30_minutes";
|
|
13
|
+
repeated_same_failing_command: "repeated_same_failing_command";
|
|
14
|
+
branch_ticket_mismatch: "branch_ticket_mismatch";
|
|
15
|
+
collector_stale: "collector_stale";
|
|
16
|
+
}>;
|
|
17
|
+
export type RiskFlagType = z.infer<typeof RiskFlagTypeSchema>;
|
|
18
|
+
export declare const RiskEvidenceLabelSchema: z.ZodEnum<{
|
|
19
|
+
missing_plan_signal: "missing_plan_signal";
|
|
20
|
+
large_edit: "large_edit";
|
|
21
|
+
p1_review_finding: "p1_review_finding";
|
|
22
|
+
p2_review_finding: "p2_review_finding";
|
|
23
|
+
add_revert_loop: "add_revert_loop";
|
|
24
|
+
same_tool_input_shape: "same_tool_input_shape";
|
|
25
|
+
tool_call_loop_window: "tool_call_loop_window";
|
|
26
|
+
same_path_churn: "same_path_churn";
|
|
27
|
+
token_pressure: "token_pressure";
|
|
28
|
+
permission_denied: "permission_denied";
|
|
29
|
+
approval_denied: "approval_denied";
|
|
30
|
+
no_pr_after_work: "no_pr_after_work";
|
|
31
|
+
idle_or_stuck_duration: "idle_or_stuck_duration";
|
|
32
|
+
same_failing_command: "same_failing_command";
|
|
33
|
+
branch_ticket_disagreement: "branch_ticket_disagreement";
|
|
34
|
+
collector_last_seen_stale: "collector_last_seen_stale";
|
|
35
|
+
}>;
|
|
36
|
+
export type RiskEvidenceLabel = z.infer<typeof RiskEvidenceLabelSchema>;
|
|
37
|
+
export declare const RiskFlagSchema: z.ZodObject<{
|
|
38
|
+
risk_flag_id: z.ZodString;
|
|
39
|
+
risk_type: z.ZodEnum<{
|
|
40
|
+
no_plan_signal_before_large_edit: "no_plan_signal_before_large_edit";
|
|
41
|
+
p1_or_p2_review_finding: "p1_or_p2_review_finding";
|
|
42
|
+
many_add_revert_loops: "many_add_revert_loops";
|
|
43
|
+
repeated_same_tool_input_shape: "repeated_same_tool_input_shape";
|
|
44
|
+
tool_call_loop: "tool_call_loop";
|
|
45
|
+
file_thrash_same_path: "file_thrash_same_path";
|
|
46
|
+
context_window_pressure: "context_window_pressure";
|
|
47
|
+
permission_denied_spike: "permission_denied_spike";
|
|
48
|
+
high_token_or_time_burn_no_pr: "high_token_or_time_burn_no_pr";
|
|
49
|
+
stuck_for_30_minutes: "stuck_for_30_minutes";
|
|
50
|
+
repeated_same_failing_command: "repeated_same_failing_command";
|
|
51
|
+
branch_ticket_mismatch: "branch_ticket_mismatch";
|
|
52
|
+
collector_stale: "collector_stale";
|
|
53
|
+
}>;
|
|
54
|
+
severity: z.ZodEnum<{
|
|
55
|
+
info: "info";
|
|
56
|
+
warning: "warning";
|
|
57
|
+
high: "high";
|
|
58
|
+
}>;
|
|
59
|
+
observed_at: z.ZodString;
|
|
60
|
+
evidence_labels: z.ZodArray<z.ZodEnum<{
|
|
61
|
+
missing_plan_signal: "missing_plan_signal";
|
|
62
|
+
large_edit: "large_edit";
|
|
63
|
+
p1_review_finding: "p1_review_finding";
|
|
64
|
+
p2_review_finding: "p2_review_finding";
|
|
65
|
+
add_revert_loop: "add_revert_loop";
|
|
66
|
+
same_tool_input_shape: "same_tool_input_shape";
|
|
67
|
+
tool_call_loop_window: "tool_call_loop_window";
|
|
68
|
+
same_path_churn: "same_path_churn";
|
|
69
|
+
token_pressure: "token_pressure";
|
|
70
|
+
permission_denied: "permission_denied";
|
|
71
|
+
approval_denied: "approval_denied";
|
|
72
|
+
no_pr_after_work: "no_pr_after_work";
|
|
73
|
+
idle_or_stuck_duration: "idle_or_stuck_duration";
|
|
74
|
+
same_failing_command: "same_failing_command";
|
|
75
|
+
branch_ticket_disagreement: "branch_ticket_disagreement";
|
|
76
|
+
collector_last_seen_stale: "collector_last_seen_stale";
|
|
77
|
+
}>>;
|
|
78
|
+
evidence_pointer_ids: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
79
|
+
provenance: z.ZodObject<{
|
|
80
|
+
capture_source: z.ZodEnum<{
|
|
81
|
+
unknown: "unknown";
|
|
82
|
+
codex_jsonl: "codex_jsonl";
|
|
83
|
+
codex_otel: "codex_otel";
|
|
84
|
+
car_state: "car_state";
|
|
85
|
+
git_state: "git_state";
|
|
86
|
+
github_state: "github_state";
|
|
87
|
+
linear_state: "linear_state";
|
|
88
|
+
mcp_local: "mcp_local";
|
|
89
|
+
claude_hooks: "claude_hooks";
|
|
90
|
+
manual_event: "manual_event";
|
|
91
|
+
collector_runtime: "collector_runtime";
|
|
92
|
+
}>;
|
|
93
|
+
capture_adapter_version: z.ZodString;
|
|
94
|
+
collector_version: z.ZodString;
|
|
95
|
+
repo: z.ZodString;
|
|
96
|
+
branch: z.ZodString;
|
|
97
|
+
operator_id: z.ZodString;
|
|
98
|
+
session_id: z.ZodString;
|
|
99
|
+
work_context_id: z.ZodString;
|
|
100
|
+
}, z.core.$strict>;
|
|
101
|
+
}, z.core.$strict>;
|
|
102
|
+
export type RiskFlag = z.infer<typeof RiskFlagSchema>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CaptureProvenanceSchema, IsoDateTimeSchema, NonEmptyStringSchema, } from "./common.js";
|
|
3
|
+
export const RiskFlagTypeSchema = z.enum([
|
|
4
|
+
"no_plan_signal_before_large_edit",
|
|
5
|
+
"p1_or_p2_review_finding",
|
|
6
|
+
"many_add_revert_loops",
|
|
7
|
+
"repeated_same_tool_input_shape",
|
|
8
|
+
"tool_call_loop",
|
|
9
|
+
"file_thrash_same_path",
|
|
10
|
+
"context_window_pressure",
|
|
11
|
+
"permission_denied_spike",
|
|
12
|
+
"high_token_or_time_burn_no_pr",
|
|
13
|
+
"stuck_for_30_minutes",
|
|
14
|
+
"repeated_same_failing_command",
|
|
15
|
+
"branch_ticket_mismatch",
|
|
16
|
+
"collector_stale",
|
|
17
|
+
]);
|
|
18
|
+
export const RiskEvidenceLabelSchema = z.enum([
|
|
19
|
+
"missing_plan_signal",
|
|
20
|
+
"large_edit",
|
|
21
|
+
"p1_review_finding",
|
|
22
|
+
"p2_review_finding",
|
|
23
|
+
"add_revert_loop",
|
|
24
|
+
"same_tool_input_shape",
|
|
25
|
+
"tool_call_loop_window",
|
|
26
|
+
"same_path_churn",
|
|
27
|
+
"token_pressure",
|
|
28
|
+
"permission_denied",
|
|
29
|
+
"approval_denied",
|
|
30
|
+
"no_pr_after_work",
|
|
31
|
+
"idle_or_stuck_duration",
|
|
32
|
+
"same_failing_command",
|
|
33
|
+
"branch_ticket_disagreement",
|
|
34
|
+
"collector_last_seen_stale",
|
|
35
|
+
]);
|
|
36
|
+
export const RiskFlagSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
risk_flag_id: NonEmptyStringSchema,
|
|
39
|
+
risk_type: RiskFlagTypeSchema,
|
|
40
|
+
severity: z.enum(["info", "warning", "high"]),
|
|
41
|
+
observed_at: IsoDateTimeSchema,
|
|
42
|
+
evidence_labels: z.array(RiskEvidenceLabelSchema).min(1),
|
|
43
|
+
evidence_pointer_ids: z.array(NonEmptyStringSchema).default([]),
|
|
44
|
+
provenance: CaptureProvenanceSchema,
|
|
45
|
+
})
|
|
46
|
+
.strict();
|