@akasecurity/ai-tc-claude-code 0.9.11 → 0.9.13
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/.claude-plugin/plugin.json +1 -1
- package/commands/scan.md +1 -1
- package/commands/setup.md +31 -3
- package/package.json +2 -2
- package/scripts/apply-suppressions.js +1722 -791
- package/scripts/backfill.js +4428 -3403
- package/scripts/content-retention.js +34307 -0
- package/scripts/filescan.js +4615 -3458
- package/scripts/firstrun.js +4389 -3379
- package/scripts/history-sync.js +1916 -866
- package/scripts/intro.js +520 -68
- package/scripts/message-display.js +1704 -773
- package/scripts/onboard.js +1711 -772
- package/scripts/post-model-switch.js +546 -83
- package/scripts/post-tool-use.js +4433 -3408
- package/scripts/pre-model-switch.js +4412 -3380
- package/scripts/pre-tool-use.js +4464 -3412
- package/scripts/query.js +4497 -3375
- package/scripts/reconcile.js +4404 -3393
- package/scripts/remediate.js +4428 -3403
- package/scripts/scan-worker.js +441 -30
- package/scripts/session-start.js +4482 -3450
- package/scripts/start-light.js +518 -66
- package/scripts/statusline.js +4388 -3377
- package/scripts/stop.js +555 -92
- package/scripts/sync.js +4621 -3464
- package/scripts/user-prompt-submit.js +4452 -3406
package/scripts/scan-worker.js
CHANGED
|
@@ -20533,7 +20533,17 @@ var UNPRICEABLE_PROVIDERS = Object.freeze([
|
|
|
20533
20533
|
"gateway",
|
|
20534
20534
|
"unknown",
|
|
20535
20535
|
"cli",
|
|
20536
|
-
"api"
|
|
20536
|
+
"api",
|
|
20537
|
+
// The browser extension's native host records these as `llm_call.provider`
|
|
20538
|
+
// for a web-chat turn — the web tool id, deliberately never the vendor id
|
|
20539
|
+
// (`openai`/`anthropic`) the session root carries. Subscription traffic
|
|
20540
|
+
// burns rate-limit budget, not dollar credits, and listing them here is
|
|
20541
|
+
// what keeps that true structurally: a later maintainer who wants to price
|
|
20542
|
+
// web-chat traffic at API rates has to delete this entry first, and meet
|
|
20543
|
+
// the reason on the way, rather than quietly adding one to
|
|
20544
|
+
// PROVIDER_PLATFORM.
|
|
20545
|
+
"chatgpt",
|
|
20546
|
+
"claude-ai"
|
|
20537
20547
|
]);
|
|
20538
20548
|
|
|
20539
20549
|
// ../../packages/schema/src/token/format.ts
|
|
@@ -20553,7 +20563,12 @@ var HARNESS = {
|
|
|
20553
20563
|
ClaudeDesktop: "claudedesktop",
|
|
20554
20564
|
ChatGpt: "chatgpt",
|
|
20555
20565
|
ClaudeAi: "claudeai",
|
|
20556
|
-
Api: "api"
|
|
20566
|
+
Api: "api",
|
|
20567
|
+
// Not a coding assistant a person drives — an in-process SDK embedded in an
|
|
20568
|
+
// application, so it has no IDE/CLI/desktop/web surface of its own. Carries
|
|
20569
|
+
// the same id as its SOURCE_TOOL counterpart, unlike every capture-side tool
|
|
20570
|
+
// whose wire spelling differs from its display spelling.
|
|
20571
|
+
AiTcSdk: "ai-tc-sdk"
|
|
20557
20572
|
};
|
|
20558
20573
|
var Harness = external_exports.enum(HARNESS).meta({ id: "Harness" });
|
|
20559
20574
|
var SOURCE_TOOL = {
|
|
@@ -20569,9 +20584,15 @@ var SOURCE_TOOL = {
|
|
|
20569
20584
|
// whose tool could not be identified both render through the read side's
|
|
20570
20585
|
// miss path rather than as a harness of their own.
|
|
20571
20586
|
Cli: "cli",
|
|
20572
|
-
Unknown: "unknown"
|
|
20587
|
+
Unknown: "unknown",
|
|
20588
|
+
// The wire id an in-process, request-path SDK stamps on its own structural
|
|
20589
|
+
// rows (`request_decision`) — never a capture of prompt/response/tool text,
|
|
20590
|
+
// since the SDK sits in front of a model call rather than inside a coding
|
|
20591
|
+
// assistant's own hook contract.
|
|
20592
|
+
AiTcSdk: "ai-tc-sdk"
|
|
20573
20593
|
};
|
|
20574
20594
|
var SourceTool = external_exports.enum(SOURCE_TOOL).meta({ id: "SourceTool" });
|
|
20595
|
+
var WebSourceTool = SourceTool.extract(["ChatGpt", "ClaudeAi"]);
|
|
20575
20596
|
var TOOL_TO_HARNESS = {
|
|
20576
20597
|
[SOURCE_TOOL.ClaudeCode]: HARNESS.ClaudeCode,
|
|
20577
20598
|
[SOURCE_TOOL.ClaudeDesktop]: HARNESS.ClaudeDesktop,
|
|
@@ -20580,7 +20601,12 @@ var TOOL_TO_HARNESS = {
|
|
|
20580
20601
|
[SOURCE_TOOL.ChatGpt]: HARNESS.ChatGpt,
|
|
20581
20602
|
[SOURCE_TOOL.Codex]: HARNESS.Codex,
|
|
20582
20603
|
[SOURCE_TOOL.Antigravity]: HARNESS.Antigravity,
|
|
20583
|
-
[SOURCE_TOOL.ClaudeAi]: HARNESS.ClaudeAi
|
|
20604
|
+
[SOURCE_TOOL.ClaudeAi]: HARNESS.ClaudeAi,
|
|
20605
|
+
// Wire and display id are the same string here, but the row still belongs:
|
|
20606
|
+
// both vocabularies carry the `AiTcSdk` member, and the join is exactly
|
|
20607
|
+
// their intersection — leaving a shared member out would read as an
|
|
20608
|
+
// uninstrumented tool on both surfaces, which this one is not.
|
|
20609
|
+
[SOURCE_TOOL.AiTcSdk]: HARNESS.AiTcSdk
|
|
20584
20610
|
};
|
|
20585
20611
|
|
|
20586
20612
|
// ../../packages/schema/src/zod/finding.ts
|
|
@@ -20614,7 +20640,8 @@ var FindingProvider = Harness.extract([
|
|
|
20614
20640
|
"ClaudeAi",
|
|
20615
20641
|
"Codex",
|
|
20616
20642
|
"Antigravity",
|
|
20617
|
-
"Api"
|
|
20643
|
+
"Api",
|
|
20644
|
+
"AiTcSdk"
|
|
20618
20645
|
]).meta({ id: "FindingProvider" });
|
|
20619
20646
|
var FindingCategory = external_exports.enum([
|
|
20620
20647
|
"secret",
|
|
@@ -20630,6 +20657,15 @@ var FindingCategory = external_exports.enum([
|
|
|
20630
20657
|
]).meta({ id: "FindingCategory" });
|
|
20631
20658
|
var FindingOrigin = external_exports.enum(["in-flight", "at-rest"]).meta({ id: "FindingOrigin" });
|
|
20632
20659
|
var FindingStatus = external_exports.enum(["open", "handled", "resolved", "dismissed"]).meta({ id: "FindingStatus" });
|
|
20660
|
+
var SyncFailureReason = external_exports.enum(["deployment_refused", "payload_invalid", "detached_undelivered"]).meta({ id: "SyncFailureReason" });
|
|
20661
|
+
var FindingDeliveryState = external_exports.enum(["sent", "queued", "not_sent", "never_offered", "local_scan"]).meta({ id: "FindingDeliveryState" });
|
|
20662
|
+
var FindingDelivery = external_exports.object({
|
|
20663
|
+
state: FindingDeliveryState,
|
|
20664
|
+
// The delivery time for `sent`; the failure time for `not_sent` when recorded.
|
|
20665
|
+
at: external_exports.iso.datetime().optional(),
|
|
20666
|
+
// Only on `not_sent`, and only when a known reason was recorded.
|
|
20667
|
+
reason: SyncFailureReason.optional()
|
|
20668
|
+
}).meta({ id: "FindingDelivery" });
|
|
20633
20669
|
var ResolutionMethod = external_exports.enum([
|
|
20634
20670
|
"enforced-in-flight",
|
|
20635
20671
|
"fixed-at-source",
|
|
@@ -20686,7 +20722,10 @@ var FindingInstance = external_exports.object({
|
|
|
20686
20722
|
// The session that event belongs to, when it has one — the seam a
|
|
20687
20723
|
// per-instance "view session" link needs. Absent for events captured
|
|
20688
20724
|
// outside a session.
|
|
20689
|
-
sessionId: external_exports.string().optional()
|
|
20725
|
+
sessionId: external_exports.string().optional(),
|
|
20726
|
+
// The delivery state of the event above (see FindingDelivery). Optional so
|
|
20727
|
+
// readers that do not project it stay valid.
|
|
20728
|
+
delivery: FindingDelivery.optional()
|
|
20690
20729
|
}).meta({ id: "FindingInstance" });
|
|
20691
20730
|
var FindingGroup = external_exports.object({
|
|
20692
20731
|
id: external_exports.string(),
|
|
@@ -20738,7 +20777,10 @@ var FindingFacets = external_exports.object({
|
|
|
20738
20777
|
// Host tool (attributes.tool_name). Present only on the instance-level
|
|
20739
20778
|
// reads, which can filter by it; the type-level read omits the dimension
|
|
20740
20779
|
// because a group spans tools.
|
|
20741
|
-
tool: external_exports.array(FindingFacetItem).optional()
|
|
20780
|
+
tool: external_exports.array(FindingFacetItem).optional(),
|
|
20781
|
+
// Delivery states (FindingDeliveryState). Present only on the
|
|
20782
|
+
// instance-level reads, like `tool`.
|
|
20783
|
+
deployment: external_exports.array(FindingFacetItem).optional()
|
|
20742
20784
|
}).meta({ id: "FindingFacets" });
|
|
20743
20785
|
var FindingTypeSummary = FindingGroup.omit({ instances: true, match: true }).meta({
|
|
20744
20786
|
id: "FindingTypeSummary"
|
|
@@ -20847,6 +20889,8 @@ var ListFindingInstancesQuery = external_exports.object({
|
|
|
20847
20889
|
// Exact host-tool names (attributes.tool_name, e.g. 'Bash'). A real filter,
|
|
20848
20890
|
// where the free-text `q` can only match the rendered "via Bash" label.
|
|
20849
20891
|
tool: external_exports.array(external_exports.string()).optional(),
|
|
20892
|
+
// The delivery state of each finding's event (see FindingDelivery).
|
|
20893
|
+
deployment: external_exports.array(FindingDeliveryState).optional(),
|
|
20850
20894
|
// Exact repository / file-path matches, for the drill-down out of the
|
|
20851
20895
|
// locations view. A row whose event carries no repo/file matches neither.
|
|
20852
20896
|
repo: external_exports.string().optional(),
|
|
@@ -20867,6 +20911,10 @@ var ListFindingInstancesResponse = external_exports.object({
|
|
|
20867
20911
|
items: external_exports.array(FindingInstanceDetail),
|
|
20868
20912
|
nextCursor: external_exports.string().nullable()
|
|
20869
20913
|
}).meta({ id: "ListFindingInstancesResponse" });
|
|
20914
|
+
var ListFindingInstancesPage = external_exports.object({
|
|
20915
|
+
items: external_exports.array(FindingInstanceDetail),
|
|
20916
|
+
nextCursor: external_exports.string().nullable()
|
|
20917
|
+
}).meta({ id: "ListFindingInstancesPage" });
|
|
20870
20918
|
var FindingLocationSummary = external_exports.object({
|
|
20871
20919
|
// Opaque, stable, minted from the pair by encodeLocationId. It exists
|
|
20872
20920
|
// because a location's identity is two values and a URL param carries one:
|
|
@@ -20908,6 +20956,8 @@ var ListFindingLocationsQuery = external_exports.object({
|
|
|
20908
20956
|
// instances that match, and folds its status from those.
|
|
20909
20957
|
status: external_exports.array(FindingStatus).optional(),
|
|
20910
20958
|
tool: external_exports.array(external_exports.string()).optional(),
|
|
20959
|
+
// The delivery state of each finding's event (see FindingDelivery).
|
|
20960
|
+
deployment: external_exports.array(FindingDeliveryState).optional(),
|
|
20911
20961
|
q: external_exports.string().optional(),
|
|
20912
20962
|
sessionId: external_exports.string().optional(),
|
|
20913
20963
|
from: external_exports.iso.datetime().optional(),
|
|
@@ -20965,18 +21015,41 @@ var AuditEventType = external_exports.enum([
|
|
|
20965
21015
|
// 'tool_call' is the reconciler's structural row for every call, while
|
|
20966
21016
|
// 'tool_use' exists only where a hook enforced against the arguments.
|
|
20967
21017
|
"tool_use",
|
|
20968
|
-
// One row per model REFUSAL
|
|
20969
|
-
//
|
|
20970
|
-
//
|
|
20971
|
-
//
|
|
20972
|
-
//
|
|
20973
|
-
//
|
|
21018
|
+
// One row per model REFUSAL, across all four seams a prohibited model can be
|
|
21019
|
+
// stopped at: a switch onto it, a turn already running on it, a subagent
|
|
21020
|
+
// spawn asking for it, or a request-path refusal an embedded request-path
|
|
21021
|
+
// SDK makes in-process before the call leaves the application. Which seam
|
|
21022
|
+
// rides `attributes.refusal_seam`, never this member name. A structural row
|
|
21023
|
+
// like the ones above rather than a capture — it carries the model that was
|
|
21024
|
+
// refused and nothing the user typed, because what is worth recording about
|
|
21025
|
+
// a governance decision is the decision, and prompt text is the thing this
|
|
21026
|
+
// product exists to keep from travelling.
|
|
20974
21027
|
"model_refusal",
|
|
21028
|
+
// One row per request-path DECISION: a policy check an embedded request-path
|
|
21029
|
+
// SDK performs in-process before a model call leaves the application, or
|
|
21030
|
+
// against that call's non-streamed response. A structural row like
|
|
21031
|
+
// 'model_refusal' rather than a capture — content-free in the same way:
|
|
21032
|
+
// which side, which seam, what action and which field are decided rides
|
|
21033
|
+
// `attributes`, never this member name, and the matched text itself never
|
|
21034
|
+
// travels.
|
|
21035
|
+
//
|
|
21036
|
+
// A prohibited-model refusal on the request path is deliberately NOT this
|
|
21037
|
+
// member: it stays 'model_refusal' with `refusal_seam: 'request'`, so it
|
|
21038
|
+
// shares one bucket with the plugin's switch/turn/spawn refusals rather
|
|
21039
|
+
// than splitting one governance concept across two event types. This
|
|
21040
|
+
// member carries every OTHER request-path decision.
|
|
21041
|
+
"request_decision",
|
|
20975
21042
|
// One row per config-inventory scan, hung off the session root. It is the
|
|
20976
21043
|
// fact the posture inspection findings reference (findings require an
|
|
20977
21044
|
// audit_event_id), and its started_at is the "scanned Nm ago" the read
|
|
20978
21045
|
// surface renders.
|
|
20979
|
-
"config_scan"
|
|
21046
|
+
"config_scan",
|
|
21047
|
+
// One row per reported browser-extension capture status, hung off the web
|
|
21048
|
+
// session root. The durable home of what one tab's network interception
|
|
21049
|
+
// is doing — a write-through of the native host's in-memory tracker, so a
|
|
21050
|
+
// second process (aka extension status) and a restarted host both have
|
|
21051
|
+
// somewhere to read it back from.
|
|
21052
|
+
"capture_status"
|
|
20980
21053
|
]).meta({ id: "AuditEventType" });
|
|
20981
21054
|
var AttributeBag = external_exports.record(external_exports.string(), external_exports.unknown());
|
|
20982
21055
|
var HostAttributes = external_exports.object({
|
|
@@ -21110,6 +21183,10 @@ var CaptureAttributes = external_exports.object({
|
|
|
21110
21183
|
// to 'allow' — the enforcement audit trail's link back to the grant that
|
|
21111
21184
|
// authorized the bypass.
|
|
21112
21185
|
exception_ids: external_exports.array(external_exports.guid()).optional(),
|
|
21186
|
+
// The persisted spellings of EventMetadata's messageId/conversationId — the
|
|
21187
|
+
// join back to the `llm_call` leaf for the same assistant turn.
|
|
21188
|
+
message_id: external_exports.string().optional(),
|
|
21189
|
+
conversation_id: external_exports.string().optional(),
|
|
21113
21190
|
// Whole milliseconds this capture's inspection blocked its caller — the
|
|
21114
21191
|
// plugin's own added latency (see EventMetadata.inspectionMs, whose value
|
|
21115
21192
|
// this is). Promoted to the `inspection_ms` generated column so the facet is
|
|
@@ -21118,7 +21195,33 @@ var CaptureAttributes = external_exports.object({
|
|
|
21118
21195
|
// inline json_extract and is not itself an optimization.
|
|
21119
21196
|
// ABSENT on replayed captures (backfill / worktree scan) and on rows written
|
|
21120
21197
|
// before the measurement shipped — never present as a placeholder 0.
|
|
21121
|
-
inspection_ms: external_exports.number().int().nonnegative().optional()
|
|
21198
|
+
inspection_ms: external_exports.number().int().nonnegative().optional(),
|
|
21199
|
+
// What a `redact` this capture could not carry out became instead (see
|
|
21200
|
+
// EventMetadata.redactDegradedTo, whose value this is). Present only when a
|
|
21201
|
+
// degrade actually happened, so absence is the ordinary case rather than a
|
|
21202
|
+
// reader having to distinguish it from a zero.
|
|
21203
|
+
//
|
|
21204
|
+
// PER CAPTURE, while `inspection_findings.action_taken` is per finding —
|
|
21205
|
+
// so on a multi-finding row this does not say which finding degraded, and
|
|
21206
|
+
// its presence does not mean the fallback decided the capture's action. A
|
|
21207
|
+
// capture denied by another finding's own Block policy carries `block`
|
|
21208
|
+
// here too. The full statement is on EventMetadata.redactDegradedTo; it is
|
|
21209
|
+
// repeated rather than referenced because a store reader opens this file.
|
|
21210
|
+
redact_degraded_to: ActionTaken.optional()
|
|
21211
|
+
}).catchall(external_exports.unknown());
|
|
21212
|
+
var CaptureStatusAttributes = external_exports.object({
|
|
21213
|
+
source_tool: external_exports.string().optional(),
|
|
21214
|
+
patched: external_exports.boolean().optional(),
|
|
21215
|
+
live: external_exports.boolean().optional(),
|
|
21216
|
+
blind: external_exports.boolean().optional(),
|
|
21217
|
+
sends_seen_dom: external_exports.number().int().nonnegative().optional(),
|
|
21218
|
+
exchanges_seen_net: external_exports.number().int().nonnegative().optional(),
|
|
21219
|
+
parse_failures: external_exports.number().int().nonnegative().optional(),
|
|
21220
|
+
unparsed_bodies: external_exports.number().int().nonnegative().optional(),
|
|
21221
|
+
shape_misses: external_exports.array(external_exports.string()).optional(),
|
|
21222
|
+
conversation_endpoints: external_exports.number().int().nonnegative().optional(),
|
|
21223
|
+
closed: external_exports.boolean().optional(),
|
|
21224
|
+
enforcement: external_exports.string().optional()
|
|
21122
21225
|
}).catchall(external_exports.unknown());
|
|
21123
21226
|
var ToolCallInspection = external_exports.object({
|
|
21124
21227
|
ruleId: external_exports.string().min(1),
|
|
@@ -21314,7 +21417,17 @@ var AuditEvent = external_exports.object({
|
|
|
21314
21417
|
/** `share` to a first-party/internal destination. */
|
|
21315
21418
|
internal: external_exports.boolean(),
|
|
21316
21419
|
/** Event needs review (e.g. unverified egress). */
|
|
21317
|
-
flagged: external_exports.boolean()
|
|
21420
|
+
flagged: external_exports.boolean(),
|
|
21421
|
+
/**
|
|
21422
|
+
* The body this event's `title` is drawn from was cleared by local body
|
|
21423
|
+
* expiry, so an EMPTY title here means "gone", not "never had one".
|
|
21424
|
+
*
|
|
21425
|
+
* A separate flag rather than a sentinel written into `title`: the title is
|
|
21426
|
+
* rendered text, and a store-layer module that invented display copy for it
|
|
21427
|
+
* would be choosing words the view is supposed to choose. Additive and
|
|
21428
|
+
* defaulted, so an older producer still validates.
|
|
21429
|
+
*/
|
|
21430
|
+
bodyExpired: external_exports.boolean().default(false)
|
|
21318
21431
|
}).meta({ id: "ActivityAuditEvent" });
|
|
21319
21432
|
var ActivitySessionSummary = external_exports.object({
|
|
21320
21433
|
id: external_exports.string(),
|
|
@@ -22119,6 +22232,11 @@ var RemoteFailureKind = external_exports.enum([
|
|
|
22119
22232
|
"rejected",
|
|
22120
22233
|
"unreachable"
|
|
22121
22234
|
]);
|
|
22235
|
+
var ControlPlaneFailure = RemoteFailureKind.extract([
|
|
22236
|
+
"unauthorized",
|
|
22237
|
+
"forbidden",
|
|
22238
|
+
"unreachable"
|
|
22239
|
+
]);
|
|
22122
22240
|
var AttachDeviceRequest = external_exports.object({
|
|
22123
22241
|
// This machine's own continuity id, so re-attaching ROTATES the credential
|
|
22124
22242
|
// on one machine record instead of producing a second one. Client-minted
|
|
@@ -22537,6 +22655,17 @@ var EventMetadata = external_exports.object({
|
|
|
22537
22655
|
// to 'allow' — the enforcement audit trail's link back to the grant that
|
|
22538
22656
|
// authorized the bypass. Absent on captures where no exception applied.
|
|
22539
22657
|
exceptionIds: external_exports.array(external_exports.guid()).optional(),
|
|
22658
|
+
// The assistant message this capture belongs to, and the conversation it sits
|
|
22659
|
+
// in — set by the browser extension's network capture so a stored `response`
|
|
22660
|
+
// row can be joined to the `llm_call` leaf describing the same turn. Absent
|
|
22661
|
+
// on every other capture path, which has no such id.
|
|
22662
|
+
//
|
|
22663
|
+
// Non-empty for the reason WebExchange.messageId is: it is the join key, and
|
|
22664
|
+
// a blank one matches no `llm_call` leaf. That refusal reaches only the
|
|
22665
|
+
// places an event is PARSED; the local write path types the event and parses
|
|
22666
|
+
// nothing, which is why `toCaptureAttributes` omits a blank one separately.
|
|
22667
|
+
messageId: external_exports.string().min(1).optional(),
|
|
22668
|
+
conversationId: external_exports.string().optional(),
|
|
22540
22669
|
// How long THIS capture's inspection blocked its caller, in whole
|
|
22541
22670
|
// milliseconds — the plugin's own added latency, NOT the LLM call it sat in
|
|
22542
22671
|
// front of. Measured inside `capture()` (@akasecurity/plugin-sdk) across
|
|
@@ -22549,7 +22678,37 @@ var EventMetadata = external_exports.object({
|
|
|
22549
22678
|
// Absent is also what every pre-measurement client writes, and what a
|
|
22550
22679
|
// clock failure degrades to — a reader must treat absence as "not measured"
|
|
22551
22680
|
// and never as a zero, which would read as "inspection is free".
|
|
22552
|
-
inspectionMs: external_exports.number().int().nonnegative().optional()
|
|
22681
|
+
inspectionMs: external_exports.number().int().nonnegative().optional(),
|
|
22682
|
+
// What a `redact` this capture COULD NOT CARRY OUT became instead — the
|
|
22683
|
+
// workspace's `redactFallback`, applied because the field could not be
|
|
22684
|
+
// masked in place (a shell command, a URL, or any argument on a host whose
|
|
22685
|
+
// hook contract offers no rewrite channel).
|
|
22686
|
+
//
|
|
22687
|
+
// It exists because the action alone cannot say why. A finding recorded as
|
|
22688
|
+
// `warn` reads identically whether its detection was ASSIGNED Warn or was
|
|
22689
|
+
// assigned Redact on a field that could not take one — and those are
|
|
22690
|
+
// different facts about the same row: the first is a policy the user chose,
|
|
22691
|
+
// the second is a masking the host could not perform. Absent means no
|
|
22692
|
+
// degrade happened, which is every ordinary capture.
|
|
22693
|
+
//
|
|
22694
|
+
// TWO LIMITS a reader of a stored row has to know, because the grain here
|
|
22695
|
+
// is the CAPTURE while `actionTaken` is per FINDING:
|
|
22696
|
+
//
|
|
22697
|
+
// - It does not say WHICH finding degraded. A capture carrying a degraded
|
|
22698
|
+
// `redact` alongside a finding ASSIGNED the same action stores both
|
|
22699
|
+
// identically and one reason for the pair; attributing it to both
|
|
22700
|
+
// describes the assigned one wrongly, and to neither loses the degrade.
|
|
22701
|
+
// - PRESENCE IS NOT CAUSATION. The value is the action the lost redact
|
|
22702
|
+
// became, not the reason the capture ended as it did — a capture denied
|
|
22703
|
+
// by some other finding's own Block policy still carries `block` here,
|
|
22704
|
+
// and clearing the workspace's fallback would not have let it through.
|
|
22705
|
+
// Gate on the value against what a fallback can produce; never read the
|
|
22706
|
+
// field's presence as "this was the fallback's doing".
|
|
22707
|
+
//
|
|
22708
|
+
// Both are pinned as behaviour in @akasecurity/plugin-sdk's runtime suite.
|
|
22709
|
+
// Closing either means moving the reason onto the finding row, which
|
|
22710
|
+
// already carries its own action.
|
|
22711
|
+
redactDegradedTo: ActionTaken.optional()
|
|
22553
22712
|
}).meta({ id: "EventMetadata" });
|
|
22554
22713
|
var Event = external_exports.object({
|
|
22555
22714
|
id: external_exports.guid(),
|
|
@@ -22659,6 +22818,15 @@ var RotateKeyInput = external_exports.object({
|
|
|
22659
22818
|
confirmation: external_exports.string()
|
|
22660
22819
|
});
|
|
22661
22820
|
|
|
22821
|
+
// ../../packages/schema/src/zod/finding-delivery.ts
|
|
22822
|
+
var KNOWN_REASONS = SyncFailureReason.options;
|
|
22823
|
+
|
|
22824
|
+
// ../../packages/schema/src/zod/findings-group-build.ts
|
|
22825
|
+
function rankByOrder(members2) {
|
|
22826
|
+
return Object.fromEntries(members2.map((member, index) => [member, index]));
|
|
22827
|
+
}
|
|
22828
|
+
var SEVERITY_RANK = rankByOrder(Severity.options);
|
|
22829
|
+
|
|
22662
22830
|
// ../../packages/schema/src/zod/installed-pack.ts
|
|
22663
22831
|
var InstalledPack = external_exports.object({
|
|
22664
22832
|
id: external_exports.guid(),
|
|
@@ -22725,6 +22893,11 @@ var Policy = external_exports.object({
|
|
|
22725
22893
|
// test `prohibitedModels` passes and `reversibleRuleIds` fails.
|
|
22726
22894
|
provenance: PolicyProvenance.optional()
|
|
22727
22895
|
}).meta({ id: "Policy" });
|
|
22896
|
+
var KNOWN_BUILTIN_IDS = ["monitor", "warn", "redact", "vault", "block"];
|
|
22897
|
+
var BuiltinPolicyId = external_exports.enum(KNOWN_BUILTIN_IDS).meta({ id: "BuiltinPolicyId" });
|
|
22898
|
+
var RedactFallback = BuiltinPolicyId.extract(["monitor", "warn", "block"]).meta({
|
|
22899
|
+
id: "RedactFallback"
|
|
22900
|
+
});
|
|
22728
22901
|
var PolicyBundle = external_exports.object({
|
|
22729
22902
|
version: external_exports.string(),
|
|
22730
22903
|
policies: external_exports.array(Policy),
|
|
@@ -22772,6 +22945,16 @@ var PolicyBundle = external_exports.object({
|
|
|
22772
22945
|
// control plane), so no name resolution stands between the decision and the
|
|
22773
22946
|
// comparison.
|
|
22774
22947
|
prohibitedModels: external_exports.array(external_exports.string()).optional(),
|
|
22948
|
+
// What a resolved `redact` becomes on a field the host cannot rewrite, as
|
|
22949
|
+
// the ORGANIZATION would have it. Merged raise-only against the device's own
|
|
22950
|
+
// `WorkspaceSettings.redactFallback` (see strongerRedactFallback below), so
|
|
22951
|
+
// a control plane can tighten a machine and never loosen one — the same
|
|
22952
|
+
// direction `mergeRaiseOnly` enforces for policies.
|
|
22953
|
+
//
|
|
22954
|
+
// Optional so an older backend, and an older on-disk cache, still parses;
|
|
22955
|
+
// absent leaves the device's own setting in force, which is the behaviour
|
|
22956
|
+
// that predates the field and the safe direction to default.
|
|
22957
|
+
redactFallback: RedactFallback.optional(),
|
|
22775
22958
|
customKeywords: external_exports.array(external_exports.string()),
|
|
22776
22959
|
fetchedAt: external_exports.iso.datetime()
|
|
22777
22960
|
}).meta({ id: "PolicyBundle" });
|
|
@@ -22801,11 +22984,6 @@ function severityFloorPolicy(category) {
|
|
|
22801
22984
|
const peak = CATEGORY_PEAK_SEVERITY[category];
|
|
22802
22985
|
return peak === "critical" || peak === "high" ? "warn" : "monitor";
|
|
22803
22986
|
}
|
|
22804
|
-
var KNOWN_BUILTIN_IDS = ["monitor", "warn", "redact", "vault", "block"];
|
|
22805
|
-
var BuiltinPolicyId = external_exports.enum(KNOWN_BUILTIN_IDS).meta({ id: "BuiltinPolicyId" });
|
|
22806
|
-
var RedactFallback = BuiltinPolicyId.extract(["monitor", "warn", "block"]).meta({
|
|
22807
|
-
id: "RedactFallback"
|
|
22808
|
-
});
|
|
22809
22987
|
var BUILTIN_POLICY_SPECS = {
|
|
22810
22988
|
monitor: {
|
|
22811
22989
|
name: "Monitor",
|
|
@@ -23067,7 +23245,7 @@ var VaultConsent = external_exports.object({
|
|
|
23067
23245
|
});
|
|
23068
23246
|
|
|
23069
23247
|
// ../../packages/schema/src/zod/local.ts
|
|
23070
|
-
var WORKSPACE_SETTINGS_SPEC_VERSION =
|
|
23248
|
+
var WORKSPACE_SETTINGS_SPEC_VERSION = 8;
|
|
23071
23249
|
var RunMode = external_exports.enum(["standalone", "attached"]);
|
|
23072
23250
|
var ControlPlaneConnection = external_exports.object({
|
|
23073
23251
|
endpoint: external_exports.string().min(1),
|
|
@@ -23086,6 +23264,27 @@ var HistorySyncConsent = external_exports.object({
|
|
|
23086
23264
|
payloadVersion: external_exports.number().int().positive(),
|
|
23087
23265
|
endpoint: external_exports.string()
|
|
23088
23266
|
});
|
|
23267
|
+
var WebChatCaptureConsent = external_exports.object({
|
|
23268
|
+
acknowledgedAt: external_exports.iso.datetime(),
|
|
23269
|
+
version: external_exports.number().int().positive()
|
|
23270
|
+
});
|
|
23271
|
+
var WebChatResponseCapture = external_exports.enum(["with-findings", "always", "never"]);
|
|
23272
|
+
var WebChatCapture = external_exports.object({
|
|
23273
|
+
responses: WebChatResponseCapture.default("with-findings"),
|
|
23274
|
+
account: external_exports.boolean().default(false),
|
|
23275
|
+
// Absent until granted. Presence alone does not authorize anything — see
|
|
23276
|
+
// isWebChatCaptureConsentValid.
|
|
23277
|
+
consent: WebChatCaptureConsent.optional()
|
|
23278
|
+
});
|
|
23279
|
+
var BODY_RETENTION_DEFAULT_DAYS = 30;
|
|
23280
|
+
var BodyRetention = external_exports.object({
|
|
23281
|
+
enabled: external_exports.boolean().default(false),
|
|
23282
|
+
// Never 0, and the ceiling is a fat-finger guard rather than a policy
|
|
23283
|
+
// limit — `enabled` is the real gate. A low value cannot reach a row the
|
|
23284
|
+
// sync ledger still owes: the sweep's age filter only ever NARROWS a
|
|
23285
|
+
// candidate set that is already bounded by "delivered, or never owed".
|
|
23286
|
+
retainDays: external_exports.number().int().min(1).max(3650).default(BODY_RETENTION_DEFAULT_DAYS)
|
|
23287
|
+
}).meta({ id: "BodyRetention" });
|
|
23089
23288
|
var WorkspaceSettings = external_exports.object({
|
|
23090
23289
|
specVersion: external_exports.number().int().positive().default(WORKSPACE_SETTINGS_SPEC_VERSION),
|
|
23091
23290
|
runMode: RunMode.default("standalone"),
|
|
@@ -23134,7 +23333,23 @@ var WorkspaceSettings = external_exports.object({
|
|
|
23134
23333
|
// carry prompt/reply/tool-output text in `content`; the key name predates
|
|
23135
23334
|
// both widenings. Absent until granted, and a grant for a different endpoint
|
|
23136
23335
|
// or an older payload no longer counts.
|
|
23137
|
-
historySyncConsent: HistorySyncConsent.optional()
|
|
23336
|
+
historySyncConsent: HistorySyncConsent.optional(),
|
|
23337
|
+
// What the browser extension may record from a web chat, and the grant that
|
|
23338
|
+
// authorizes it. Absent until the user answers: recording something that was
|
|
23339
|
+
// never recorded before is never an assumed grant on upgrade, so the whole
|
|
23340
|
+
// block is optional rather than defaulted in. What an absent block means is
|
|
23341
|
+
// webChatCaptureOf's answer, in one place.
|
|
23342
|
+
//
|
|
23343
|
+
// Enforcement is NOT gated on this. A machine that has never answered still
|
|
23344
|
+
// blocks, redacts and warns on what a user sends; the grant covers what is
|
|
23345
|
+
// written down.
|
|
23346
|
+
webChatCapture: WebChatCapture.optional(),
|
|
23347
|
+
// Local body expiry (see BodyRetention). Off until switched on; expiring a
|
|
23348
|
+
// body never removes the row or its findings.
|
|
23349
|
+
bodyRetention: BodyRetention.default({
|
|
23350
|
+
enabled: false,
|
|
23351
|
+
retainDays: BODY_RETENTION_DEFAULT_DAYS
|
|
23352
|
+
})
|
|
23138
23353
|
});
|
|
23139
23354
|
|
|
23140
23355
|
// ../../packages/schema/src/zod/managed.ts
|
|
@@ -23147,13 +23362,22 @@ var ManagedSettingKey = external_exports.enum([
|
|
|
23147
23362
|
"vaultInlineReveal",
|
|
23148
23363
|
"modelJudgeConsent",
|
|
23149
23364
|
"dataSharesInPlace",
|
|
23150
|
-
"redactFallback"
|
|
23365
|
+
"redactFallback",
|
|
23366
|
+
// Pins the toggle and the day count together — see BodyRetention on why the
|
|
23367
|
+
// two are one unit. An administrator mandating a window wants the count
|
|
23368
|
+
// enforced with it, not one a user can widen while the toggle stays on.
|
|
23369
|
+
"bodyRetention"
|
|
23151
23370
|
]).meta({ id: "ManagedSettingKey" });
|
|
23152
23371
|
function isManagedSettingKey(value) {
|
|
23153
23372
|
return ManagedSettingKey.safeParse(value).success;
|
|
23154
23373
|
}
|
|
23155
23374
|
var ManagedSettingsValues = external_exports.object({
|
|
23156
23375
|
runMode: external_exports.enum(["standalone", "attached"]).optional(),
|
|
23376
|
+
// `controlPlane` and `bodyRetention` are the two nested values, and both are
|
|
23377
|
+
// plain, non-strict objects: a key under either that this build does not know
|
|
23378
|
+
// is stripped and nothing reports it. The unknown-value split in
|
|
23379
|
+
// ManagedSettings below classifies top-level names only, so it stops at
|
|
23380
|
+
// these boundaries.
|
|
23157
23381
|
controlPlane: external_exports.object({
|
|
23158
23382
|
endpoint: external_exports.string().min(1),
|
|
23159
23383
|
label: external_exports.string().min(1).optional()
|
|
@@ -23164,7 +23388,8 @@ var ManagedSettingsValues = external_exports.object({
|
|
|
23164
23388
|
vaultInlineReveal: external_exports.enum(["masked", "full", "off"]).optional(),
|
|
23165
23389
|
modelJudgeConsent: external_exports.boolean().optional(),
|
|
23166
23390
|
dataSharesInPlace: external_exports.boolean().optional(),
|
|
23167
|
-
redactFallback: RedactFallback.optional()
|
|
23391
|
+
redactFallback: RedactFallback.optional(),
|
|
23392
|
+
bodyRetention: BodyRetention.optional()
|
|
23168
23393
|
}).meta({ id: "ManagedSettingsValues" });
|
|
23169
23394
|
var ManagedSettings = external_exports.object({
|
|
23170
23395
|
specVersion: external_exports.number().int().positive().default(MANAGED_SETTINGS_SPEC_VERSION),
|
|
@@ -23172,7 +23397,21 @@ var ManagedSettings = external_exports.object({
|
|
|
23172
23397
|
// decision from a bug. Absent renders as a generic "your organization".
|
|
23173
23398
|
organization: external_exports.string().min(1).optional(),
|
|
23174
23399
|
// What the administrator pinned.
|
|
23175
|
-
|
|
23400
|
+
//
|
|
23401
|
+
// Parsed as a RECORD rather than as the nested schema, and split below for
|
|
23402
|
+
// the same reason `lockedFields` is parsed as names: a plain `z.object`
|
|
23403
|
+
// drops an unrecognised key and succeeds, so a pin this build does not know
|
|
23404
|
+
// vanished and nothing anywhere said so. A pin with no lock is a supported
|
|
23405
|
+
// shape — it is a DEFAULT the user may still change — so that silence hit
|
|
23406
|
+
// exactly the file an administrator is most likely to write while a fleet
|
|
23407
|
+
// is mid-upgrade.
|
|
23408
|
+
//
|
|
23409
|
+
// Splitting here rather than calling `.strict()`: strict would REFUSE the
|
|
23410
|
+
// file, which is the outcome the lock half already rejected — an older
|
|
23411
|
+
// build then runs entirely unmanaged, every pin and lock gone. A bad KNOWN
|
|
23412
|
+
// value still fails, because the nested schema is re-run over the known
|
|
23413
|
+
// subset and its issues are re-raised on this parse.
|
|
23414
|
+
values: external_exports.record(external_exports.string(), external_exports.unknown()).default({}),
|
|
23176
23415
|
// Which of those the user may not change. A key here with no matching value
|
|
23177
23416
|
// freezes whatever the user last chose; a value with no lock is a DEFAULT
|
|
23178
23417
|
// the user may still override. The two are separable on purpose.
|
|
@@ -23185,17 +23424,31 @@ var ManagedSettings = external_exports.object({
|
|
|
23185
23424
|
// the fleets most likely to carry a version skew. A name outside the enum
|
|
23186
23425
|
// is still never HONOURED: the lockable set stays explicit above.
|
|
23187
23426
|
lockedFields: external_exports.array(external_exports.string()).default([])
|
|
23188
|
-
}).transform(({ lockedFields, ...rest }) => {
|
|
23427
|
+
}).transform(({ lockedFields, values, ...rest }, ctx) => {
|
|
23189
23428
|
const known = [];
|
|
23190
23429
|
const unknown2 = [];
|
|
23191
23430
|
for (const name of lockedFields) {
|
|
23192
23431
|
if (isManagedSettingKey(name)) known.push(name);
|
|
23193
23432
|
else unknown2.push(name);
|
|
23194
23433
|
}
|
|
23434
|
+
const knownValues = /* @__PURE__ */ Object.create(null);
|
|
23435
|
+
const unknownValues = [];
|
|
23436
|
+
for (const [name, value] of Object.entries(values)) {
|
|
23437
|
+
if (Object.hasOwn(ManagedSettingsValues.shape, name)) knownValues[name] = value;
|
|
23438
|
+
else unknownValues.push(name);
|
|
23439
|
+
}
|
|
23440
|
+
const pinned = ManagedSettingsValues.safeParse(knownValues);
|
|
23441
|
+
if (!pinned.success) {
|
|
23442
|
+
for (const issue2 of pinned.error.issues)
|
|
23443
|
+
ctx.addIssue({ ...issue2, path: ["values", ...issue2.path] });
|
|
23444
|
+
return external_exports.NEVER;
|
|
23445
|
+
}
|
|
23195
23446
|
return {
|
|
23196
23447
|
...rest,
|
|
23448
|
+
values: pinned.data,
|
|
23197
23449
|
lockedFields: known,
|
|
23198
|
-
...unknown2.length > 0 ? { unknownLockedFields: unknown2 } : {}
|
|
23450
|
+
...unknown2.length > 0 ? { unknownLockedFields: unknown2 } : {},
|
|
23451
|
+
...unknownValues.length > 0 ? { unknownValueFields: unknownValues } : {}
|
|
23199
23452
|
};
|
|
23200
23453
|
}).meta({ id: "ManagedSettings" });
|
|
23201
23454
|
|
|
@@ -23448,12 +23701,30 @@ var RecommendedActionIdParam = external_exports.object({ id: external_exports.st
|
|
|
23448
23701
|
// ../../packages/schema/src/zod/settings-action.ts
|
|
23449
23702
|
var HistorySyncConsentChoice = external_exports.enum(["granted", "revoked", "unchanged"]).meta({ id: "HistorySyncConsentChoice" });
|
|
23450
23703
|
var ModelJudgeConsentChoice = external_exports.enum(["granted", "revoked", "unchanged"]).meta({ id: "ModelJudgeConsentChoice" });
|
|
23704
|
+
var WebChatCaptureConsentChoice = external_exports.enum(["granted", "revoked", "unchanged"]).meta({ id: "WebChatCaptureConsentChoice" });
|
|
23451
23705
|
var SaveSettingsInput = external_exports.object({
|
|
23452
23706
|
historicalAccess: external_exports.string(),
|
|
23453
23707
|
modelJudgeConsent: ModelJudgeConsentChoice,
|
|
23454
23708
|
historySyncConsent: HistorySyncConsentChoice,
|
|
23455
23709
|
vaultConsent: external_exports.string(),
|
|
23456
|
-
vaultInlineReveal: external_exports.string()
|
|
23710
|
+
vaultInlineReveal: external_exports.string(),
|
|
23711
|
+
webChatCaptureConsent: WebChatCaptureConsentChoice,
|
|
23712
|
+
// Widened to `string` like its neighbours rather than typed as
|
|
23713
|
+
// `RedactFallback`, on this module's own layering rule: shape here, VALUE at
|
|
23714
|
+
// the call site, so the domain check receives the type it was written for.
|
|
23715
|
+
//
|
|
23716
|
+
// NOT because a narrower schema would reject differently. `parseActionInput`
|
|
23717
|
+
// is a `safeParse` wrapper and throws for no field schema, so either spelling
|
|
23718
|
+
// reaches a recoverable `{ ok: false }` and there is no rejected promise to
|
|
23719
|
+
// trade against. The real cost runs the other way and is the part worth
|
|
23720
|
+
// knowing: a value this schema admits and the domain enum then rejects lands
|
|
23721
|
+
// on the action's shared refusal, which names NO field, where a shape
|
|
23722
|
+
// rejection reaches `malformedInput` and names the schema key.
|
|
23723
|
+
redactFallback: external_exports.string(),
|
|
23724
|
+
// Shape only, the way the enum fields above are strings only: the RANGE is
|
|
23725
|
+
// `BodyRetention`'s and the action checks it there, so there is one place
|
|
23726
|
+
// that decides what a legal horizon is rather than two that can drift.
|
|
23727
|
+
bodyRetention: external_exports.object({ enabled: external_exports.boolean(), retainDays: external_exports.number() })
|
|
23457
23728
|
});
|
|
23458
23729
|
var AttachInput = external_exports.object({
|
|
23459
23730
|
endpoint: external_exports.string(),
|
|
@@ -23579,6 +23850,96 @@ var SetupHandoffOffer = external_exports.object({
|
|
|
23579
23850
|
path: ["liveKeys"]
|
|
23580
23851
|
});
|
|
23581
23852
|
|
|
23853
|
+
// ../../packages/schema/src/zod/web-capture.ts
|
|
23854
|
+
var WebUsageSource = external_exports.enum(["site", "estimated", "none"]);
|
|
23855
|
+
var WebUsage = external_exports.object({
|
|
23856
|
+
inputTokens: external_exports.number().int().nonnegative().optional(),
|
|
23857
|
+
outputTokens: external_exports.number().int().nonnegative().optional(),
|
|
23858
|
+
cacheReadInputTokens: external_exports.number().int().nonnegative().optional(),
|
|
23859
|
+
cacheCreationInputTokens: external_exports.number().int().nonnegative().optional()
|
|
23860
|
+
});
|
|
23861
|
+
var WebToolCall = external_exports.object({
|
|
23862
|
+
toolUseId: external_exports.string().min(1),
|
|
23863
|
+
toolName: external_exports.string().min(1),
|
|
23864
|
+
target: external_exports.string().optional(),
|
|
23865
|
+
isError: external_exports.boolean().optional(),
|
|
23866
|
+
inputSize: external_exports.number().int().nonnegative().optional(),
|
|
23867
|
+
outputSize: external_exports.number().int().nonnegative().optional()
|
|
23868
|
+
});
|
|
23869
|
+
var WebExchange = external_exports.object({
|
|
23870
|
+
messageId: external_exports.string().min(1),
|
|
23871
|
+
startedAt: external_exports.iso.datetime(),
|
|
23872
|
+
model: external_exports.string().optional(),
|
|
23873
|
+
usage: WebUsage.optional(),
|
|
23874
|
+
usageSource: WebUsageSource,
|
|
23875
|
+
stopReason: external_exports.string().optional(),
|
|
23876
|
+
conversationId: external_exports.string().optional(),
|
|
23877
|
+
turnIndex: external_exports.number().int().nonnegative().optional(),
|
|
23878
|
+
toolCalls: external_exports.array(WebToolCall).default([]),
|
|
23879
|
+
// Absent when the adapter recovered no text. Capped by the caller at
|
|
23880
|
+
// RESPONSE_TEXT_MAX_BYTES, so a short capture is never mistaken for a short
|
|
23881
|
+
// reply.
|
|
23882
|
+
responseText: external_exports.string().optional(),
|
|
23883
|
+
// The stored text is short of the reply. It does NOT say which of the two
|
|
23884
|
+
// ceilings on this path cut it: the caller applies its own cap on the raw
|
|
23885
|
+
// bytes it reads off the wire, which can be reached by a stream whose
|
|
23886
|
+
// recovered text stays well under RESPONSE_TEXT_MAX_BYTES, and applies that
|
|
23887
|
+
// one to the text. A reader cannot tell them apart, and nothing downstream
|
|
23888
|
+
// should branch as though it could.
|
|
23889
|
+
truncated: external_exports.boolean().default(false)
|
|
23890
|
+
});
|
|
23891
|
+
var WebEnforcementState = external_exports.enum([
|
|
23892
|
+
"watching",
|
|
23893
|
+
"composer-only",
|
|
23894
|
+
"button-only",
|
|
23895
|
+
"unattached",
|
|
23896
|
+
"unknown"
|
|
23897
|
+
]);
|
|
23898
|
+
var RESPONSE_TEXT_MAX_BYTES = 2 * 1024 * 1024;
|
|
23899
|
+
var WebCaptureStatus = external_exports.object({
|
|
23900
|
+
patched: external_exports.boolean(),
|
|
23901
|
+
live: external_exports.boolean(),
|
|
23902
|
+
blind: external_exports.boolean(),
|
|
23903
|
+
sendsSeenDom: external_exports.number().int().nonnegative(),
|
|
23904
|
+
exchangesSeenNet: external_exports.number().int().nonnegative(),
|
|
23905
|
+
parseFailures: external_exports.number().int().nonnegative(),
|
|
23906
|
+
unparsedBodies: external_exports.number().int().nonnegative(),
|
|
23907
|
+
// The adapter-declared JSON key paths that were absent from a real payload —
|
|
23908
|
+
// the earliest signal that a site's contract moved.
|
|
23909
|
+
shapeMisses: external_exports.array(external_exports.string()).default([]),
|
|
23910
|
+
// How many `kind: 'conversation'` endpoints the reporting tab's adapter
|
|
23911
|
+
// compiled. Zero means this build declares none for the site, so observing
|
|
23912
|
+
// nothing is the design rather than a fault — the one fact that separates a
|
|
23913
|
+
// site nobody has surveyed yet from one whose contract moved. Defaulted so a
|
|
23914
|
+
// build predating the field is read as declaring nothing rather than refused.
|
|
23915
|
+
conversationEndpoints: external_exports.number().int().nonnegative().default(0),
|
|
23916
|
+
// The document that sent this report is going away. The bridge sets it on
|
|
23917
|
+
// its `pagehide` report and nowhere else.
|
|
23918
|
+
//
|
|
23919
|
+
// A property of the REPORT rather than of capture health, which is why
|
|
23920
|
+
// nothing in `deriveWebCaptureState` reads it and why it stays out of the
|
|
23921
|
+
// bridge's own report signature — a closing tab's last word must not be
|
|
23922
|
+
// suppressed for carrying the same health as the report before it. What
|
|
23923
|
+
// reads it is the per-site fold: a document that said it was unloading stops
|
|
23924
|
+
// voting on the site's state, so the reload the `blind` remediation asks for
|
|
23925
|
+
// can actually clear the verdict it was shown. A document that dies without
|
|
23926
|
+
// sending one is covered by CAPTURE_STATUS_DOCUMENT_QUIET_MS instead.
|
|
23927
|
+
//
|
|
23928
|
+
// Defaulted so a build predating the field reads as a document that never
|
|
23929
|
+
// said it was closing — which keeps it voting, the same as every report that
|
|
23930
|
+
// is not a final one.
|
|
23931
|
+
closed: external_exports.boolean().default(false),
|
|
23932
|
+
// What the DOM enforcement path is doing, which none of the counters above
|
|
23933
|
+
// can say: `sendsSeenDom` rises only once a send has COMPLETED, so a tab
|
|
23934
|
+
// whose watcher never bound reports zero exactly like a tab nobody typed in.
|
|
23935
|
+
// Defaulted to 'unknown' rather than 'watching' so a status from a build
|
|
23936
|
+
// predating the field is not read as reporting a healthy one.
|
|
23937
|
+
enforcement: WebEnforcementState.default("unknown")
|
|
23938
|
+
});
|
|
23939
|
+
var CAPTURE_STATUS_RECENCY_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
23940
|
+
var CAPTURE_STATUS_RECENCY_DAYS = CAPTURE_STATUS_RECENCY_MS / (24 * 60 * 60 * 1e3);
|
|
23941
|
+
var CAPTURE_STATUS_DOCUMENT_QUIET_MS = 12 * 60 * 60 * 1e3;
|
|
23942
|
+
|
|
23582
23943
|
// ../../packages/detections/src/posture/config-posture.ts
|
|
23583
23944
|
var RULE_VERSION = "1";
|
|
23584
23945
|
var KNOWN_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -23636,6 +23997,56 @@ var CONFIG_POSTURE_RULES = [
|
|
|
23636
23997
|
}
|
|
23637
23998
|
];
|
|
23638
23999
|
|
|
24000
|
+
// ../../packages/detections/src/posture/web-capture-posture.ts
|
|
24001
|
+
var RULE_VERSION2 = "1";
|
|
24002
|
+
var DRIFT_MIN_PARSE_FAILURES = 2;
|
|
24003
|
+
var WEB_CAPTURE_DRIFT_STATES = /* @__PURE__ */ new Set([
|
|
24004
|
+
"blind",
|
|
24005
|
+
"degraded"
|
|
24006
|
+
]);
|
|
24007
|
+
var WEB_CAPTURE_DRIFT_RULE = {
|
|
24008
|
+
ruleId: "web-capture-drift",
|
|
24009
|
+
version: RULE_VERSION2,
|
|
24010
|
+
name: "Web chat capture is not reading the site",
|
|
24011
|
+
category: "config",
|
|
24012
|
+
severity: "medium",
|
|
24013
|
+
definition: JSON.stringify({
|
|
24014
|
+
kind: "web-capture-drift",
|
|
24015
|
+
states: [...WEB_CAPTURE_DRIFT_STATES],
|
|
24016
|
+
minParseFailures: DRIFT_MIN_PARSE_FAILURES
|
|
24017
|
+
})
|
|
24018
|
+
};
|
|
24019
|
+
var STATIC_COPY = {
|
|
24020
|
+
active: { headline: "turns are being observed on this site" },
|
|
24021
|
+
unreported: {
|
|
24022
|
+
// Says "recently" rather than "yet": the store read is bounded to
|
|
24023
|
+
// CAPTURE_STATUS_RECENCY_MS, so this state covers a site nothing has ever
|
|
24024
|
+
// reported for AND one whose last report has aged out. The two are the
|
|
24025
|
+
// same fact to a reader — nobody has confirmed anything lately — and the
|
|
24026
|
+
// copy may not claim the stronger of them.
|
|
24027
|
+
headline: `no report in the last ${String(CAPTURE_STATUS_RECENCY_DAYS)} days \u2014 open the site in Chrome with the extension loaded`
|
|
24028
|
+
},
|
|
24029
|
+
standby: {
|
|
24030
|
+
headline: "this build declares no endpoints for the site, so nothing is observed yet"
|
|
24031
|
+
},
|
|
24032
|
+
unpatched: {
|
|
24033
|
+
// Says what the flags say and no more. `patched` is false both for a tap
|
|
24034
|
+
// that installed and hooked neither transport and for one that never ran
|
|
24035
|
+
// at all — a page reports the same status either way, so the copy may not
|
|
24036
|
+
// assert one of them.
|
|
24037
|
+
headline: "the page tap captured neither fetch nor XHR \u2014 it may not have installed; reload the extension at chrome://extensions"
|
|
24038
|
+
},
|
|
24039
|
+
idle: { headline: "watching; no turn has been observed yet" },
|
|
24040
|
+
blind: {
|
|
24041
|
+
headline: "messages were sent in the page that the network capture never saw",
|
|
24042
|
+
remediation: "reload the tab. If it persists after `aka update` and reloading the extension at chrome://extensions, the site's send path has changed and needs a new extension build."
|
|
24043
|
+
},
|
|
24044
|
+
degraded: {
|
|
24045
|
+
headline: "the site's payloads no longer carry the fields the extension reads",
|
|
24046
|
+
remediation: "run `aka update`, then reload the extension at chrome://extensions. If it stays degraded after an update, the site's contract has changed and needs a new extension build."
|
|
24047
|
+
}
|
|
24048
|
+
};
|
|
24049
|
+
|
|
23639
24050
|
// ../../packages/detections/src/security/redos-probe.ts
|
|
23640
24051
|
var BUDGET_MS = 100;
|
|
23641
24052
|
var EXPONENTIAL_UNITS = [
|