deepdebug-local-agent 1.3.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 (108) hide show
  1. package/.github/workflows/deploy-gcp.yml +58 -26
  2. package/CHANGELOG.md +6 -0
  3. package/docs/la-protocol-v2.md +68 -0
  4. package/package.json +2 -1
  5. package/scripts/sync-la-protocol-v2-contract.mjs +58 -0
  6. package/src/la-protocol-v2/chunks.js +45 -0
  7. package/src/la-protocol-v2/config.js +27 -0
  8. package/src/la-protocol-v2/content.js +57 -0
  9. package/src/la-protocol-v2/contract/CONTRACT_SOURCE.json +81 -0
  10. package/src/la-protocol-v2/contract/README.md +103 -0
  11. package/src/la-protocol-v2/contract/ack.schema.json +51 -0
  12. package/src/la-protocol-v2/contract/alert.schema.json +62 -0
  13. package/src/la-protocol-v2/contract/approval.decision.schema.json +57 -0
  14. package/src/la-protocol-v2/contract/audit.event.schema.json +86 -0
  15. package/src/la-protocol-v2/contract/config.update.schema.json +73 -0
  16. package/src/la-protocol-v2/contract/content.request.schema.json +110 -0
  17. package/src/la-protocol-v2/contract/content.response.schema.json +90 -0
  18. package/src/la-protocol-v2/contract/defs.schema.json +191 -0
  19. package/src/la-protocol-v2/contract/envelope.schema.json +89 -0
  20. package/src/la-protocol-v2/contract/error.schema.json +59 -0
  21. package/src/la-protocol-v2/contract/heartbeat.schema.json +100 -0
  22. package/src/la-protocol-v2/contract/hello.schema.json +111 -0
  23. package/src/la-protocol-v2/contract/incident.candidate.schema.json +102 -0
  24. package/src/la-protocol-v2/contract/index.json +166 -0
  25. package/src/la-protocol-v2/contract/job.assign.schema.json +212 -0
  26. package/src/la-protocol-v2/contract/job.cancel.schema.json +52 -0
  27. package/src/la-protocol-v2/contract/job.event.schema.json +115 -0
  28. package/src/la-protocol-v2/contract/job.result.schema.json +100 -0
  29. package/src/la-protocol-v2/contract/log.stats.schema.json +79 -0
  30. package/src/la-protocol-v2/contract/ready.schema.json +106 -0
  31. package/src/la-protocol-v2/contract/register.schema.json +92 -0
  32. package/src/la-protocol-v2/contract/scan.upload.schema.json +59 -0
  33. package/src/la-protocol-v2/contract/scan.uploaded.schema.json +51 -0
  34. package/src/la-protocol-v2/contract/webhook.forward.schema.json +69 -0
  35. package/src/la-protocol-v2/contract.js +90 -0
  36. package/src/la-protocol-v2/errors.js +34 -0
  37. package/src/la-protocol-v2/index.js +8 -0
  38. package/src/la-protocol-v2/link.js +93 -0
  39. package/src/la-protocol-v2/runtime.js +72 -0
  40. package/src/la-protocol-v2/session.js +650 -0
  41. package/src/la-protocol-v2/strict-json.js +47 -0
  42. package/src/server.js +22 -4
  43. package/test/contract/la-protocol-v2/vectors/ack.vectors.json +149 -0
  44. package/test/contract/la-protocol-v2/vectors/alert.vectors.json +101 -0
  45. package/test/contract/la-protocol-v2/vectors/approval.decision.vectors.json +165 -0
  46. package/test/contract/la-protocol-v2/vectors/audit.event.vectors.json +156 -0
  47. package/test/contract/la-protocol-v2/vectors/config.update.vectors.json +189 -0
  48. package/test/contract/la-protocol-v2/vectors/content.request.vectors.json +325 -0
  49. package/test/contract/la-protocol-v2/vectors/content.response.vectors.json +413 -0
  50. package/test/contract/la-protocol-v2/vectors/cross-type.vectors.json +260 -0
  51. package/test/contract/la-protocol-v2/vectors/error.vectors.json +179 -0
  52. package/test/contract/la-protocol-v2/vectors/heartbeat.vectors.json +109 -0
  53. package/test/contract/la-protocol-v2/vectors/hello.vectors.json +224 -0
  54. package/test/contract/la-protocol-v2/vectors/incident.candidate.vectors.json +186 -0
  55. package/test/contract/la-protocol-v2/vectors/job.assign.vectors.json +631 -0
  56. package/test/contract/la-protocol-v2/vectors/job.cancel.vectors.json +133 -0
  57. package/test/contract/la-protocol-v2/vectors/job.event.vectors.json +233 -0
  58. package/test/contract/la-protocol-v2/vectors/job.result.vectors.json +137 -0
  59. package/test/contract/la-protocol-v2/vectors/log.stats.vectors.json +137 -0
  60. package/test/contract/la-protocol-v2/vectors/ready.vectors.json +177 -0
  61. package/test/contract/la-protocol-v2/vectors/register.vectors.json +399 -0
  62. package/test/contract/la-protocol-v2/vectors/scan.upload.vectors.json +137 -0
  63. package/test/contract/la-protocol-v2/vectors/scan.uploaded.vectors.json +101 -0
  64. package/test/contract/la-protocol-v2/vectors/traces/invalid-agent-mismatch.json +140 -0
  65. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-after-last.json +200 -0
  66. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-byte-length-mismatch.json +174 -0
  67. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-last-flag.json +200 -0
  68. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-out-of-order.json +200 -0
  69. package/test/contract/la-protocol-v2/vectors/traces/invalid-chunk-total-changes.json +200 -0
  70. package/test/contract/la-protocol-v2/vectors/traces/invalid-clock-skew.json +46 -0
  71. package/test/contract/la-protocol-v2/vectors/traces/invalid-event-before-ready.json +72 -0
  72. package/test/contract/la-protocol-v2/vectors/traces/invalid-first-frame-not-register.json +48 -0
  73. package/test/contract/la-protocol-v2/vectors/traces/invalid-frame-over-48kib.json +141 -0
  74. package/test/contract/la-protocol-v2/vectors/traces/invalid-la-sends-job-assign.json +173 -0
  75. package/test/contract/la-protocol-v2/vectors/traces/invalid-params-raw-differs-from-payload.json +172 -0
  76. package/test/contract/la-protocol-v2/vectors/traces/invalid-payload-above-limit.json +174 -0
  77. package/test/contract/la-protocol-v2/vectors/traces/invalid-resume-restarts-seq.json +144 -0
  78. package/test/contract/la-protocol-v2/vectors/traces/invalid-seq-gap.json +166 -0
  79. package/test/contract/la-protocol-v2/vectors/traces/invalid-seq-repeated.json +166 -0
  80. package/test/contract/la-protocol-v2/vectors/traces/invalid-sig-tenant-mismatch.json +172 -0
  81. package/test/contract/la-protocol-v2/vectors/traces/invalid-signature-warn-with-enforce-required.json +77 -0
  82. package/test/contract/la-protocol-v2/vectors/traces/invalid-tenant-mismatch.json +140 -0
  83. package/test/contract/la-protocol-v2/vectors/traces/invalid-type-outside-allowlist.json +140 -0
  84. package/test/contract/la-protocol-v2/vectors/traces/valid-content-chunks-in-order.json +224 -0
  85. package/test/contract/la-protocol-v2/vectors/traces/valid-handshake-and-job.json +266 -0
  86. package/test/contract/la-protocol-v2/vectors/traces/valid-resume-continues-seq.json +168 -0
  87. package/test/contract/la-protocol-v2/vectors/traces/valid-retransmit-is-idempotent.json +193 -0
  88. package/test/contract/la-protocol-v2/vectors/webhook.forward.vectors.json +170 -0
  89. package/test/la-protocol-v2/contract.test.js +131 -0
  90. package/test/la-protocol-v2/helpers/la-rig.js +83 -0
  91. package/test/la-protocol-v2/helpers/reference-cp.js +349 -0
  92. package/test/la-protocol-v2/helpers/spawn-agent.js +35 -0
  93. package/test/la-protocol-v2/link.test.js +141 -0
  94. package/test/la-protocol-v2/session-inbound.test.js +279 -0
  95. package/test/la-protocol-v2/session-outbound.test.js +382 -0
  96. package/test/la-protocol-v2/traces.test.js +270 -0
  97. package/test/la-protocol-v2/tunnel-e2e.test.js +124 -0
  98. package/tools/graphify-validation/extras/README.md +19 -0
  99. package/tools/graphify-validation/extras/bymethod.py +35 -0
  100. package/tools/graphify-validation/extras/docker/Dockerfile +16 -0
  101. package/tools/graphify-validation/extras/docker/inner.sh +7 -0
  102. package/tools/graphify-validation/extras/g10.py +59 -0
  103. package/tools/graphify-validation/extras/g3aug.py +49 -0
  104. package/tools/graphify-validation/extras/hybrid.py +34 -0
  105. package/tools/graphify-validation/extras/truth2.py +44 -0
  106. package/tools/interop/LaV2NodeInteropTest.java +266 -0
  107. package/tools/interop/README.md +21 -0
  108. package/tools/interop/la-interop-client.mjs +97 -0
