deepdebug-local-agent 1.2.0 → 1.4.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.
Files changed (123) hide show
  1. package/.github/workflows/deploy-gcp.yml +58 -26
  2. package/CHANGELOG.md +13 -0
  3. package/docs/la-protocol-v2.md +68 -0
  4. package/docs/ws-metadata-only.md +44 -0
  5. package/env.example +7 -0
  6. package/package.json +2 -1
  7. package/scripts/sync-la-protocol-v2-contract.mjs +58 -0
  8. package/src/la-protocol-v2/chunks.js +45 -0
  9. package/src/la-protocol-v2/config.js +27 -0
  10. package/src/la-protocol-v2/content.js +57 -0
  11. package/src/la-protocol-v2/contract/CONTRACT_SOURCE.json +81 -0
  12. package/src/la-protocol-v2/contract/README.md +103 -0
  13. package/src/la-protocol-v2/contract/ack.schema.json +51 -0
  14. package/src/la-protocol-v2/contract/alert.schema.json +62 -0
  15. package/src/la-protocol-v2/contract/approval.decision.schema.json +57 -0
  16. package/src/la-protocol-v2/contract/audit.event.schema.json +86 -0
  17. package/src/la-protocol-v2/contract/config.update.schema.json +73 -0
  18. package/src/la-protocol-v2/contract/content.request.schema.json +110 -0
  19. package/src/la-protocol-v2/contract/content.response.schema.json +90 -0
  20. package/src/la-protocol-v2/contract/defs.schema.json +191 -0
  21. package/src/la-protocol-v2/contract/envelope.schema.json +89 -0
  22. package/src/la-protocol-v2/contract/error.schema.json +59 -0
  23. package/src/la-protocol-v2/contract/heartbeat.schema.json +100 -0
  24. package/src/la-protocol-v2/contract/hello.schema.json +111 -0
  25. package/src/la-protocol-v2/contract/incident.candidate.schema.json +102 -0
  26. package/src/la-protocol-v2/contract/index.json +166 -0
  27. package/src/la-protocol-v2/contract/job.assign.schema.json +212 -0
  28. package/src/la-protocol-v2/contract/job.cancel.schema.json +52 -0
  29. package/src/la-protocol-v2/contract/job.event.schema.json +115 -0
  30. package/src/la-protocol-v2/contract/job.result.schema.json +100 -0
  31. package/src/la-protocol-v2/contract/log.stats.schema.json +79 -0
  32. package/src/la-protocol-v2/contract/ready.schema.json +106 -0
  33. package/src/la-protocol-v2/contract/register.schema.json +92 -0
  34. package/src/la-protocol-v2/contract/scan.upload.schema.json +59 -0
  35. package/src/la-protocol-v2/contract/scan.uploaded.schema.json +51 -0
  36. package/src/la-protocol-v2/contract/webhook.forward.schema.json +69 -0
  37. package/src/la-protocol-v2/contract.js +90 -0
  38. package/src/la-protocol-v2/errors.js +34 -0
  39. package/src/la-protocol-v2/index.js +8 -0
  40. package/src/la-protocol-v2/link.js +93 -0
  41. package/src/la-protocol-v2/runtime.js +72 -0
  42. package/src/la-protocol-v2/session.js +650 -0
  43. package/src/la-protocol-v2/strict-json.js +47 -0
  44. package/src/mcp-http-server.js +5 -3
  45. package/src/server.js +70 -9
  46. package/src/utils/exec-policy.js +8 -1
  47. package/src/ws-channel/allowlist.js +143 -0
  48. package/src/ws-channel/config.js +22 -0
  49. package/src/ws-channel/connection-state.js +18 -0
  50. package/src/ws-channel/index.js +6 -0
  51. package/src/ws-channel/metadata-guard.js +78 -0
  52. package/src/ws-channel/policy-offline.js +40 -0
  53. package/src/ws-channel/transit-guard.js +55 -0
  54. package/test/contract/la-protocol-v2/vectors/ack.vectors.json +149 -0
  55. package/test/contract/la-protocol-v2/vectors/alert.vectors.json +101 -0
  56. package/test/contract/la-protocol-v2/vectors/approval.decision.vectors.json +165 -0
  57. package/test/contract/la-protocol-v2/vectors/audit.event.vectors.json +156 -0
  58. package/test/contract/la-protocol-v2/vectors/config.update.vectors.json +189 -0
  59. package/test/contract/la-protocol-v2/vectors/content.request.vectors.json +325 -0
  60. package/test/contract/la-protocol-v2/vectors/content.response.vectors.json +413 -0
  61. package/test/contract/la-protocol-v2/vectors/cross-type.vectors.json +260 -0
  62. package/test/contract/la-protocol-v2/vectors/error.vectors.json +179 -0
  63. package/test/contract/la-protocol-v2/vectors/heartbeat.vectors.json +109 -0
  64. package/test/contract/la-protocol-v2/vectors/hello.vectors.json +224 -0
  65. package/test/contract/la-protocol-v2/vectors/incident.candidate.vectors.json +186 -0
  66. package/test/contract/la-protocol-v2/vectors/job.assign.vectors.json +631 -0
  67. package/test/contract/la-protocol-v2/vectors/job.cancel.vectors.json +133 -0
  68. package/test/contract/la-protocol-v2/vectors/job.event.vectors.json +233 -0
  69. package/test/contract/la-protocol-v2/vectors/job.result.vectors.json +137 -0
  70. package/test/contract/la-protocol-v2/vectors/log.stats.vectors.json +137 -0
  71. package/test/contract/la-protocol-v2/vectors/ready.vectors.json +177 -0
  72. package/test/contract/la-protocol-v2/vectors/register.vectors.json +399 -0
  73. package/test/contract/la-protocol-v2/vectors/scan.upload.vectors.json +137 -0
  74. package/test/contract/la-protocol-v2/vectors/scan.uploaded.vectors.json +101 -0
  75. package/test/contract/la-protocol-v2/vectors/traces/invalid-agent-mismatch.json +140 -0
  76. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-after-last.json +200 -0
  77. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-byte-length-mismatch.json +174 -0
  78. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-last-flag.json +200 -0
  79. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-out-of-order.json +200 -0
  80. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-total-changes.json +200 -0
  81. package/test/contract/la-protocol-v2/vectors/traces/invalid-clock-skew.json +46 -0
  82. package/test/contract/la-protocol-v2/vectors/traces/invalid-event-before-ready.json +72 -0
  83. package/test/contract/la-protocol-v2/vectors/traces/invalid-first-frame-not-register.json +48 -0
  84. package/test/contract/la-protocol-v2/vectors/traces/invalid-frame-over-48kib.json +141 -0
  85. package/test/contract/la-protocol-v2/vectors/traces/invalid-la-sends-job-assign.json +173 -0
  86. package/test/contract/la-protocol-v2/vectors/traces/invalid-params-raw-differs-from-payload.json +172 -0
  87. package/test/contract/la-protocol-v2/vectors/traces/invalid-payload-above-limit.json +174 -0
  88. package/test/contract/la-protocol-v2/vectors/traces/invalid-resume-restarts-seq.json +144 -0
  89. package/test/contract/la-protocol-v2/vectors/traces/invalid-seq-gap.json +166 -0
  90. package/test/contract/la-protocol-v2/vectors/traces/invalid-seq-repeated.json +166 -0
  91. package/test/contract/la-protocol-v2/vectors/traces/invalid-sig-tenant-mismatch.json +172 -0
  92. package/test/contract/la-protocol-v2/vectors/traces/invalid-signature-warn-with-enforce-required.json +77 -0
  93. package/test/contract/la-protocol-v2/vectors/traces/invalid-tenant-mismatch.json +140 -0
  94. package/test/contract/la-protocol-v2/vectors/traces/invalid-type-outside-allowlist.json +140 -0
  95. package/test/contract/la-protocol-v2/vectors/traces/valid-content-chunks-in-order.json +224 -0
  96. package/test/contract/la-protocol-v2/vectors/traces/valid-handshake-and-job.json +266 -0
  97. package/test/contract/la-protocol-v2/vectors/traces/valid-resume-continues-seq.json +168 -0
  98. package/test/contract/la-protocol-v2/vectors/traces/valid-retransmit-is-idempotent.json +193 -0
  99. package/test/contract/la-protocol-v2/vectors/webhook.forward.vectors.json +170 -0
  100. package/test/la-protocol-v2/contract.test.js +131 -0
  101. package/test/la-protocol-v2/helpers/la-rig.js +83 -0
  102. package/test/la-protocol-v2/helpers/reference-cp.js +349 -0
  103. package/test/la-protocol-v2/helpers/spawn-agent.js +35 -0
  104. package/test/la-protocol-v2/link.test.js +141 -0
  105. package/test/la-protocol-v2/session-inbound.test.js +279 -0
  106. package/test/la-protocol-v2/session-outbound.test.js +382 -0
  107. package/test/la-protocol-v2/traces.test.js +270 -0
  108. package/test/la-protocol-v2/tunnel-e2e.test.js +124 -0
  109. package/test/ws-channel/allowlist.test.js +67 -0
  110. package/test/ws-channel/metadata-guard.test.js +104 -0
  111. package/test/ws-channel/policy-offline.test.js +99 -0
  112. package/test/ws-channel/tunnel-e2e.test.js +88 -0
  113. package/tools/graphify-validation/extras/README.md +19 -0
  114. package/tools/graphify-validation/extras/bymethod.py +35 -0
  115. package/tools/graphify-validation/extras/docker/Dockerfile +16 -0
  116. package/tools/graphify-validation/extras/docker/inner.sh +7 -0
  117. package/tools/graphify-validation/extras/g10.py +59 -0
  118. package/tools/graphify-validation/extras/g3aug.py +49 -0
  119. package/tools/graphify-validation/extras/hybrid.py +34 -0
  120. package/tools/graphify-validation/extras/truth2.py +44 -0
  121. package/tools/interop/LaV2NodeInteropTest.java +266 -0
  122. package/tools/interop/README.md +21 -0
  123. package/tools/interop/la-interop-client.mjs +97 -0
