@noodleseed/one 0.127.2 → 0.128.0
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/commands/assistant-embed-ops.d.ts.map +1 -1
- package/dist/commands/assistant-embed-ops.js +82 -9
- package/dist/commands/assistant-embed-ops.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.d.ts.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js +6 -4
- package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js.map +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.d.ts +9 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.d.ts.map +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.js +11 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.js.map +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/elevation.d.ts +13 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/elevation.d.ts.map +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/elevation.js +4 -3
- package/node_modules/@noodle-borg/assistant-gateway/dist/elevation.js.map +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/postgres-assistant.d.ts +3 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/postgres-assistant.d.ts.map +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/postgres-assistant.js +8 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/postgres-assistant.js.map +1 -1
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-assistant.d.ts.map +1 -1
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-assistant.js +16 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-assistant.js.map +1 -1
- package/node_modules/@noodle-borg/connector-defs/dist/delegated-token-exchange-identity.js +16 -1
- package/node_modules/@noodle-borg/connector-defs/dist/delegated-token-exchange-identity.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/assistant-delegated-projection.d.ts +12 -0
- package/node_modules/@noodle-borg/service/dist/assistant-delegated-projection.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/assistant-delegated-projection.js +68 -0
- package/node_modules/@noodle-borg/service/dist/assistant-delegated-projection.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/credential-broker.d.ts +6 -0
- package/node_modules/@noodle-borg/service/dist/credential-broker.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/credential-broker.js +9 -0
- package/node_modules/@noodle-borg/service/dist/credential-broker.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/registry-compile.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/registry-compile.js +8 -0
- package/node_modules/@noodle-borg/service/dist/registry-compile.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-agent.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-agent.js +26 -7
- package/node_modules/@noodle-borg/service/dist/routes/assistant-agent.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-dispatch.js +2 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-dispatch.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-doctor.d.ts +10 -0
- package/node_modules/@noodle-borg/service/dist/routes/assistant-doctor.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/assistant-doctor.js +164 -0
- package/node_modules/@noodle-borg/service/dist/routes/assistant-doctor.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/assistant-elevation.d.ts +21 -3
- package/node_modules/@noodle-borg/service/dist/routes/assistant-elevation.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant-elevation.js +45 -7
- package/node_modules/@noodle-borg/service/dist/routes/assistant-elevation.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant.d.ts +0 -2
- package/node_modules/@noodle-borg/service/dist/routes/assistant.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/assistant.js +7 -88
- package/node_modules/@noodle-borg/service/dist/routes/assistant.js.map +1 -1
- package/node_modules/@noodleseed/assistant/README.md +68 -0
- package/node_modules/@noodleseed/assistant/dist/{chunk-S373FCAI.js → chunk-52XT7BLR.js} +9 -4
- package/node_modules/@noodleseed/assistant/dist/{chunk-S373FCAI.js.map → chunk-52XT7BLR.js.map} +1 -1
- package/node_modules/@noodleseed/assistant/dist/{chunk-RFETV5KQ.js → chunk-DLUINP4W.js} +9 -9
- package/node_modules/@noodleseed/assistant/dist/{chunk-RFETV5KQ.js.map → chunk-DLUINP4W.js.map} +1 -1
- package/node_modules/@noodleseed/assistant/dist/{client-BQ30Fq-c.d.cts → client-7o7n2nqw.d.cts} +6 -4
- package/node_modules/@noodleseed/assistant/dist/{client-B6pnBmF8.d.ts → client-CysBQBdd.d.ts} +6 -4
- package/node_modules/@noodleseed/assistant/dist/client.cjs +8 -3
- package/node_modules/@noodleseed/assistant/dist/client.cjs.map +1 -1
- package/node_modules/@noodleseed/assistant/dist/client.d.cts +1 -1
- package/node_modules/@noodleseed/assistant/dist/client.d.ts +1 -1
- package/node_modules/@noodleseed/assistant/dist/client.js +1 -1
- package/node_modules/@noodleseed/assistant/dist/embed.global.js +4 -4
- package/node_modules/@noodleseed/assistant/dist/index.cjs +15 -10
- package/node_modules/@noodleseed/assistant/dist/index.cjs.map +1 -1
- package/node_modules/@noodleseed/assistant/dist/index.d.cts +2 -2
- package/node_modules/@noodleseed/assistant/dist/index.d.ts +2 -2
- package/node_modules/@noodleseed/assistant/dist/index.js +2 -2
- package/node_modules/@noodleseed/assistant/dist/react/client.cjs +8 -3
- package/node_modules/@noodleseed/assistant/dist/react/client.cjs.map +1 -1
- package/node_modules/@noodleseed/assistant/dist/react/client.d.cts +1 -1
- package/node_modules/@noodleseed/assistant/dist/react/client.d.ts +1 -1
- package/node_modules/@noodleseed/assistant/dist/react/client.js +1 -1
- package/node_modules/@noodleseed/assistant/dist/react.cjs +15 -10
- package/node_modules/@noodleseed/assistant/dist/react.cjs.map +1 -1
- package/node_modules/@noodleseed/assistant/dist/react.d.cts +1 -1
- package/node_modules/@noodleseed/assistant/dist/react.d.ts +1 -1
- package/node_modules/@noodleseed/assistant/dist/react.js +2 -2
- package/node_modules/@noodleseed/assistant/dist/server.cjs +47 -1
- package/node_modules/@noodleseed/assistant/dist/server.cjs.map +1 -1
- package/node_modules/@noodleseed/assistant/dist/server.d.cts +60 -7
- package/node_modules/@noodleseed/assistant/dist/server.d.ts +60 -7
- package/node_modules/@noodleseed/assistant/dist/server.js +45 -1
- package/node_modules/@noodleseed/assistant/dist/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-dispatch.js","sourceRoot":"","sources":["../../src/routes/assistant-dispatch.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,
|
|
1
|
+
{"version":3,"file":"assistant-dispatch.js","sourceRoot":"","sources":["../../src/routes/assistant-dispatch.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAsBhE,MAAM,UAAU,uBAAuB,CACrC,GAAoB,EACpB,GAAmB,EACnB,GAAQ,EACR,IAA2B;IAE3B,IAAI,GAAG,CAAC,QAAQ,KAAK,qCAAqC,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACpF,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,0BAA0B,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC/E,CAAC;IACD,IACE,CAAC,GAAG,CAAC,QAAQ,KAAK,+BAA+B;QAC/C,GAAG,CAAC,QAAQ,KAAK,qBAAqB;QACtC,GAAG,CAAC,QAAQ,KAAK,kCAAkC;QACnD,GAAG,CAAC,QAAQ,KAAK,4BAA4B;QAC7C,GAAG,CAAC,QAAQ,KAAK,oBAAoB,CAAC;QACxC,GAAG,CAAC,MAAM,KAAK,SAAS,EACxB,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACzC,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,wBAAwB,EAAE,CAAC;QAC9C,8FAA8F;QAC9F,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACvD,0BAA0B,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,uBAAuB,EAAE,CAAC;QAC7C,+FAA+F;QAC/F,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACvD,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,+BAA+B,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC9E,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,4BAA4B,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IACjF,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,wBAAwB,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACvE,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,qBAAqB,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACpE,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,oBAAoB,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACnE,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,yBAAyB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,WAAW,GAAG,wEAAwE,CAAC,IAAI,CAC/F,GAAG,CAAC,QAAQ,CACb,CAAC;IACF,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,WAAW,GACf,sFAAsF,CAAC,IAAI,CACzF,GAAG,CAAC,QAAQ,CACb,CAAC;IACJ,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChF,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,kCAAkC,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACjF,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,2BAA2B,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,4BAA4B,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC3E,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,0BAA0B,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,KAAK,GACT,sGAAsG,CAAC,IAAI,CACzG,GAAG,CAAC,QAAQ,CACb,CAAC;IACJ,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;IAC7E,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,SAAS,GAAG,CACV,GAAoB,EACpB,GAAmB,EACnB,IAA2B,EAC3B,OAA4B;IAE5B,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvD,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,GAAG,CAAC,WAAW;YAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,KAAsB;IAC1C,IAAI,CAAC;QACH,OAAO;YACL,GAAG,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACvC,GAAG,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACvC,GAAG,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACxC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { TenantRef } from '../store.js';
|
|
3
|
+
import type { AssistantRouteDeps } from './assistant.js';
|
|
4
|
+
/**
|
|
5
|
+
* The doctor half of the assistant boundary, kept out of `assistant.ts` for the same reason the
|
|
6
|
+
* elevation half is: a different responsibility, and that file is at its size limit.
|
|
7
|
+
*/
|
|
8
|
+
/** Validate the customer backend ↔ active embedded-assistant boundary without invoking a tool. */
|
|
9
|
+
export declare function handleAssistantDoctor(req: IncomingMessage, res: ServerResponse, tenant: TenantRef, deps: AssistantRouteDeps): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=assistant-doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assistant-doctor.d.ts","sourceRoot":"","sources":["../../src/routes/assistant-doctor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAQjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAIzD;;;GAGG;AAEH,kGAAkG;AAClG,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAqJf"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { assistantCustomerIssuer, completeElevation, publicSurfaceOf, } from '@noodle-borg/assistant-gateway';
|
|
3
|
+
import { readJsonBody, sendForbidden, sendJson } from '../http-util.js';
|
|
4
|
+
import { tenantMcpUrl } from '../registry-helpers.js';
|
|
5
|
+
import { now } from './assistant-route-http.js';
|
|
6
|
+
import { authorizeControlPlane } from './control-plane.js';
|
|
7
|
+
/**
|
|
8
|
+
* The doctor half of the assistant boundary, kept out of `assistant.ts` for the same reason the
|
|
9
|
+
* elevation half is: a different responsibility, and that file is at its size limit.
|
|
10
|
+
*/
|
|
11
|
+
/** Validate the customer backend ↔ active embedded-assistant boundary without invoking a tool. */
|
|
12
|
+
export async function handleAssistantDoctor(req, res, tenant, deps) {
|
|
13
|
+
if (req.method !== 'POST')
|
|
14
|
+
return sendJson(res, 405, { error: 'method not allowed' });
|
|
15
|
+
const identity = await authorizeControlPlane(req, res, deps.gate, { requireIdentity: false });
|
|
16
|
+
if (identity === false)
|
|
17
|
+
return;
|
|
18
|
+
if (identity && !identity.superAdmin) {
|
|
19
|
+
const member = await deps.controlPlane.isOrgMember({
|
|
20
|
+
org: tenant.org,
|
|
21
|
+
subject: identity.subject,
|
|
22
|
+
});
|
|
23
|
+
if (!member)
|
|
24
|
+
return sendForbidden(res, 'forbidden');
|
|
25
|
+
}
|
|
26
|
+
const body = await readJsonBody(req, deps.maxBody);
|
|
27
|
+
if (!body.ok)
|
|
28
|
+
return sendJson(res, body.status, { error: body.error });
|
|
29
|
+
if (!isRecord(body.value))
|
|
30
|
+
return sendJson(res, 400, { error: 'invalid doctor request' });
|
|
31
|
+
const { clientId, clientSecret, origin, userId } = body.value;
|
|
32
|
+
if (typeof clientId !== 'string' ||
|
|
33
|
+
clientId.length < 1 ||
|
|
34
|
+
typeof clientSecret !== 'string' ||
|
|
35
|
+
clientSecret.length < 1 ||
|
|
36
|
+
typeof origin !== 'string' ||
|
|
37
|
+
origin.length < 1 ||
|
|
38
|
+
(userId !== undefined &&
|
|
39
|
+
(typeof userId !== 'string' || userId.length < 1 || userId.length > 240))) {
|
|
40
|
+
return sendJson(res, 400, { error: 'clientId, clientSecret, and origin are required' });
|
|
41
|
+
}
|
|
42
|
+
const target = await deps.registry.getActiveByTenant(tenant);
|
|
43
|
+
const assistant = target?.served.artifact.server.assistant;
|
|
44
|
+
const deploymentOk = Boolean(target?.deploymentId && assistant);
|
|
45
|
+
const client = await deps.store.authenticateClient(clientId, clientSecret);
|
|
46
|
+
const clientOk = client !== undefined && sameTenant(client.tenant, tenant);
|
|
47
|
+
const originOk = assistant?.allowedOrigins.includes(origin) === true;
|
|
48
|
+
let delegatedCredentials;
|
|
49
|
+
if (!deploymentOk || !clientOk || !originOk || !target || !client) {
|
|
50
|
+
delegatedCredentials = {
|
|
51
|
+
ok: false,
|
|
52
|
+
skipped: true,
|
|
53
|
+
reason: 'deployment, client, and origin checks must pass first',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
else if (target.served.deps.broker.probeDelegatedCredentials === undefined) {
|
|
57
|
+
delegatedCredentials = {
|
|
58
|
+
ok: false,
|
|
59
|
+
skipped: true,
|
|
60
|
+
reason: 'deployment credential broker does not support diagnostics',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const probes = await target.served.deps.broker.probeDelegatedCredentials({
|
|
65
|
+
subject: typeof userId === 'string' ? userId : 'noodle-assistant-doctor',
|
|
66
|
+
identityKind: 'customer',
|
|
67
|
+
audience: tenantMcpUrl(deps.serviceBase(req), tenant),
|
|
68
|
+
}, undefined, assistantCustomerIssuer(client.id));
|
|
69
|
+
delegatedCredentials = { ok: probes.every((probe) => probe.ok), probes };
|
|
70
|
+
}
|
|
71
|
+
// Synthetic sign-in round trip (ADR 0201, 5.6b): issue -> claim -> elevate against a throwaway
|
|
72
|
+
// anonymous session, the same code path a real sign-in takes — including the clientId (issuer
|
|
73
|
+
// basis, ADR 0152) and origin rebind. Without this, doctor certified the authenticated exchange
|
|
74
|
+
// while the sign-in leg could be broken or unconfigured. The ticket is spent inside the probe and
|
|
75
|
+
// never leaves this handler; the throwaway session expires on its own.
|
|
76
|
+
let elevation;
|
|
77
|
+
const signInSurface = publicSurfaceOf(assistant)?.mode === 'mixed';
|
|
78
|
+
if (!deploymentOk || !clientOk || !originOk || !target || !client) {
|
|
79
|
+
elevation = {
|
|
80
|
+
ok: false,
|
|
81
|
+
skipped: true,
|
|
82
|
+
reason: 'deployment, client, and origin checks must pass first',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
else if (!signInSurface) {
|
|
86
|
+
elevation = { ok: true, skipped: true, reason: 'no mixed surface declares sign-in' };
|
|
87
|
+
}
|
|
88
|
+
else if (!deps.elevations) {
|
|
89
|
+
elevation = {
|
|
90
|
+
ok: false,
|
|
91
|
+
reason: 'a mixed surface promises sign-in, but no elevation store is configured',
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const current = now(deps);
|
|
96
|
+
const probeSession = await deps.store.createSession({
|
|
97
|
+
clientId: client.id,
|
|
98
|
+
tenant: client.tenant,
|
|
99
|
+
deploymentId: target.deploymentId ?? '',
|
|
100
|
+
origin,
|
|
101
|
+
caller: { subject: `noodle-doctor-anon-${randomUUID()}`, identityKind: 'anonymous' },
|
|
102
|
+
createdAt: current.toISOString(),
|
|
103
|
+
expiresAt: new Date(current.getTime() + 60_000).toISOString(),
|
|
104
|
+
absoluteExpiresAt: new Date(current.getTime() + 60_000).toISOString(),
|
|
105
|
+
});
|
|
106
|
+
const { continuation } = await deps.elevations.request({
|
|
107
|
+
sessionId: probeSession.session.id,
|
|
108
|
+
tenant: client.tenant,
|
|
109
|
+
tool: 'noodle_assistant_doctor',
|
|
110
|
+
now: current,
|
|
111
|
+
});
|
|
112
|
+
const elevated = await completeElevation({
|
|
113
|
+
continuation,
|
|
114
|
+
tenant: client.tenant,
|
|
115
|
+
caller: {
|
|
116
|
+
subject: typeof userId === 'string' ? userId : 'noodle-assistant-doctor',
|
|
117
|
+
identityKind: 'customer',
|
|
118
|
+
audience: tenantMcpUrl(deps.serviceBase(req), tenant),
|
|
119
|
+
},
|
|
120
|
+
clientId: client.id,
|
|
121
|
+
origin,
|
|
122
|
+
}, {
|
|
123
|
+
elevations: deps.elevations,
|
|
124
|
+
elevateSession: (request) => deps.store.elevateSession(request),
|
|
125
|
+
now: () => now(deps),
|
|
126
|
+
});
|
|
127
|
+
elevation =
|
|
128
|
+
elevated.ok && elevated.session.clientId === client.id && elevated.session.origin === origin
|
|
129
|
+
? { ok: true, issuerRebound: true }
|
|
130
|
+
: {
|
|
131
|
+
ok: false,
|
|
132
|
+
reason: elevated.ok ? 'elevation did not rebind the session' : elevated.code,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const checks = {
|
|
136
|
+
deployment: {
|
|
137
|
+
ok: deploymentOk,
|
|
138
|
+
...(target?.deploymentId ? { deploymentId: target.deploymentId } : {}),
|
|
139
|
+
},
|
|
140
|
+
client: {
|
|
141
|
+
ok: clientOk,
|
|
142
|
+
...(clientOk && client ? { createdAgainstDeploymentId: client.deploymentId } : {}),
|
|
143
|
+
},
|
|
144
|
+
origin: {
|
|
145
|
+
ok: originOk,
|
|
146
|
+
origin,
|
|
147
|
+
...(assistant ? { allowedOrigins: assistant.allowedOrigins } : {}),
|
|
148
|
+
},
|
|
149
|
+
elevation,
|
|
150
|
+
delegatedCredentials,
|
|
151
|
+
};
|
|
152
|
+
return sendJson(res, 200, {
|
|
153
|
+
ok: Object.values(checks).every((check) => check.ok),
|
|
154
|
+
...(target?.deploymentId ? { deploymentId: target.deploymentId } : {}),
|
|
155
|
+
checks,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function isRecord(value) {
|
|
159
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
160
|
+
}
|
|
161
|
+
function sameTenant(a, b) {
|
|
162
|
+
return a.org === b.org && a.app === b.app && a.env === b.env;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=assistant-doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assistant-doctor.js","sourceRoot":"","sources":["../../src/routes/assistant-doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,GAChB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;GAGG;AAEH,kGAAkG;AAClG,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAoB,EACpB,GAAmB,EACnB,MAAiB,EACjB,IAAwB;IAExB,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;IACtF,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9F,IAAI,QAAQ,KAAK,KAAK;QAAE,OAAO;IAC/B,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC;YACjD,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,OAAO,EAAE,QAAQ,CAAC,OAAO;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM;YAAE,OAAO,aAAa,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACvE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;IAC1F,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;IAC9D,IACE,OAAO,QAAQ,KAAK,QAAQ;QAC5B,QAAQ,CAAC,MAAM,GAAG,CAAC;QACnB,OAAO,YAAY,KAAK,QAAQ;QAChC,YAAY,CAAC,MAAM,GAAG,CAAC;QACvB,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,CAAC,MAAM,GAAG,CAAC;QACjB,CAAC,MAAM,KAAK,SAAS;YACnB,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,EAC3E,CAAC;QACD,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,iDAAiD,EAAE,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;IAC3D,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,YAAY,IAAI,SAAS,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,MAAM,KAAK,SAAS,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,SAAS,EAAE,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACrE,IAAI,oBAEuE,CAAC;IAC5E,IAAI,CAAC,YAAY,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAClE,oBAAoB,GAAG;YACrB,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,uDAAuD;SAChE,CAAC;IACJ,CAAC;SAAM,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,yBAAyB,KAAK,SAAS,EAAE,CAAC;QAC7E,oBAAoB,GAAG;YACrB,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,2DAA2D;SACpE,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,yBAAyB,CACtE;YACE,OAAO,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,yBAAyB;YACxE,YAAY,EAAE,UAAU;YACxB,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;SACtD,EACD,SAAS,EACT,uBAAuB,CAAC,MAAM,CAAC,EAAE,CAAC,CACnC,CAAC;QACF,oBAAoB,GAAG,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3E,CAAC;IACD,+FAA+F;IAC/F,8FAA8F;IAC9F,gGAAgG;IAChG,kGAAkG;IAClG,uEAAuE;IACvE,IAAI,SAEmD,CAAC;IACxD,MAAM,aAAa,GAAG,eAAe,CAAC,SAAS,CAAC,EAAE,IAAI,KAAK,OAAO,CAAC;IACnE,IAAI,CAAC,YAAY,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAClE,SAAS,GAAG;YACV,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,uDAAuD;SAChE,CAAC;IACJ,CAAC;SAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC1B,SAAS,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,mCAAmC,EAAE,CAAC;IACvF,CAAC;SAAM,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QAC5B,SAAS,GAAG;YACV,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,wEAAwE;SACjF,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;YAClD,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE;YACvC,MAAM;YACN,MAAM,EAAE,EAAE,OAAO,EAAE,sBAAsB,UAAU,EAAE,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE;YACpF,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE;YAChC,SAAS,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE;YAC7D,iBAAiB,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE;SACtE,CAAC,CAAC;QACH,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YACrD,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE;YAClC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,IAAI,EAAE,yBAAyB;YAC/B,GAAG,EAAE,OAAO;SACb,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CACtC;YACE,YAAY;YACZ,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE;gBACN,OAAO,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,yBAAyB;gBACxE,YAAY,EAAE,UAAU;gBACxB,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;aACtD;YACD,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,MAAM;SACP,EACD;YACE,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,cAAc,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC;YAC/D,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;SACrB,CACF,CAAC;QACF,SAAS;YACP,QAAQ,CAAC,EAAE,IAAI,QAAQ,CAAC,OAAO,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM;gBAC1F,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;gBACnC,CAAC,CAAC;oBACE,EAAE,EAAE,KAAK;oBACT,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI;iBAC7E,CAAC;IACV,CAAC;IACD,MAAM,MAAM,GAAG;QACb,UAAU,EAAE;YACV,EAAE,EAAE,YAAY;YAChB,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvE;QACD,MAAM,EAAE;YACN,EAAE,EAAE,QAAQ;YACZ,GAAG,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,0BAA0B,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnF;QACD,MAAM,EAAE;YACN,EAAE,EAAE,QAAQ;YACZ,MAAM;YACN,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnE;QACD,SAAS;QACT,oBAAoB;KACrB,CAAC;IACF,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE;QACxB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,MAAM;KACP,CAAC,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,UAAU,CAAC,CAAY,EAAE,CAAY;IAC5C,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC;AAC/D,CAAC"}
|
|
@@ -11,9 +11,11 @@ import type { TenantRef } from '../store.js';
|
|
|
11
11
|
* doing. What must never happen is the call proceeding — so the interception sits after authorization
|
|
12
12
|
* and before dispatch, and returns an elevation request instead of a result.
|
|
13
13
|
*
|
|
14
|
-
* The
|
|
14
|
+
* The sign-in ticket goes to the browser. That is safe only because spending one also requires the
|
|
15
15
|
* customer's client credentials and a tenant match, both enforced where it is claimed; on its own it
|
|
16
|
-
* names a conversation and nothing more.
|
|
16
|
+
* names a conversation and nothing more. It is named `signInTicket` on the wire precisely because the
|
|
17
|
+
* runtime's server-held interaction `continuation` has the opposite property — that one must never
|
|
18
|
+
* reach browser code — and one word must not carry both contracts.
|
|
17
19
|
*/
|
|
18
20
|
export interface ElevationInterception {
|
|
19
21
|
/** Streamed to the widget, which renders the sign-in card. */
|
|
@@ -22,6 +24,8 @@ export interface ElevationInterception {
|
|
|
22
24
|
readonly data: {
|
|
23
25
|
readonly id: string;
|
|
24
26
|
readonly tool: string;
|
|
27
|
+
readonly signInTicket: string;
|
|
28
|
+
/** Legacy alias of `signInTicket`: widgets published before the rename guard on this key. Drop at the next coordinated widget major (ADR 0151). */
|
|
25
29
|
readonly continuation: string;
|
|
26
30
|
readonly expiresAt: string;
|
|
27
31
|
};
|
|
@@ -29,6 +33,8 @@ export interface ElevationInterception {
|
|
|
29
33
|
/** Fed back to the model as this tool call's result, so it explains rather than stalls. */
|
|
30
34
|
readonly modelResult: string;
|
|
31
35
|
}
|
|
36
|
+
/** Whether this assistant's public surface can turn a denial into a sign-in offer (ADR 0201, 5.6b). */
|
|
37
|
+
export declare function offersSignIn(assistant: unknown): boolean;
|
|
32
38
|
/**
|
|
33
39
|
* Decide whether this call is an elevation instead of an execution.
|
|
34
40
|
*
|
|
@@ -40,6 +46,13 @@ export declare function interceptForElevation(input: {
|
|
|
40
46
|
readonly session: AssistantSessionRecord;
|
|
41
47
|
readonly assistant: unknown;
|
|
42
48
|
readonly elevations: AssistantElevationStore | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* The connector-auth-kind half of the classification (ADR 0201, amended 2026-08-19):
|
|
51
|
+
* `anonymousBehavior` cannot see connector bindings, so the caller joins them in. Absent
|
|
52
|
+
* resolver = the `${user}`/authorization classification alone, which fails closed to the
|
|
53
|
+
* ordinary refusal — never an offer the deployment cannot complete.
|
|
54
|
+
*/
|
|
55
|
+
readonly requiresDelegatedIdentity?: (tool: ArtifactTool) => boolean;
|
|
43
56
|
readonly now: Date;
|
|
44
57
|
}): Promise<ElevationInterception | undefined>;
|
|
45
58
|
/**
|
|
@@ -59,10 +72,15 @@ export declare function elevateAssistantSession(res: ServerResponse, deps: {
|
|
|
59
72
|
readonly audit: AuditSink;
|
|
60
73
|
readonly clock?: () => Date;
|
|
61
74
|
}, input: {
|
|
62
|
-
readonly
|
|
75
|
+
readonly signInTicket: unknown;
|
|
63
76
|
readonly client: {
|
|
77
|
+
readonly id: string;
|
|
64
78
|
readonly tenant: TenantRef;
|
|
65
79
|
};
|
|
80
|
+
/** Already allowlist-validated by the route; where the elevated conversation continues. */
|
|
81
|
+
readonly origin: string;
|
|
82
|
+
/** Already validated against the artifact's customerEndpoints; absent means unchanged. */
|
|
83
|
+
readonly customerRouting?: AssistantSessionRecord['customerRouting'];
|
|
66
84
|
readonly caller: AssistantSessionRecord['caller'];
|
|
67
85
|
readonly configuration: AssistantSessionRecord['configuration'];
|
|
68
86
|
readonly endpoints: Readonly<Record<string, string>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-elevation.d.ts","sourceRoot":"","sources":["../../src/routes/assistant-elevation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,cAAc,EAEf,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,KAAK,YAAY,EAAqB,MAAM,uBAAuB,CAAC;AAG7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C
|
|
1
|
+
{"version":3,"file":"assistant-elevation.d.ts","sourceRoot":"","sources":["../../src/routes/assistant-elevation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,cAAc,EAEf,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,KAAK,YAAY,EAAqB,MAAM,uBAAuB,CAAC;AAG7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;QACjC,QAAQ,CAAC,IAAI,EAAE;YACb,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;YAC9B,mJAAmJ;YACnJ,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;YAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;SAC5B,CAAC;KACH,CAAC;IACF,2FAA2F;IAC3F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAMD,uGAAuG;AACvG,wBAAgB,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAExD;AAcD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,uBAAuB,GAAG,SAAS,CAAC;IACzD;;;;;OAKG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC;IACrE,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;CACpB,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAqC7C;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE;IACJ,QAAQ,CAAC,UAAU,CAAC,EAAE,uBAAuB,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE;QAAE,cAAc,EAAE,cAAc,CAAC,gBAAgB,CAAC,CAAA;KAAE,CAAC;IACrE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,EACD,KAAK,EAAE;IACL,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;KAAE,CAAC;IACrE,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0FAA0F;IAC1F,QAAQ,CAAC,eAAe,CAAC,EAAE,sBAAsB,CAAC,iBAAiB,CAAC,CAAC;IACrE,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAClD,QAAQ,CAAC,aAAa,EAAE,sBAAsB,CAAC,eAAe,CAAC,CAAC;IAChE,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACtD,GACA,OAAO,CAAC,IAAI,CAAC,CAuEf"}
|
|
@@ -5,6 +5,18 @@ import { sendJson } from '../http-util.js';
|
|
|
5
5
|
function isMixed(surface) {
|
|
6
6
|
return surface?.mode === 'mixed';
|
|
7
7
|
}
|
|
8
|
+
/** Whether this assistant's public surface can turn a denial into a sign-in offer (ADR 0201, 5.6b). */
|
|
9
|
+
export function offersSignIn(assistant) {
|
|
10
|
+
return isMixed(publicSurfaceOf(assistant));
|
|
11
|
+
}
|
|
12
|
+
/** Human halves of the refusal envelope; the machine half is the gateway's `ElevationResult` code. */
|
|
13
|
+
const ELEVATION_REFUSAL_MESSAGES = {
|
|
14
|
+
elevation_ticket_invalid: 'sign-in ticket is not valid or was already used',
|
|
15
|
+
elevation_ticket_expired: 'sign-in ticket has expired; ask the visitor to retry the action',
|
|
16
|
+
elevation_tenant_mismatch: 'sign-in ticket belongs to a different tenant',
|
|
17
|
+
elevation_session_unavailable: 'the conversation behind this sign-in is no longer available',
|
|
18
|
+
elevation_already_signed_in: 'this conversation is already signed in',
|
|
19
|
+
};
|
|
8
20
|
/**
|
|
9
21
|
* Decide whether this call is an elevation instead of an execution.
|
|
10
22
|
*
|
|
@@ -14,9 +26,11 @@ function isMixed(surface) {
|
|
|
14
26
|
export async function interceptForElevation(input) {
|
|
15
27
|
if (input.session.caller.identityKind !== 'anonymous')
|
|
16
28
|
return undefined;
|
|
17
|
-
if (anonymousBehavior(input.tool) !== 'requires-identity'
|
|
29
|
+
if (anonymousBehavior(input.tool) !== 'requires-identity' &&
|
|
30
|
+
input.requiresDelegatedIdentity?.(input.tool) !== true) {
|
|
18
31
|
return undefined;
|
|
19
|
-
|
|
32
|
+
}
|
|
33
|
+
if (!offersSignIn(input.assistant))
|
|
20
34
|
return undefined;
|
|
21
35
|
// A deployment without the store configured cannot offer sign-in. Returning undefined lets the
|
|
22
36
|
// existing authorization refusal stand, which is the safe direction: no offer, no execution.
|
|
@@ -34,6 +48,7 @@ export async function interceptForElevation(input) {
|
|
|
34
48
|
data: {
|
|
35
49
|
id: elevation.id,
|
|
36
50
|
tool: input.tool.name,
|
|
51
|
+
signInTicket: continuation,
|
|
37
52
|
continuation,
|
|
38
53
|
expiresAt: elevation.expiresAt,
|
|
39
54
|
},
|
|
@@ -55,13 +70,30 @@ export async function interceptForElevation(input) {
|
|
|
55
70
|
* does not own is the one an operator should be able to see.
|
|
56
71
|
*/
|
|
57
72
|
export async function elevateAssistantSession(res, deps, input) {
|
|
58
|
-
if (typeof input.
|
|
59
|
-
|
|
73
|
+
if (typeof input.signInTicket !== 'string' || input.signInTicket.length === 0) {
|
|
74
|
+
// Same recovery as a spent ticket — obtain a fresh one — so it reuses the same code; the 400
|
|
75
|
+
// status preserves the malformed-vs-refused distinction for operators.
|
|
76
|
+
return sendJson(res, 400, {
|
|
77
|
+
error: 'signInTicket must be a non-empty string',
|
|
78
|
+
code: 'elevation_ticket_invalid',
|
|
79
|
+
});
|
|
60
80
|
}
|
|
61
81
|
if (!deps.elevations) {
|
|
62
|
-
return sendJson(res, 503, {
|
|
82
|
+
return sendJson(res, 503, {
|
|
83
|
+
error: 'sign-in elevation is not available on this deployment',
|
|
84
|
+
code: 'elevation_unavailable',
|
|
85
|
+
});
|
|
63
86
|
}
|
|
64
|
-
const elevated = await completeElevation({
|
|
87
|
+
const elevated = await completeElevation({
|
|
88
|
+
continuation: input.signInTicket,
|
|
89
|
+
tenant: input.client.tenant,
|
|
90
|
+
caller: input.caller,
|
|
91
|
+
// The elevating client, not the session's minting embed id: post-elevation delegated
|
|
92
|
+
// exchanges must assert the issuer a fresh authenticated mint would (ADR 0152).
|
|
93
|
+
clientId: input.client.id,
|
|
94
|
+
origin: input.origin,
|
|
95
|
+
...(input.customerRouting ? { customerRouting: input.customerRouting } : {}),
|
|
96
|
+
}, {
|
|
65
97
|
elevations: deps.elevations,
|
|
66
98
|
elevateSession: (request) => deps.store.elevateSession(request),
|
|
67
99
|
now: () => deps.clock?.() ?? new Date(),
|
|
@@ -76,7 +108,13 @@ export async function elevateAssistantSession(res, deps, input) {
|
|
|
76
108
|
reasonCode: elevated.code,
|
|
77
109
|
actorSubject: input.caller.subject,
|
|
78
110
|
});
|
|
79
|
-
|
|
111
|
+
// `{ error: <human>, code: <machine> }`, the same envelope as public-session refusals: the
|
|
112
|
+
// published client reads `body.code`, and a host must be able to tell "the visitor took too
|
|
113
|
+
// long" from "a client reached across a tenant boundary" without string-matching prose.
|
|
114
|
+
return sendJson(res, elevated.status, {
|
|
115
|
+
error: ELEVATION_REFUSAL_MESSAGES[elevated.code],
|
|
116
|
+
code: elevated.code,
|
|
117
|
+
});
|
|
80
118
|
}
|
|
81
119
|
await deps.audit.emit({
|
|
82
120
|
eventType: 'assistant.session.elevated',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-elevation.js","sourceRoot":"","sources":["../../src/routes/assistant-elevation.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACpF,OAAO,EAAqB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,8BAA8B,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"assistant-elevation.js","sourceRoot":"","sources":["../../src/routes/assistant-elevation.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,8 +33,6 @@ export interface AssistantRouteDeps {
|
|
|
33
33
|
}
|
|
34
34
|
export declare function handleConsoleApprovalNonce(req: IncomingMessage, res: ServerResponse, deps: AssistantRouteDeps): Promise<void>;
|
|
35
35
|
export declare function handleAssistantClients(req: IncomingMessage, res: ServerResponse, tenant: TenantRef, id: string | undefined, action: 'collection' | 'rotate' | 'item', deps: AssistantRouteDeps): Promise<void>;
|
|
36
|
-
/** Validate the customer backend ↔ active embedded-assistant boundary without invoking a tool. */
|
|
37
|
-
export declare function handleAssistantDoctor(req: IncomingMessage, res: ServerResponse, tenant: TenantRef, deps: AssistantRouteDeps): Promise<void>;
|
|
38
36
|
export declare function handleAssistantSession(req: IncomingMessage, res: ServerResponse, deps: AssistantRouteDeps): Promise<void>;
|
|
39
37
|
export declare function handleAssistantTurn(req: IncomingMessage, res: ServerResponse, deps: AssistantRouteDeps): Promise<void>;
|
|
40
38
|
/** Standard MCP operations exposed to an initialized app inside the embedded assistant host. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../src/routes/assistant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAE1F,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAChG,OAAO,EAEL,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../src/routes/assistant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAE1F,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAChG,OAAO,EAEL,KAAK,cAAc,EAKpB,MAAM,gCAAgC,CAAC;AAYxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAK1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAUhE,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,GAAG,EACJ,MAAM,2BAA2B,CAAC;AAInC,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAAC;AAIhF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,gBAAgB,CAAC;IACzC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAC/C,yGAAyG;IACzG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAC/C,mGAAmG;IACnG,QAAQ,CAAC,UAAU,CAAC,EAAE,uBAAuB,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,CAAC;IACvD,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,KAAK,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAED,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,SAAS,EACjB,EAAE,EAAE,MAAM,GAAG,SAAS,EACtB,MAAM,EAAE,YAAY,GAAG,QAAQ,GAAG,MAAM,EACxC,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CA+Ff;AAED,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAmJf;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAsGf;AAED,gGAAgG;AAChG,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAuIf"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clientAddressBucket } from '@noodle-borg/admission-limits';
|
|
2
|
-
import { ASSISTANT_SESSION_IDLE_MS,
|
|
2
|
+
import { ASSISTANT_SESSION_IDLE_MS, dispatchAssistantTool, parseAssistantContextPreferences, parseAssistantCustomerRouting, withAssistantSessionExecutionAuthority, } from '@noodle-borg/assistant-gateway';
|
|
3
3
|
import { canonicalizeAuthorizationClaimValues } from '@noodle-borg/auth';
|
|
4
4
|
import { validateJsonSchemaWithDefaults } from '@noodle-borg/compiler';
|
|
5
5
|
import { evaluateToolAuthorization, mapExecutionError, mapResourceContents, mapResourcesList, mapToolOutput, mapToolsList, } from '@noodle-borg/protocol';
|
|
@@ -143,88 +143,6 @@ export async function handleAssistantClients(req, res, tenant, id, action, deps)
|
|
|
143
143
|
}
|
|
144
144
|
sendJson(res, 405, { error: 'method not allowed' });
|
|
145
145
|
}
|
|
146
|
-
/** Validate the customer backend ↔ active embedded-assistant boundary without invoking a tool. */
|
|
147
|
-
export async function handleAssistantDoctor(req, res, tenant, deps) {
|
|
148
|
-
if (req.method !== 'POST')
|
|
149
|
-
return sendJson(res, 405, { error: 'method not allowed' });
|
|
150
|
-
const identity = await authorizeControlPlane(req, res, deps.gate, { requireIdentity: false });
|
|
151
|
-
if (identity === false)
|
|
152
|
-
return;
|
|
153
|
-
if (identity && !identity.superAdmin) {
|
|
154
|
-
const member = await deps.controlPlane.isOrgMember({
|
|
155
|
-
org: tenant.org,
|
|
156
|
-
subject: identity.subject,
|
|
157
|
-
});
|
|
158
|
-
if (!member)
|
|
159
|
-
return sendForbidden(res, 'forbidden');
|
|
160
|
-
}
|
|
161
|
-
const body = await readJsonBody(req, deps.maxBody);
|
|
162
|
-
if (!body.ok)
|
|
163
|
-
return sendJson(res, body.status, { error: body.error });
|
|
164
|
-
if (!isRecord(body.value))
|
|
165
|
-
return sendJson(res, 400, { error: 'invalid doctor request' });
|
|
166
|
-
const { clientId, clientSecret, origin, userId } = body.value;
|
|
167
|
-
if (typeof clientId !== 'string' ||
|
|
168
|
-
clientId.length < 1 ||
|
|
169
|
-
typeof clientSecret !== 'string' ||
|
|
170
|
-
clientSecret.length < 1 ||
|
|
171
|
-
typeof origin !== 'string' ||
|
|
172
|
-
origin.length < 1 ||
|
|
173
|
-
(userId !== undefined &&
|
|
174
|
-
(typeof userId !== 'string' || userId.length < 1 || userId.length > 240))) {
|
|
175
|
-
return sendJson(res, 400, { error: 'clientId, clientSecret, and origin are required' });
|
|
176
|
-
}
|
|
177
|
-
const target = await deps.registry.getActiveByTenant(tenant);
|
|
178
|
-
const assistant = target?.served.artifact.server.assistant;
|
|
179
|
-
const deploymentOk = Boolean(target?.deploymentId && assistant);
|
|
180
|
-
const client = await deps.store.authenticateClient(clientId, clientSecret);
|
|
181
|
-
const clientOk = client !== undefined && sameTenant(client.tenant, tenant);
|
|
182
|
-
const originOk = assistant?.allowedOrigins.includes(origin) === true;
|
|
183
|
-
let delegatedCredentials;
|
|
184
|
-
if (!deploymentOk || !clientOk || !originOk || !target || !client) {
|
|
185
|
-
delegatedCredentials = {
|
|
186
|
-
ok: false,
|
|
187
|
-
skipped: true,
|
|
188
|
-
reason: 'deployment, client, and origin checks must pass first',
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
else if (target.served.deps.broker.probeDelegatedCredentials === undefined) {
|
|
192
|
-
delegatedCredentials = {
|
|
193
|
-
ok: false,
|
|
194
|
-
skipped: true,
|
|
195
|
-
reason: 'deployment credential broker does not support diagnostics',
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
const probes = await target.served.deps.broker.probeDelegatedCredentials({
|
|
200
|
-
subject: typeof userId === 'string' ? userId : 'noodle-assistant-doctor',
|
|
201
|
-
identityKind: 'customer',
|
|
202
|
-
audience: tenantMcpUrl(deps.serviceBase(req), tenant),
|
|
203
|
-
}, undefined, assistantCustomerIssuer(client.id));
|
|
204
|
-
delegatedCredentials = { ok: probes.every((probe) => probe.ok), probes };
|
|
205
|
-
}
|
|
206
|
-
const checks = {
|
|
207
|
-
deployment: {
|
|
208
|
-
ok: deploymentOk,
|
|
209
|
-
...(target?.deploymentId ? { deploymentId: target.deploymentId } : {}),
|
|
210
|
-
},
|
|
211
|
-
client: {
|
|
212
|
-
ok: clientOk,
|
|
213
|
-
...(clientOk && client ? { createdAgainstDeploymentId: client.deploymentId } : {}),
|
|
214
|
-
},
|
|
215
|
-
origin: {
|
|
216
|
-
ok: originOk,
|
|
217
|
-
origin,
|
|
218
|
-
...(assistant ? { allowedOrigins: assistant.allowedOrigins } : {}),
|
|
219
|
-
},
|
|
220
|
-
delegatedCredentials,
|
|
221
|
-
};
|
|
222
|
-
return sendJson(res, 200, {
|
|
223
|
-
ok: Object.values(checks).every((check) => check.ok),
|
|
224
|
-
...(target?.deploymentId ? { deploymentId: target.deploymentId } : {}),
|
|
225
|
-
checks,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
146
|
export async function handleAssistantSession(req, res, deps) {
|
|
229
147
|
const credentials = basicCredentials(req);
|
|
230
148
|
if (!credentials)
|
|
@@ -300,10 +218,14 @@ export async function handleAssistantSession(req, res, deps) {
|
|
|
300
218
|
};
|
|
301
219
|
// Mid-conversation sign-in (5.6b). Its decision, refusals, audit, and response live in
|
|
302
220
|
// `assistant-elevation.ts`, which owns elevation; this is only the branch.
|
|
303
|
-
if (parsed.
|
|
221
|
+
if (parsed.signInTicket !== undefined) {
|
|
304
222
|
return elevateAssistantSession(res, deps, {
|
|
305
|
-
|
|
223
|
+
signInTicket: parsed.signInTicket,
|
|
306
224
|
client,
|
|
225
|
+
origin: parsed.origin,
|
|
226
|
+
...(customerRouting.customerRouting
|
|
227
|
+
? { customerRouting: customerRouting.customerRouting }
|
|
228
|
+
: {}),
|
|
307
229
|
caller,
|
|
308
230
|
configuration,
|
|
309
231
|
endpoints: {
|
|
@@ -543,9 +465,6 @@ export async function handleAssistantAppRequest(req, res, deps) {
|
|
|
543
465
|
function isRecord(value) {
|
|
544
466
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
545
467
|
}
|
|
546
|
-
function sameTenant(a, b) {
|
|
547
|
-
return a.org === b.org && a.app === b.app && a.env === b.env;
|
|
548
|
-
}
|
|
549
468
|
function basicCredentials(req) {
|
|
550
469
|
const match = /^Basic\s+(.+)$/i.exec(req.headers.authorization ?? '');
|
|
551
470
|
if (!match?.[1])
|