neatlogs-cli 0.2.1 → 0.2.2
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/CHANGELOG.md +32 -7
- package/README.md +148 -67
- package/SECURITY.md +4 -0
- package/dist/bin.js +105783 -80796
- package/docs/command-reference.md +2214 -357
- package/docs/execution-secret-custody.md +86 -0
- package/docs/runtime-detection-reads.md +63 -0
- package/package.json +2 -2
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Execution secrets and the local MCP transport
|
|
2
|
+
|
|
3
|
+
Secret-producing commands persist a random 256-bit replay key **before dispatch**.
|
|
4
|
+
They reuse it when the same authenticated actor, canonical API host/issuer,
|
|
5
|
+
operation and idempotency key retry the same canonical input. Changed input is a
|
|
6
|
+
local conflict. Access-token refresh does not change the stable actor binding.
|
|
7
|
+
This covers managed credentials, guest links, and service-account tokens.
|
|
8
|
+
|
|
9
|
+
The default store is the native keyring under
|
|
10
|
+
`com.neatlogs.cli.execution-secrets.v1`, separate from OAuth login credentials.
|
|
11
|
+
A profile that explicitly enabled protected-file login storage uses private
|
|
12
|
+
execution files (0700 directory, 0600 files, no symlink following) instead.
|
|
13
|
+
File keys are published as complete, fsynced immutable records with atomic hard
|
|
14
|
+
links. Concurrent processes return the same winning key. Native creation uses
|
|
15
|
+
an exclusive private lock with atomically published process-owner metadata. A dead
|
|
16
|
+
owner is recovered under a per-inode reaper lock; suspended/live processes are never
|
|
17
|
+
displaced. Contention is bounded to ten seconds. Unparseable legacy lock files remain
|
|
18
|
+
fail-closed because owner liveness cannot be established.
|
|
19
|
+
Once the key was committed, retries bypass the creation lock and reuse it.
|
|
20
|
+
|
|
21
|
+
Keep the original idempotency key. Recovery reads must find an existing local
|
|
22
|
+
key and never create a replacement. Losing or deleting the local key makes the
|
|
23
|
+
original ciphertext unrecoverable. Retain custody records for at least the
|
|
24
|
+
server's result retention period. This change does not delete keys on success.
|
|
25
|
+
|
|
26
|
+
## MCP client integration
|
|
27
|
+
|
|
28
|
+
First authorize a server-registered MCP client with native loopback redirects enabled:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
neatlogs mcp login --issuer https://dev.neatlogs.com --endpoint https://neatlogs-dev-cloud.neatlogs.com/mcp/user --client-id REGISTERED_CLIENT_ID --scope context:read access:write offline_access
|
|
32
|
+
neatlogs mcp proxy --issuer https://dev.neatlogs.com --endpoint https://neatlogs-dev-cloud.neatlogs.com/mcp/user --client-id REGISTERED_CLIENT_ID
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Choose the scopes needed by the intended actions. Configure the MCP host to launch
|
|
36
|
+
that proxy command with stdio. Browser sign-in uses PKCE; access and refresh tokens
|
|
37
|
+
use the existing native credential store. Resource/client-specific profiles are
|
|
38
|
+
isolated from ordinary CLI credentials. The proxy refreshes before expiry under a
|
|
39
|
+
cross-process lock. `--allow-file-custody` explicitly permits protected-file storage
|
|
40
|
+
and must also be present when using a file-backed profile. No bearer token belongs
|
|
41
|
+
in the MCP host configuration. Server client registration remains an operator
|
|
42
|
+
prerequisite; these source changes do not establish enabled dev acceptance.
|
|
43
|
+
|
|
44
|
+
The proxy privately discovers the stable actor and action policy, persists the
|
|
45
|
+
key, and supplies proof in transient HTTP headers. Tool arguments and stored
|
|
46
|
+
server receipts contain no replay key. The server verifies actual key material;
|
|
47
|
+
a model-supplied capability boolean alone is insufficient. Headers are not
|
|
48
|
+
included in the serialized invocation input. The proxy rejects model-supplied
|
|
49
|
+
secret transport headers and prevents reflected replay keys from reaching its
|
|
50
|
+
stdout or custody records.
|
|
51
|
+
|
|
52
|
+
For secret actions, the model receives a local-custody acknowledgement. It does
|
|
53
|
+
not receive the secret envelope or plaintext. The user retrieves the result in
|
|
54
|
+
a separate terminal:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
neatlogs mcp reveal INVOCATION_UUID --issuer https://dev.neatlogs.com --client-id REGISTERED_CLIENT_ID --endpoint https://neatlogs-dev-cloud.neatlogs.com/mcp/user
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This command verifies the current actor and decrypts locally using the existing
|
|
61
|
+
strict credential, guest-link, or service-account envelope validators. It prints
|
|
62
|
+
plaintext intentionally to that terminal. It is never registered as a model
|
|
63
|
+
tool. Guest URL and token audience validation use the verified regional issuer.
|
|
64
|
+
|
|
65
|
+
`get_action_result` recovers an existing invocation. After receipt expiry,
|
|
66
|
+
`get_saved_action_result` supplies the original operation/input/idempotency key
|
|
67
|
+
and uses the existing custody key without dispatching another mutation. The
|
|
68
|
+
proxy retains the recovered envelope locally for explicit reveal. Missing
|
|
69
|
+
server output, expired retention, missing local keys, revoked access and
|
|
70
|
+
uncertain outcomes remain errors; none authorize a fresh mutation.
|
|
71
|
+
|
|
72
|
+
`--allow-file-custody` explicitly selects private files for the MCP transport.
|
|
73
|
+
Use the same option for reveal. CLI and MCP share the execution-secret namespace
|
|
74
|
+
and canonical input representation, so a cross-transport retry does not invent
|
|
75
|
+
a second decryption key. Input/receipt metadata and wrapped responses stay in
|
|
76
|
+
the keyring, or the explicitly selected private-file store; ordinary CLI
|
|
77
|
+
configuration and model transcripts contain no raw replay key.
|
|
78
|
+
|
|
79
|
+
## Qualification
|
|
80
|
+
|
|
81
|
+
Hosted tests cover immutable file publication across OS processes, restart
|
|
82
|
+
recovery, changed-input rejection, keyring namespace and locks, unsafe files,
|
|
83
|
+
secret-free decrypted server receipts, wrong proof, compatibility of legacy
|
|
84
|
+
read receipts, and proxy lost-response recovery without another execution.
|
|
85
|
+
Run the CLI core suite and backend user-MCP suite remotely. Source tests do not
|
|
86
|
+
establish real client OAuth onboarding, deployment, or live secret acceptance.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Runtime detection read reference
|
|
2
|
+
|
|
3
|
+
The detection read pilot adds `--live` to the existing `api`, `schema list`,
|
|
4
|
+
`schema search`, and `schema show` commands. These additions require the matching
|
|
5
|
+
backend change. This source change does not establish that a deployment or a
|
|
6
|
+
published CLI package includes the pilot.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
neatlogs --host https://dev.neatlogs.com --project <uuid> schema list --live
|
|
10
|
+
neatlogs --project <uuid> schema search detections --live
|
|
11
|
+
neatlogs --project <uuid> schema show get_api_v1_public_detections --live
|
|
12
|
+
neatlogs --project <uuid> api get_api_v1_public_detections --live --query limit=1
|
|
13
|
+
neatlogs --project <uuid> api get_api_v1_public_detections_detectionId_history --live --param detectionId=<uuid> --query limit=1
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Live commands require an OAuth or service-account credential, a selected project,
|
|
17
|
+
`configuration:read`, and `detection:read` permission in that project. Legacy
|
|
18
|
+
public keys and SDK ingestion keys cannot use this catalog.
|
|
19
|
+
|
|
20
|
+
Each live invocation fetches a fresh authenticated catalog from
|
|
21
|
+
`GET /api/v1/public/action-catalog`. The CLI retains no catalog on disk and reuses
|
|
22
|
+
no catalog between commands. The credential and host resolved for discovery are
|
|
23
|
+
also used for execution within that invocation. A failed or unsupported live
|
|
24
|
+
catalog does not fall back to the embedded contract.
|
|
25
|
+
|
|
26
|
+
Without `--live`, `schema` remains offline and `api` keeps the release's explicit
|
|
27
|
+
handler registry. Friendly commands keep their current behavior and operation
|
|
28
|
+
IDs. A newly registered compatible backend read can be listed, inspected, and
|
|
29
|
+
executed with the same discovery-capable CLI artifact.
|
|
30
|
+
|
|
31
|
+
The pilot accepts catalog version `1`, descriptor version `1`, and schema dialect
|
|
32
|
+
`neatlogs-json-schema-v1`. Unknown versions, duplicate operation IDs, unsupported
|
|
33
|
+
schema keywords, unsafe paths, and descriptors outside the detection read policy
|
|
34
|
+
fail before action dispatch. The CLI never downloads or executes action code.
|
|
35
|
+
|
|
36
|
+
The descriptor contains the method, public path, read effect, accepted credential
|
|
37
|
+
kinds, project requirement, authorization metadata, input/output JSON schemas,
|
|
38
|
+
timeout, and response budget. The backend enforces authorization again when the
|
|
39
|
+
action executes. A catalog entry grants no access by itself.
|
|
40
|
+
|
|
41
|
+
Requests stay on the configured authenticated origin. The pilot permits only GET
|
|
42
|
+
paths beneath `/api/v1/public/detections` and
|
|
43
|
+
`/api/v1/public/detection-suggestion-runs`. Redirects, absolute URLs, encoded path
|
|
44
|
+
templates, traversal segments, write effects, request bodies, and idempotency keys
|
|
45
|
+
are rejected. Each request has a maximum 10-second timeout. Catalogs are limited
|
|
46
|
+
to 1 MiB and 100 descriptors. Action responses are limited to 2 MiB.
|
|
47
|
+
|
|
48
|
+
List actions return one bounded page. `--query limit=1` through `limit=100` and
|
|
49
|
+
`--query cursor=<opaque-cursor>` use the backend contract. Live `api` does not
|
|
50
|
+
automatically follow pages. The CLI validates supplied path and query values and
|
|
51
|
+
the complete success response before output. HTTP errors retain the existing
|
|
52
|
+
exit codes and sanitized request-ID diagnostics.
|
|
53
|
+
|
|
54
|
+
`UNSUPPORTED_CATALOG_VERSION` identifies an unsupported catalog version or
|
|
55
|
+
dialect. `UNSUPPORTED_ACTION_DESCRIPTOR` identifies an unsupported descriptor.
|
|
56
|
+
`UNSUPPORTED_ACTION_SCHEMA` identifies a schema outside the supported subset.
|
|
57
|
+
`ACTION_NOT_AVAILABLE` means that the fresh catalog omits the requested operation.
|
|
58
|
+
A 404 from discovery means that the host lacks that endpoint. A 401 or 403 remains
|
|
59
|
+
an authentication or authorization failure.
|
|
60
|
+
|
|
61
|
+
The [backend catalog reference](../../backend/docs/public-api/runtime-detection-reads.md)
|
|
62
|
+
defines backend registration and schema compatibility. CLI-Anything is not a
|
|
63
|
+
runtime dependency. This pilot extends the existing TypeScript/Commander CLI.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neatlogs-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Non-interactive CLI for the NeatLogs public API",
|
|
5
5
|
"homepage": "https://github.com/neatlogs/neatlogs-app#readme",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@github/keytar": "7.10.6",
|
|
44
44
|
"commander": "^14.0.0",
|
|
45
|
-
"zod": "^4.
|
|
45
|
+
"zod": "^4.6.6"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^24.10.1",
|