@@ -0,0 +1,177 @@
1
+ {
2
+ "type": "ready",
3
+ "schema": "ready.schema.json",
4
+ "vectors": [
5
+ {
6
+ "name": "minimal-valid",
7
+ "expect": {
8
+ "valid": true
9
+ },
10
+ "message": {
11
+ "schemaVersion": 2,
12
+ "type": "ready",
13
+ "msgId": "00000000-0000-4000-8000-000000000001",
14
+ "seq": 0,
15
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
16
+ "workspaceId": "ws-1",
17
+ "ts": "2026-10-29T10:00:00Z",
18
+ "paramsRaw": "{\"protocol\":2,\"sessionId\":\"e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091\",\"resumed\":false,\"peerLastSeq\":0,\"limits\":{\"maxFrameBytes\":49152,\"chunkRawBytes\":32768,\"maxChunks\":64,\"ackTimeoutMs\":5000,\"maxRetries\":3,\"heartbeatSeconds\":30,\"contentFirstByteMs\":10000,\"contentTotalMs\":30000}}",
19
+ "sig": {
20
+ "keyId": "vh-cp-2026-10",
21
+ "timestamp": "1793268000",
22
+ "nonce": "Zm9vYmFyYmF6cXV4MTIzNDU2",
23
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
24
+ "workspaceId": "ws-1",
25
+ "signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
26
+ },
27
+ "payload": {
28
+ "protocol": 2,
29
+ "sessionId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
30
+ "resumed": false,
31
+ "peerLastSeq": 0,
32
+ "limits": {
33
+ "maxFrameBytes": 49152,
34
+ "chunkRawBytes": 32768,
35
+ "maxChunks": 64,
36
+ "ackTimeoutMs": 5000,
37
+ "maxRetries": 3,
38
+ "heartbeatSeconds": 30,
39
+ "contentFirstByteMs": 10000,
40
+ "contentTotalMs": 30000
41
+ }
42
+ }
43
+ }
44
+ },
45
+ {
46
+ "name": "extra-top-level-field",
47
+ "why": "envelope is closed (additionalProperties:false)",
48
+ "expect": {
49
+ "valid": false,
50
+ "code": "schema_violation",
51
+ "keyword": "additionalProperties"
52
+ },
53
+ "message": {
54
+ "schemaVersion": 2,
55
+ "type": "ready",
56
+ "msgId": "00000000-0000-4000-8000-000000000001",
57
+ "seq": 0,
58
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
59
+ "workspaceId": "ws-1",
60
+ "ts": "2026-10-29T10:00:00Z",
61
+ "paramsRaw": "{\"protocol\":2,\"sessionId\":\"e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091\",\"resumed\":false,\"peerLastSeq\":0,\"limits\":{\"maxFrameBytes\":49152,\"chunkRawBytes\":32768,\"maxChunks\":64,\"ackTimeoutMs\":5000,\"maxRetries\":3,\"heartbeatSeconds\":30,\"contentFirstByteMs\":10000,\"contentTotalMs\":30000}}",
62
+ "sig": {
63
+ "keyId": "vh-cp-2026-10",
64
+ "timestamp": "1793268000",
65
+ "nonce": "Zm9vYmFyYmF6cXV4MTIzNDU2",
66
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
67
+ "workspaceId": "ws-1",
68
+ "signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
69
+ },
70
+ "payload": {
71
+ "protocol": 2,
72
+ "sessionId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
73
+ "resumed": false,
74
+ "peerLastSeq": 0,
75
+ "limits": {
76
+ "maxFrameBytes": 49152,
77
+ "chunkRawBytes": 32768,
78
+ "maxChunks": 64,
79
+ "ackTimeoutMs": 5000,
80
+ "maxRetries": 3,
81
+ "heartbeatSeconds": 30,
82
+ "contentFirstByteMs": 10000,
83
+ "contentTotalMs": 30000
84
+ }
85
+ },
86
+ "extra": "x"
87
+ }
88
+ },
89
+ {
90
+ "name": "extra-payload-field",
91
+ "why": "payload is closed: no free-form fields",
92
+ "expect": {
93
+ "valid": false,
94
+ "code": "schema_violation",
95
+ "keyword": "additionalProperties"
96
+ },
97
+ "message": {
98
+ "schemaVersion": 2,
99
+ "type": "ready",
100
+ "msgId": "00000000-0000-4000-8000-000000000001",
101
+ "seq": 0,
102
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
103
+ "workspaceId": "ws-1",
104
+ "ts": "2026-10-29T10:00:00Z",
105
+ "paramsRaw": "{\"protocol\":2,\"sessionId\":\"e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091\",\"resumed\":false,\"peerLastSeq\":0,\"limits\":{\"maxFrameBytes\":49152,\"chunkRawBytes\":32768,\"maxChunks\":64,\"ackTimeoutMs\":5000,\"maxRetries\":3,\"heartbeatSeconds\":30,\"contentFirstByteMs\":10000,\"contentTotalMs\":30000}}",
106
+ "sig": {
107
+ "keyId": "vh-cp-2026-10",
108
+ "timestamp": "1793268000",
109
+ "nonce": "Zm9vYmFyYmF6cXV4MTIzNDU2",
110
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
111
+ "workspaceId": "ws-1",
112
+ "signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
113
+ },
114
+ "payload": {
115
+ "protocol": 2,
116
+ "sessionId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
117
+ "resumed": false,
118
+ "peerLastSeq": 0,
119
+ "limits": {
120
+ "maxFrameBytes": 49152,
121
+ "chunkRawBytes": 32768,
122
+ "maxChunks": 64,
123
+ "ackTimeoutMs": 5000,
124
+ "maxRetries": 3,
125
+ "heartbeatSeconds": 30,
126
+ "contentFirstByteMs": 10000,
127
+ "contentTotalMs": 30000
128
+ },
129
+ "freeText": "client text"
130
+ }
131
+ }
132
+ },
133
+ {
134
+ "name": "tenant-id-not-uuid",
135
+ "why": "tenantId must be a UUID",
136
+ "expect": {
137
+ "valid": false,
138
+ "code": "schema_violation",
139
+ "keyword": "pattern"
140
+ },
141
+ "message": {
142
+ "schemaVersion": 2,
143
+ "type": "ready",
144
+ "msgId": "00000000-0000-4000-8000-000000000001",
145
+ "seq": 0,
146
+ "tenantId": "tenant-1",
147
+ "workspaceId": "ws-1",
148
+ "ts": "2026-10-29T10:00:00Z",
149
+ "paramsRaw": "{\"protocol\":2,\"sessionId\":\"e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091\",\"resumed\":false,\"peerLastSeq\":0,\"limits\":{\"maxFrameBytes\":49152,\"chunkRawBytes\":32768,\"maxChunks\":64,\"ackTimeoutMs\":5000,\"maxRetries\":3,\"heartbeatSeconds\":30,\"contentFirstByteMs\":10000,\"contentTotalMs\":30000}}",
150
+ "sig": {
151
+ "keyId": "vh-cp-2026-10",
152
+ "timestamp": "1793268000",
153
+ "nonce": "Zm9vYmFyYmF6cXV4MTIzNDU2",
154
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
155
+ "workspaceId": "ws-1",
156
+ "signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
157
+ },
158
+ "payload": {
159
+ "protocol": 2,
160
+ "sessionId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
161
+ "resumed": false,
162
+ "peerLastSeq": 0,
163
+ "limits": {
164
+ "maxFrameBytes": 49152,
165
+ "chunkRawBytes": 32768,
166
+ "maxChunks": 64,
167
+ "ackTimeoutMs": 5000,
168
+ "maxRetries": 3,
169
+ "heartbeatSeconds": 30,
170
+ "contentFirstByteMs": 10000,
171
+ "contentTotalMs": 30000
172
+ }
173
+ }
174
+ }
175
+ }
176
+ ]
177
+ }
@@ -0,0 +1,399 @@
1
+ {
2
+ "type": "register",
3
+ "schema": "register.schema.json",
4
+ "vectors": [
5
+ {
6
+ "name": "minimal-valid",
7
+ "expect": {
8
+ "valid": true
9
+ },
10
+ "message": {
11
+ "schemaVersion": 2,
12
+ "type": "register",
13
+ "msgId": "00000000-0000-4000-8000-000000000001",
14
+ "seq": 0,
15
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
16
+ "workspaceId": "ws-1",
17
+ "ts": "2026-10-29T10:00:00Z",
18
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
19
+ "payload": {
20
+ "protocol": 2,
21
+ "laVersion": "2.4.0",
22
+ "capabilities": [
23
+ "content.request",
24
+ "job.assign",
25
+ "incident.detect"
26
+ ],
27
+ "signatureMode": "enforce",
28
+ "workspaces": [
29
+ {
30
+ "workspaceId": "ws-1",
31
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
32
+ }
33
+ ]
34
+ }
35
+ }
36
+ },
37
+ {
38
+ "name": "extra-top-level-field",
39
+ "why": "envelope is closed (additionalProperties:false)",
40
+ "expect": {
41
+ "valid": false,
42
+ "code": "schema_violation",
43
+ "keyword": "additionalProperties"
44
+ },
45
+ "message": {
46
+ "schemaVersion": 2,
47
+ "type": "register",
48
+ "msgId": "00000000-0000-4000-8000-000000000001",
49
+ "seq": 0,
50
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
51
+ "workspaceId": "ws-1",
52
+ "ts": "2026-10-29T10:00:00Z",
53
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
54
+ "payload": {
55
+ "protocol": 2,
56
+ "laVersion": "2.4.0",
57
+ "capabilities": [
58
+ "content.request",
59
+ "job.assign",
60
+ "incident.detect"
61
+ ],
62
+ "signatureMode": "enforce",
63
+ "workspaces": [
64
+ {
65
+ "workspaceId": "ws-1",
66
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
67
+ }
68
+ ]
69
+ },
70
+ "extra": "x"
71
+ }
72
+ },
73
+ {
74
+ "name": "extra-payload-field",
75
+ "why": "payload is closed: no free-form fields",
76
+ "expect": {
77
+ "valid": false,
78
+ "code": "schema_violation",
79
+ "keyword": "additionalProperties"
80
+ },
81
+ "message": {
82
+ "schemaVersion": 2,
83
+ "type": "register",
84
+ "msgId": "00000000-0000-4000-8000-000000000001",
85
+ "seq": 0,
86
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
87
+ "workspaceId": "ws-1",
88
+ "ts": "2026-10-29T10:00:00Z",
89
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
90
+ "payload": {
91
+ "protocol": 2,
92
+ "laVersion": "2.4.0",
93
+ "capabilities": [
94
+ "content.request",
95
+ "job.assign",
96
+ "incident.detect"
97
+ ],
98
+ "signatureMode": "enforce",
99
+ "workspaces": [
100
+ {
101
+ "workspaceId": "ws-1",
102
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
103
+ }
104
+ ],
105
+ "freeText": "client text"
106
+ }
107
+ }
108
+ },
109
+ {
110
+ "name": "tenant-id-not-uuid",
111
+ "why": "tenantId must be a UUID",
112
+ "expect": {
113
+ "valid": false,
114
+ "code": "schema_violation",
115
+ "keyword": "pattern"
116
+ },
117
+ "message": {
118
+ "schemaVersion": 2,
119
+ "type": "register",
120
+ "msgId": "00000000-0000-4000-8000-000000000001",
121
+ "seq": 0,
122
+ "tenantId": "tenant-1",
123
+ "workspaceId": "ws-1",
124
+ "ts": "2026-10-29T10:00:00Z",
125
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
126
+ "payload": {
127
+ "protocol": 2,
128
+ "laVersion": "2.4.0",
129
+ "capabilities": [
130
+ "content.request",
131
+ "job.assign",
132
+ "incident.detect"
133
+ ],
134
+ "signatureMode": "enforce",
135
+ "workspaces": [
136
+ {
137
+ "workspaceId": "ws-1",
138
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
139
+ }
140
+ ]
141
+ }
142
+ }
143
+ },
144
+ {
145
+ "name": "protocol-1",
146
+ "why": "register v2 must declare protocol 2 (v1 agents send the legacy frame)",
147
+ "expect": {
148
+ "valid": false,
149
+ "code": "schema_violation",
150
+ "keyword": "const"
151
+ },
152
+ "message": {
153
+ "schemaVersion": 2,
154
+ "type": "register",
155
+ "msgId": "00000000-0000-4000-8000-000000000001",
156
+ "seq": 0,
157
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
158
+ "workspaceId": "ws-1",
159
+ "ts": "2026-10-29T10:00:00Z",
160
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
161
+ "payload": {
162
+ "protocol": 1,
163
+ "laVersion": "2.4.0",
164
+ "capabilities": [
165
+ "content.request",
166
+ "job.assign",
167
+ "incident.detect"
168
+ ],
169
+ "signatureMode": "enforce",
170
+ "workspaces": [
171
+ {
172
+ "workspaceId": "ws-1",
173
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
174
+ }
175
+ ]
176
+ }
177
+ }
178
+ },
179
+ {
180
+ "name": "raw-workspace-path",
181
+ "why": "disk paths do not travel in v2 (only pathSha256)",
182
+ "expect": {
183
+ "valid": false,
184
+ "code": "schema_violation",
185
+ "keyword": "additionalProperties"
186
+ },
187
+ "message": {
188
+ "schemaVersion": 2,
189
+ "type": "register",
190
+ "msgId": "00000000-0000-4000-8000-000000000001",
191
+ "seq": 0,
192
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
193
+ "workspaceId": "ws-1",
194
+ "ts": "2026-10-29T10:00:00Z",
195
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
196
+ "payload": {
197
+ "protocol": 2,
198
+ "laVersion": "2.4.0",
199
+ "capabilities": [
200
+ "content.request",
201
+ "job.assign",
202
+ "incident.detect"
203
+ ],
204
+ "signatureMode": "enforce",
205
+ "workspaces": [
206
+ {
207
+ "workspaceId": "ws-1",
208
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
209
+ }
210
+ ],
211
+ "workspacePath": "/home/user/code"
212
+ }
213
+ }
214
+ },
215
+ {
216
+ "name": "bad-signature-mode",
217
+ "why": "signatureMode in off|warn|enforce",
218
+ "expect": {
219
+ "valid": false,
220
+ "code": "schema_violation",
221
+ "keyword": "enum"
222
+ },
223
+ "message": {
224
+ "schemaVersion": 2,
225
+ "type": "register",
226
+ "msgId": "00000000-0000-4000-8000-000000000001",
227
+ "seq": 0,
228
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
229
+ "workspaceId": "ws-1",
230
+ "ts": "2026-10-29T10:00:00Z",
231
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
232
+ "payload": {
233
+ "protocol": 2,
234
+ "laVersion": "2.4.0",
235
+ "capabilities": [
236
+ "content.request",
237
+ "job.assign",
238
+ "incident.detect"
239
+ ],
240
+ "signatureMode": "disabled",
241
+ "workspaces": [
242
+ {
243
+ "workspaceId": "ws-1",
244
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
245
+ }
246
+ ]
247
+ }
248
+ }
249
+ },
250
+ {
251
+ "name": "handshake-seq-not-zero",
252
+ "why": "handshake frames use seq 0",
253
+ "expect": {
254
+ "valid": false,
255
+ "code": "schema_violation",
256
+ "keyword": "const"
257
+ },
258
+ "message": {
259
+ "schemaVersion": 2,
260
+ "type": "register",
261
+ "msgId": "00000000-0000-4000-8000-000000000001",
262
+ "seq": 5,
263
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
264
+ "workspaceId": "ws-1",
265
+ "ts": "2026-10-29T10:00:00Z",
266
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
267
+ "payload": {
268
+ "protocol": 2,
269
+ "laVersion": "2.4.0",
270
+ "capabilities": [
271
+ "content.request",
272
+ "job.assign",
273
+ "incident.detect"
274
+ ],
275
+ "signatureMode": "enforce",
276
+ "workspaces": [
277
+ {
278
+ "workspaceId": "ws-1",
279
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
280
+ }
281
+ ]
282
+ }
283
+ }
284
+ },
285
+ {
286
+ "name": "with-resume",
287
+ "expect": {
288
+ "valid": true
289
+ },
290
+ "message": {
291
+ "schemaVersion": 2,
292
+ "type": "register",
293
+ "msgId": "00000000-0000-4000-8000-000000000001",
294
+ "seq": 0,
295
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
296
+ "workspaceId": "ws-1",
297
+ "ts": "2026-10-29T10:00:00Z",
298
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
299
+ "payload": {
300
+ "protocol": 2,
301
+ "laVersion": "2.4.0",
302
+ "capabilities": [
303
+ "content.request",
304
+ "job.assign",
305
+ "incident.detect"
306
+ ],
307
+ "signatureMode": "enforce",
308
+ "workspaces": [
309
+ {
310
+ "workspaceId": "ws-1",
311
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
312
+ }
313
+ ],
314
+ "resume": {
315
+ "sessionId": "e5f6a7b8-c9d0-4e1f-8a2b-4c5d6e7f8091",
316
+ "lastRecvSeq": 5
317
+ }
318
+ }
319
+ },
320
+ "why": "reconnect: resume the previous session from the last received seq"
321
+ },
322
+ {
323
+ "name": "missing-agent-id",
324
+ "why": "LA->CP frames carry agentId",
325
+ "expect": {
326
+ "valid": false,
327
+ "code": "schema_violation",
328
+ "keyword": "required"
329
+ },
330
+ "message": {
331
+ "schemaVersion": 2,
332
+ "type": "register",
333
+ "msgId": "00000000-0000-4000-8000-000000000001",
334
+ "seq": 0,
335
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
336
+ "workspaceId": "ws-1",
337
+ "ts": "2026-10-29T10:00:00Z",
338
+ "payload": {
339
+ "protocol": 2,
340
+ "laVersion": "2.4.0",
341
+ "capabilities": [
342
+ "content.request",
343
+ "job.assign",
344
+ "incident.detect"
345
+ ],
346
+ "signatureMode": "enforce",
347
+ "workspaces": [
348
+ {
349
+ "workspaceId": "ws-1",
350
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
351
+ }
352
+ ]
353
+ }
354
+ }
355
+ },
356
+ {
357
+ "name": "la-frame-with-sig",
358
+ "why": "LA->CP frames are not signed in v2.0 (F3-X3 reserves it)",
359
+ "expect": {
360
+ "valid": false,
361
+ "code": "schema_violation"
362
+ },
363
+ "message": {
364
+ "schemaVersion": 2,
365
+ "type": "register",
366
+ "msgId": "00000000-0000-4000-8000-000000000001",
367
+ "seq": 0,
368
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
369
+ "workspaceId": "ws-1",
370
+ "ts": "2026-10-29T10:00:00Z",
371
+ "agentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
372
+ "payload": {
373
+ "protocol": 2,
374
+ "laVersion": "2.4.0",
375
+ "capabilities": [
376
+ "content.request",
377
+ "job.assign",
378
+ "incident.detect"
379
+ ],
380
+ "signatureMode": "enforce",
381
+ "workspaces": [
382
+ {
383
+ "workspaceId": "ws-1",
384
+ "pathSha256": "abababababababababababababababababababababababababababababababab"
385
+ }
386
+ ]
387
+ },
388
+ "sig": {
389
+ "keyId": "vh-cp-2026-10",
390
+ "timestamp": "1793268000",
391
+ "nonce": "Zm9vYmFyYmF6cXV4MTIzNDU2",
392
+ "tenantId": "3f2b8c1e-5a4d-4e7b-9c21-0a1b2c3d4e5f",
393
+ "workspaceId": "ws-1",
394
+ "signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
395
+ }
396
+ }
397
+ }
398
+ ]
399
+ }