@adtl/gateway 0.5.0 → 0.5.1
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 +8 -4
- package/dist/gateway.d.ts +1 -1
- package/dist/gateway.js +1 -1
- package/package.json +4 -4
- package/src/gateway.ts +1 -1
package/README.md
CHANGED
|
@@ -61,6 +61,7 @@ One file holds both the labels and the gateway settings.
|
|
|
61
61
|
| `egress` | `none`, `internal`, `external`, `public` | Where *calling* the tool can send data. |
|
|
62
62
|
| `labelInto` | an argument name, e.g. `metadata` | Write tools of servers that store an object per record: stamp the session label into it. See [labels on records](#labels-on-records). |
|
|
63
63
|
| `readLabels` | `true` | Read tools of those servers: join the stamps found on returned records into the result's label. |
|
|
64
|
+
| `scopeInto` | a scope-id argument, e.g. `run_id` | Write tools of servers that resolve references from earlier messages of the same scope (such as Mem0): give a tainted session's writes a scope of their own. |
|
|
64
65
|
|
|
65
66
|
Tools without a rule use the defaults (`untrusted`, `private`, egress `unknown`). That's safe but strict, so describe the tools you use. Resources and prompts use the server's `defaults`.
|
|
66
67
|
|
|
@@ -248,13 +249,16 @@ Some memory servers extract facts with a model on write, or merge records, so wh
|
|
|
248
249
|
servers:
|
|
249
250
|
memory:
|
|
250
251
|
tools:
|
|
251
|
-
add_memory: { egress: internal, labelInto: metadata }
|
|
252
|
+
add_memory: { egress: internal, labelInto: metadata, scopeInto: run_id }
|
|
253
|
+
update_memory: { egress: internal, labelInto: metadata }
|
|
252
254
|
search_memory: { integrity: trusted, confidentiality: public, egress: none, readLabels: true }
|
|
253
255
|
```
|
|
254
256
|
|
|
255
|
-
- On every `add_memory` call the gateway sets `metadata["adtl/record-label"]` to `{ integrity, confidentiality, writer }` from the session,
|
|
256
|
-
- On `search_memory`, stamps anywhere in the result (also inside JSON text) are joined into its label, with the origin `adtl-record` / `session:<id>`, and the audit entry gets `records: { stamps, writers }`. Anyone who can write to the store can write a stamp, so stamps only make a label stricter. A malformed stamp counts as the global defaults.
|
|
257
|
-
-
|
|
257
|
+
- **Write.** On every `add_memory` and `update_memory` call the gateway sets `metadata["adtl/record-label/<session>"]` to `{ integrity, confidentiality, writer }` from the session, and drops any stamp keys the agent put there. Each session stamps under its own key, so on a server that lays an update's metadata over the stored metadata (as Mem0 does), a clean session's update adds a stamp instead of replacing a tainted one.
|
|
258
|
+
- **Read.** On `search_memory`, stamps anywhere in the result (also inside JSON text) are joined into its label, with the origin `adtl-record` / `session:<id>`, and the audit entry gets `records: { stamps, writers }`. Anyone who can write to the store can write a stamp, so stamps only make a label stricter. A malformed stamp counts as the global defaults.
|
|
259
|
+
- **Scope.** Some servers also keep recent raw messages per scope, without metadata, and resolve references in a new message from them: Mem0 keeps the last 10 per `user_id`/`agent_id`/`run_id` and asks its extractor to resolve pronouns from them. A clean session writing under a tainted session's ids could then store a fact built from the tainted text, with a clean stamp. With `scopeInto: run_id`, a tainted session's writes get a run id named after its label (`<run_id>:adtl-untrusted-public`, or just `adtl-untrusted-public`), so the server keeps its messages apart. Clean sessions keep their ids, minus any label mark the agent added, so they can't join a tainted scope. Mem0 filters searches by the ids a call sets: a read that names the agent's own `run_id` doesn't see the tainted session's records, and one by `user_id` alone sees them all, with their stamps.
|
|
260
|
+
- **Tools that return text without metadata** can't carry the label, and the ledger can't recognize extracted text. Give them a strict rule, such as `integrity: untrusted`. In Mem0 that is `history()`, and on Mem0's hosted MCP server `list_events` and `get_event_status`.
|
|
261
|
+
- **Servers that drop or replace metadata** (when they consolidate records, or an update overwrites the metadata instead of merging it) can't carry the label either. Give their read tools a strict rule.
|
|
258
262
|
|
|
259
263
|
## How it works
|
|
260
264
|
|
package/dist/gateway.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { ApprovalBroker } from "./approvals.js";
|
|
|
5
5
|
import type { AuditSink } from "./audit.js";
|
|
6
6
|
import { type Authorizer, type Principal } from "./authorizer.js";
|
|
7
7
|
import type { InterceptorInvoker } from "./invoker.js";
|
|
8
|
-
export declare const GATEWAY_VERSION = "0.5.
|
|
8
|
+
export declare const GATEWAY_VERSION = "0.5.1";
|
|
9
9
|
/** `_meta` key on gateway-generated error results describing why a call was stopped. */
|
|
10
10
|
export declare const GATEWAY_DECISION_KEY = "adtl/gateway";
|
|
11
11
|
export interface GatewayLogger {
|
package/dist/gateway.js
CHANGED
|
@@ -35,7 +35,7 @@ import { CallToolRequestSchema, ErrorCode, GetPromptRequestSchema, ListPromptsRe
|
|
|
35
35
|
import { callBindingHash } from "@adtl/labels";
|
|
36
36
|
import { authorize } from "./authorizer.js";
|
|
37
37
|
import { TOOL_SEPARATOR } from "./config.js";
|
|
38
|
-
export const GATEWAY_VERSION = "0.5.
|
|
38
|
+
export const GATEWAY_VERSION = "0.5.1";
|
|
39
39
|
/** `_meta` key on gateway-generated error results describing why a call was stopped. */
|
|
40
40
|
export const GATEWAY_DECISION_KEY = "adtl/gateway";
|
|
41
41
|
const stderrLogger = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adtl/gateway",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Experimental: MCP gateway that labels every tool result and blocks risky tool calls using ADTL trust labels",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"url": "https://github.com/probita-ai/adtl/issues"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@adtl/interceptors": "0.5.
|
|
50
|
-
"@adtl/labels": "0.5.
|
|
51
|
-
"@adtl/ledger": "0.5.
|
|
49
|
+
"@adtl/interceptors": "0.5.1",
|
|
50
|
+
"@adtl/labels": "0.5.1",
|
|
51
|
+
"@adtl/ledger": "0.5.1",
|
|
52
52
|
"@modelcontextprotocol/sdk": "1.31.0",
|
|
53
53
|
"nodemailer": "10.0.12",
|
|
54
54
|
"yaml": "2.9.1",
|
package/src/gateway.ts
CHANGED
|
@@ -59,7 +59,7 @@ import { authorize, type AuthorizationRequest, type Authorizer, type Denial, typ
|
|
|
59
59
|
import { TOOL_SEPARATOR } from "./config.js";
|
|
60
60
|
import type { Blocked, PhaseOutcome, InterceptorInvoker } from "./invoker.js";
|
|
61
61
|
|
|
62
|
-
export const GATEWAY_VERSION = "0.5.
|
|
62
|
+
export const GATEWAY_VERSION = "0.5.1";
|
|
63
63
|
|
|
64
64
|
/** `_meta` key on gateway-generated error results describing why a call was stopped. */
|
|
65
65
|
export const GATEWAY_DECISION_KEY = "adtl/gateway";
|