managed-deepagents 0.5.0-dev.90 → 0.5.0-dev.97
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 +36 -37
- package/dist/channels/manifest.d.ts +1 -1
- package/dist/channels/manifest.d.ts.map +1 -1
- package/dist/channels/slack/adapter.d.ts.map +1 -1
- package/dist/channels/slack/adapter.js +0 -1
- package/dist/channels/slack/adapter.js.map +1 -1
- package/dist/channels/slack/http.d.ts +3 -1
- package/dist/channels/slack/http.d.ts.map +1 -1
- package/dist/channels/slack/http.js +40 -5
- package/dist/channels/slack/http.js.map +1 -1
- package/dist/channels/slack/index.d.ts +23 -8
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +32 -29
- package/dist/channels/slack/index.js.map +1 -1
- package/dist/channels/slack/normalize.d.ts +4 -1
- package/dist/channels/slack/normalize.d.ts.map +1 -1
- package/dist/channels/slack/normalize.js +46 -10
- package/dist/channels/slack/normalize.js.map +1 -1
- package/dist/channels/store.d.ts +14 -0
- package/dist/channels/store.d.ts.map +1 -1
- package/dist/channels/store.js +41 -27
- package/dist/channels/store.js.map +1 -1
- package/dist/define-deep-agent.d.ts.map +1 -1
- package/dist/define-deep-agent.js +9 -3
- package/dist/define-deep-agent.js.map +1 -1
- package/dist/extension.d.ts +6 -14
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +5 -24
- package/dist/extension.js.map +1 -1
- package/dist/identity/github/connect-http.d.ts +1 -2
- package/dist/identity/github/connect-http.d.ts.map +1 -1
- package/dist/identity/github/connect-http.js +5 -8
- package/dist/identity/github/connect-http.js.map +1 -1
- package/dist/identity/github/credentials-store.d.ts.map +1 -1
- package/dist/identity/github/credentials-store.js +26 -10
- package/dist/identity/github/credentials-store.js.map +1 -1
- package/dist/identity/index.d.ts +15 -71
- package/dist/identity/index.d.ts.map +1 -1
- package/dist/identity/index.js +30 -223
- package/dist/identity/index.js.map +1 -1
- package/dist/identity/oauth-env.d.ts +4 -3
- package/dist/identity/oauth-env.d.ts.map +1 -1
- package/dist/identity/oauth-env.js +4 -3
- package/dist/identity/oauth-env.js.map +1 -1
- package/dist/identity/options.d.ts +12 -71
- package/dist/identity/options.d.ts.map +1 -1
- package/dist/identity/options.js +38 -112
- package/dist/identity/options.js.map +1 -1
- package/dist/identity/slack/links.d.ts +1 -1
- package/dist/identity/slack/links.d.ts.map +1 -1
- package/dist/identity/slack/links.js +27 -11
- package/dist/identity/slack/links.js.map +1 -1
- package/dist/identity/types.d.ts +11 -42
- package/dist/identity/types.d.ts.map +1 -1
- package/dist/index.d.ts +7 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/ingress/index.d.ts.map +1 -1
- package/dist/ingress/index.js +26 -10
- package/dist/ingress/index.js.map +1 -1
- package/dist/memory/define-memory.d.ts +39 -0
- package/dist/memory/define-memory.d.ts.map +1 -0
- package/dist/memory/define-memory.js +78 -0
- package/dist/memory/define-memory.js.map +1 -0
- package/dist/memory/index.d.ts +9 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +8 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/instructions-middleware.d.ts +74 -0
- package/dist/memory/instructions-middleware.d.ts.map +1 -0
- package/dist/memory/instructions-middleware.js +115 -0
- package/dist/memory/instructions-middleware.js.map +1 -0
- package/dist/memory/slices.d.ts +21 -0
- package/dist/memory/slices.d.ts.map +1 -0
- package/dist/memory/slices.js +61 -0
- package/dist/memory/slices.js.map +1 -0
- package/dist/memory/types.d.ts +71 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +10 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/namespaces.d.ts +3 -9
- package/dist/namespaces.d.ts.map +1 -1
- package/dist/namespaces.js +2 -19
- package/dist/namespaces.js.map +1 -1
- package/dist/runtime/auth.d.ts +30 -18
- package/dist/runtime/auth.d.ts.map +1 -1
- package/dist/runtime/auth.js +179 -65
- package/dist/runtime/auth.js.map +1 -1
- package/dist/runtime/identity-http.d.ts +1 -3
- package/dist/runtime/identity-http.d.ts.map +1 -1
- package/dist/runtime/identity-http.js +23 -40
- package/dist/runtime/identity-http.js.map +1 -1
- package/dist/runtime/identity-runtime.d.ts +0 -18
- package/dist/runtime/identity-runtime.d.ts.map +1 -1
- package/dist/runtime/identity-runtime.js +0 -27
- package/dist/runtime/identity-runtime.js.map +1 -1
- package/dist/runtime/index.d.ts +2 -3
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +29 -31
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/memory/index.d.ts +0 -3
- package/dist/runtime/memory/index.d.ts.map +1 -1
- package/dist/runtime/memory/index.js +0 -3
- package/dist/runtime/memory/index.js.map +1 -1
- package/dist/runtime/memory/mounts.d.ts +2 -10
- package/dist/runtime/memory/mounts.d.ts.map +1 -1
- package/dist/runtime/memory/mounts.js +3 -11
- package/dist/runtime/memory/mounts.js.map +1 -1
- package/dist/runtime/sandbox-manager.d.ts +5 -0
- package/dist/runtime/sandbox-manager.d.ts.map +1 -1
- package/dist/runtime/sandbox-manager.js +18 -13
- package/dist/runtime/sandbox-manager.js.map +1 -1
- package/dist/runtime/types.d.ts +8 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/validated-token.d.ts +7 -12
- package/dist/runtime/validated-token.d.ts.map +1 -1
- package/dist/runtime/validated-token.js +10 -66
- package/dist/runtime/validated-token.js.map +1 -1
- package/dist/sandbox.d.ts +16 -38
- package/dist/sandbox.d.ts.map +1 -1
- package/dist/sandbox.js +9 -16
- package/dist/sandbox.js.map +1 -1
- package/dist/types.d.ts +4 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -8
- package/dist/identity/memory-slices.d.ts +0 -21
- package/dist/identity/memory-slices.d.ts.map +0 -1
- package/dist/identity/memory-slices.js +0 -105
- package/dist/identity/memory-slices.js.map +0 -1
- package/dist/runtime/memory/lazy-context-backend.d.ts +0 -74
- package/dist/runtime/memory/lazy-context-backend.d.ts.map +0 -1
- package/dist/runtime/memory/lazy-context-backend.js +0 -166
- package/dist/runtime/memory/lazy-context-backend.js.map +0 -1
- package/dist/runtime/memory/seed.d.ts +0 -30
- package/dist/runtime/memory/seed.d.ts.map +0 -1
- package/dist/runtime/memory/seed.js +0 -199
- package/dist/runtime/memory/seed.js.map +0 -1
- package/dist/runtime/memory/user-repo.d.ts +0 -18
- package/dist/runtime/memory/user-repo.d.ts.map +0 -1
- package/dist/runtime/memory/user-repo.js +0 -50
- package/dist/runtime/memory/user-repo.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
package/dist/namespaces.d.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* and providers can be added without growing the barrel:
|
|
7
7
|
*
|
|
8
8
|
* ```ts
|
|
9
|
-
* channels.slack(
|
|
9
|
+
* channels.slack();
|
|
10
10
|
* connectors.slack({ includeTools: ["slack_list_channels"] });
|
|
11
|
-
*
|
|
11
|
+
* defineSandbox({ defaultTimeout: 600 });
|
|
12
12
|
* auth.supabase({ projectRef: "abc" });
|
|
13
13
|
* credentials.github({ read: ["user"] });
|
|
14
14
|
* connect.github();
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
* These are the only primitives the managed runtime will mount. A project
|
|
22
22
|
* cannot contribute its own — `defineExtension` stays internal.
|
|
23
23
|
*/
|
|
24
|
-
import { LangSmithSandbox } from "deepagents";
|
|
25
24
|
import { type MarketplaceConnectors } from "./connectors/marketplace/index.js";
|
|
26
25
|
import { mcpConnector } from "./connectors/mcp/index.js";
|
|
27
26
|
import { slackChannel } from "./channels/slack/index.js";
|
|
@@ -35,12 +34,7 @@ import { connect as linkedinConnect } from "./identity/linkedin/connect-http.js"
|
|
|
35
34
|
import { connect as microsoftConnect } from "./identity/microsoft/connect-http.js";
|
|
36
35
|
import { connect as slackConnect } from "./identity/slack/connect-http.js";
|
|
37
36
|
import { connect as xConnect } from "./identity/x/connect-http.js";
|
|
38
|
-
import { type LangSmithSandboxOptions, type SandboxDefinition } from "./sandbox.js";
|
|
39
37
|
export { auth } from "./identity/index.js";
|
|
40
|
-
/** Execution environments the agent's shell runs in. Exported from `sandbox/`. */
|
|
41
|
-
export declare const sandboxes: {
|
|
42
|
-
langsmith(options?: LangSmithSandboxOptions): SandboxDefinition<typeof LangSmithSandbox>;
|
|
43
|
-
};
|
|
44
38
|
/**
|
|
45
39
|
* Integrations: tools, HTTP routes, sandbox provisioning, inbound events, and
|
|
46
40
|
* named messaging. Exported from `connectors/*`.
|
|
@@ -115,7 +109,7 @@ export interface Channels {
|
|
|
115
109
|
*
|
|
116
110
|
* @example
|
|
117
111
|
* ```ts
|
|
118
|
-
* export const channel = channels.slack(
|
|
112
|
+
* export const channel = channels.slack();
|
|
119
113
|
* ```
|
|
120
114
|
*
|
|
121
115
|
* @see {@link slackChannel}
|
package/dist/namespaces.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"namespaces.d.ts","sourceRoot":"","sources":["../src/namespaces.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"namespaces.d.ts","sourceRoot":"","sources":["../src/namespaces.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,WAAW,IAAI,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACpF,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,UACf,SAAQ,oBAAoB,EAAE,qBAAqB;IACnD;;;;;;;;;;;;;;OAcG;IACH,GAAG,EAAE,OAAO,YAAY,CAAC;IAEzB;;;;;;;;;;;;;;OAcG;IACH,KAAK,EAAE,OAAO,cAAc,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,UAKxB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;;;;;;;;OAYG;IACH,KAAK,EAAE,OAAO,YAAY,CAAC;CAC5B;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,QAEtB,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,WAAW;IACtB,MAAM;CACP,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,OAAQ,SAAQ,kBAAkB;IACjD;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,EAAE,OAAO,aAAa,CAAC;IAE7B;;;;;;;;;;;;;;OAcG;IACH,MAAM,EAAE,OAAO,aAAa,CAAC;IAE7B;;;;;;;;;;;;;OAaG;IACH,SAAS,EAAE,OAAO,gBAAgB,CAAC;IAEnC;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,OAAO,eAAe,CAAC;IAEjC;;;;;;;;;;;;;OAaG;IACH,CAAC,EAAE,OAAO,QAAQ,CAAC;IAEnB;;;;;;;;;;;;;;;OAeG;IACH,KAAK,EAAE,OAAO,YAAY,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,OAAO,EAAE,OAQrB,CAAC"}
|
package/dist/namespaces.js
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* and providers can be added without growing the barrel:
|
|
7
7
|
*
|
|
8
8
|
* ```ts
|
|
9
|
-
* channels.slack(
|
|
9
|
+
* channels.slack();
|
|
10
10
|
* connectors.slack({ includeTools: ["slack_list_channels"] });
|
|
11
|
-
*
|
|
11
|
+
* defineSandbox({ defaultTimeout: 600 });
|
|
12
12
|
* auth.supabase({ projectRef: "abc" });
|
|
13
13
|
* credentials.github({ read: ["user"] });
|
|
14
14
|
* connect.github();
|
|
@@ -21,13 +21,11 @@
|
|
|
21
21
|
* These are the only primitives the managed runtime will mount. A project
|
|
22
22
|
* cannot contribute its own — `defineExtension` stays internal.
|
|
23
23
|
*/
|
|
24
|
-
import { LangSmithSandbox } from "deepagents";
|
|
25
24
|
import { marketplaceConnectors, } from "./connectors/marketplace/index.js";
|
|
26
25
|
import { mcpConnector } from "./connectors/mcp/index.js";
|
|
27
26
|
import { slackChannel } from "./channels/slack/index.js";
|
|
28
27
|
import { slackConnector } from "./connectors/slack/index.js";
|
|
29
28
|
import { toolServerConnectors, } from "./connectors/toolserver/index.js";
|
|
30
|
-
import { defineExtension } from "./extension.js";
|
|
31
29
|
import { connect as githubConnect } from "./identity/github/connect-http.js";
|
|
32
30
|
import { credentials as githubCredentials } from "./identity/github/credentials.js";
|
|
33
31
|
import { connect as googleConnect } from "./identity/google/connect-http.js";
|
|
@@ -36,22 +34,7 @@ import { connect as linkedinConnect } from "./identity/linkedin/connect-http.js"
|
|
|
36
34
|
import { connect as microsoftConnect } from "./identity/microsoft/connect-http.js";
|
|
37
35
|
import { connect as slackConnect } from "./identity/slack/connect-http.js";
|
|
38
36
|
import { connect as xConnect } from "./identity/x/connect-http.js";
|
|
39
|
-
import {} from "./sandbox.js";
|
|
40
37
|
export { auth } from "./identity/index.js";
|
|
41
|
-
const langsmithSandbox = defineExtension("sandbox", {
|
|
42
|
-
label: "sandboxes.langsmith",
|
|
43
|
-
provider: LangSmithSandbox,
|
|
44
|
-
// Not a schema: a sandbox's options are inferred from the provider class's
|
|
45
|
-
// own `create(...)` types, so a hand-written one would restate deepagents'
|
|
46
|
-
// surface and drift from it.
|
|
47
|
-
args: (options) => options ?? {},
|
|
48
|
-
});
|
|
49
|
-
/** Execution environments the agent's shell runs in. Exported from `sandbox/`. */
|
|
50
|
-
export const sandboxes = {
|
|
51
|
-
langsmith(options) {
|
|
52
|
-
return langsmithSandbox(options);
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
38
|
/**
|
|
56
39
|
* Integrations: tools, HTTP routes, sandbox provisioning, inbound events, and
|
|
57
40
|
* named messaging. Exported from `connectors/*`.
|
package/dist/namespaces.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"namespaces.js","sourceRoot":"","sources":["../src/namespaces.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"namespaces.js","sourceRoot":"","sources":["../src/namespaces.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EACL,qBAAqB,GAEtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACL,oBAAoB,GAErB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAAE,WAAW,IAAI,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACpF,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EACL,kBAAkB,GAEnB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAuD3C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAe;IACpC,GAAG,oBAAoB;IACvB,GAAG,qBAAqB;IACxB,GAAG,EAAE,YAAY;IACjB,KAAK,EAAE,cAAc;CACtB,CAAC;AAyBF;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAa;IAChC,KAAK,EAAE,YAAY;CACpB,CAAC;AAEF,oFAAoF;AACpF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,iBAAiB;CAC1B,CAAC;AAgHF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,GAAG,kBAAkB;IACrB,MAAM,EAAE,aAAa;IACrB,MAAM,EAAE,aAAa;IACrB,SAAS,EAAE,gBAAgB;IAC3B,QAAQ,EAAE,eAAe;IACzB,CAAC,EAAE,QAAQ;IACX,KAAK,EAAE,YAAY;CACpB,CAAC"}
|
package/dist/runtime/auth.d.ts
CHANGED
|
@@ -8,18 +8,24 @@ import { type IdentityConfig, type IdentityDefinition, type RuntimeIdentity } fr
|
|
|
8
8
|
*/
|
|
9
9
|
/** Trusted-backend / channel-loopback identity headers (single source of truth). */
|
|
10
10
|
export declare const USER_HEADER = "x-mda-user-id";
|
|
11
|
-
/** Comma- or space-delimited group memberships. */
|
|
12
|
-
export declare const GROUPS_HEADER = "x-mda-groups";
|
|
13
11
|
export declare const INGRESS_SECRET_HEADER = "x-mda-ingress-secret";
|
|
14
12
|
/**
|
|
15
|
-
* Internal channel handoff headers. Accepted only after
|
|
16
|
-
* validates — never part of the public HTTP identity
|
|
17
|
-
* not allowlisted into `config.configurable`.
|
|
13
|
+
* Internal channel handoff headers. Accepted only after a server API key or
|
|
14
|
+
* legacy ingress secret validates — never part of the public HTTP identity
|
|
15
|
+
* surface, and deliberately not allowlisted into `config.configurable`.
|
|
18
16
|
*/
|
|
19
17
|
export declare const SOURCE_PROVIDER_HEADER = "x-mda-source-provider";
|
|
20
18
|
export declare const SOURCE_THREAD_HEADER = "x-mda-source-thread-id";
|
|
21
19
|
/** Deployment env var carrying the shared secret the trusted backend presents. */
|
|
22
20
|
export declare const INGRESS_SECRET_ENV = "MDA_INGRESS_SECRET";
|
|
21
|
+
/** Deploy/dev-owned credential used only for internal identity handoffs. */
|
|
22
|
+
export declare const HANDOFF_SECRET_ENV = "MDA_HANDOFF_SECRET";
|
|
23
|
+
export declare const HANDOFF_SECRET_HEADER = "x-mda-handoff-secret";
|
|
24
|
+
/** Platform-owned LangSmith auth configuration. */
|
|
25
|
+
export declare const LANGSMITH_AUTH_ENDPOINT_ENV = "LANGSMITH_AUTH_ENDPOINT";
|
|
26
|
+
export declare const LANGSMITH_TENANT_ID_ENV = "LANGSMITH_TENANT_ID";
|
|
27
|
+
export declare const LANGSMITH_API_KEY_HEADER = "x-api-key";
|
|
28
|
+
export declare const LANGSMITH_API_KEY_ENV = "LANGSMITH_API_KEY";
|
|
23
29
|
/**
|
|
24
30
|
* The user object `@auth.authenticate` returns. `identity`/`permissions` satisfy
|
|
25
31
|
* the LangGraph base shape; the `mda_*` fields carry the identity envelope into
|
|
@@ -30,7 +36,7 @@ export interface ManagedUser {
|
|
|
30
36
|
permissions: string[];
|
|
31
37
|
mda_user_id: string;
|
|
32
38
|
mda_user_email?: string;
|
|
33
|
-
/**
|
|
39
|
+
/** Resolved group memberships; read-only, never an isolation key. */
|
|
34
40
|
mda_groups?: string[];
|
|
35
41
|
mda_claims?: Record<string, unknown>;
|
|
36
42
|
/** Trusted source provider stamped by managed ingress (never client-supplied). */
|
|
@@ -42,10 +48,8 @@ export interface ManagedUser {
|
|
|
42
48
|
/**
|
|
43
49
|
* Build the managed LangGraph custom-auth handler from a declared identity.
|
|
44
50
|
*
|
|
45
|
-
* Handles
|
|
46
|
-
*
|
|
47
|
-
* verified via JWKS / introspection / MDA-signed guest). Also registers thread
|
|
48
|
-
* and store scoping with a studio bypass.
|
|
51
|
+
* Handles trusted-backend, LangSmith API-key, and validated-token ingress.
|
|
52
|
+
* Also registers thread and store scoping with a studio bypass.
|
|
49
53
|
*/
|
|
50
54
|
export declare function buildManagedAuth(identity: IdentityDefinition): Auth;
|
|
51
55
|
/**
|
|
@@ -72,11 +76,19 @@ export declare const GITHUB_CREDENTIALS_STORE_PREFIX = "mda_github_credentials";
|
|
|
72
76
|
*/
|
|
73
77
|
export declare const IDENTITY_LINKS_SERVICE_USER = "mda:identity-links";
|
|
74
78
|
/**
|
|
75
|
-
* Fail-closed (403)
|
|
76
|
-
*
|
|
77
|
-
*
|
|
79
|
+
* Fail-closed (403) on the managed reserved namespaces.
|
|
80
|
+
*
|
|
81
|
+
* `mda_identity_links` and `mda_github_credentials` are deployment-wide managed
|
|
82
|
+
* tables — account links and OAuth tokens for every caller — so only the trusted
|
|
83
|
+
* identity-links service principal may touch them. This check deliberately does
|
|
84
|
+
* not consult memory: it used to sit behind a per-caller memory check, which left
|
|
85
|
+
* the tables open to any authenticated caller on deployments without a user
|
|
86
|
+
* slice.
|
|
87
|
+
*
|
|
88
|
+
* There is no per-caller store partition to enforce beyond that, because no
|
|
89
|
+
* declaration mounts per-caller state in this release.
|
|
78
90
|
*/
|
|
79
|
-
export declare function assertStoreAccess(
|
|
91
|
+
export declare function assertStoreAccess(user: ManagedUser, value: unknown): void;
|
|
80
92
|
/** True when `required` appears as a contiguous ordered subsequence of `namespace`. */
|
|
81
93
|
export declare function namespaceHasOrderedSegments(namespace: string[], required: string[]): boolean;
|
|
82
94
|
/**
|
|
@@ -93,6 +105,8 @@ export declare function namespaceHasOrderedSegments(namespace: string[], require
|
|
|
93
105
|
* loopback handoff — ordinary clients without the secret cannot stamp them.
|
|
94
106
|
*/
|
|
95
107
|
export declare function resolveTrustedBackendUser(cfg: IdentityConfig, request: Request): ManagedUser;
|
|
108
|
+
/** Verify a LangSmith API key without replacing MDA's authorization hooks. */
|
|
109
|
+
export declare function resolveLangSmithApiKeyUser(request: Request): Promise<ManagedUser>;
|
|
96
110
|
/**
|
|
97
111
|
* Under `mda dev`, synthetic local/Companion service principals are unscoped
|
|
98
112
|
* for thread search + store so authors can see Studio-created Local threads.
|
|
@@ -108,14 +122,12 @@ export declare function isLocalDevUnscopedUser(user: unknown): boolean;
|
|
|
108
122
|
export declare function tryLocalDevTrustedUser(_cfg: IdentityConfig, request: Request): ManagedUser | null;
|
|
109
123
|
/** Derive the owner value `@auth.on.threads` filters on (the caller user id). */
|
|
110
124
|
export declare function threadOwnerKey(user: ManagedUser): string;
|
|
111
|
-
/** True when this deployment exposes guest issuance and the request targets it. */
|
|
112
|
-
export declare function isGuestIssuanceRequest(request: Request, cfg: IdentityConfig): boolean;
|
|
113
125
|
/** True when the request targets a public channel/connector Events ingress route. */
|
|
114
126
|
export declare function isChannelEventsRequest(request: Request): boolean;
|
|
115
127
|
/** True when the request is a public identity-provider OAuth/OIDC callback. */
|
|
116
128
|
export declare function isIdentityProviderCallbackRequest(request: Request): boolean;
|
|
117
|
-
/** Placeholder identity so LangGraph auth middleware allows
|
|
118
|
-
export declare function
|
|
129
|
+
/** Placeholder identity so LangGraph auth middleware allows public routes. */
|
|
130
|
+
export declare function publicRouteBypassUser(): ManagedUser;
|
|
119
131
|
/** Placeholder identity so middleware allows provider-signed channel Events. */
|
|
120
132
|
export declare function channelEventsBypassUser(): ManagedUser;
|
|
121
133
|
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -1 +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;AAIvC,OAAO,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/runtime/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/auth.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Auth, HTTPException, isStudioUser, } from "@langchain/langgraph-sdk/auth";
|
|
2
2
|
import { trustedMessagingProviders } from "../channels/messaging-registry.js";
|
|
3
3
|
import { trustedChannelSourceProviders } from "../channels/registry-store.js";
|
|
4
|
-
import {
|
|
5
|
-
import { buildRuntimeIdentity
|
|
4
|
+
import {} from "../identity/index.js";
|
|
5
|
+
import { buildRuntimeIdentity } from "./identity-runtime.js";
|
|
6
6
|
import { resolveValidatedTokenUser } from "./validated-token.js";
|
|
7
7
|
/**
|
|
8
8
|
* Reserved transport for the trusted-backend ingress mode. User identity
|
|
@@ -12,18 +12,24 @@ import { resolveValidatedTokenUser } from "./validated-token.js";
|
|
|
12
12
|
*/
|
|
13
13
|
/** Trusted-backend / channel-loopback identity headers (single source of truth). */
|
|
14
14
|
export const USER_HEADER = "x-mda-user-id";
|
|
15
|
-
/** Comma- or space-delimited group memberships. */
|
|
16
|
-
export const GROUPS_HEADER = "x-mda-groups";
|
|
17
15
|
export const INGRESS_SECRET_HEADER = "x-mda-ingress-secret";
|
|
18
16
|
/**
|
|
19
|
-
* Internal channel handoff headers. Accepted only after
|
|
20
|
-
* validates — never part of the public HTTP identity
|
|
21
|
-
* not allowlisted into `config.configurable`.
|
|
17
|
+
* Internal channel handoff headers. Accepted only after a server API key or
|
|
18
|
+
* legacy ingress secret validates — never part of the public HTTP identity
|
|
19
|
+
* surface, and deliberately not allowlisted into `config.configurable`.
|
|
22
20
|
*/
|
|
23
21
|
export const SOURCE_PROVIDER_HEADER = "x-mda-source-provider";
|
|
24
22
|
export const SOURCE_THREAD_HEADER = "x-mda-source-thread-id";
|
|
25
23
|
/** Deployment env var carrying the shared secret the trusted backend presents. */
|
|
26
24
|
export const INGRESS_SECRET_ENV = "MDA_INGRESS_SECRET";
|
|
25
|
+
/** Deploy/dev-owned credential used only for internal identity handoffs. */
|
|
26
|
+
export const HANDOFF_SECRET_ENV = "MDA_HANDOFF_SECRET";
|
|
27
|
+
export const HANDOFF_SECRET_HEADER = "x-mda-handoff-secret";
|
|
28
|
+
/** Platform-owned LangSmith auth configuration. */
|
|
29
|
+
export const LANGSMITH_AUTH_ENDPOINT_ENV = "LANGSMITH_AUTH_ENDPOINT";
|
|
30
|
+
export const LANGSMITH_TENANT_ID_ENV = "LANGSMITH_TENANT_ID";
|
|
31
|
+
export const LANGSMITH_API_KEY_HEADER = "x-api-key";
|
|
32
|
+
export const LANGSMITH_API_KEY_ENV = "LANGSMITH_API_KEY";
|
|
27
33
|
/**
|
|
28
34
|
* Set to `"1"` by `mda dev` so local Studio / API clients can exercise
|
|
29
35
|
* `trusted_backend` identity without injecting ingress headers. Never set in
|
|
@@ -32,8 +38,6 @@ export const INGRESS_SECRET_ENV = "MDA_INGRESS_SECRET";
|
|
|
32
38
|
const LOCAL_DEV_ENV = "MDA_LOCAL_DEV";
|
|
33
39
|
/** Synthetic user for local `mda dev` when ingress headers are absent. */
|
|
34
40
|
const LOCAL_DEV_USER = "mda:local-dev";
|
|
35
|
-
/** Path MDA exposes for anonymous guest token issuance (must stay public). */
|
|
36
|
-
const GUEST_ISSUANCE_PATH = "/identity/guest";
|
|
37
41
|
/**
|
|
38
42
|
* Provider OAuth/OIDC callbacks must stay public (IdP redirects the browser
|
|
39
43
|
* here). Path shape: `/identity/{provider}/callback`.
|
|
@@ -56,17 +60,15 @@ function isTrustedSourceProvider(provider) {
|
|
|
56
60
|
trustedMessagingProviders().has(provider) ||
|
|
57
61
|
trustedChannelSourceProviders().has(provider));
|
|
58
62
|
}
|
|
59
|
-
/** Synthetic user used only to satisfy auth middleware on
|
|
60
|
-
const
|
|
63
|
+
/** Synthetic user used only to satisfy auth middleware on public routes. */
|
|
64
|
+
const PUBLIC_ROUTE_USER = "mda:public-route";
|
|
61
65
|
/** Synthetic user so middleware_first allows unsigned Slack Events ingress. */
|
|
62
66
|
const CHANNEL_EVENTS_USER = "mda:channel-events";
|
|
63
67
|
/**
|
|
64
68
|
* Build the managed LangGraph custom-auth handler from a declared identity.
|
|
65
69
|
*
|
|
66
|
-
* Handles
|
|
67
|
-
*
|
|
68
|
-
* verified via JWKS / introspection / MDA-signed guest). Also registers thread
|
|
69
|
-
* and store scoping with a studio bypass.
|
|
70
|
+
* Handles trusted-backend, LangSmith API-key, and validated-token ingress.
|
|
71
|
+
* Also registers thread and store scoping with a studio bypass.
|
|
70
72
|
*/
|
|
71
73
|
export function buildManagedAuth(identity) {
|
|
72
74
|
const cfg = identity.config;
|
|
@@ -78,18 +80,24 @@ export function buildManagedAuth(identity) {
|
|
|
78
80
|
if (isChannelEventsRequest(request)) {
|
|
79
81
|
return channelEventsBypassUser();
|
|
80
82
|
}
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
// Provider OAuth/OIDC callback requests bypass auth (the IdP redirects the
|
|
84
|
+
// browser here with no MDA token to present).
|
|
85
|
+
if (isIdentityProviderCallbackRequest(request)) {
|
|
86
|
+
return publicRouteBypassUser();
|
|
87
|
+
}
|
|
88
|
+
// Deploy/dev inject a private handoff credential. A local server API key
|
|
89
|
+
// remains compatible, as does the legacy trusted-backend ingress secret.
|
|
90
|
+
const managedHandoff = resolveManagedHandoffUser(request);
|
|
91
|
+
if (managedHandoff) {
|
|
92
|
+
return managedHandoff;
|
|
87
93
|
}
|
|
88
|
-
// Channel loopback (and other trusted handoffs) stamp the ingress secret
|
|
89
|
-
// even when public HTTP ingress is validated_token (e.g. Supabase web).
|
|
90
94
|
if (http === "backend" || hasValidIngressSecret(request)) {
|
|
91
95
|
return resolveTrustedBackendUser(cfg, request);
|
|
92
96
|
}
|
|
97
|
+
rejectUntrustedHandoffHeaders(request);
|
|
98
|
+
if (isLangSmithApiKeyAuth(http)) {
|
|
99
|
+
return resolveLangSmithApiKeyUser(request);
|
|
100
|
+
}
|
|
93
101
|
return resolveValidatedTokenUser(cfg, http, request);
|
|
94
102
|
});
|
|
95
103
|
auth.on("threads", ({ user, value }) => {
|
|
@@ -109,7 +117,7 @@ export function buildManagedAuth(identity) {
|
|
|
109
117
|
if (isStudioUser(user) || isLocalDevUnscopedUser(user)) {
|
|
110
118
|
return true;
|
|
111
119
|
}
|
|
112
|
-
assertStoreAccess(
|
|
120
|
+
assertStoreAccess(user, value);
|
|
113
121
|
return true;
|
|
114
122
|
});
|
|
115
123
|
return auth;
|
|
@@ -125,12 +133,20 @@ export function buildManagedAuth(identity) {
|
|
|
125
133
|
*/
|
|
126
134
|
export async function resolveRequestIdentity(cfg, request) {
|
|
127
135
|
const http = cfg.ingress.http;
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
136
|
+
const managedHandoff = resolveManagedHandoffUser(request);
|
|
137
|
+
const trustedHandoff = managedHandoff !== null || hasValidIngressSecret(request);
|
|
138
|
+
if (!managedHandoff && http !== "backend" && !trustedHandoff) {
|
|
139
|
+
rejectUntrustedHandoffHeaders(request);
|
|
140
|
+
}
|
|
141
|
+
const user = managedHandoff
|
|
142
|
+
? managedHandoff
|
|
143
|
+
: http === "backend" || trustedHandoff
|
|
144
|
+
? resolveTrustedBackendUser(cfg, request)
|
|
145
|
+
: isLangSmithApiKeyAuth(http)
|
|
146
|
+
? await resolveLangSmithApiKeyUser(request)
|
|
147
|
+
: await resolveValidatedTokenUser(cfg, http, request);
|
|
131
148
|
// Preserve trusted channel source stamps; default public HTTP to "http".
|
|
132
|
-
const sourceProvider = user.mda_source_provider ??
|
|
133
|
-
(hasValidIngressSecret(request) ? undefined : "http");
|
|
149
|
+
const sourceProvider = user.mda_source_provider ?? (trustedHandoff ? undefined : "http");
|
|
134
150
|
const identity = buildRuntimeIdentity({
|
|
135
151
|
langgraph_auth_user: {
|
|
136
152
|
...user,
|
|
@@ -156,17 +172,19 @@ export const GITHUB_CREDENTIALS_STORE_PREFIX = "mda_github_credentials";
|
|
|
156
172
|
*/
|
|
157
173
|
export const IDENTITY_LINKS_SERVICE_USER = "mda:identity-links";
|
|
158
174
|
/**
|
|
159
|
-
* Fail-closed (403)
|
|
160
|
-
*
|
|
161
|
-
*
|
|
175
|
+
* Fail-closed (403) on the managed reserved namespaces.
|
|
176
|
+
*
|
|
177
|
+
* `mda_identity_links` and `mda_github_credentials` are deployment-wide managed
|
|
178
|
+
* tables — account links and OAuth tokens for every caller — so only the trusted
|
|
179
|
+
* identity-links service principal may touch them. This check deliberately does
|
|
180
|
+
* not consult memory: it used to sit behind a per-caller memory check, which left
|
|
181
|
+
* the tables open to any authenticated caller on deployments without a user
|
|
182
|
+
* slice.
|
|
183
|
+
*
|
|
184
|
+
* There is no per-caller store partition to enforce beyond that, because no
|
|
185
|
+
* declaration mounts per-caller state in this release.
|
|
162
186
|
*/
|
|
163
|
-
export function assertStoreAccess(
|
|
164
|
-
const required = hasUserMemorySlice(cfg.scope.memory)
|
|
165
|
-
? memoryIdentitySegments(user.mda_user_id ? String(user.mda_user_id) : undefined)
|
|
166
|
-
: [];
|
|
167
|
-
if (required.length === 0) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
187
|
+
export function assertStoreAccess(user, value) {
|
|
170
188
|
const namespace = value &&
|
|
171
189
|
typeof value === "object" &&
|
|
172
190
|
Array.isArray(value.namespace)
|
|
@@ -184,11 +202,6 @@ export function assertStoreAccess(cfg, user, value) {
|
|
|
184
202
|
message: "store namespace is outside the caller's identity boundary",
|
|
185
203
|
});
|
|
186
204
|
}
|
|
187
|
-
if (!namespaceHasOrderedSegments(namespace, required)) {
|
|
188
|
-
throw new HTTPException(403, {
|
|
189
|
-
message: "store namespace is outside the caller's identity boundary",
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
205
|
}
|
|
193
206
|
/** True when `required` appears as a contiguous ordered subsequence of `namespace`. */
|
|
194
207
|
export function namespaceHasOrderedSegments(namespace, required) {
|
|
@@ -224,11 +237,14 @@ export function resolveTrustedBackendUser(cfg, request) {
|
|
|
224
237
|
return local;
|
|
225
238
|
}
|
|
226
239
|
requireIngressSecret(request);
|
|
240
|
+
return trustedHeadersUser(request);
|
|
241
|
+
}
|
|
242
|
+
/** Resolve headers only after the caller has established a trusted credential. */
|
|
243
|
+
function trustedHeadersUser(request) {
|
|
227
244
|
const userId = trustedUserId(request);
|
|
228
245
|
if (!userId) {
|
|
229
246
|
throw new HTTPException(401, { message: `missing ${USER_HEADER}` });
|
|
230
247
|
}
|
|
231
|
-
const groups = normalizeGroups(request.headers.get(GROUPS_HEADER));
|
|
232
248
|
const sourceProvider = request.headers.get(SOURCE_PROVIDER_HEADER) ?? undefined;
|
|
233
249
|
const sourceThread = request.headers.get(SOURCE_THREAD_HEADER) ?? undefined;
|
|
234
250
|
if (sourceProvider !== undefined) {
|
|
@@ -257,7 +273,6 @@ export function resolveTrustedBackendUser(cfg, request) {
|
|
|
257
273
|
permissions: [],
|
|
258
274
|
mda_user_id: userId,
|
|
259
275
|
...(isService ? { mda_user_kind: "service" } : {}),
|
|
260
|
-
...(groups.length > 0 ? { mda_groups: groups } : {}),
|
|
261
276
|
...(sourceProvider
|
|
262
277
|
? {
|
|
263
278
|
mda_source_provider: sourceProvider,
|
|
@@ -266,6 +281,117 @@ export function resolveTrustedBackendUser(cfg, request) {
|
|
|
266
281
|
: {}),
|
|
267
282
|
};
|
|
268
283
|
}
|
|
284
|
+
/** Resolve reserved identity headers authenticated by an internal credential. */
|
|
285
|
+
function resolveManagedHandoffUser(request) {
|
|
286
|
+
if (!hasHandoffHeaders(request) ||
|
|
287
|
+
(!hasValidHandoffSecret(request) && !hasServerApiKey(request))) {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
return trustedHeadersUser(request);
|
|
291
|
+
}
|
|
292
|
+
function hasValidHandoffSecret(request) {
|
|
293
|
+
const expected = process.env[HANDOFF_SECRET_ENV]?.trim();
|
|
294
|
+
const provided = request.headers.get(HANDOFF_SECRET_HEADER)?.trim();
|
|
295
|
+
return Boolean(expected && provided && constantTimeEquals(expected, provided));
|
|
296
|
+
}
|
|
297
|
+
function hasHandoffHeaders(request) {
|
|
298
|
+
return (request.headers.has(USER_HEADER) ||
|
|
299
|
+
request.headers.has(SOURCE_PROVIDER_HEADER) ||
|
|
300
|
+
request.headers.has(SOURCE_THREAD_HEADER));
|
|
301
|
+
}
|
|
302
|
+
function rejectUntrustedHandoffHeaders(request) {
|
|
303
|
+
if (hasHandoffHeaders(request)) {
|
|
304
|
+
throw new HTTPException(401, {
|
|
305
|
+
message: "reserved MDA identity headers require a trusted server credential",
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function hasServerApiKey(request) {
|
|
310
|
+
const expected = process.env[LANGSMITH_API_KEY_ENV]?.trim();
|
|
311
|
+
const provided = request.headers.get(LANGSMITH_API_KEY_HEADER)?.trim();
|
|
312
|
+
return Boolean(expected && provided && constantTimeEquals(expected, provided));
|
|
313
|
+
}
|
|
314
|
+
/** Verify a LangSmith API key without replacing MDA's authorization hooks. */
|
|
315
|
+
export async function resolveLangSmithApiKeyUser(request) {
|
|
316
|
+
const apiKey = request.headers.get(LANGSMITH_API_KEY_HEADER)?.trim();
|
|
317
|
+
const endpoint = process.env[LANGSMITH_AUTH_ENDPOINT_ENV]?.trim();
|
|
318
|
+
const expectedTenant = process.env[LANGSMITH_TENANT_ID_ENV]?.trim();
|
|
319
|
+
if (process.env[LOCAL_DEV_ENV] === "1" && (!endpoint || !expectedTenant)) {
|
|
320
|
+
return localDevServiceUser(request);
|
|
321
|
+
}
|
|
322
|
+
if (!apiKey) {
|
|
323
|
+
throw new HTTPException(401, { message: "missing x-api-key" });
|
|
324
|
+
}
|
|
325
|
+
if (!endpoint || !expectedTenant) {
|
|
326
|
+
throw new HTTPException(500, {
|
|
327
|
+
message: "LangSmith API-key authentication is not configured",
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
const headers = new Headers({ "x-api-key": apiKey });
|
|
331
|
+
const tenantHeader = request.headers.get("x-tenant-id");
|
|
332
|
+
if (tenantHeader) {
|
|
333
|
+
headers.set("x-tenant-id", tenantHeader);
|
|
334
|
+
}
|
|
335
|
+
let response;
|
|
336
|
+
try {
|
|
337
|
+
response = await fetch(new URL("/auth/public", endpoint), {
|
|
338
|
+
headers,
|
|
339
|
+
signal: AbortSignal.timeout(2_000),
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
throw new HTTPException(503, {
|
|
344
|
+
message: "LangSmith API-key verification unavailable",
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
if (response.status === 401) {
|
|
348
|
+
throw new HTTPException(401, { message: "invalid API key" });
|
|
349
|
+
}
|
|
350
|
+
if (response.status === 403) {
|
|
351
|
+
throw new HTTPException(403, { message: "API key is forbidden" });
|
|
352
|
+
}
|
|
353
|
+
if (!response.ok) {
|
|
354
|
+
throw new HTTPException(503, {
|
|
355
|
+
message: "LangSmith API-key verification unavailable",
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
let verified;
|
|
359
|
+
try {
|
|
360
|
+
verified = await response.json();
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
throw new HTTPException(503, {
|
|
364
|
+
message: "LangSmith API-key verification returned an invalid response",
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
if (!isJsonObject(verified)) {
|
|
368
|
+
throw new HTTPException(503, {
|
|
369
|
+
message: "LangSmith API-key verification returned an invalid response",
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
if (typeof verified.tenant_id !== "string" ||
|
|
373
|
+
verified.tenant_id !== expectedTenant) {
|
|
374
|
+
throw new HTTPException(403, { message: "API key tenant mismatch" });
|
|
375
|
+
}
|
|
376
|
+
const userId = typeof verified.user_id === "string" && verified.user_id.trim()
|
|
377
|
+
? `langsmith:user:${verified.user_id.trim()}`
|
|
378
|
+
: `langsmith:tenant:${verified.tenant_id}`;
|
|
379
|
+
return {
|
|
380
|
+
identity: userId,
|
|
381
|
+
permissions: [],
|
|
382
|
+
mda_user_id: userId,
|
|
383
|
+
mda_user_kind: "service",
|
|
384
|
+
...(typeof verified.user_email === "string" && verified.user_email.trim()
|
|
385
|
+
? { mda_user_email: verified.user_email.trim() }
|
|
386
|
+
: {}),
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function isJsonObject(value) {
|
|
390
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
391
|
+
}
|
|
392
|
+
function isLangSmithApiKeyAuth(http) {
|
|
393
|
+
return typeof http === "object" && http.mode === "langsmith_api_key";
|
|
394
|
+
}
|
|
269
395
|
/** Caller id from the trusted headers. */
|
|
270
396
|
function trustedUserId(request) {
|
|
271
397
|
return request.headers.get(USER_HEADER) ?? undefined;
|
|
@@ -303,6 +429,9 @@ export function tryLocalDevTrustedUser(_cfg, request) {
|
|
|
303
429
|
if (hasValidIngressSecret(request)) {
|
|
304
430
|
return null;
|
|
305
431
|
}
|
|
432
|
+
return localDevServiceUser(request);
|
|
433
|
+
}
|
|
434
|
+
function localDevServiceUser(request) {
|
|
306
435
|
const userId = trustedUserId(request) ?? LOCAL_DEV_USER;
|
|
307
436
|
return {
|
|
308
437
|
identity: userId,
|
|
@@ -327,21 +456,6 @@ function hasValidIngressSecret(request) {
|
|
|
327
456
|
const provided = request.headers.get(INGRESS_SECRET_HEADER);
|
|
328
457
|
return Boolean(expected && provided && constantTimeEquals(expected, provided));
|
|
329
458
|
}
|
|
330
|
-
/** True when this deployment exposes guest issuance and the request targets it. */
|
|
331
|
-
export function isGuestIssuanceRequest(request, cfg) {
|
|
332
|
-
if (request.method !== "POST") {
|
|
333
|
-
return false;
|
|
334
|
-
}
|
|
335
|
-
const { pathname } = new URL(request.url);
|
|
336
|
-
if (pathname !== GUEST_ISSUANCE_PATH) {
|
|
337
|
-
return false;
|
|
338
|
-
}
|
|
339
|
-
const http = cfg.ingress.http;
|
|
340
|
-
if (http === "backend") {
|
|
341
|
-
return false;
|
|
342
|
-
}
|
|
343
|
-
return http.providers.some((provider) => provider.guest?.issue);
|
|
344
|
-
}
|
|
345
459
|
/** True when the request targets a public channel/connector Events ingress route. */
|
|
346
460
|
export function isChannelEventsRequest(request) {
|
|
347
461
|
if (request.method !== "POST") {
|
|
@@ -358,12 +472,12 @@ export function isIdentityProviderCallbackRequest(request) {
|
|
|
358
472
|
const { pathname } = new URL(request.url);
|
|
359
473
|
return IDENTITY_PROVIDER_CALLBACK_PATH.test(pathname);
|
|
360
474
|
}
|
|
361
|
-
/** Placeholder identity so LangGraph auth middleware allows
|
|
362
|
-
export function
|
|
475
|
+
/** Placeholder identity so LangGraph auth middleware allows public routes. */
|
|
476
|
+
export function publicRouteBypassUser() {
|
|
363
477
|
return {
|
|
364
|
-
identity:
|
|
478
|
+
identity: PUBLIC_ROUTE_USER,
|
|
365
479
|
permissions: [],
|
|
366
|
-
mda_user_id:
|
|
480
|
+
mda_user_id: PUBLIC_ROUTE_USER,
|
|
367
481
|
};
|
|
368
482
|
}
|
|
369
483
|
/** Placeholder identity so middleware allows provider-signed channel Events. */
|