@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 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, replacing anything the agent put there.
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
- - A server that drops or rewrites metadata (for example when it consolidates records) can't carry the label. Give its read tools a strict rule, such as `integrity: untrusted`, once in the config.
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.0";
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.0";
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.0",
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.0",
50
- "@adtl/labels": "0.5.0",
51
- "@adtl/ledger": "0.5.0",
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.0";
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";