@sema-agent/server 7.87.2 → 7.88.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/auth-bridge.js +5 -3
- package/dist/boot/device-lane.d.ts +12 -19
- package/dist/boot/device-lane.js +3 -13
- package/dist/boot/stage-05-execution-env.js +1 -2
- package/dist/boot/stage-07-capability-layer.js +2 -1
- package/dist/boot/stage-09-leader.js +2 -1
- package/dist/boot/stage-10-http-server.js +4 -2
- package/dist/boot/stores.js +2 -1
- package/dist/brain.js +3 -2
- package/dist/config-catalog.js +4 -3
- package/dist/config-center/apply-effective.js +3 -2
- package/dist/config-center/http-client.d.ts +11 -2
- package/dist/config-center/http-client.js +1 -1
- package/dist/config-center/read-warnings.d.ts +1 -1
- package/dist/config-center/read-warnings.js +5 -3
- package/dist/config-center/types.d.ts +3 -1
- package/dist/config-invariants.d.ts +2 -2
- package/dist/config-invariants.js +12 -0
- package/dist/config-provider.d.ts +9 -1
- package/dist/config-provider.js +3 -1
- package/dist/config-types.d.ts +7 -0
- package/dist/config.js +28 -3
- package/dist/device-enrollment.d.ts +25 -4
- package/dist/device-enrollment.js +20 -2
- package/dist/device-protocol.d.ts +15 -0
- package/dist/device-protocol.js +2 -0
- package/dist/device-ws-hub.d.ts +11 -0
- package/dist/device-ws-hub.js +6 -0
- package/dist/fleet-client.js +2 -1
- package/dist/http/admission.js +10 -1
- package/dist/http/device-placement.d.ts +177 -0
- package/dist/http/device-placement.js +148 -0
- package/dist/http/durable-run-leg.js +4 -0
- package/dist/http/resume-legs.js +4 -0
- package/dist/http/route-ctx.d.ts +8 -0
- package/dist/http/routes/capabilities.js +1 -1
- package/dist/http/routes/devices.d.ts +18 -8
- package/dist/http/routes/devices.js +175 -12
- package/dist/http/routes/tasks.js +10 -0
- package/dist/http/server.d.ts +13 -0
- package/dist/http/wire-types.d.ts +15 -0
- package/dist/model-route-url.d.ts +15 -0
- package/dist/model-route-url.js +19 -0
- package/dist/request-key-closure.js +1 -1
- package/dist/run-local.js +2 -1
- package/dist/sealed-key.js +2 -1
- package/dist/security.d.ts +6 -0
- package/dist/security.js +3 -0
- package/dist/trace/redact.d.ts +20 -0
- package/dist/trace/redact.js +117 -26
- package/package.json +7 -3
package/dist/trace/redact.js
CHANGED
|
@@ -591,11 +591,28 @@ const keywordArm = (keywordSrc, valueClass, min, tailSrc = "") => {
|
|
|
591
591
|
`|(?<!${WORD_SEGMENT_CLASS})${keywordSrc}(?:${twoStrongAhead(valueClass)}|${noConnectorAhead(valueClass)})${atLeast(valueClass, min)}${tailSrc})`, "g");
|
|
592
592
|
return re;
|
|
593
593
|
};
|
|
594
|
+
const CREDENTIAL_NAME_WORDS = [
|
|
595
|
+
"api_key", "apikey", "api-key", "key",
|
|
596
|
+
"token", "access_token", "refresh_token", "id_token",
|
|
597
|
+
"auth", "authorization",
|
|
598
|
+
"password", "passwd", "pwd",
|
|
599
|
+
"secret", "client_secret", "private_key",
|
|
600
|
+
"signature", "sig",
|
|
601
|
+
"x-amz-signature", "x-amz-security-token", "x-amz-credential",
|
|
602
|
+
"sas",
|
|
603
|
+
];
|
|
604
|
+
const CREDENTIAL_NAME_ALT = (() => {
|
|
605
|
+
for (const w of CREDENTIAL_NAME_WORDS) {
|
|
606
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(w))
|
|
607
|
+
throw new Error(`redact: credential name ${JSON.stringify(w)} must be lowercase [a-z0-9_-] (the alternation is built without escaping)`);
|
|
608
|
+
}
|
|
609
|
+
return [...CREDENTIAL_NAME_WORDS].sort((a, b) => b.length - a.length || (a < b ? -1 : 1)).join("|");
|
|
610
|
+
})();
|
|
594
611
|
const STRUCTURAL_SECRET_PATTERNS = [
|
|
595
612
|
[/-----BEGIN(?:[^-](?:[^-](?:[^-]|-(?!-))*)?)?PRIVATE KEY(?: BLOCK)?-----[\s\S]{0,8192}?-----END(?:[^-](?:[^-](?:[^-]|-(?!-))*)?)?PRIVATE KEY(?: BLOCK)?-----/g, "«redacted:private-key»"],
|
|
596
613
|
[/---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----[\s\S]{0,8192}?---- END SSH2 ENCRYPTED PRIVATE KEY ----/g, "«redacted:private-key»"],
|
|
597
|
-
[/:(?<=[A-Za-z][A-Za-z0-9+.-]*:)\/\//g, "$1
|
|
598
|
-
[
|
|
614
|
+
[/:(?<=[A-Za-z][A-Za-z0-9+.-]*:)\/\//g, "$1«redacted»"],
|
|
615
|
+
[new RegExp(String.raw `("(?:${CREDENTIAL_NAME_ALT})"\s*:\s*)"[^"\\]*(?:\\.[^"\\]*)*"`, "gi"), '$1"«redacted»"'],
|
|
599
616
|
];
|
|
600
617
|
const PPK_CONTAINER_TOKEN = "«redacted:private-key»";
|
|
601
618
|
const PEM_FRAGMENT_TOKEN = "«redacted:private-key:partial»";
|
|
@@ -1067,7 +1084,8 @@ const FRAGMENT_SECRET_PATTERNS = [
|
|
|
1067
1084
|
[valueArm("(?:gl(?:pat|dt|rt|rtr|cbt|ptt|oas|ft|imt|agent|wt|soat|ffct)-|(?:sk|rk)_(?:live|test|org)_|pypi-)", "[A-Za-z0-9_-]", 8, "needs-left-boundary"), "«redacted:key:partial»"],
|
|
1068
1085
|
[valueArm("xapp-\\d-", "[A-Za-z0-9-]", 4, "needs-left-boundary"), "«redacted:slack-token:partial»"],
|
|
1069
1086
|
];
|
|
1070
|
-
const
|
|
1087
|
+
const DISPLAY_SAFE_URL_TOKEN = "«redacted:url»";
|
|
1088
|
+
const REDACTION_TOKENS = new Set([...FULL_ARM_PATTERNS.map(([, r]) => r), PEM_FRAGMENT_TOKEN, DISPLAY_SAFE_URL_TOKEN, ...FRAGMENT_SECRET_PATTERNS.map(([, r]) => r)]
|
|
1071
1089
|
.flatMap((r) => r.match(/«[^»]*»/g) ?? []));
|
|
1072
1090
|
{
|
|
1073
1091
|
const closed = new RegExp(`^${REDACTION_TOKEN_RE_SRC}$`);
|
|
@@ -1091,11 +1109,11 @@ const FRAGMENT_ARM_TOKENS = new Set(FRAGMENT_SECRET_PATTERNS.map(([, repl]) => r
|
|
|
1091
1109
|
}
|
|
1092
1110
|
const armOfToken = (repl) => (FRAGMENT_ARM_TOKENS.has(repl) ? "fragment" : "full");
|
|
1093
1111
|
const NO_HITS = [];
|
|
1094
|
-
const
|
|
1095
|
-
const
|
|
1096
|
-
if (
|
|
1097
|
-
throw new Error(
|
|
1098
|
-
return
|
|
1112
|
+
const URL_CREDENTIAL_PATTERN = (() => {
|
|
1113
|
+
const rows = FULL_ARM_PATTERNS.filter(([, repl]) => repl === "$1«redacted»");
|
|
1114
|
+
if (rows.length !== 1)
|
|
1115
|
+
throw new Error(`redact: expected exactly one URL-credential rule (replacement "$1«redacted»") in FULL_ARM_PATTERNS, found ${rows.length}`);
|
|
1116
|
+
return rows[0];
|
|
1099
1117
|
})();
|
|
1100
1118
|
const SSH2_FENCE_PATTERN = (() => {
|
|
1101
1119
|
const row = FULL_ARM_PATTERNS.find(([re]) => re.source.startsWith(SSH2_FENCE_OPEN));
|
|
@@ -1105,7 +1123,51 @@ const SSH2_FENCE_PATTERN = (() => {
|
|
|
1105
1123
|
})();
|
|
1106
1124
|
const isRegexSpace = (c) => c === 32 || (c >= 9 && c <= 13) || c === 0xa0 || c === 0x1680 || (c >= 0x2000 && c <= 0x200a) || c === 0x2028 || c === 0x2029 || c === 0x202f || c === 0x205f || c === 0x3000 || c === 0xfeff;
|
|
1107
1125
|
const isLineTerminator = (c) => c === 10 || c === 13 || c === 0x2028 || c === 0x2029;
|
|
1126
|
+
const isControlCode = (c) => c < 0x20 || c === 0x7f;
|
|
1108
1127
|
const TOKEN_UNIT_Y = new RegExp(REDACTION_TOKEN_RE_SRC, "y");
|
|
1128
|
+
const CREDENTIAL_PARAM_Y = new RegExp(`(?:${CREDENTIAL_NAME_ALT})=`, "iy");
|
|
1129
|
+
const CREDENTIAL_NAME_SET = new Set(CREDENTIAL_NAME_WORDS);
|
|
1130
|
+
const CREDENTIAL_NAME_SCAN_MAX = Math.max(...CREDENTIAL_NAME_WORDS.map((w) => w.length)) * 3 + 1;
|
|
1131
|
+
function decodeAsciiName(name) {
|
|
1132
|
+
let out = "";
|
|
1133
|
+
for (let i = 0; i < name.length; i++) {
|
|
1134
|
+
const c = name.charCodeAt(i);
|
|
1135
|
+
if (c !== 37) {
|
|
1136
|
+
out += name[i];
|
|
1137
|
+
continue;
|
|
1138
|
+
}
|
|
1139
|
+
const hex = name.slice(i + 1, i + 3);
|
|
1140
|
+
if (hex.length !== 2 || !/^[0-9A-Fa-f]{2}$/.test(hex))
|
|
1141
|
+
return undefined;
|
|
1142
|
+
const b = Number.parseInt(hex, 16);
|
|
1143
|
+
if (b >= 0x80)
|
|
1144
|
+
return undefined;
|
|
1145
|
+
out += String.fromCharCode(b);
|
|
1146
|
+
i += 2;
|
|
1147
|
+
}
|
|
1148
|
+
return out;
|
|
1149
|
+
}
|
|
1150
|
+
function credentialParamValueStart(text, p) {
|
|
1151
|
+
CREDENTIAL_PARAM_Y.lastIndex = p;
|
|
1152
|
+
if (CREDENTIAL_PARAM_Y.test(text))
|
|
1153
|
+
return CREDENTIAL_PARAM_Y.lastIndex;
|
|
1154
|
+
const limit = Math.min(text.length, p + CREDENTIAL_NAME_SCAN_MAX);
|
|
1155
|
+
let hasPct = false;
|
|
1156
|
+
for (let i = p; i < limit; i++) {
|
|
1157
|
+
const c = text.charCodeAt(i);
|
|
1158
|
+
if (c === 37) {
|
|
1159
|
+
hasPct = true;
|
|
1160
|
+
continue;
|
|
1161
|
+
}
|
|
1162
|
+
if (c !== CH_EQ)
|
|
1163
|
+
continue;
|
|
1164
|
+
if (!hasPct)
|
|
1165
|
+
return -1;
|
|
1166
|
+
const decoded = decodeAsciiName(text.slice(p, i));
|
|
1167
|
+
return decoded !== undefined && CREDENTIAL_NAME_SET.has(decoded.toLowerCase()) ? i + 1 : -1;
|
|
1168
|
+
}
|
|
1169
|
+
return -1;
|
|
1170
|
+
}
|
|
1109
1171
|
function tokenUnitEnd(text, p) {
|
|
1110
1172
|
TOKEN_UNIT_Y.lastIndex = p;
|
|
1111
1173
|
return TOKEN_UNIT_Y.test(text) ? TOKEN_UNIT_Y.lastIndex : -1;
|
|
@@ -1195,8 +1257,10 @@ function opaqueUnitEnd(p) {
|
|
|
1195
1257
|
scanEvidenceCursor = k;
|
|
1196
1258
|
return k < st.length && st[k] === p ? scanEvidence.ends[k] : -1;
|
|
1197
1259
|
}
|
|
1198
|
-
|
|
1260
|
+
let lastAtInRun = -1;
|
|
1261
|
+
function scanUrlRun(text, i, kind, json) {
|
|
1199
1262
|
const n = text.length;
|
|
1263
|
+
lastAtInRun = -1;
|
|
1200
1264
|
while (i < n) {
|
|
1201
1265
|
const unit = opaqueUnitEnd(i);
|
|
1202
1266
|
if (unit >= 0) {
|
|
@@ -1211,11 +1275,11 @@ function scanUserinfoRun(text, i, kind, json) {
|
|
|
1211
1275
|
}
|
|
1212
1276
|
return i;
|
|
1213
1277
|
}
|
|
1214
|
-
if (
|
|
1278
|
+
if (isRegexSpace(c) || (json && c === 34))
|
|
1215
1279
|
return i;
|
|
1216
1280
|
switch (kind) {
|
|
1217
1281
|
case "plain-user":
|
|
1218
|
-
if (c === 47 || c === 58)
|
|
1282
|
+
if (c === CH_AT || c === 47 || c === 58)
|
|
1219
1283
|
return i;
|
|
1220
1284
|
break;
|
|
1221
1285
|
case "plain-pass":
|
|
@@ -1226,33 +1290,50 @@ function scanUserinfoRun(text, i, kind, json) {
|
|
|
1226
1290
|
if (c === 58 && text.charCodeAt(i + 1) === 47 && text.charCodeAt(i + 2) === 47)
|
|
1227
1291
|
return i;
|
|
1228
1292
|
break;
|
|
1293
|
+
case "param-value":
|
|
1294
|
+
if (c === 38 || c === 35 || isControlCode(c))
|
|
1295
|
+
return i;
|
|
1296
|
+
break;
|
|
1229
1297
|
}
|
|
1298
|
+
if (c === CH_AT)
|
|
1299
|
+
lastAtInRun = i;
|
|
1230
1300
|
i += 1;
|
|
1231
1301
|
}
|
|
1232
1302
|
return i;
|
|
1233
1303
|
}
|
|
1234
1304
|
function matchUserinfoAt(text, p, json) {
|
|
1235
|
-
const
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
const passEnd = scanUserinfoRun(text, userEnd + 1, keyId ? "token-pass" : "plain-pass", json);
|
|
1240
|
-
if (passEnd === userEnd + 1 || text.charCodeAt(passEnd) !== 64)
|
|
1305
|
+
const probeEnd = scanUrlRun(text, p, "plain-user", json);
|
|
1306
|
+
const keyId = probeEnd > p && text.charCodeAt(probeEnd) === 58 && credentialSpansCover(scanEvidence, p, probeEnd);
|
|
1307
|
+
scanUrlRun(text, p, keyId ? "token-pass" : "plain-pass", json);
|
|
1308
|
+
if (lastAtInRun <= p)
|
|
1241
1309
|
return null;
|
|
1242
|
-
return
|
|
1310
|
+
return lastAtInRun;
|
|
1243
1311
|
}
|
|
1244
|
-
function
|
|
1245
|
-
const head =
|
|
1312
|
+
function collectUrlCredentialSpans(text, json, span) {
|
|
1313
|
+
const head = URL_CREDENTIAL_PATTERN[0];
|
|
1246
1314
|
head.lastIndex = 0;
|
|
1247
1315
|
for (let m = head.exec(text); m !== null; m = head.exec(text)) {
|
|
1248
1316
|
const colon = m.index;
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1317
|
+
const start = colon + 3;
|
|
1318
|
+
const at = matchUserinfoAt(text, start, json);
|
|
1319
|
+
if (at === null) {
|
|
1251
1320
|
head.lastIndex = colon + 1;
|
|
1252
1321
|
continue;
|
|
1253
1322
|
}
|
|
1254
|
-
span(
|
|
1255
|
-
head.lastIndex =
|
|
1323
|
+
span(start, at);
|
|
1324
|
+
head.lastIndex = at + 1;
|
|
1325
|
+
}
|
|
1326
|
+
for (let i = 0; i < text.length; i++) {
|
|
1327
|
+
const c = text.charCodeAt(i);
|
|
1328
|
+
if (c !== 63 && c !== 38 && c !== 35)
|
|
1329
|
+
continue;
|
|
1330
|
+
const valueStart = credentialParamValueStart(text, i + 1);
|
|
1331
|
+
if (valueStart < 0)
|
|
1332
|
+
continue;
|
|
1333
|
+
const valueEnd = scanUrlRun(text, valueStart, "param-value", json);
|
|
1334
|
+
if (valueEnd > valueStart)
|
|
1335
|
+
span(valueStart, valueEnd);
|
|
1336
|
+
i = valueEnd - 1;
|
|
1256
1337
|
}
|
|
1257
1338
|
}
|
|
1258
1339
|
let ppkScanBytes = 0;
|
|
@@ -1437,8 +1518,8 @@ const armPool = (() => {
|
|
|
1437
1518
|
const members = [];
|
|
1438
1519
|
for (const row of STRUCTURAL_SECRET_PATTERNS) {
|
|
1439
1520
|
const order = members.length;
|
|
1440
|
-
members.push(row ===
|
|
1441
|
-
? scannerMember(row[1], order, 2, (text, json, _observe, span) =>
|
|
1521
|
+
members.push(row === URL_CREDENTIAL_PATTERN
|
|
1522
|
+
? scannerMember(row[1], order, 2, (text, json, _observe, span) => collectUrlCredentialSpans(text, json, span))
|
|
1442
1523
|
: row === SSH2_FENCE_PATTERN
|
|
1443
1524
|
? scannerMember(row[1], order, 2, (text, _json, _observe, span) => collectSsh2FenceSpans(text, span))
|
|
1444
1525
|
: regexMember(row, ARM_RANK.structural, order, true));
|
|
@@ -1631,4 +1712,14 @@ export function redactedPreview(value, cap = 2000) {
|
|
|
1631
1712
|
s = redactSecrets(s, { json: true });
|
|
1632
1713
|
return s.length > cap ? `${s.slice(0, cap)}…[truncated]` : s;
|
|
1633
1714
|
}
|
|
1715
|
+
export function buildDisplaySafeUrl(raw) {
|
|
1716
|
+
if (raw === "")
|
|
1717
|
+
return "";
|
|
1718
|
+
if (!URL.canParse(raw))
|
|
1719
|
+
return DISPLAY_SAFE_URL_TOKEN;
|
|
1720
|
+
const u = new URL(raw);
|
|
1721
|
+
if (!u.href.startsWith(`${u.protocol}//`))
|
|
1722
|
+
return DISPLAY_SAFE_URL_TOKEN;
|
|
1723
|
+
return redactSecrets(u.href);
|
|
1724
|
+
}
|
|
1634
1725
|
//# sourceMappingURL=redact.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.88.0",
|
|
4
4
|
"description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"./main": {
|
|
15
15
|
"default": "./dist/main.js"
|
|
16
16
|
},
|
|
17
|
+
"./device-protocol": {
|
|
18
|
+
"types": "./dist/device-protocol.d.ts",
|
|
19
|
+
"default": "./dist/device-protocol.js"
|
|
20
|
+
},
|
|
17
21
|
"./package.json": "./package.json"
|
|
18
22
|
},
|
|
19
23
|
"files": [
|
|
@@ -54,8 +58,8 @@
|
|
|
54
58
|
"build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
|
|
55
59
|
},
|
|
56
60
|
"dependencies": {
|
|
57
|
-
"@sema-agent/core": "7.23.
|
|
58
|
-
"@sema-agent/settings-schema": "
|
|
61
|
+
"@sema-agent/core": "7.23.3",
|
|
62
|
+
"@sema-agent/settings-schema": "3.0.0",
|
|
59
63
|
"e2b": "^2.28.0",
|
|
60
64
|
"libsodium-wrappers": "^0.8.4",
|
|
61
65
|
"mysql2": "^3.22.4",
|