@@ -0,0 +1,103 @@
1
+ # Gateway <-> Local Agent WebSocket protocol v2 (contract, F3-22)
2
+
3
+ Machine-readable contract for the control-plane (CP, gateway) <-> Local Agent (LA) channel, shared by both
4
+ sides. Design: vault `10 Library/Plans/Fase 3 Desenho Tecnico 2026-10-28.md` sec. 4.2. Status: the gateway
5
+ implements it behind `deepdebug.agent-ws.protocol-v2.enabled` (default off, F3-05a); the LA side (F3-05b) does not
6
+ exist yet. v1 is untouched. The gateway packages `*.schema.json` + `index.json` from this folder as classpath
7
+ `la-protocol-v2/` (pom resource; both Dockerfiles copy this folder), so this folder stays the only source.
8
+
9
+ ## Files
10
+ - `envelope.schema.json`: common frame, closed (`additionalProperties:false`). `<type>.schema.json` (21):
11
+ one per allowlisted type, each `$ref`s the envelope and closes `payload`. `defs.schema.json`: shared types.
12
+ - `index.json`: allowlist, direction, signed/control flags, content class per type, and the limits below.
13
+ - `vectors/<type>.vectors.json` (+ `cross-type`): valid and invalid messages with `expect` (`valid`, error `code`,
14
+ optional JSON Schema `keyword`, optional session `rule`). `vectors/traces/*.json`: whole sessions for the stateful rules.
15
+
16
+ ## Envelope
17
+ `{schemaVersion:2, type, msgId(uuid), seq, ack?, requestId?, tenantId, agentId?, workspaceId, ts, chunk?, paramsRaw?, sig?, payload}`.
18
+ CP->LA frames carry `paramsRaw` (the exact signed JSON, which must equal `payload`) and `sig` (Ed25519, same
19
+ `VH-AGENT-SIG-V1` canonical as v1); LA->CP frames carry `agentId` (required in EVERY LA->CP frame, `ack` and `error` included: the gateway refuses one without it as
20
+ `agent_mismatch`; the per-type schemas of `ack`/`error` require it for both directions, and the gateway always sets it on its own)
21
+ and never a signature (F3-X3 may add one).
22
+ `ack` = highest contiguous `seq` received from the peer, piggybacked on any frame. The design's flat fields
23
+ live under `payload`; its `reqId` is `requestId`; `chunkNo,last` is `chunk{index,total,last}` (index from 0).
24
+
25
+ ## Limits (index.json)
26
+ Frame <= 48 KiB UTF-8; chunk <= 32 KiB raw (43692 base64 chars); <= 64 chunks (2 MiB per response);
27
+ ack timeout 5 s, <= 3 retransmissions; handshake steps 10 s; `ping`/`heartbeat` 30 s, session dead after 90 s
28
+ (= Redis `la:session` TTL); clock skew <= 60 s. Duplicate detection (gateway, F3-05a): the last 512 `seq`->`msgId` pairs
29
+ per session, in memory (`dedupe-entries`); the 10 min Redis window of the design (`dedupeWindowSeconds` in `index.json`)
30
+ is NOT implemented, a replay older than those 512 frames is `seq_replayed`. CP->LA frames repeat the payload in
31
+ `paramsRaw`, so their effective payload budget is about 20 KiB; larger inputs travel by `ref`.
32
+
33
+ ## State machine
34
+ `AWAIT_REGISTER -> AWAIT_HELLO -> AWAIT_READY -> READY`, after the WS upgrade authenticates (Bearer, as v1).
35
+ 1. LA sends `register` (`protocol:2`, version, capabilities, `signatureMode`, `workspaces[]` with `pathSha256`,
36
+ optional `resume{sessionId,lastRecvSeq}`). 2. LA sends `hello` (state: `signatureMode`, Graphify, disk, queue, clock).
37
+ 3. CP validates (tenant, agent, skew, `signatureMode=enforce` when the tenant is `hybrid`/`client`) and answers
38
+ `ready{sessionId, resumed, peerLastSeq, limits}`. Handshake and control frames (`register hello ready ack error`)
39
+ use `seq 0`; every other frame has `seq` 1.. consecutive per direction. Text `ping`/`pong` stays as liveness.
40
+ - **Resume:** with `resume` and a live Redis session the CP answers `resumed:true`; the LA continues at
41
+ `peerLastSeq+1` and re-sends unacked frames; otherwise `resumed:false`, both restart at 1 and in-flight requests fail.
42
+ - **Rules (reference model in `ProtocolV2ContractTest`, same order):** size, allowlist, schema, tenant/agent, direction,
43
+ handshake state, `seq` (same seq + same `msgId` = idempotent duplicate, re-ack; same seq + other `msgId` =
44
+ `seq_replayed`; skip = `seq_gap`), chunks (index 0.., `total` constant, `last` iff last index, none after last; then `payload.byteLength` must equal the size of
45
+ the base64-DECODED `payload.data`, else `chunk_inconsistent`: JSON Schema cannot state it, so the vector files carry
46
+ `expect.rule:"byteLength-decoded"` and both validators apply it).
47
+ - **Errors** (`error{code,retryable}`, then WS close 4400-4499 when fatal): `bad_frame unknown_type schema_violation
48
+ frame_too_large payload_too_large wrong_direction handshake_violation not_ready seq_gap seq_replayed
49
+ chunk_out_of_order chunk_inconsistent tenant_mismatch agent_mismatch params_mismatch signature_mode_insufficient
50
+ clock_skew protocol_unsupported unauthorized agent_offline timeout rate_limited internal`.
51
+ - **Timeouts:** `content.request` 10 s to first chunk, 30 s total, then `timeout`; v1-style commands keep 120 s.
52
+
53
+ ## Compatibility with v1
54
+ Same endpoint, auth and signature. A v2 LA sends the `register` above; a gateway with v2 off (the default) ignores
55
+ it (it has no `requestId`/`workspacePath`) and the LA, with no `ready` in 10 s, falls back to the legacy
56
+ `{type:"register",tenantId,port,workspacePath}` and v1 commands. A v2 gateway treats a frame without `schemaVersion`
57
+ as v1 for that session. v1 command names are not v2 types (`mcp.execute-command` is rejected). v2 needs a CP
58
+ signing key: without one the gateway does not negotiate v2.
59
+
60
+ ## What never goes in the envelope
61
+ Everything is closed: no free-text fields, no extra properties, free strings <= 512 chars (identifiers, enums,
62
+ hashes, counts). Client content may exist only in three declared fields (`x-content-class`, pinned by the test):
63
+ `content.response.data` (relay, LA->CP, never persisted or logged by the CP), `job.assign.inputs[].inline` and
64
+ `webhook.forward.bodyB64` (transit, CP->LA, `transient:true`, not persisted; `paramsRaw` echoes them).
65
+ Long non-content strings are marked `x-large-metadata` (`paramsRaw`, `signedPutUrl`, `vhapr1` token). `error.detail` <= 200 chars
66
+ and `audit.event` have no summary text; stack traces, diffs, logs and paths go only through `content.*`.
67
+
68
+ ## Verify
69
+ - Java (gateway, runs in `mvn test`): `mvn -o test -Dtest=ProtocolV2ContractTest` (JDK 21).
70
+ - Node (LA, F3-05b; Ajv 2020, no LA code needed): `cd docs/contracts/la-protocol-v2 && npm i --no-save ajv@8 &&
71
+ node tools/validate-vectors.cjs`. Traces are language-neutral; the LA must reproduce each `expect.error`.
72
+ - Changing a schema = change the vectors in the same PR; adding a type = update `index.json` and the envelope enum.
73
+
74
+ ## Gateway behaviour (F3-05a) and gaps the code revealed
75
+ Each frame is checked in the order of the Rules (size, parse with duplicate keys refused, allowlist, schema, tenant,
76
+ agent, direction, state, seq, chunks); `error` frames carry the wire code only, never the content. CP->LA frames are
77
+ built from the unsigned payload and validated against these schemas before they are written, so the CP cannot send a field the
78
+ schema does not know. That runtime check covers the data frames sent through the API (`job.*`, `content.request`, ...); the
79
+ handshake and control frames (`ready`, `ack`, `error`) are assembled by fixed code and are NOT schema-checked at runtime: the
80
+ test transport validates every frame the session writes, and the tests fail on a violation.
81
+ A fatal error closes the socket with 4400 + the position of its code in the `errorCode` enum (a test pins the order; `timeout` = 4420). Resume works only on the same gateway instance (state is in memory, 90 s); elsewhere `resumed:false`. Not done in
82
+ F3-05a: relaying a v2 stream between gateway instances, the HTTP relay (F3-06), LA handlers (F3-05b/07). Gaps, for
83
+ F3-05b to confirm (none changes a schema):
84
+ 1. **`byteLength` is the decoded size of `data`**; the gateway refuses a chunk where it differs (`chunk_inconsistent`).
85
+ The F3-22 vectors had 27 for a 26-byte payload and a `max-size-chunk` that decoded to 32769 bytes (fixed in F3-05a); the
86
+ above-limit vectors still disagreed and a non-canonical 43693-char `data` was in use: all fixed, and
87
+ `ProtocolV2ContractTest` now fails on any vector or trace whose `byteLength` differs from the decoded size.
88
+ 2. **`content.request` is acked implicitly by its first `content.response`**, also when the request timed out or was
89
+ cancelled meanwhile. The ack timeout is 5 s but the first chunk may take 10 s: an LA that is slow to start must
90
+ send an explicit `ack` (`accepted`) first, else the request is sent again (same seq and msgId) up to 3 times.
91
+ 3. **Retransmissions are re-signed**: same `seq` and `msgId`, new `sig.nonce`/`timestamp` (the LA keeps a nonce LRU
92
+ and a 60 s skew). The LA must dedupe by `seq`+`msgId` and re-ack, never execute twice.
93
+ 4. **No window in `ready.limits` and no `content.cancel` type.** The gateway bounds each request with a queue of
94
+ `maxChunksInFlight` (16): a consumer that falls further behind loses that request (`rate_limited`) while the
95
+ chunks still in flight are validated, acked and dropped. Cancelling a request cannot stop the LA; a cancel
96
+ message (or a window in `ready.limits`) is a contract change for later.
97
+ 5. `content.response.sha256` has no stated scope (chunk or whole content); the gateway passes it through unchecked.
98
+ 6. After 3 unanswered retransmissions the gateway closes with 4420 (`timeout`) and keeps the frame for a resume; the
99
+ LA must reconnect with `resume` to receive it. A silent connection (no frame and no text `ping` for 90 s) is closed
100
+ the same way.
101
+ 7. v1 commands are refused for an LA that speaks v2 (`protocol_mismatch`): until F3-06/07 move the callers, a v2 LA
102
+ cannot serve `sendCommand`, so the LA must stay on v1 for tenants whose flows still use v1 commands.
103
+
@@ -0,0 +1,51 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.visionhammer.io/la-protocol-v2/ack.schema.json",
4
+ "title": "LA protocol v2: ack (both)",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "envelope.schema.json"
9
+ }
10
+ ],
11
+ "properties": {
12
+ "type": {
13
+ "const": "ack"
14
+ },
15
+ "payload": {
16
+ "type": "object",
17
+ "additionalProperties": false,
18
+ "properties": {
19
+ "ackSeq": {
20
+ "$ref": "defs.schema.json#/$defs/seq"
21
+ },
22
+ "status": {
23
+ "type": "string",
24
+ "enum": [
25
+ "accepted",
26
+ "duplicate",
27
+ "rejected"
28
+ ]
29
+ },
30
+ "errorCode": {
31
+ "$ref": "defs.schema.json#/$defs/errorCode"
32
+ }
33
+ },
34
+ "required": [
35
+ "ackSeq",
36
+ "status"
37
+ ]
38
+ },
39
+ "seq": {
40
+ "const": 0
41
+ },
42
+ "chunk": false,
43
+ "sig": false,
44
+ "paramsRaw": false,
45
+ "agentId": true
46
+ },
47
+ "required": [
48
+ "payload",
49
+ "agentId"
50
+ ]
51
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.visionhammer.io/la-protocol-v2/alert.schema.json",
4
+ "title": "LA protocol v2: alert (la->cp)",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "envelope.schema.json"
9
+ }
10
+ ],
11
+ "properties": {
12
+ "type": {
13
+ "const": "alert"
14
+ },
15
+ "payload": {
16
+ "type": "object",
17
+ "additionalProperties": false,
18
+ "properties": {
19
+ "code": {
20
+ "type": "string",
21
+ "enum": [
22
+ "la_degraded",
23
+ "index_stale",
24
+ "disk_low",
25
+ "signature_warn",
26
+ "queue_full",
27
+ "clock_skew"
28
+ ]
29
+ },
30
+ "severity": {
31
+ "type": "string",
32
+ "enum": [
33
+ "warning",
34
+ "critical"
35
+ ]
36
+ },
37
+ "value": {
38
+ "type": "integer",
39
+ "minimum": 0,
40
+ "maximum": 9007199254740991
41
+ }
42
+ },
43
+ "required": [
44
+ "code",
45
+ "severity"
46
+ ]
47
+ },
48
+ "seq": {
49
+ "type": "integer",
50
+ "minimum": 1,
51
+ "maximum": 9007199254740991
52
+ },
53
+ "chunk": false,
54
+ "sig": false,
55
+ "paramsRaw": false,
56
+ "agentId": true
57
+ },
58
+ "required": [
59
+ "payload",
60
+ "agentId"
61
+ ]
62
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.visionhammer.io/la-protocol-v2/approval.decision.schema.json",
4
+ "title": "LA protocol v2: approval.decision (cp->la)",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "envelope.schema.json"
9
+ }
10
+ ],
11
+ "properties": {
12
+ "type": {
13
+ "const": "approval.decision"
14
+ },
15
+ "payload": {
16
+ "type": "object",
17
+ "additionalProperties": false,
18
+ "properties": {
19
+ "approvalId": {
20
+ "$ref": "defs.schema.json#/$defs/uuid"
21
+ },
22
+ "decision": {
23
+ "type": "string",
24
+ "enum": [
25
+ "approved",
26
+ "denied"
27
+ ]
28
+ },
29
+ "token": {
30
+ "type": "string",
31
+ "minLength": 1,
32
+ "maxLength": 4096,
33
+ "pattern": "^vhapr1\\.[A-Za-z0-9_-]{1,64}\\.[A-Za-z0-9_-]{1,2048}\\.[A-Za-z0-9_-]{1,512}$",
34
+ "x-large-metadata": true
35
+ }
36
+ },
37
+ "required": [
38
+ "approvalId",
39
+ "decision",
40
+ "token"
41
+ ]
42
+ },
43
+ "seq": {
44
+ "type": "integer",
45
+ "minimum": 1,
46
+ "maximum": 9007199254740991
47
+ },
48
+ "chunk": false,
49
+ "sig": true,
50
+ "paramsRaw": true
51
+ },
52
+ "required": [
53
+ "payload",
54
+ "sig",
55
+ "paramsRaw"
56
+ ]
57
+ }
@@ -0,0 +1,86 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.visionhammer.io/la-protocol-v2/audit.event.schema.json",
4
+ "title": "LA protocol v2: audit.event (la->cp)",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "envelope.schema.json"
9
+ }
10
+ ],
11
+ "properties": {
12
+ "type": {
13
+ "const": "audit.event"
14
+ },
15
+ "payload": {
16
+ "type": "object",
17
+ "additionalProperties": false,
18
+ "properties": {
19
+ "action": {
20
+ "type": "string",
21
+ "enum": [
22
+ "policy_decision",
23
+ "approval_requested",
24
+ "redaction",
25
+ "content_served",
26
+ "config_applied"
27
+ ]
28
+ },
29
+ "decision": {
30
+ "type": "string",
31
+ "enum": [
32
+ "allow",
33
+ "deny",
34
+ "require_human",
35
+ "n/a"
36
+ ]
37
+ },
38
+ "actionType": {
39
+ "$ref": "defs.schema.json#/$defs/shortId"
40
+ },
41
+ "toolName": {
42
+ "$ref": "defs.schema.json#/$defs/shortId"
43
+ },
44
+ "requestHash": {
45
+ "$ref": "defs.schema.json#/$defs/sha256"
46
+ },
47
+ "redactionSummary": {
48
+ "type": "object",
49
+ "additionalProperties": false,
50
+ "properties": {
51
+ "rules": {
52
+ "type": "integer",
53
+ "minimum": 0,
54
+ "maximum": 100000
55
+ },
56
+ "matches": {
57
+ "type": "integer",
58
+ "minimum": 0,
59
+ "maximum": 100000000
60
+ }
61
+ },
62
+ "required": [
63
+ "rules",
64
+ "matches"
65
+ ]
66
+ }
67
+ },
68
+ "required": [
69
+ "action"
70
+ ]
71
+ },
72
+ "seq": {
73
+ "type": "integer",
74
+ "minimum": 1,
75
+ "maximum": 9007199254740991
76
+ },
77
+ "chunk": false,
78
+ "sig": false,
79
+ "paramsRaw": false,
80
+ "agentId": true
81
+ },
82
+ "required": [
83
+ "payload",
84
+ "agentId"
85
+ ]
86
+ }
@@ -0,0 +1,73 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.visionhammer.io/la-protocol-v2/config.update.schema.json",
4
+ "title": "LA protocol v2: config.update (cp->la)",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "envelope.schema.json"
9
+ }
10
+ ],
11
+ "properties": {
12
+ "type": {
13
+ "const": "config.update"
14
+ },
15
+ "payload": {
16
+ "type": "object",
17
+ "additionalProperties": false,
18
+ "properties": {
19
+ "flags": {
20
+ "type": "array",
21
+ "maxItems": 64,
22
+ "items": {
23
+ "type": "object",
24
+ "additionalProperties": false,
25
+ "properties": {
26
+ "name": {
27
+ "type": "string",
28
+ "minLength": 1,
29
+ "maxLength": 64,
30
+ "pattern": "^[a-z0-9]+([._-][a-z0-9]+)*$"
31
+ },
32
+ "enabled": {
33
+ "type": "boolean"
34
+ }
35
+ },
36
+ "required": [
37
+ "name",
38
+ "enabled"
39
+ ]
40
+ }
41
+ },
42
+ "dlpRulesetSha256": {
43
+ "$ref": "defs.schema.json#/$defs/sha256"
44
+ },
45
+ "minLaVersion": {
46
+ "$ref": "defs.schema.json#/$defs/semver"
47
+ },
48
+ "retentionDays": {
49
+ "type": "integer",
50
+ "minimum": 1,
51
+ "maximum": 3650
52
+ },
53
+ "dataPlaneMode": {
54
+ "$ref": "defs.schema.json#/$defs/dataPlaneMode"
55
+ }
56
+ },
57
+ "minProperties": 1
58
+ },
59
+ "seq": {
60
+ "type": "integer",
61
+ "minimum": 1,
62
+ "maximum": 9007199254740991
63
+ },
64
+ "chunk": false,
65
+ "sig": true,
66
+ "paramsRaw": true
67
+ },
68
+ "required": [
69
+ "payload",
70
+ "sig",
71
+ "paramsRaw"
72
+ ]
73
+ }
@@ -0,0 +1,110 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.visionhammer.io/la-protocol-v2/content.request.schema.json",
4
+ "title": "LA protocol v2: content.request (cp->la)",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "envelope.schema.json"
9
+ }
10
+ ],
11
+ "properties": {
12
+ "type": {
13
+ "const": "content.request"
14
+ },
15
+ "payload": {
16
+ "type": "object",
17
+ "additionalProperties": false,
18
+ "properties": {
19
+ "kind": {
20
+ "type": "string",
21
+ "enum": [
22
+ "incident.detail",
23
+ "incident.stack",
24
+ "file",
25
+ "diff",
26
+ "log.window",
27
+ "log.groups",
28
+ "chat.session",
29
+ "wiki.page",
30
+ "job.stream",
31
+ "job.timeline",
32
+ "approval.detail",
33
+ "report"
34
+ ]
35
+ },
36
+ "ref": {
37
+ "type": "string",
38
+ "minLength": 1,
39
+ "maxLength": 512,
40
+ "pattern": "^[^\\u0000-\\u001f]{1,512}$"
41
+ },
42
+ "range": {
43
+ "type": "object",
44
+ "additionalProperties": false,
45
+ "properties": {
46
+ "offset": {
47
+ "type": "integer",
48
+ "minimum": 0,
49
+ "maximum": 2097152
50
+ },
51
+ "length": {
52
+ "type": "integer",
53
+ "minimum": 1,
54
+ "maximum": 2097152
55
+ }
56
+ },
57
+ "required": [
58
+ "offset",
59
+ "length"
60
+ ]
61
+ },
62
+ "limit": {
63
+ "type": "integer",
64
+ "minimum": 1,
65
+ "maximum": 1000
66
+ },
67
+ "actor": {
68
+ "type": "object",
69
+ "additionalProperties": false,
70
+ "properties": {
71
+ "userId": {
72
+ "$ref": "defs.schema.json#/$defs/shortId"
73
+ },
74
+ "role": {
75
+ "type": "string",
76
+ "enum": [
77
+ "viewer",
78
+ "member",
79
+ "admin",
80
+ "root"
81
+ ]
82
+ }
83
+ },
84
+ "required": [
85
+ "userId",
86
+ "role"
87
+ ]
88
+ }
89
+ },
90
+ "required": [
91
+ "kind",
92
+ "ref",
93
+ "actor"
94
+ ]
95
+ },
96
+ "seq": {
97
+ "type": "integer",
98
+ "minimum": 1,
99
+ "maximum": 9007199254740991
100
+ },
101
+ "chunk": false,
102
+ "sig": true,
103
+ "paramsRaw": true
104
+ },
105
+ "required": [
106
+ "payload",
107
+ "sig",
108
+ "paramsRaw"
109
+ ]
110
+ }
@@ -0,0 +1,90 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.visionhammer.io/la-protocol-v2/content.response.schema.json",
4
+ "title": "LA protocol v2: content.response (la->cp)",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "envelope.schema.json"
9
+ }
10
+ ],
11
+ "properties": {
12
+ "type": {
13
+ "const": "content.response"
14
+ },
15
+ "payload": {
16
+ "type": "object",
17
+ "additionalProperties": false,
18
+ "properties": {
19
+ "status": {
20
+ "type": "string",
21
+ "enum": [
22
+ "ok",
23
+ "error",
24
+ "not_found",
25
+ "forbidden"
26
+ ]
27
+ },
28
+ "errorCode": {
29
+ "$ref": "defs.schema.json#/$defs/errorCode"
30
+ },
31
+ "contentType": {
32
+ "type": "string",
33
+ "enum": [
34
+ "text/plain",
35
+ "text/markdown",
36
+ "text/x-diff",
37
+ "application/json",
38
+ "application/zip",
39
+ "application/octet-stream"
40
+ ]
41
+ },
42
+ "encoding": {
43
+ "const": "base64"
44
+ },
45
+ "data": {
46
+ "type": "string",
47
+ "minLength": 0,
48
+ "maxLength": 43692,
49
+ "pattern": "^[A-Za-z0-9+/]*={0,2}$",
50
+ "x-content-class": "relay"
51
+ },
52
+ "byteLength": {
53
+ "type": "integer",
54
+ "minimum": 0,
55
+ "maximum": 32768
56
+ },
57
+ "totalBytes": {
58
+ "type": "integer",
59
+ "minimum": 0,
60
+ "maximum": 2097152
61
+ },
62
+ "sha256": {
63
+ "$ref": "defs.schema.json#/$defs/sha256"
64
+ }
65
+ },
66
+ "required": [
67
+ "status",
68
+ "encoding",
69
+ "data",
70
+ "byteLength"
71
+ ]
72
+ },
73
+ "seq": {
74
+ "type": "integer",
75
+ "minimum": 1,
76
+ "maximum": 9007199254740991
77
+ },
78
+ "sig": false,
79
+ "paramsRaw": false,
80
+ "chunk": true,
81
+ "requestId": true,
82
+ "agentId": true
83
+ },
84
+ "required": [
85
+ "payload",
86
+ "chunk",
87
+ "requestId",
88
+ "agentId"
89
+ ]
90
+ }