sernixa-agent 1.5.0__tar.gz
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.
- sernixa_agent-1.5.0/PKG-INFO +391 -0
- sernixa_agent-1.5.0/README.md +371 -0
- sernixa_agent-1.5.0/pyproject.toml +42 -0
- sernixa_agent-1.5.0/sernixa_agent/__init__.py +3 -0
- sernixa_agent-1.5.0/sernixa_agent/cli.py +4165 -0
- sernixa_agent-1.5.0/sernixa_agent/py.typed +1 -0
- sernixa_agent-1.5.0/sernixa_agent.egg-info/PKG-INFO +391 -0
- sernixa_agent-1.5.0/sernixa_agent.egg-info/SOURCES.txt +11 -0
- sernixa_agent-1.5.0/sernixa_agent.egg-info/dependency_links.txt +1 -0
- sernixa_agent-1.5.0/sernixa_agent.egg-info/entry_points.txt +2 -0
- sernixa_agent-1.5.0/sernixa_agent.egg-info/top_level.txt +1 -0
- sernixa_agent-1.5.0/setup.cfg +4 -0
- sernixa_agent-1.5.0/tests/test_cli.py +2126 -0
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sernixa-agent
|
|
3
|
+
Version: 1.5.0
|
|
4
|
+
Summary: Sernixa local MCP discovery agent
|
|
5
|
+
Author: Sernixa Team
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Changelog, https://github.com/abhishekdhull63/Sernixa.ai-Web/tree/main/packages/sernixa-agent/CHANGELOG.md
|
|
8
|
+
Project-URL: Documentation, https://github.com/abhishekdhull63/Sernixa.ai-Web/tree/main/packages/sernixa-agent/README.md
|
|
9
|
+
Keywords: sernixa,mcp,discovery,local-agent
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Sernixa Local Agent
|
|
22
|
+
|
|
23
|
+
Local MCP discovery agent for Sernixa. It scans only configured hosts, ports,
|
|
24
|
+
and paths from the machine where it runs, then optionally syncs evidence-backed
|
|
25
|
+
candidates to Sernixa.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
python -m pip install -e packages/sernixa-agent
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
From a repo checkout, prefer the shared target because it clears stale editable
|
|
34
|
+
metadata, reinstalls the package, and prints the loaded `cli.py` path:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
make agent-install-local
|
|
38
|
+
make agent-which
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For internal rollout from a built wheel:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python -m pip install --upgrade dist/sernixa_agent-1.5.0-py3-none-any.whl
|
|
45
|
+
pipx install --force dist/sernixa_agent-1.5.0-py3-none-any.whl
|
|
46
|
+
uv tool install --force dist/sernixa_agent-1.5.0-py3-none-any.whl
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Build and verify release artifacts:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python packages/sernixa-agent/scripts/release.py --check
|
|
53
|
+
cd packages/sernixa-agent
|
|
54
|
+
python -m pip install build
|
|
55
|
+
python -m build
|
|
56
|
+
python scripts/release.py --build
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`pipx` and `uv tool` are the preferred paths for operators who should not manage
|
|
60
|
+
a Python virtual environment directly. Native single-file binaries are not
|
|
61
|
+
published yet; use wheel-based distribution for v1.5.
|
|
62
|
+
|
|
63
|
+
## Initialize
|
|
64
|
+
|
|
65
|
+
Fast path for one machine:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
curl -fsSL https://raw.githubusercontent.com/abhishekdhull63/Sernixa.ai-Web/main/packages/sernixa-agent/install.sh | sh -s -- --machine-label "Security laptop"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The installer prompts for an org-scoped key when one is not already available
|
|
72
|
+
through `SERNIXA_AGENT_TOKEN`, `SERNIXA_API_KEY`, or an existing token file. It
|
|
73
|
+
installs the requested agent version, writes `~/.sernixa/agent.token` with
|
|
74
|
+
`0600` permissions, runs `init`, `diagnose --check-backend`, `enroll`, one
|
|
75
|
+
`sync`, and installs a user-level daemon service where supported. The token is
|
|
76
|
+
never printed. Install is not verification; the first accepted sync is the
|
|
77
|
+
evidence Sernixa can show.
|
|
78
|
+
|
|
79
|
+
When device-code enrollment is enabled on the API, a first-time operator can
|
|
80
|
+
avoid pasting a raw API key for inventory enrollment:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
curl -fsSL https://raw.githubusercontent.com/abhishekdhull63/Sernixa.ai-Web/main/packages/sernixa-agent/install.sh | sh -s -- --device-enroll --machine-label "Security laptop"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Device-code enrollment creates the enrollment inventory record after an
|
|
87
|
+
authenticated admin approves the displayed code. It does not yet mint a
|
|
88
|
+
long-lived daemon sync token, so the first accepted sync and auto-syncing state
|
|
89
|
+
still require a configured sync token until sync-token minting ships. Backend
|
|
90
|
+
completion returns `next_step_token_status=requires_manual_sync_token` to make
|
|
91
|
+
that second step explicit. Treat the current pilot path as four steps:
|
|
92
|
+
enroll inventory, configure the sync token through the tenant secret channel,
|
|
93
|
+
install it with `sernixa-agent rotate-token --new-token-stdin`, run
|
|
94
|
+
`sernixa-agent sync`, then start daemon mode after accepted sync. See
|
|
95
|
+
`docs/mcp-local-agent-pilot-rollout.md` before enabling a tenant pilot.
|
|
96
|
+
|
|
97
|
+
Create a non-secret config and private token file:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
sernixa-agent init --machine-label "Security laptop"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Install an org-scoped Sernixa sync token through stdin:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
printf '%s\n' "$APPROVED_SYNC_TOKEN" | sernixa-agent rotate-token --new-token-stdin --token-file ~/.sernixa/agent.token --check-backend
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The token needs access to MCP registry read/discovery ingestion for the target
|
|
110
|
+
organization. The agent sends it only as an HTTP bearer token and never includes
|
|
111
|
+
it in scan JSON, logs, or evidence.
|
|
112
|
+
|
|
113
|
+
Check local readiness without scanning endpoints:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
sernixa-agent status
|
|
117
|
+
sernixa-agent status --json
|
|
118
|
+
sernixa-agent diagnose --check-backend
|
|
119
|
+
sernixa-agent enroll
|
|
120
|
+
sernixa-agent enroll-device --open-browser
|
|
121
|
+
sernixa-agent sync
|
|
122
|
+
sernixa-agent daemon
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`enroll` registers stable machine identity, non-secret label, and current agent
|
|
126
|
+
version in Sernixa inventory. It does not scan endpoints or claim the machine is
|
|
127
|
+
continuously online.
|
|
128
|
+
|
|
129
|
+
## Auto-Discovery
|
|
130
|
+
|
|
131
|
+
Auto-discovery v2 means the helper is installed and enrolled once, usually by
|
|
132
|
+
the standard installer or fleet deployment, then kept running as a daemon. After
|
|
133
|
+
the first accepted sync appears in the MCP Control Plane, normal admins use
|
|
134
|
+
**Auto Discover now** in the web UI. The daemon pulls scoped jobs and reports
|
|
135
|
+
observations; Sernixa treats only accepted sync events as discovery evidence,
|
|
136
|
+
and enrollment alone remains inventory evidence.
|
|
137
|
+
|
|
138
|
+
CLI commands below are support, debugging, and rollout tools. They are not the
|
|
139
|
+
recurring customer workflow after the helper is installed and syncing.
|
|
140
|
+
The web/API Auto Discover job path is controlled by `MCP_AUTO_DISCOVER_ENABLED`
|
|
141
|
+
and remains off by default until an operator enables the rollout.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
sernixa-agent daemon --interval 300
|
|
145
|
+
sernixa-agent daemon --once
|
|
146
|
+
sernixa-agent run
|
|
147
|
+
sernixa-agent install-service --platform auto
|
|
148
|
+
sernixa-agent uninstall-service --platform auto --stop
|
|
149
|
+
sernixa-agent status --json
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Defaults:
|
|
153
|
+
|
|
154
|
+
- successful runs sleep for 300 seconds
|
|
155
|
+
- intervals are bounded from 30 seconds to 24 hours
|
|
156
|
+
- transient failures use exponential backoff with jitter, capped at 900 seconds
|
|
157
|
+
- scans never overlap inside a process, and a lock file prevents two daemon
|
|
158
|
+
processes from running the same agent loop
|
|
159
|
+
- non-secret daemon state is written to `~/.sernixa/agent-state.json`
|
|
160
|
+
- the default daemon lock file is `~/.sernixa/agent.lock`
|
|
161
|
+
|
|
162
|
+
Fail-closed errors such as missing auth, rejected tokens, disabled or revoked
|
|
163
|
+
machines, unsupported payload versions, invalid signatures, and clock skew stop
|
|
164
|
+
the daemon instead of silently degrading to partial success. Network and 429/5xx
|
|
165
|
+
failures are retried with backoff and recorded in local state.
|
|
166
|
+
|
|
167
|
+
`status --json` reports `daemon.health`, `daemon.status`,
|
|
168
|
+
`last_successful_scan_at`, `last_successful_sync_at`, `backoff_seconds`,
|
|
169
|
+
`next_run_at`, `last_error_category`, `configured_lock_file`, and user-service
|
|
170
|
+
installation state. It never prints the token value.
|
|
171
|
+
|
|
172
|
+
User-level service helpers write templates only; they do not mint tokens or
|
|
173
|
+
enable services without operator action:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
sernixa-agent install-service --platform linux
|
|
177
|
+
systemctl --user daemon-reload
|
|
178
|
+
systemctl --user enable --now sernixa-agent.service
|
|
179
|
+
journalctl --user -u sernixa-agent.service -f
|
|
180
|
+
|
|
181
|
+
sernixa-agent install-service --platform macos
|
|
182
|
+
launchctl load ~/Library/LaunchAgents/com.sernixa.agent.plist
|
|
183
|
+
tail -f ~/Library/Logs/sernixa-agent.err.log
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Generated services run `sernixa-agent daemon --service-mode`. In service mode,
|
|
187
|
+
a deliberate fail-closed condition writes state and exits successfully so the
|
|
188
|
+
service manager does not restart forever on a revoked or invalid key. Unexpected
|
|
189
|
+
process crashes still restart.
|
|
190
|
+
|
|
191
|
+
## Upgrade
|
|
192
|
+
|
|
193
|
+
Print the supported internal upgrade commands and compatibility expectations:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
sernixa-agent upgrade
|
|
197
|
+
sernixa-agent upgrade --json
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
For existing `pipx` installs, distribute the new wheel and run:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
pipx install --force dist/sernixa_agent-1.5.0-py3-none-any.whl
|
|
204
|
+
sernixa-agent diagnose --check-backend
|
|
205
|
+
sernixa-agent enroll
|
|
206
|
+
sernixa-agent sync
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
For `uv tool` installs:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
uv tool install --force dist/sernixa_agent-1.5.0-py3-none-any.whl
|
|
213
|
+
sernixa-agent diagnose --check-backend
|
|
214
|
+
sernixa-agent sync
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Saved scans with unsupported schemas are not migrated automatically. After an
|
|
218
|
+
upgrade, rerun `sernixa-agent scan` or `sernixa-agent sync` so the backend
|
|
219
|
+
receives a current payload.
|
|
220
|
+
|
|
221
|
+
## Scan
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
sernixa-agent scan
|
|
225
|
+
sernixa-agent scan --ports 3000,8000,8080
|
|
226
|
+
sernixa-agent scan --hosts 127.0.0.1 --paths /mcp,/sse --output /tmp/sernixa-mcp-scan.json
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
`scan` prints a safe count/source summary. Pass `--output` to explicitly write a
|
|
230
|
+
`sernixa.mcp.local_agent.discovery.v1` payload to a local file. It does not
|
|
231
|
+
inspect arbitrary networks unless you explicitly pass hosts. Default candidate
|
|
232
|
+
paths include `/mcp`, `/sse`, `/messages`, `/rpc`, `/jsonrpc`, `/api/mcp`, and
|
|
233
|
+
well-known MCP metadata paths.
|
|
234
|
+
|
|
235
|
+
To force execution from this checkout and verify the loaded module:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
make agent-install-local
|
|
239
|
+
make agent-version-check
|
|
240
|
+
make agent-which
|
|
241
|
+
make agent-cli ARGS="sync"
|
|
242
|
+
./run_dev_cli.sh --version-check
|
|
243
|
+
./run_dev_cli.sh sync
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
The version check is part of the packaged `sernixa-agent` CLI and prints the
|
|
247
|
+
executing `cli.py` path plus active sync candidate whitelist. `which
|
|
248
|
+
sernixa-agent` normally points at a Python bin shim; `sernixa-agent
|
|
249
|
+
--version-check` is the authoritative check for the source file loaded by that
|
|
250
|
+
shim. It never prints discovery results or environment values.
|
|
251
|
+
|
|
252
|
+
## Sync
|
|
253
|
+
|
|
254
|
+
Preferred local setup uses the token file created by `init`:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
sernixa-agent sync
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
For CI or ephemeral sessions, environment variables are also supported:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
export SERNIXA_API_KEY=srnx_live_...
|
|
264
|
+
sernixa-agent sync --api-base-url https://api.sernixa.com
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Use the API origin for sync. The CLI canonicalizes `https://sernixa.com` and
|
|
268
|
+
`https://www.sernixa.com` to `https://api.sernixa.com` to avoid routing local
|
|
269
|
+
agent sync through the web app.
|
|
270
|
+
|
|
271
|
+
You may also set `SERNIXA_AGENT_TOKEN`; it takes precedence over
|
|
272
|
+
`SERNIXA_API_KEY`. `--token-file` and `--token-env` can override the configured
|
|
273
|
+
auth source.
|
|
274
|
+
|
|
275
|
+
Sync retries transient network and 429/5xx failures, sends a stable
|
|
276
|
+
`Idempotency-Key`, and keeps deterministic endpoint ordering and stable
|
|
277
|
+
candidate `result_id` values for repeated runs. Retry diagnostics are written
|
|
278
|
+
to stderr so JSON responses on stdout stay parseable.
|
|
279
|
+
|
|
280
|
+
The agent never captures environment variables, files, request bodies, or
|
|
281
|
+
secrets from discovered endpoints.
|
|
282
|
+
|
|
283
|
+
## Discovery-Only and Shadow AI Candidates
|
|
284
|
+
|
|
285
|
+
Use `discover-only` when you want reviewable candidates without enrolling the
|
|
286
|
+
machine in fleet inventory:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
sernixa-agent discover-only --ports 3000,8000 --paths /mcp,/sse
|
|
290
|
+
sernixa-agent discover-only --shadow-scope . --sync
|
|
291
|
+
sernixa-agent discover-only --include-default-configs --include-processes --sync
|
|
292
|
+
sernixa-agent discover-only --no-endpoint-scan --shadow-scope /repo --output shadow-candidates.json
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Discovery-only mode labels every candidate as `discovered_not_enrolled` and
|
|
296
|
+
adds guardrail evidence explaining that it is not enrollment, accepted sync
|
|
297
|
+
proof, or verification. `--shadow-scope` is explicit and bounded: the agent
|
|
298
|
+
inspects only supplied files/directories, skips common dependency/cache folders,
|
|
299
|
+
looks for MCP and AI-agent markers in config/code/container files, and records
|
|
300
|
+
markers plus file location metadata without copying secret values.
|
|
301
|
+
|
|
302
|
+
`--sync` sends candidates to the existing Sernixa discovery review queue through
|
|
303
|
+
`POST /api/mcp/discovery/sync`. It does not import or register anything;
|
|
304
|
+
an admin still has to approve for enrollment, ignore, mark out of scope, defer,
|
|
305
|
+
or import candidates separately. Each review action records actor, timestamp,
|
|
306
|
+
reason, evidence source, and evidence codes.
|
|
307
|
+
Process discovery is opt-in and reads process names only; command arguments and
|
|
308
|
+
environment variables are not captured.
|
|
309
|
+
|
|
310
|
+
## Config
|
|
311
|
+
|
|
312
|
+
By default the agent reads `./sernixa-agent.json` first and then
|
|
313
|
+
`~/.sernixa/agent.json`.
|
|
314
|
+
|
|
315
|
+
Precedence is:
|
|
316
|
+
|
|
317
|
+
1. CLI flags
|
|
318
|
+
2. Config file
|
|
319
|
+
3. Environment variables such as `SERNIXA_API_BASE_URL`, `SERNIXA_AGENT_ID`, and `SERNIXA_MACHINE_LABEL`
|
|
320
|
+
4. Built-in defaults
|
|
321
|
+
|
|
322
|
+
```json
|
|
323
|
+
{
|
|
324
|
+
"agent_id": "sernixa-agent-workstation",
|
|
325
|
+
"api_base_url": "https://api.sernixa.com",
|
|
326
|
+
"daemon_interval_seconds": 300,
|
|
327
|
+
"daemon_lock_file": "~/.sernixa/agent.lock",
|
|
328
|
+
"daemon_max_backoff_seconds": 900,
|
|
329
|
+
"daemon_stale_after_seconds": 900,
|
|
330
|
+
"daemon_state_file": "~/.sernixa/agent-state.json",
|
|
331
|
+
"hosts": ["127.0.0.1"],
|
|
332
|
+
"machine_label": "Security laptop",
|
|
333
|
+
"paths": ["/mcp", "/sse", "/api/mcp"],
|
|
334
|
+
"ports": [3000, 8000, 8080],
|
|
335
|
+
"sync_retries": 2,
|
|
336
|
+
"sync_timeout_seconds": 10.0,
|
|
337
|
+
"timeout_seconds": 1.5,
|
|
338
|
+
"token_file": "~/.sernixa/agent.token"
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Unknown config keys and wrong JSON types fail fast with exit code `3`.
|
|
343
|
+
Missing auth exits with code `4`. Sync failures exit with code `5`.
|
|
344
|
+
|
|
345
|
+
## Machine Inventory
|
|
346
|
+
|
|
347
|
+
Each scan includes a stable, non-secret `machine_id`, the optional
|
|
348
|
+
`machine_label`, `agent_version`, `scan_fingerprint`, and `payload_schema`. The
|
|
349
|
+
raw hostname is not emitted. Recent syncs in Sernixa use these fields to show
|
|
350
|
+
which enrolled machine produced each scan.
|
|
351
|
+
|
|
352
|
+
Change a label by editing `machine_label` in `~/.sernixa/agent.json` or by
|
|
353
|
+
running commands with `--machine-label`. The stable `machine_id` does not change,
|
|
354
|
+
so history remains tied to the same enrolled machine.
|
|
355
|
+
|
|
356
|
+
Rotate a token with the admin dashboard and local handoff loop:
|
|
357
|
+
|
|
358
|
+
1. Security admin marks token rotation requested for the machine.
|
|
359
|
+
2. Operator receives the replacement token through the approved secret channel.
|
|
360
|
+
3. Operator replaces the local token without echoing it:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
sernixa-agent rotate-token --new-token-stdin --check-backend
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
For non-interactive shells, use `--new-token-env SERNIXA_REPLACEMENT_TOKEN`.
|
|
367
|
+
The command writes only the configured token file, sets mode `0600`, and never
|
|
368
|
+
prints the old or new token. It does not mint tokens or prove the token has
|
|
369
|
+
synced.
|
|
370
|
+
|
|
371
|
+
4. Admin marks the dashboard rotation as local install complete after the local
|
|
372
|
+
file is replaced. This is an audit marker, not backend verification.
|
|
373
|
+
5. Operator runs `sernixa-agent sync`. The dashboard changes to
|
|
374
|
+
`verified_after_rotation` only after Sernixa receives a successful sync from
|
|
375
|
+
that machine after the install marker.
|
|
376
|
+
|
|
377
|
+
`sernixa-agent diagnose --check-backend` proves backend reachability, not token
|
|
378
|
+
verification. The `rotate-token` command prints the expected verification step
|
|
379
|
+
as `sernixa-agent sync` so support can distinguish local replacement from
|
|
380
|
+
dashboard verification. If sync fails, share CLI stderr with support; support
|
|
381
|
+
can log reminder, backend recheck, owner-contact, or revoke/re-enroll escalation
|
|
382
|
+
actions in the dashboard. Those actions are audit records only; they do not
|
|
383
|
+
deliver tokens, re-enable machines, or verify rotation.
|
|
384
|
+
Do not place tokens in scan output, config commits, shell history, or rollout
|
|
385
|
+
scripts.
|
|
386
|
+
|
|
387
|
+
## Compatibility
|
|
388
|
+
|
|
389
|
+
The backend accepts `sernixa.mcp.local_agent.discovery.v1` payloads from
|
|
390
|
+
`sernixa-agent >=1.0,<2.0`. Saved scans with another payload schema or missing
|
|
391
|
+
required fields are rejected before sync.
|