@suveren/gateway 0.36.1 → 0.37.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/content/integrations/erp.json +1 -1
- package/dist/mcp-server/http.mjs +66 -18
- package/dist/ui/assets/{index-BQ5Pr6As.js → index-BC2bXeCQ.js} +26 -26
- package/dist/ui/index.html +1 -1
- package/node_modules/fast-uri/.github/workflows/release.yml +35 -0
- package/node_modules/fast-uri/README.md +8 -0
- package/node_modules/fast-uri/index.js +98 -18
- package/node_modules/fast-uri/lib/utils.js +52 -0
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/host-delimiter-security.test.js +94 -0
- package/node_modules/fast-uri/test/relative-normalization-security.test.js +156 -0
- package/node_modules/fast-uri/test/reserved-path-normalization.test.js +32 -4
- package/node_modules/fast-uri/test/scheme-validation.test.js +53 -14
- package/node_modules/jose/README.md +2 -2
- package/node_modules/jose/dist/types/jwe/compact/decrypt.d.ts +5 -4
- package/node_modules/jose/dist/types/jwe/compact/encrypt.d.ts +4 -4
- package/node_modules/jose/dist/types/jwe/flattened/decrypt.d.ts +5 -4
- package/node_modules/jose/dist/types/jwe/flattened/encrypt.d.ts +5 -5
- package/node_modules/jose/dist/types/jwe/general/decrypt.d.ts +5 -4
- package/node_modules/jose/dist/types/jwe/general/encrypt.d.ts +5 -5
- package/node_modules/jose/dist/types/jws/compact/sign.d.ts +5 -4
- package/node_modules/jose/dist/types/jws/compact/verify.d.ts +5 -5
- package/node_modules/jose/dist/types/jws/flattened/sign.d.ts +5 -4
- package/node_modules/jose/dist/types/jws/flattened/verify.d.ts +6 -5
- package/node_modules/jose/dist/types/jws/general/sign.d.ts +9 -6
- package/node_modules/jose/dist/types/jws/general/verify.d.ts +7 -5
- package/node_modules/jose/dist/types/jwt/decrypt.d.ts +7 -6
- package/node_modules/jose/dist/types/jwt/encrypt.d.ts +1 -1
- package/node_modules/jose/dist/types/jwt/sign.d.ts +1 -1
- package/node_modules/jose/dist/types/jwt/unsecured.d.ts +1 -1
- package/node_modules/jose/dist/types/jwt/verify.d.ts +3 -5
- package/node_modules/jose/dist/types/key/export.d.ts +1 -1
- package/node_modules/jose/dist/types/key/generate_secret.d.ts +1 -1
- package/node_modules/jose/dist/types/key/import.d.ts +2 -2
- package/node_modules/jose/dist/types/types.d.ts +165 -107
- package/node_modules/jose/dist/types/util/decode_jwt.d.ts +2 -2
- package/node_modules/jose/dist/types/util/errors.d.ts +1 -1
- package/node_modules/jose/dist/webapi/jwe/general/encrypt.js +3 -3
- package/node_modules/jose/dist/webapi/jwk/thumbprint.js +8 -8
- package/node_modules/jose/dist/webapi/jwks/local.js +2 -1
- package/node_modules/jose/dist/webapi/jwks/remote.js +4 -4
- package/node_modules/jose/dist/webapi/jws/general/sign.js +3 -3
- package/node_modules/jose/dist/webapi/jws/general/verify.js +3 -3
- package/node_modules/jose/dist/webapi/jwt/encrypt.js +2 -2
- package/node_modules/jose/dist/webapi/jwt/sign.js +2 -2
- package/node_modules/jose/dist/webapi/jwt/unsecured.js +3 -3
- package/node_modules/jose/dist/webapi/key/generate_secret.js +4 -4
- package/node_modules/jose/dist/webapi/lib/asn1.js +2 -2
- package/node_modules/jose/dist/webapi/lib/buffer_utils.js +4 -4
- package/node_modules/jose/dist/webapi/lib/content_encryption.js +8 -8
- package/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +14 -14
- package/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +3 -3
- package/node_modules/jose/dist/webapi/lib/jws_algorithms.js +2 -2
- package/node_modules/jose/dist/webapi/lib/jws_sign.js +11 -11
- package/node_modules/jose/dist/webapi/lib/jws_verify.js +19 -16
- package/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +44 -43
- package/node_modules/jose/dist/webapi/lib/key.js +4 -4
- package/node_modules/jose/dist/webapi/lib/key_management.js +17 -17
- package/node_modules/jose/dist/webapi/lib/validate.js +10 -10
- package/node_modules/jose/dist/webapi/util/decode_jwt.js +12 -12
- package/node_modules/jose/dist/webapi/util/decode_protected_header.js +5 -5
- package/node_modules/jose/package.json +1 -1
- package/package.json +1 -1
- package/profiles/delegation/0.6.profile.json +183 -0
- package/profiles/index.json +2 -1
package/dist/mcp-server/http.mjs
CHANGED
|
@@ -4801,6 +4801,15 @@ async function readPreview(integrationManager2, integrationId, previewTool, args
|
|
|
4801
4801
|
};
|
|
4802
4802
|
}
|
|
4803
4803
|
}
|
|
4804
|
+
function unavailableReadMessage(integrationManager2, read, connector, tool, declaredAt) {
|
|
4805
|
+
if (read.reason === "no_connector") {
|
|
4806
|
+
const running = integrationManager2.getAllTools().some((t) => t.integrationId === connector);
|
|
4807
|
+
if (running) {
|
|
4808
|
+
return `Connector "${connector}" is running but has no tool "${tool}" (declared in ${declaredAt}) \u2014 the installed connector version does not offer it.`;
|
|
4809
|
+
}
|
|
4810
|
+
}
|
|
4811
|
+
return read.message ?? `Connector "${connector}" could not be reached.`;
|
|
4812
|
+
}
|
|
4804
4813
|
function hashPreviewBody(body) {
|
|
4805
4814
|
if (body.structured !== void 0) {
|
|
4806
4815
|
return computeContentHash({ kind: "jcs", version: "1" }, body.structured);
|
|
@@ -5461,7 +5470,8 @@ async function resolveDocumentReference(integrationManager2, ref) {
|
|
|
5461
5470
|
return { ok: false, error: { code: "NOT_FOUND", message: read.message ?? `No document "${ref.kind}"/"${ref.id}" on "${ref.connector}".` } };
|
|
5462
5471
|
}
|
|
5463
5472
|
if (read.status !== "ok") {
|
|
5464
|
-
|
|
5473
|
+
const message = unavailableReadMessage(integrationManager2, read, ref.connector, docConfig.tool, `documents.${ref.kind}`);
|
|
5474
|
+
return { ok: false, error: { code: "UNAVAILABLE", message } };
|
|
5465
5475
|
}
|
|
5466
5476
|
const body = structuredOrJsonText(read.body);
|
|
5467
5477
|
if (!body || typeof body !== "object") {
|
|
@@ -5542,7 +5552,8 @@ async function resolveInsertValue(integrationManager2, ref) {
|
|
|
5542
5552
|
return { ok: false, error: { code: "NOT_FOUND", message: read.message ?? `No value "${ref.kind}"/"${ref.id}" on "${ref.connector}".` } };
|
|
5543
5553
|
}
|
|
5544
5554
|
if (read.status !== "ok") {
|
|
5545
|
-
|
|
5555
|
+
const message = unavailableReadMessage(integrationManager2, read, ref.connector, valueConfig.tool, `values.${ref.kind}`);
|
|
5556
|
+
return { ok: false, error: { code: "UNAVAILABLE", message } };
|
|
5546
5557
|
}
|
|
5547
5558
|
const body = structuredOrJsonText(read.body);
|
|
5548
5559
|
if (!body || typeof body !== "object") {
|
|
@@ -6829,7 +6840,9 @@ function createGatedToolHandlerInner(tool, integrationManager2, state2) {
|
|
|
6829
6840
|
content: [{
|
|
6830
6841
|
type: "text",
|
|
6831
6842
|
text: `Awaiting commitment from domain${auth.deferredCommitmentDomains.length > 1 ? "s" : ""} "${auth.deferredCommitmentDomains.join('", "')}" for tool ${tool.originalName}.
|
|
6832
|
-
Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposal_id: "${proposal.id}").` + await unreadableForNote(unreadableFor ?? [], state2)
|
|
6843
|
+
Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposal_id: "${proposal.id}").` + await unreadableForNote(unreadableFor ?? [], state2) + // Optional wait (2026-10-19): the AI can stay on the line instead of ending its turn.
|
|
6844
|
+
`
|
|
6845
|
+
Tell the person what you proposed and that it waits for their approval in the gateway; then you may wait for the decision: check-pending-commitments(proposal_id: "${proposal.id}", wait_seconds: 50).`
|
|
6833
6846
|
}]
|
|
6834
6847
|
};
|
|
6835
6848
|
} catch (err) {
|
|
@@ -8043,6 +8056,18 @@ Reason: ${detail}` : "";
|
|
|
8043
8056
|
isError: false
|
|
8044
8057
|
};
|
|
8045
8058
|
}
|
|
8059
|
+
var MAX_WAIT_SECONDS = 50;
|
|
8060
|
+
var WAIT_POLL_MS = 2e3;
|
|
8061
|
+
async function getProposalWaiting(get, id, waitSeconds, sleep2 = (ms) => new Promise((r) => setTimeout(r, ms)), now = Date.now) {
|
|
8062
|
+
const waitMs = Math.min(Math.max(Number(waitSeconds) || 0, 0), MAX_WAIT_SECONDS) * 1e3;
|
|
8063
|
+
const deadline = now() + waitMs;
|
|
8064
|
+
let match = await get(id);
|
|
8065
|
+
while (match && match.status === "pending" && now() < deadline) {
|
|
8066
|
+
await sleep2(Math.min(WAIT_POLL_MS, deadline - now()));
|
|
8067
|
+
match = await get(id);
|
|
8068
|
+
}
|
|
8069
|
+
return match;
|
|
8070
|
+
}
|
|
8046
8071
|
function checkPendingCommitmentsHandler(state2, integrationManager2) {
|
|
8047
8072
|
return async (args) => {
|
|
8048
8073
|
if (!state2.spClient.isUnlocked()) {
|
|
@@ -8050,7 +8075,11 @@ function checkPendingCommitmentsHandler(state2, integrationManager2) {
|
|
|
8050
8075
|
}
|
|
8051
8076
|
try {
|
|
8052
8077
|
if (args.proposal_id) {
|
|
8053
|
-
const match = await
|
|
8078
|
+
const match = await getProposalWaiting(
|
|
8079
|
+
(id) => state2.spClient.getProposalById(id),
|
|
8080
|
+
args.proposal_id,
|
|
8081
|
+
args.wait_seconds
|
|
8082
|
+
);
|
|
8054
8083
|
if (!match) {
|
|
8055
8084
|
return {
|
|
8056
8085
|
content: [{
|
|
@@ -8304,9 +8333,10 @@ function createMcpServer(state2, integrationManager2) {
|
|
|
8304
8333
|
server.registerTool(
|
|
8305
8334
|
"check-pending-commitments",
|
|
8306
8335
|
{
|
|
8307
|
-
description: "Check status of pending proposals awaiting domain owner commitment. Call with a proposal_id to check a specific proposal, or without to see all.",
|
|
8336
|
+
description: "Check status of pending proposals awaiting domain owner commitment. Call with a proposal_id to check a specific proposal, or without to see all. With a proposal_id you may also pass wait_seconds (max 50): the gateway then waits until the person decides and answers at once \u2014 first tell the person what you proposed and that it waits for their approval in the gateway.",
|
|
8308
8337
|
inputSchema: {
|
|
8309
|
-
proposal_id: z2.string().optional().describe("Specific proposal ID to check. Omit to see all.")
|
|
8338
|
+
proposal_id: z2.string().optional().describe("Specific proposal ID to check. Omit to see all."),
|
|
8339
|
+
wait_seconds: z2.number().int().min(0).max(50).optional().describe("Only with proposal_id: wait up to this many seconds (max 50) while the proposal is still pending; answers as soon as the person decides. Omit or 0 to answer at once.")
|
|
8310
8340
|
}
|
|
8311
8341
|
},
|
|
8312
8342
|
withOutcomeOutbox(checkPendingCommitmentsHandler(state2, integrationManager2))
|
|
@@ -10497,7 +10527,7 @@ function unifiedLineDiff(before, after) {
|
|
|
10497
10527
|
}
|
|
10498
10528
|
|
|
10499
10529
|
// src/lib/builtins/setup.ts
|
|
10500
|
-
import { getProfile as getProfile9 } from "@hap/core";
|
|
10530
|
+
import { getProfile as getProfile9, listProfiles } from "@hap/core";
|
|
10501
10531
|
var DELEGATION_PROFILE = "delegation";
|
|
10502
10532
|
var DELEGATION_INTENT_HINT = [
|
|
10503
10533
|
"Why \u2014 With test data only, I want to find out which routine parts of my work an AI could take over, so people gain time \u2014 before anything touches real systems.",
|
|
@@ -10541,10 +10571,28 @@ function shortName(idOrName) {
|
|
|
10541
10571
|
function versionOf(id) {
|
|
10542
10572
|
return id.split("@")[1] ?? "";
|
|
10543
10573
|
}
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
|
|
10574
|
+
var MANDATE_ACTION = "mandate";
|
|
10575
|
+
function knownVersions(short) {
|
|
10576
|
+
const byId = /* @__PURE__ */ new Map();
|
|
10577
|
+
for (const key of listProfiles()) {
|
|
10578
|
+
if (shortName(key) !== short) continue;
|
|
10579
|
+
const p = getProfile9(key);
|
|
10580
|
+
if (p) byId.set(p.id, p);
|
|
10581
|
+
}
|
|
10582
|
+
return [...byId.values()];
|
|
10583
|
+
}
|
|
10584
|
+
function proposalTargetRefusal(args) {
|
|
10585
|
+
const requested = typeof args.profile === "string" ? shortName(args.profile.trim()) : "";
|
|
10586
|
+
const versions = requested ? knownVersions(requested) : [];
|
|
10587
|
+
if (versions.length === 0) {
|
|
10588
|
+
return { code: "UNKNOWN_PROFILE", message: `Unknown profile "${requested}" \u2014 not in this gateway's profile catalog.` };
|
|
10589
|
+
}
|
|
10590
|
+
if (versions.some((p) => p.boundsSchema?.actionTypes?.includes(MANDATE_ACTION))) {
|
|
10591
|
+
const name = versions.map((p) => p.name).find(Boolean) ?? requested;
|
|
10592
|
+
return {
|
|
10593
|
+
code: "DELEGATION_NOT_PROPOSABLE",
|
|
10594
|
+
message: `${name} can never be proposed \u2014 it lets an AI propose mandates, and the AI cannot widen its own delegation.`
|
|
10595
|
+
};
|
|
10548
10596
|
}
|
|
10549
10597
|
return void 0;
|
|
10550
10598
|
}
|
|
@@ -10711,7 +10759,7 @@ function setupBuiltin(deps) {
|
|
|
10711
10759
|
},
|
|
10712
10760
|
create_mandate: {
|
|
10713
10761
|
executionMapping: { profile: "allowed_profiles", mode: "allowed_modes" },
|
|
10714
|
-
staticExecution: { action_type:
|
|
10762
|
+
staticExecution: { action_type: MANDATE_ACTION },
|
|
10715
10763
|
actionLabel: "Mandate proposed",
|
|
10716
10764
|
hideUnlessAuthorized: true,
|
|
10717
10765
|
// Shown like the mandate screen: limits and scope by the profile's own names.
|
|
@@ -10800,7 +10848,7 @@ ${body}`);
|
|
|
10800
10848
|
description: "Propose a new mandate for the person running this gateway \u2014 the authority another tool needs (e.g. sales quotes up to a value). Always goes to the person's current workspace (their team, or Personal if they are not in one) \u2014 there is no way to name a different one. A person approves or rejects the proposal; only after approval is the mandate created, exactly as if they had signed it on the mandate screen. Checked against the profile before the proposal: unknown limits, a mode the profile does not allow, or a team where the person may not give this mandate are refused at once. Outside simulation mode, the profile and mode you may propose are themselves limited by your Delegation mandate's scope \u2014 Delegation itself can never be proposed. Create only.",
|
|
10801
10849
|
inputSchema: CREATE_MANDATE_INPUT_SCHEMA,
|
|
10802
10850
|
validate: async (args) => {
|
|
10803
|
-
const fixed =
|
|
10851
|
+
const fixed = proposalTargetRefusal(args);
|
|
10804
10852
|
if (fixed) {
|
|
10805
10853
|
deps.state.denialLog?.record({
|
|
10806
10854
|
ts: Date.now(),
|
|
@@ -10808,18 +10856,18 @@ ${body}`);
|
|
|
10808
10856
|
integrationId: "setup",
|
|
10809
10857
|
profile: DELEGATION_PROFILE,
|
|
10810
10858
|
kind: "bound",
|
|
10811
|
-
detail: fixed,
|
|
10859
|
+
detail: fixed.message,
|
|
10812
10860
|
who: "gateway",
|
|
10813
|
-
code:
|
|
10861
|
+
code: fixed.code
|
|
10814
10862
|
});
|
|
10815
|
-
return fixed;
|
|
10863
|
+
return fixed.message;
|
|
10816
10864
|
}
|
|
10817
10865
|
const check = await controlPlaneMandate(true, mandateRequest(args));
|
|
10818
10866
|
return check.ok ? void 0 : check.message;
|
|
10819
10867
|
},
|
|
10820
10868
|
handler: async (args) => {
|
|
10821
|
-
const fixed =
|
|
10822
|
-
if (fixed) return { ...builtinText(`Refused: ${fixed}`), isError: true };
|
|
10869
|
+
const fixed = proposalTargetRefusal(args);
|
|
10870
|
+
if (fixed) return { ...builtinText(`Refused: ${fixed.message}`), isError: true };
|
|
10823
10871
|
const r = await controlPlaneMandate(false, mandateRequest(args));
|
|
10824
10872
|
if (!r.ok) return { ...builtinText(`Refused: ${r.message}`), isError: true };
|
|
10825
10873
|
return builtinText(
|