managed-deepagents 0.0.3-dev.26 → 0.0.3-dev.29
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/dist/identity.d.ts +273 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +358 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime/auth.d.ts +44 -0
- package/dist/runtime/auth.d.ts.map +1 -0
- package/dist/runtime/auth.js +168 -0
- package/dist/runtime/auth.js.map +1 -0
- package/dist/runtime/credentials.d.ts +60 -0
- package/dist/runtime/credentials.d.ts.map +1 -0
- package/dist/runtime/credentials.js +189 -0
- package/dist/runtime/credentials.js.map +1 -0
- package/dist/runtime/identity-http.d.ts +8 -0
- package/dist/runtime/identity-http.d.ts.map +1 -0
- package/dist/runtime/identity-http.js +23 -0
- package/dist/runtime/identity-http.js.map +1 -0
- package/dist/runtime/identity-runtime.d.ts +54 -0
- package/dist/runtime/identity-runtime.d.ts.map +1 -0
- package/dist/runtime/identity-runtime.js +151 -0
- package/dist/runtime/identity-runtime.js.map +1 -0
- package/dist/runtime/index.d.ts +11 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +26 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/managed-middleware.d.ts +25 -0
- package/dist/runtime/managed-middleware.d.ts.map +1 -0
- package/dist/runtime/managed-middleware.js +76 -0
- package/dist/runtime/managed-middleware.js.map +1 -0
- package/dist/runtime/managed-tools.d.ts +61 -0
- package/dist/runtime/managed-tools.d.ts.map +1 -0
- package/dist/runtime/managed-tools.js +102 -0
- package/dist/runtime/managed-tools.js.map +1 -0
- package/dist/runtime/types.d.ts +18 -3
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/validated-token.d.ts +25 -0
- package/dist/runtime/validated-token.d.ts.map +1 -0
- package/dist/runtime/validated-token.js +260 -0
- package/dist/runtime/validated-token.js.map +1 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -8
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE5E,YAAY,EACV,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,OAAO,EACP,WAAW,EACX,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,OAAO,EACP,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,YAAY,GACb,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,4 +2,5 @@ export { defineDeepAgent } from "./define-deep-agent.js";
|
|
|
2
2
|
export { defineMcpServers } from "./connectors.js";
|
|
3
3
|
export { defineSchedule } from "./schedules.js";
|
|
4
4
|
export { defineSandbox } from "./sandbox.js";
|
|
5
|
+
export { defineIdentity, providers, validateIdentity } from "./identity.js";
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Auth } from "@langchain/langgraph-sdk/auth";
|
|
2
|
+
import type { IdentityConfig, IdentityDefinition } from "../identity.js";
|
|
3
|
+
/**
|
|
4
|
+
* The user object `@auth.authenticate` returns. `identity`/`permissions` satisfy
|
|
5
|
+
* the LangGraph base shape; the `mda_*` fields carry the identity envelope into
|
|
6
|
+
* `config.configurable.langgraph_auth_user` for the runtime seam.
|
|
7
|
+
*/
|
|
8
|
+
export interface ManagedUser {
|
|
9
|
+
identity: string;
|
|
10
|
+
permissions: string[];
|
|
11
|
+
mda_actor_id: string;
|
|
12
|
+
mda_tenant_id?: string;
|
|
13
|
+
mda_actor_email?: string;
|
|
14
|
+
mda_claims?: Record<string, unknown>;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build the managed LangGraph custom-auth handler from a declared identity.
|
|
19
|
+
*
|
|
20
|
+
* Handles both ingress modes: `trusted_backend` (reserved headers behind a
|
|
21
|
+
* shared ingress secret) and `validated_token` (browser-direct IdP tokens
|
|
22
|
+
* verified via JWKS / introspection / MDA-signed guest). Also registers thread
|
|
23
|
+
* and store scoping with a studio bypass.
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildManagedAuth(identity: IdentityDefinition): Auth;
|
|
26
|
+
/**
|
|
27
|
+
* Fail-closed (403) unless every identity segment the memory scope requires is
|
|
28
|
+
* present in the store `namespace`. `agent`/`none` scopes carry no per-identity
|
|
29
|
+
* restriction (shared or absent memory), so any namespace is allowed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function assertStoreAccess(cfg: IdentityConfig, user: ManagedUser, value: unknown): void;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the caller identity for `trusted_backend`: validate the shared ingress
|
|
34
|
+
* secret, then trust the reserved actor/tenant headers. Fail-closed (401) on a
|
|
35
|
+
* missing/invalid secret, a missing actor, or a missing tenant under multi.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveTrustedBackendUser(cfg: IdentityConfig, request: Request): ManagedUser;
|
|
38
|
+
/** Derive the owner value `@auth.on.threads` filters on, per the `threads` axis. */
|
|
39
|
+
export declare function threadOwnerKey(cfg: IdentityConfig, user: ManagedUser): string;
|
|
40
|
+
/** True when this deployment exposes guest issuance and the request targets it. */
|
|
41
|
+
export declare function isGuestIssuanceRequest(request: Request, cfg: IdentityConfig): boolean;
|
|
42
|
+
/** Placeholder identity so LangGraph auth middleware allows tokenless issuance. */
|
|
43
|
+
export declare function guestIssuanceBypassUser(): ManagedUser;
|
|
44
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/runtime/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EAGL,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAuBzE;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAsCnE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,OAAO,GACb,IAAI,CAuBN;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,OAAO,GACf,WAAW,CAgBb;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,CAY7E;AAuBD,mFAAmF;AACnF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,cAAc,GAClB,OAAO,CAaT;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,IAAI,WAAW,CAMrD"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Auth, HTTPException, isStudioUser, } from "@langchain/langgraph-sdk/auth";
|
|
2
|
+
import { memoryIdentitySegments } from "./identity-runtime.js";
|
|
3
|
+
import { resolveValidatedTokenUser } from "./validated-token.js";
|
|
4
|
+
/**
|
|
5
|
+
* Reserved transport for the trusted-backend ingress mode. Actor/tenant travel
|
|
6
|
+
* as reserved headers (mapped into `config.configurable` by the generated
|
|
7
|
+
* `langgraph.json` allowlist); the ingress secret is validated here and is
|
|
8
|
+
* deliberately **not** allowlisted, so it never reaches `config.configurable`.
|
|
9
|
+
*/
|
|
10
|
+
const ACTOR_HEADER = "x-mda-actor-id";
|
|
11
|
+
const TENANT_HEADER = "x-mda-tenant-id";
|
|
12
|
+
const INGRESS_SECRET_HEADER = "x-mda-ingress-secret";
|
|
13
|
+
/** Deployment env var carrying the shared secret the trusted backend presents. */
|
|
14
|
+
const INGRESS_SECRET_ENV = "MDA_INGRESS_SECRET";
|
|
15
|
+
/** Path MDA exposes for anonymous guest token issuance (must stay public). */
|
|
16
|
+
const GUEST_ISSUANCE_PATH = "/identity/guest";
|
|
17
|
+
/** Synthetic actor used only to satisfy auth middleware on the issuance route. */
|
|
18
|
+
const GUEST_ISSUER_ACTOR = "mda:guest-issuer";
|
|
19
|
+
/**
|
|
20
|
+
* Build the managed LangGraph custom-auth handler from a declared identity.
|
|
21
|
+
*
|
|
22
|
+
* Handles both ingress modes: `trusted_backend` (reserved headers behind a
|
|
23
|
+
* shared ingress secret) and `validated_token` (browser-direct IdP tokens
|
|
24
|
+
* verified via JWKS / introspection / MDA-signed guest). Also registers thread
|
|
25
|
+
* and store scoping with a studio bypass.
|
|
26
|
+
*/
|
|
27
|
+
export function buildManagedAuth(identity) {
|
|
28
|
+
const cfg = identity.config;
|
|
29
|
+
const http = cfg.ingress.http;
|
|
30
|
+
const auth = new Auth();
|
|
31
|
+
auth.authenticate(async (request) => {
|
|
32
|
+
if (isGuestIssuanceRequest(request, cfg)) {
|
|
33
|
+
return guestIssuanceBypassUser();
|
|
34
|
+
}
|
|
35
|
+
if (http === "trusted_backend") {
|
|
36
|
+
return resolveTrustedBackendUser(cfg, request);
|
|
37
|
+
}
|
|
38
|
+
return resolveValidatedTokenUser(cfg, http, request);
|
|
39
|
+
});
|
|
40
|
+
auth.on("threads", ({ user, value }) => {
|
|
41
|
+
if (isStudioUser(user)) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
const key = threadOwnerKey(cfg, user);
|
|
45
|
+
if (value && typeof value === "object") {
|
|
46
|
+
const container = value;
|
|
47
|
+
container.metadata = { ...(container.metadata ?? {}), owner: key };
|
|
48
|
+
}
|
|
49
|
+
return { owner: key };
|
|
50
|
+
});
|
|
51
|
+
// Mirror the memory namespace so raw store ops can't cross the identity
|
|
52
|
+
// boundary a run is scoped to (§5, §6.2).
|
|
53
|
+
auth.on("store", ({ user, value }) => {
|
|
54
|
+
if (isStudioUser(user)) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
assertStoreAccess(cfg, user, value);
|
|
58
|
+
return true;
|
|
59
|
+
});
|
|
60
|
+
return auth;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Fail-closed (403) unless every identity segment the memory scope requires is
|
|
64
|
+
* present in the store `namespace`. `agent`/`none` scopes carry no per-identity
|
|
65
|
+
* restriction (shared or absent memory), so any namespace is allowed.
|
|
66
|
+
*/
|
|
67
|
+
export function assertStoreAccess(cfg, user, value) {
|
|
68
|
+
const required = memoryIdentitySegments(cfg.scoping.memory, cfg.tenancy, user.mda_actor_id ? String(user.mda_actor_id) : undefined, user.mda_tenant_id ? String(user.mda_tenant_id) : undefined);
|
|
69
|
+
if (required.length === 0) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const namespace = value &&
|
|
73
|
+
typeof value === "object" &&
|
|
74
|
+
Array.isArray(value.namespace)
|
|
75
|
+
? value.namespace.map(String)
|
|
76
|
+
: [];
|
|
77
|
+
for (const segment of required) {
|
|
78
|
+
if (!namespace.includes(segment)) {
|
|
79
|
+
throw new HTTPException(403, {
|
|
80
|
+
message: "store namespace is outside the caller's identity boundary",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve the caller identity for `trusted_backend`: validate the shared ingress
|
|
87
|
+
* secret, then trust the reserved actor/tenant headers. Fail-closed (401) on a
|
|
88
|
+
* missing/invalid secret, a missing actor, or a missing tenant under multi.
|
|
89
|
+
*/
|
|
90
|
+
export function resolveTrustedBackendUser(cfg, request) {
|
|
91
|
+
requireIngressSecret(request);
|
|
92
|
+
const actor = request.headers.get(ACTOR_HEADER);
|
|
93
|
+
if (!actor) {
|
|
94
|
+
throw new HTTPException(401, { message: `missing ${ACTOR_HEADER}` });
|
|
95
|
+
}
|
|
96
|
+
const tenant = request.headers.get(TENANT_HEADER) ?? undefined;
|
|
97
|
+
assertTenantPresentIfMulti(cfg, tenant);
|
|
98
|
+
return {
|
|
99
|
+
identity: actor,
|
|
100
|
+
permissions: [],
|
|
101
|
+
mda_actor_id: actor,
|
|
102
|
+
...(tenant ? { mda_tenant_id: tenant } : {}),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/** Derive the owner value `@auth.on.threads` filters on, per the `threads` axis. */
|
|
106
|
+
export function threadOwnerKey(cfg, user) {
|
|
107
|
+
const scope = cfg.scoping.threads ?? "actor";
|
|
108
|
+
const actor = String(user.mda_actor_id ?? "");
|
|
109
|
+
const tenant = user.mda_tenant_id ? String(user.mda_tenant_id) : undefined;
|
|
110
|
+
if (scope === "tenant") {
|
|
111
|
+
return tenant ?? actor;
|
|
112
|
+
}
|
|
113
|
+
if (scope === "channel") {
|
|
114
|
+
const channel = user.mda_source_thread_id;
|
|
115
|
+
return channel ? String(channel) : actor;
|
|
116
|
+
}
|
|
117
|
+
return actor;
|
|
118
|
+
}
|
|
119
|
+
function requireIngressSecret(request) {
|
|
120
|
+
const expected = process.env[INGRESS_SECRET_ENV];
|
|
121
|
+
const provided = request.headers.get(INGRESS_SECRET_HEADER);
|
|
122
|
+
if (!expected || !provided || !constantTimeEquals(expected, provided)) {
|
|
123
|
+
throw new HTTPException(401, {
|
|
124
|
+
message: "invalid or missing ingress secret",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function assertTenantPresentIfMulti(cfg, tenant) {
|
|
129
|
+
if (cfg.tenancy === "multi" && !tenant) {
|
|
130
|
+
throw new HTTPException(401, {
|
|
131
|
+
message: "missing tenant for multi-tenant deployment",
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** True when this deployment exposes guest issuance and the request targets it. */
|
|
136
|
+
export function isGuestIssuanceRequest(request, cfg) {
|
|
137
|
+
if (request.method !== "POST") {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
const { pathname } = new URL(request.url);
|
|
141
|
+
if (pathname !== GUEST_ISSUANCE_PATH) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
const http = cfg.ingress.http;
|
|
145
|
+
if (http === "trusted_backend") {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return http.providers.some((provider) => provider.guest?.issue);
|
|
149
|
+
}
|
|
150
|
+
/** Placeholder identity so LangGraph auth middleware allows tokenless issuance. */
|
|
151
|
+
export function guestIssuanceBypassUser() {
|
|
152
|
+
return {
|
|
153
|
+
identity: GUEST_ISSUER_ACTOR,
|
|
154
|
+
permissions: [],
|
|
155
|
+
mda_actor_id: GUEST_ISSUER_ACTOR,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function constantTimeEquals(a, b) {
|
|
159
|
+
if (a.length !== b.length) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
let mismatch = 0;
|
|
163
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
164
|
+
mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
165
|
+
}
|
|
166
|
+
return mismatch === 0;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/runtime/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { CredentialTarget, IdentityConfig, ResolvedCredential, RuntimeIdentity } from "../identity.js";
|
|
2
|
+
/**
|
|
3
|
+
* Component 5 — Credentials, custom mode (`scoping.credentials: "custom"`, §7.2).
|
|
4
|
+
*
|
|
5
|
+
* The escape hatch Agent Auth can't cover: bespoke per-actor credential minting
|
|
6
|
+
* via an in-process resolver callback or a hosted token-exchange endpoint. It
|
|
7
|
+
* runs in the worker (not the shared ingress auth handler), applies the output
|
|
8
|
+
* to downstream calls, and caches per `(actor, tenant, target)` until the
|
|
9
|
+
* credential's `expiresAt`. Secrets live only in this in-memory cache keyed by
|
|
10
|
+
* identity — never in thread state or traces (§7.2, §8, identity-final §10).
|
|
11
|
+
*
|
|
12
|
+
* The managed modes (`agent`/`actor`) route to Agent Auth
|
|
13
|
+
* (`@langchain/auth`/`langchain-auth`, §7.1) and are wired separately; this
|
|
14
|
+
* module is only the custom path.
|
|
15
|
+
*/
|
|
16
|
+
/** Env var holding the HMAC secret MDA signs the endpoint assertion with. */
|
|
17
|
+
export declare const CREDENTIAL_SIGNING_SECRET_ENV = "MDA_TOKEN_EXCHANGE_SECRET";
|
|
18
|
+
/** Per-call options for {@link CredentialsProvider.for}. */
|
|
19
|
+
export interface CredentialForOptions {
|
|
20
|
+
/** Skip the cache and force a fresh mint (e.g. after a downstream 401). */
|
|
21
|
+
forceRefresh?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The per-run credential surface a tool receives as `runtime.credentials`.
|
|
25
|
+
* Tools call `runtime.credentials.for(target)` and attach the returned headers
|
|
26
|
+
* to their downstream request.
|
|
27
|
+
*/
|
|
28
|
+
export interface CredentialsProvider {
|
|
29
|
+
for(target: CredentialTarget, options?: CredentialForOptions): Promise<ResolvedCredential>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Side effects the executor depends on, injectable so resolution is
|
|
33
|
+
* deterministic under test (no real clock, network, or signing key).
|
|
34
|
+
*/
|
|
35
|
+
export interface CredentialDeps {
|
|
36
|
+
fetch: typeof fetch;
|
|
37
|
+
now: () => number;
|
|
38
|
+
/** Signs the assertion MDA presents to a hosted token-exchange endpoint. */
|
|
39
|
+
signAssertion: (identity: RuntimeIdentity, target: CredentialTarget) => Promise<string>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* TTL cache for resolved credentials, keyed by `(actor, tenant, target)` so
|
|
43
|
+
* per-repo/per-install tokens never collide. Kept out of thread state; entries
|
|
44
|
+
* expire at the credential's `expiresAt`.
|
|
45
|
+
*/
|
|
46
|
+
export declare class CredentialCache {
|
|
47
|
+
private readonly entries;
|
|
48
|
+
get(key: string, nowMs: number): ResolvedCredential | undefined;
|
|
49
|
+
set(key: string, value: ResolvedCredential): void;
|
|
50
|
+
clear(): void;
|
|
51
|
+
}
|
|
52
|
+
/** Clear the process-level credential cache. Test-only. */
|
|
53
|
+
export declare function clearCredentialCacheForTests(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Build the `runtime.credentials` provider for a run, or `undefined` when the
|
|
56
|
+
* deployment isn't in custom-credentials mode. The provider is bound to the
|
|
57
|
+
* run's resolved identity; every `for(target)` call is scoped to that actor.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createCredentialsProvider(cfg: IdentityConfig, identity: RuntimeIdentity | undefined, deps?: Partial<CredentialDeps>, cache?: CredentialCache): CredentialsProvider | undefined;
|
|
60
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/runtime/credentials.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,eAAe,EAChB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;GAaG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,6BAA6B,8BAA8B,CAAC;AAKzE,4DAA4D;AAC5D,MAAM,WAAW,oBAAoB;IACnC,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,GAAG,CACD,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,4EAA4E;IAC5E,aAAa,EAAE,CACb,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,gBAAgB,KACrB,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAQD;;;;GAIG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IAEzD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAY/D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IASjD,KAAK,IAAI,IAAI;CAGd;AAKD,2DAA2D;AAC3D,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,cAAc,EACnB,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,IAAI,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,EAC9B,KAAK,GAAE,eAA8B,GACpC,mBAAmB,GAAG,SAAS,CA8BjC"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { SignJWT } from "jose";
|
|
2
|
+
/**
|
|
3
|
+
* Component 5 — Credentials, custom mode (`scoping.credentials: "custom"`, §7.2).
|
|
4
|
+
*
|
|
5
|
+
* The escape hatch Agent Auth can't cover: bespoke per-actor credential minting
|
|
6
|
+
* via an in-process resolver callback or a hosted token-exchange endpoint. It
|
|
7
|
+
* runs in the worker (not the shared ingress auth handler), applies the output
|
|
8
|
+
* to downstream calls, and caches per `(actor, tenant, target)` until the
|
|
9
|
+
* credential's `expiresAt`. Secrets live only in this in-memory cache keyed by
|
|
10
|
+
* identity — never in thread state or traces (§7.2, §8, identity-final §10).
|
|
11
|
+
*
|
|
12
|
+
* The managed modes (`agent`/`actor`) route to Agent Auth
|
|
13
|
+
* (`@langchain/auth`/`langchain-auth`, §7.1) and are wired separately; this
|
|
14
|
+
* module is only the custom path.
|
|
15
|
+
*/
|
|
16
|
+
/** Env var holding the HMAC secret MDA signs the endpoint assertion with. */
|
|
17
|
+
export const CREDENTIAL_SIGNING_SECRET_ENV = "MDA_TOKEN_EXCHANGE_SECRET";
|
|
18
|
+
/** How long a signed endpoint assertion is valid, in seconds. */
|
|
19
|
+
const ASSERTION_TTL_SECONDS = 60;
|
|
20
|
+
/**
|
|
21
|
+
* TTL cache for resolved credentials, keyed by `(actor, tenant, target)` so
|
|
22
|
+
* per-repo/per-install tokens never collide. Kept out of thread state; entries
|
|
23
|
+
* expire at the credential's `expiresAt`.
|
|
24
|
+
*/
|
|
25
|
+
export class CredentialCache {
|
|
26
|
+
entries = new Map();
|
|
27
|
+
get(key, nowMs) {
|
|
28
|
+
const hit = this.entries.get(key);
|
|
29
|
+
if (!hit) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
if (hit.expiresAtMs !== undefined && nowMs >= hit.expiresAtMs) {
|
|
33
|
+
this.entries.delete(key);
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
return hit.value;
|
|
37
|
+
}
|
|
38
|
+
set(key, value) {
|
|
39
|
+
let expiresAtMs;
|
|
40
|
+
if (value.expiresAt) {
|
|
41
|
+
const parsed = Date.parse(value.expiresAt);
|
|
42
|
+
expiresAtMs = Number.isNaN(parsed) ? undefined : parsed;
|
|
43
|
+
}
|
|
44
|
+
this.entries.set(key, { value, expiresAtMs });
|
|
45
|
+
}
|
|
46
|
+
clear() {
|
|
47
|
+
this.entries.clear();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Process-level cache shared across runs for the lifetime of the deployment. */
|
|
51
|
+
const defaultCache = new CredentialCache();
|
|
52
|
+
/** Clear the process-level credential cache. Test-only. */
|
|
53
|
+
export function clearCredentialCacheForTests() {
|
|
54
|
+
defaultCache.clear();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Build the `runtime.credentials` provider for a run, or `undefined` when the
|
|
58
|
+
* deployment isn't in custom-credentials mode. The provider is bound to the
|
|
59
|
+
* run's resolved identity; every `for(target)` call is scoped to that actor.
|
|
60
|
+
*/
|
|
61
|
+
export function createCredentialsProvider(cfg, identity, deps, cache = defaultCache) {
|
|
62
|
+
if (cfg.scoping.credentials !== "custom" || !cfg.credentials) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
const resolved = {
|
|
66
|
+
fetch: deps?.fetch ?? fetch,
|
|
67
|
+
now: deps?.now ?? (() => Date.now()),
|
|
68
|
+
signAssertion: deps?.signAssertion ?? defaultSignAssertion,
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
async for(target, options) {
|
|
72
|
+
if (!identity) {
|
|
73
|
+
throw new Error("runtime.credentials.for(...) requires a resolved identity, but none " +
|
|
74
|
+
"was available for this run.");
|
|
75
|
+
}
|
|
76
|
+
const key = cacheKey(identity, target);
|
|
77
|
+
if (!options?.forceRefresh) {
|
|
78
|
+
const hit = cache.get(key, resolved.now());
|
|
79
|
+
if (hit) {
|
|
80
|
+
return hit;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Fail-closed: a resolver/endpoint error propagates and nothing is cached.
|
|
84
|
+
const out = await resolveCredential(cfg, identity, target, resolved);
|
|
85
|
+
cache.set(key, out);
|
|
86
|
+
return out;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
async function resolveCredential(cfg, identity, target, deps) {
|
|
91
|
+
const creds = cfg.credentials;
|
|
92
|
+
if (!creds) {
|
|
93
|
+
throw new Error("No credentials resolver is configured for this deployment.");
|
|
94
|
+
}
|
|
95
|
+
if ("resolve" in creds) {
|
|
96
|
+
const out = await creds.resolve({ identity, target });
|
|
97
|
+
return normalizeResolved(out, "resolver");
|
|
98
|
+
}
|
|
99
|
+
const assertion = await deps.signAssertion(identity, target);
|
|
100
|
+
return callTokenExchange(creds.endpoint.url, assertion, deps);
|
|
101
|
+
}
|
|
102
|
+
async function callTokenExchange(url, assertion, deps) {
|
|
103
|
+
const response = await deps.fetch(url, {
|
|
104
|
+
method: "POST",
|
|
105
|
+
headers: {
|
|
106
|
+
"content-type": "application/json",
|
|
107
|
+
authorization: `Bearer ${assertion}`,
|
|
108
|
+
},
|
|
109
|
+
body: JSON.stringify({ assertion }),
|
|
110
|
+
});
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
throw new Error(`Credential token-exchange endpoint ${url} responded ${response.status}.`);
|
|
113
|
+
}
|
|
114
|
+
return normalizeResolved(await response.json(), `endpoint ${url}`);
|
|
115
|
+
}
|
|
116
|
+
async function defaultSignAssertion(identity, target) {
|
|
117
|
+
const secret = process.env[CREDENTIAL_SIGNING_SECRET_ENV];
|
|
118
|
+
if (!secret) {
|
|
119
|
+
throw new Error(`A hosted credential endpoint requires a signing secret. Set ` +
|
|
120
|
+
`${CREDENTIAL_SIGNING_SECRET_ENV} in the deployment environment.`);
|
|
121
|
+
}
|
|
122
|
+
const issuedAt = Math.floor(Date.now() / 1000);
|
|
123
|
+
return new SignJWT({
|
|
124
|
+
actor_id: identity.actor.id,
|
|
125
|
+
actor_type: identity.actor.type,
|
|
126
|
+
tenant_id: identity.tenant?.id,
|
|
127
|
+
target: { kind: target.kind, name: target.name, intent: target.intent },
|
|
128
|
+
})
|
|
129
|
+
.setProtectedHeader({ alg: "HS256" })
|
|
130
|
+
.setSubject(identity.actor.id)
|
|
131
|
+
.setIssuedAt(issuedAt)
|
|
132
|
+
.setExpirationTime(issuedAt + ASSERTION_TTL_SECONDS)
|
|
133
|
+
.sign(new TextEncoder().encode(secret));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The cache key that discriminates a minted credential: the actor + tenant it
|
|
137
|
+
* belongs to, plus the target's kind/name/intent/thread and metadata (§7.2).
|
|
138
|
+
*/
|
|
139
|
+
function cacheKey(identity, target) {
|
|
140
|
+
return stableStringify([
|
|
141
|
+
identity.actor.id,
|
|
142
|
+
identity.tenant?.id ?? null,
|
|
143
|
+
target.kind,
|
|
144
|
+
target.name,
|
|
145
|
+
target.intent ?? null,
|
|
146
|
+
target.threadId ?? null,
|
|
147
|
+
target.metadata ?? null,
|
|
148
|
+
]);
|
|
149
|
+
}
|
|
150
|
+
/** Deterministic JSON with object keys sorted, so the cache key is stable. */
|
|
151
|
+
function stableStringify(value) {
|
|
152
|
+
if (value === null || typeof value !== "object") {
|
|
153
|
+
return JSON.stringify(value) ?? "null";
|
|
154
|
+
}
|
|
155
|
+
if (Array.isArray(value)) {
|
|
156
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
157
|
+
}
|
|
158
|
+
const obj = value;
|
|
159
|
+
return `{${Object.keys(obj)
|
|
160
|
+
.sort()
|
|
161
|
+
.map((key) => `${JSON.stringify(key)}:${stableStringify(obj[key])}`)
|
|
162
|
+
.join(",")}}`;
|
|
163
|
+
}
|
|
164
|
+
/** Validate a resolver/endpoint result into a {@link ResolvedCredential}. */
|
|
165
|
+
function normalizeResolved(value, sourceLabel) {
|
|
166
|
+
if (!value || typeof value !== "object") {
|
|
167
|
+
throw new Error(`Credential ${sourceLabel} returned a non-object result.`);
|
|
168
|
+
}
|
|
169
|
+
const { headers, expiresAt } = value;
|
|
170
|
+
if (!headers || typeof headers !== "object" || Array.isArray(headers)) {
|
|
171
|
+
throw new Error(`Credential ${sourceLabel} result is missing a headers object.`);
|
|
172
|
+
}
|
|
173
|
+
const normalizedHeaders = {};
|
|
174
|
+
for (const [name, headerValue] of Object.entries(headers)) {
|
|
175
|
+
if (typeof headerValue !== "string") {
|
|
176
|
+
throw new Error(`Credential ${sourceLabel} header "${name}" must be a string.`);
|
|
177
|
+
}
|
|
178
|
+
normalizedHeaders[name] = headerValue;
|
|
179
|
+
}
|
|
180
|
+
const result = { headers: normalizedHeaders };
|
|
181
|
+
if (expiresAt !== undefined) {
|
|
182
|
+
if (typeof expiresAt !== "string") {
|
|
183
|
+
throw new Error(`Credential ${sourceLabel} \`expiresAt\` must be an ISO string.`);
|
|
184
|
+
}
|
|
185
|
+
result.expiresAt = expiresAt;
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/runtime/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import type { IdentityDefinition } from "../identity.js";
|
|
3
|
+
/**
|
|
4
|
+
* Build the managed identity HTTP app (guest issuance, etc.) from a declared
|
|
5
|
+
* identity. Mounted via `langgraph.json` `http.app` when identity is enabled.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildManagedIdentityApp(identity: IdentityDefinition): Hono;
|
|
8
|
+
//# sourceMappingURL=identity-http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-http.d.ts","sourceRoot":"","sources":["../../src/runtime/identity-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGzD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAoB1E"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { issueGuestToken } from "./validated-token.js";
|
|
3
|
+
/**
|
|
4
|
+
* Build the managed identity HTTP app (guest issuance, etc.) from a declared
|
|
5
|
+
* identity. Mounted via `langgraph.json` `http.app` when identity is enabled.
|
|
6
|
+
*/
|
|
7
|
+
export function buildManagedIdentityApp(identity) {
|
|
8
|
+
const app = new Hono();
|
|
9
|
+
const http = identity.config.ingress.http;
|
|
10
|
+
if (http === "trusted_backend") {
|
|
11
|
+
return app;
|
|
12
|
+
}
|
|
13
|
+
const guestProvider = http.providers.find((provider) => provider.guest?.issue);
|
|
14
|
+
if (!guestProvider) {
|
|
15
|
+
return app;
|
|
16
|
+
}
|
|
17
|
+
app.post("/identity/guest", async (c) => {
|
|
18
|
+
const token = await issueGuestToken(guestProvider);
|
|
19
|
+
return c.json({ token });
|
|
20
|
+
});
|
|
21
|
+
return app;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=identity-http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-http.js","sourceRoot":"","sources":["../../src/runtime/identity-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAA4B;IAClE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1C,IAAI,IAAI,KAAK,iBAAiB,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CACvC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CACpC,CAAC;IACF,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACtC,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACnD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { IdentityConfig, MemoryScope, RuntimeIdentity, Tenancy } from "../identity.js";
|
|
2
|
+
import type { ConfigurableCarrier } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the LangGraph `configurable` bag from either a flat runtime or the
|
|
5
|
+
* nested `ToolRuntime` shape LangChain passes to tools (`runtime.config.configurable`).
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveRuntimeConfigurable(runtime: RuntimeConfigLike | undefined): Record<string, unknown> | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Build the frozen identity envelope for the current run from the trusted
|
|
10
|
+
* `langgraph_auth_user` the custom-auth handler produced (§6.1). Returns
|
|
11
|
+
* `undefined` when the deployment has no resolvable actor (identity is opt-in).
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildRuntimeIdentity(configurable: Record<string, unknown> | undefined): RuntimeIdentity | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* The durable Store namespace for the run, per `scoping.memory` (§6.2). A
|
|
16
|
+
* `deploymentId` prefix isolates deployments; identity segments follow. Returns
|
|
17
|
+
* `undefined` for `none` (no durable memory). Fail-closed: an `actor` scope with
|
|
18
|
+
* no actor already rejects at ingress, so the segments are never empty here.
|
|
19
|
+
*/
|
|
20
|
+
export declare function memoryNamespace(cfg: IdentityConfig, ident: RuntimeIdentity, deploymentId: string): string[] | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* The runtime the managed seam sees: the shared `configurable` carrier, plus the
|
|
23
|
+
* optional nested `config` (e.g. LangGraph `ToolRuntime.config`) and the frozen
|
|
24
|
+
* `identity` envelope the seam layers on. Single source for the tool, middleware,
|
|
25
|
+
* and memory-namespace helpers.
|
|
26
|
+
*/
|
|
27
|
+
export interface RuntimeConfigLike extends ConfigurableCarrier {
|
|
28
|
+
identity?: RuntimeIdentity;
|
|
29
|
+
config?: {
|
|
30
|
+
configurable?: Record<string, unknown>;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the durable memory namespace for a run directly from the runtime the
|
|
35
|
+
* memory `StoreBackend` receives, per `scoping.memory` (§6.2). This is the
|
|
36
|
+
* plug-in point for the (deferred) Store-backed memory: a `StoreBackend`
|
|
37
|
+
* namespace factory becomes `(ctx) => memoryNamespaceFor(ctx.runtime, cfg, id)`.
|
|
38
|
+
* Returns `undefined` when the run has no durable namespace (`none`, or a
|
|
39
|
+
* per-actor scope with no resolved actor).
|
|
40
|
+
*/
|
|
41
|
+
export declare function memoryNamespaceFor(runtime: RuntimeConfigLike | undefined, cfg: IdentityConfig, deploymentId: string): string[] | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* The identity portion of the memory namespace (no deployment prefix), shared by
|
|
44
|
+
* the memory `StoreBackend` and the `@auth.on.store` boundary check so both agree
|
|
45
|
+
* on exactly which segments identify a namespace.
|
|
46
|
+
*/
|
|
47
|
+
export declare function memoryIdentitySegments(scope: MemoryScope, tenancy: Tenancy, actorId: string | undefined, tenantId: string | undefined): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Strip client-supplied identity keys from an incoming `configurable` so a
|
|
50
|
+
* request body can never spoof the actor/tenant the handler resolved (§8). The
|
|
51
|
+
* platform-set `langgraph_auth_user` is preserved — it is the only trusted source.
|
|
52
|
+
*/
|
|
53
|
+
export declare function sanitizeConfigurable(configurable: Record<string, unknown> | undefined): Record<string, unknown>;
|
|
54
|
+
//# sourceMappingURL=identity-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/identity-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,eAAe,EACf,OAAO,EACR,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AA0BtD;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GACrC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAErC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAChD,eAAe,GAAG,SAAS,CAyB7B;AAaD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,eAAe,EACtB,YAAY,EAAE,MAAM,GACnB,MAAM,EAAE,GAAG,SAAS,CAiBtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,MAAM,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;CACrD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,GAAG,EAAE,cAAc,EACnB,YAAY,EAAE,MAAM,GACnB,MAAM,EAAE,GAAG,SAAS,CAQtB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,MAAM,EAAE,CAgBV;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB"}
|