@shieldaai/agent-map 0.1.0-alpha.2 → 0.1.0-alpha.3
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/README.md +7 -2
- package/dist/assets.js +2 -2
- package/dist/boundary.d.ts +2 -0
- package/dist/boundary.js +6 -0
- package/dist/cli-entry.d.ts +2 -0
- package/dist/cli-entry.js +18 -0
- package/dist/cli.js +4 -4
- package/dist/identity-cli.js +2 -2
- package/package.json +18 -4
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Agent Guard reference map
|
|
2
2
|
|
|
3
|
+
Query AI agent and MCP inventory, snapshot changes and access explanations over
|
|
4
|
+
scoped HTTP and MCP interfaces. See the
|
|
5
|
+
[package selection guide](https://github.com/ShieldaAI/agent-guard/blob/main/docs/package-guide.md)
|
|
6
|
+
for tool authorization and model response validation.
|
|
7
|
+
|
|
3
8
|
Optional read-only reference service for the immutable Agent Guard projections
|
|
4
9
|
published by the [Cartography collector](../../integrations/cartography/README.md).
|
|
5
10
|
It supplies the same evidence to HTTP, MCP clients and the
|
|
@@ -31,7 +36,7 @@ clearly labeled synthetic demo uses only browser-local fixture data.
|
|
|
31
36
|
|
|
32
37
|
The launcher requires nonblocking file-open support, as provided by the pilot's
|
|
33
38
|
POSIX hosts. Its configuration must resolve to a regular file of at most 128 KiB;
|
|
34
|
-
symlinks to regular files remain supported. It checks the opened descriptor and
|
|
39
|
+
symlinks to regular files remain supported. The file must belong to the service user or root, with group and other write access disabled. Protect the configuration path and its parent directories from replacement. It checks the opened descriptor and
|
|
35
40
|
limits bytes read even if the file grows. Named pipes and other nonregular inputs
|
|
36
41
|
fail startup with the same safe diagnostic. Native Windows is outside the
|
|
37
42
|
[pilot's supported host profile](../../deployment/cartography/RUNBOOK.md#prerequisites-and-layout).
|
|
@@ -40,7 +45,7 @@ Viewer asset hosting on both HTTP and HTTPS also requires nonblocking and
|
|
|
40
45
|
no-follow file-open support, as provided by the POSIX pilot hosts. The fixed
|
|
41
46
|
`index.html`, `app.js` and `app.css` entries must each be regular files of at most
|
|
42
47
|
4 MiB. The loader checks each opened descriptor, rejects a symlink replacing an
|
|
43
|
-
asset, and bounds reads even if the file grows. It captures the bytes at startup;
|
|
48
|
+
asset, and bounds reads even if the file grows. Assets must belong to the service user or root, with group and other write access disabled. Keep the entire asset path in trusted directories. It captures the bytes at startup;
|
|
44
49
|
later path replacements do not change the served assets. Starting an API without
|
|
45
50
|
`viewerDirectory` does not require these file-open capabilities.
|
|
46
51
|
|
package/dist/assets.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { constants } from 'node:fs';
|
|
2
2
|
import { open } from 'node:fs/promises';
|
|
3
3
|
import { isAbsolute, join } from 'node:path';
|
|
4
|
-
import { fail } from './boundary.js';
|
|
4
|
+
import { fail, trustedHostFile } from './boundary.js';
|
|
5
5
|
/** Load the fixed public assets once; never follow a replaced leaf or read beyond the cap. */
|
|
6
6
|
export async function loadMapAssets(directory) {
|
|
7
7
|
const assets = new Map();
|
|
@@ -16,7 +16,7 @@ export async function loadMapAssets(directory) {
|
|
|
16
16
|
const file = await open(join(directory, name), constants.O_RDONLY | constants.O_NONBLOCK | constants.O_NOFOLLOW);
|
|
17
17
|
try {
|
|
18
18
|
const info = await file.stat();
|
|
19
|
-
if (!info
|
|
19
|
+
if (!trustedHostFile(info) || info.size > maximum)
|
|
20
20
|
fail('MAP_CONFIG_INVALID');
|
|
21
21
|
const data = Buffer.alloc(maximum + 1);
|
|
22
22
|
let bytes = 0;
|
package/dist/boundary.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { Stats } from 'node:fs';
|
|
1
2
|
export declare function fail(code: string): never;
|
|
3
|
+
export declare function trustedHostFile(info: Stats): boolean;
|
|
2
4
|
export declare function fields(value: unknown, allowed: readonly string[], required?: readonly string[]): Record<string, unknown>;
|
|
3
5
|
export declare function integer(value: unknown, fallback: number, min: number, max: number): number;
|
|
4
6
|
/** Bounded strict JSON, including duplicate decoded keys that JSON.parse would discard. */
|
package/dist/boundary.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { MapQueryError } from './types.js';
|
|
2
2
|
export function fail(code) { throw new MapQueryError(code); }
|
|
3
|
+
// Configuration selects credential destinations. Viewer assets run in authenticated browsers.
|
|
4
|
+
// Check the descriptor after open so the test applies to the bytes that will be used.
|
|
5
|
+
export function trustedHostFile(info) {
|
|
6
|
+
return typeof process.geteuid === 'function' && info.isFile() &&
|
|
7
|
+
(info.uid === 0 || info.uid === process.geteuid()) && (info.mode & 0o022) === 0;
|
|
8
|
+
}
|
|
3
9
|
export function fields(value, allowed, required = []) {
|
|
4
10
|
if (!value || typeof value !== 'object' || Array.isArray(value) ||
|
|
5
11
|
![null, Object.prototype].includes(Object.getPrototypeOf(value)) || Object.getOwnPropertySymbols(value).length)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { realpathSync } from 'node:fs';
|
|
2
|
+
import { pathToFileURL } from 'node:url';
|
|
3
|
+
/** npm's POSIX executable is a symlink. Node resolves it when loading the module. */
|
|
4
|
+
export function isCliEntry(meta) {
|
|
5
|
+
if (typeof meta.main === 'boolean')
|
|
6
|
+
return meta.main;
|
|
7
|
+
const entry = process.argv[1];
|
|
8
|
+
if (!entry)
|
|
9
|
+
return false;
|
|
10
|
+
try {
|
|
11
|
+
// Older supported Node versions do not expose import.meta.main.
|
|
12
|
+
return pathToFileURL(realpathSync(entry)).href === meta.url;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// Imports from eval/stdin can supply an argv value that is not a file.
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -3,12 +3,12 @@ import { constants } from 'node:fs';
|
|
|
3
3
|
import { open } from 'node:fs/promises';
|
|
4
4
|
import { resolve } from 'node:path';
|
|
5
5
|
import { parseArgs } from 'node:util';
|
|
6
|
-
import {
|
|
6
|
+
import { isCliEntry } from './cli-entry.js';
|
|
7
7
|
import { createNeo4jMapStore } from './store.js';
|
|
8
8
|
import { MapService } from './service.js';
|
|
9
9
|
import { startMapServer } from './http.js';
|
|
10
10
|
import { validateReadScope } from './types.js';
|
|
11
|
-
import { fields, fail, integer, parseRequest } from './boundary.js';
|
|
11
|
+
import { fields, fail, integer, parseRequest, trustedHostFile } from './boundary.js';
|
|
12
12
|
function environmentName(value) {
|
|
13
13
|
if (typeof value !== 'string' || !/^[A-Za-z_][A-Za-z0-9_]{0,127}$/.test(value))
|
|
14
14
|
fail('MAP_CONFIG_INVALID');
|
|
@@ -22,7 +22,7 @@ async function configBytes(path) {
|
|
|
22
22
|
const file = await open(path, constants.O_RDONLY | constants.O_NONBLOCK);
|
|
23
23
|
try {
|
|
24
24
|
const info = await file.stat();
|
|
25
|
-
if (!info
|
|
25
|
+
if (!trustedHostFile(info) || info.size > maximum)
|
|
26
26
|
fail('MAP_CONFIG_INVALID');
|
|
27
27
|
// The file may grow after stat; never use an unbounded readFile here.
|
|
28
28
|
const data = Buffer.alloc(maximum + 1);
|
|
@@ -88,6 +88,6 @@ export async function runMapCli(argv = process.argv.slice(2)) {
|
|
|
88
88
|
await store.close();
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
if (
|
|
91
|
+
if (isCliEntry(import.meta)) {
|
|
92
92
|
void runMapCli().catch(() => { process.stderr.write('MAP_START_FAILED\n'); process.exitCode = 1; });
|
|
93
93
|
}
|
package/dist/identity-cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { constants } from 'node:fs';
|
|
|
3
3
|
import { open } from 'node:fs/promises';
|
|
4
4
|
import { dirname, resolve } from 'node:path';
|
|
5
5
|
import { parseArgs } from 'node:util';
|
|
6
|
-
import {
|
|
6
|
+
import { isCliEntry } from './cli-entry.js';
|
|
7
7
|
import { createNeo4jMapStore } from './store.js';
|
|
8
8
|
import { MapService } from './service.js';
|
|
9
9
|
import { startMapIdentityServer } from './identity-http.js';
|
|
@@ -98,6 +98,6 @@ export async function runMapIdentityCli(argv = process.argv.slice(2)) {
|
|
|
98
98
|
await store.close();
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
if (
|
|
101
|
+
if (isCliEntry(import.meta)) {
|
|
102
102
|
void runMapIdentityCli().catch(() => { process.stderr.write('MAP_START_FAILED\n'); process.exitCode = 1; });
|
|
103
103
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shieldaai/agent-map",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.0-alpha.3",
|
|
4
|
+
"description": "Read-only AI agent and MCP inventory queries over HTTP and MCP, with scoped access to Cartography projections.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@modelcontextprotocol/server": "2.4.0",
|
|
29
|
-
"@shieldaai/agent-guard": "0.1.0-alpha.
|
|
29
|
+
"@shieldaai/agent-guard": "0.1.0-alpha.3",
|
|
30
30
|
"neo4j-driver": "6.3.0",
|
|
31
31
|
"openid-client": "6.8.8"
|
|
32
32
|
},
|
|
@@ -43,5 +43,19 @@
|
|
|
43
43
|
"build": "tsc -p tsconfig.json",
|
|
44
44
|
"prepack": "node ../../scripts/build.mjs",
|
|
45
45
|
"prepublishOnly": "node ../../scripts/release-check.mjs"
|
|
46
|
-
}
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/ShieldaAI/agent-guard/tree/main/packages/agent-map#readme",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/ShieldaAI/agent-guard/issues"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"ai-agents",
|
|
53
|
+
"agent-inventory",
|
|
54
|
+
"mcp",
|
|
55
|
+
"model-context-protocol",
|
|
56
|
+
"cartography",
|
|
57
|
+
"neo4j",
|
|
58
|
+
"typescript",
|
|
59
|
+
"access-explanations"
|
|
60
|
+
]
|
|
47
61
|
}
|