@nextera.one/axis-server-sdk 2.2.8 → 2.3.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/{index-CZ3RXsBC.d.mts → index-Bng8utj8.d.mts} +8 -4
- package/dist/{index-DEh3s2yx.d.ts → index-DJbM2lNM.d.ts} +8 -4
- package/dist/index.d.mts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +499 -467
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +499 -467
- package/dist/index.mjs.map +1 -1
- package/dist/sensors/index.d.mts +3 -3
- package/dist/sensors/index.d.ts +3 -3
- package/dist/sensors/index.js +497 -467
- package/dist/sensors/index.js.map +1 -1
- package/dist/sensors/index.mjs +497 -467
- package/dist/sensors/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -237,6 +237,16 @@ function AxisPublic() {
|
|
|
237
237
|
return target;
|
|
238
238
|
};
|
|
239
239
|
}
|
|
240
|
+
function AxisAuthorized() {
|
|
241
|
+
return (target, propertyKey, descriptor) => {
|
|
242
|
+
if (descriptor) {
|
|
243
|
+
Reflect.defineMetadata(AXIS_AUTHORIZED_KEY, true, target, propertyKey);
|
|
244
|
+
return descriptor;
|
|
245
|
+
}
|
|
246
|
+
Reflect.defineMetadata(AXIS_AUTHORIZED_KEY, true, target);
|
|
247
|
+
return target;
|
|
248
|
+
};
|
|
249
|
+
}
|
|
240
250
|
function AxisAnonymous() {
|
|
241
251
|
return (target, propertyKey, descriptor) => {
|
|
242
252
|
if (descriptor) {
|
|
@@ -253,7 +263,7 @@ function AxisRateLimit(config) {
|
|
|
253
263
|
return descriptor;
|
|
254
264
|
};
|
|
255
265
|
}
|
|
256
|
-
var import_reflect_metadata3, AXIS_META_KEY, SENSITIVITY_METADATA_KEY, CONTRACT_METADATA_KEY, REQUIRED_PROOF_METADATA_KEY, AXIS_PUBLIC_KEY, AXIS_ANONYMOUS_KEY, AXIS_RATE_LIMIT_KEY;
|
|
266
|
+
var import_reflect_metadata3, AXIS_META_KEY, SENSITIVITY_METADATA_KEY, CONTRACT_METADATA_KEY, REQUIRED_PROOF_METADATA_KEY, AXIS_PUBLIC_KEY, AXIS_ANONYMOUS_KEY, AXIS_AUTHORIZED_KEY, AXIS_RATE_LIMIT_KEY;
|
|
257
267
|
var init_intent_policy_decorator = __esm({
|
|
258
268
|
"src/decorators/intent-policy.decorator.ts"() {
|
|
259
269
|
import_reflect_metadata3 = require("reflect-metadata");
|
|
@@ -263,6 +273,7 @@ var init_intent_policy_decorator = __esm({
|
|
|
263
273
|
REQUIRED_PROOF_METADATA_KEY = "axis:required_proof";
|
|
264
274
|
AXIS_PUBLIC_KEY = "axis:public";
|
|
265
275
|
AXIS_ANONYMOUS_KEY = "axis:anonymous";
|
|
276
|
+
AXIS_AUTHORIZED_KEY = "axis:authorized";
|
|
266
277
|
AXIS_RATE_LIMIT_KEY = "axis:rateLimit";
|
|
267
278
|
}
|
|
268
279
|
});
|
|
@@ -1396,199 +1407,464 @@ var init_axis_chain_executor = __esm({
|
|
|
1396
1407
|
}
|
|
1397
1408
|
});
|
|
1398
1409
|
|
|
1399
|
-
// src/
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
CCE_PROTOCOL_VERSION = "cce-v1";
|
|
1404
|
-
CCE_DERIVATION = {
|
|
1405
|
-
/** Request execution context */
|
|
1406
|
-
REQUEST: "axis:cce:req:v1",
|
|
1407
|
-
/** Response execution context */
|
|
1408
|
-
RESPONSE: "axis:cce:resp:v1",
|
|
1409
|
-
/** Witness binding context */
|
|
1410
|
-
WITNESS: "axis:cce:witness:v1"
|
|
1411
|
-
};
|
|
1412
|
-
CCE_AES_KEY_BYTES = 32;
|
|
1413
|
-
CCE_IV_BYTES = 12;
|
|
1414
|
-
CCE_NONCE_BYTES = 32;
|
|
1415
|
-
CCE_ERROR = {
|
|
1416
|
-
// Envelope errors
|
|
1417
|
-
INVALID_ENVELOPE: "CCE_INVALID_ENVELOPE",
|
|
1418
|
-
UNSUPPORTED_VERSION: "CCE_UNSUPPORTED_VERSION",
|
|
1419
|
-
MISSING_CAPSULE: "CCE_MISSING_CAPSULE",
|
|
1420
|
-
MISSING_ENCRYPTED_KEY: "CCE_MISSING_ENCRYPTED_KEY",
|
|
1421
|
-
// Signature errors
|
|
1422
|
-
CLIENT_SIG_INVALID: "CCE_CLIENT_SIG_INVALID",
|
|
1423
|
-
CLIENT_KEY_NOT_FOUND: "CCE_CLIENT_KEY_NOT_FOUND",
|
|
1424
|
-
// Capsule errors
|
|
1425
|
-
CAPSULE_SIG_INVALID: "CCE_CAPSULE_SIG_INVALID",
|
|
1426
|
-
CAPSULE_EXPIRED: "CCE_CAPSULE_EXPIRED",
|
|
1427
|
-
CAPSULE_NOT_YET_VALID: "CCE_CAPSULE_NOT_YET_VALID",
|
|
1428
|
-
CAPSULE_REVOKED: "CCE_CAPSULE_REVOKED",
|
|
1429
|
-
CAPSULE_CONSUMED: "CCE_CAPSULE_CONSUMED",
|
|
1430
|
-
CAPSULE_NOT_VERIFIED: "CCE_CAPSULE_NOT_VERIFIED",
|
|
1431
|
-
// Binding errors
|
|
1432
|
-
AUDIENCE_MISMATCH: "CCE_AUDIENCE_MISMATCH",
|
|
1433
|
-
INTENT_MISMATCH: "CCE_INTENT_MISMATCH",
|
|
1434
|
-
TPS_WINDOW_EXPIRED: "CCE_TPS_WINDOW_EXPIRED",
|
|
1435
|
-
TPS_WINDOW_FUTURE: "CCE_TPS_WINDOW_FUTURE",
|
|
1436
|
-
// Replay / nonce errors
|
|
1437
|
-
REPLAY_DETECTED: "CCE_REPLAY_DETECTED",
|
|
1438
|
-
NONCE_REUSED: "CCE_NONCE_REUSED",
|
|
1439
|
-
// Decryption errors
|
|
1440
|
-
DECRYPTION_FAILED: "CCE_DECRYPTION_FAILED",
|
|
1441
|
-
KEY_UNWRAP_FAILED: "CCE_KEY_UNWRAP_FAILED",
|
|
1442
|
-
AEAD_TAG_MISMATCH: "CCE_AEAD_TAG_MISMATCH",
|
|
1443
|
-
PAYLOAD_TOO_LARGE: "CCE_PAYLOAD_TOO_LARGE",
|
|
1444
|
-
// Schema / validation errors
|
|
1445
|
-
PAYLOAD_SCHEMA_INVALID: "CCE_PAYLOAD_SCHEMA_INVALID",
|
|
1446
|
-
INTENT_SCHEMA_MISMATCH: "CCE_INTENT_SCHEMA_MISMATCH",
|
|
1447
|
-
// Policy errors
|
|
1448
|
-
POLICY_DENIED: "CCE_POLICY_DENIED",
|
|
1449
|
-
CONSTRAINT_VIOLATED: "CCE_CONSTRAINT_VIOLATED",
|
|
1450
|
-
// Handler errors
|
|
1451
|
-
HANDLER_NOT_FOUND: "CCE_HANDLER_NOT_FOUND",
|
|
1452
|
-
HANDLER_EXECUTION_FAILED: "CCE_HANDLER_EXECUTION_FAILED",
|
|
1453
|
-
HANDLER_TIMEOUT: "CCE_HANDLER_TIMEOUT",
|
|
1454
|
-
// Response errors
|
|
1455
|
-
RESPONSE_ENCRYPTION_FAILED: "CCE_RESPONSE_ENCRYPTION_FAILED"
|
|
1456
|
-
};
|
|
1457
|
-
CceError = class extends Error {
|
|
1458
|
-
constructor(code, message, metadata) {
|
|
1459
|
-
super(`[${code}] ${message}`);
|
|
1460
|
-
this.code = code;
|
|
1461
|
-
this.metadata = metadata;
|
|
1462
|
-
this.name = "CceError";
|
|
1463
|
-
}
|
|
1464
|
-
/** Whether this error is safe to expose to the client */
|
|
1465
|
-
get clientSafe() {
|
|
1466
|
-
const internal = [
|
|
1467
|
-
CCE_ERROR.DECRYPTION_FAILED,
|
|
1468
|
-
CCE_ERROR.KEY_UNWRAP_FAILED,
|
|
1469
|
-
CCE_ERROR.AEAD_TAG_MISMATCH,
|
|
1470
|
-
CCE_ERROR.HANDLER_EXECUTION_FAILED,
|
|
1471
|
-
CCE_ERROR.RESPONSE_ENCRYPTION_FAILED
|
|
1472
|
-
];
|
|
1473
|
-
return !internal.includes(this.code);
|
|
1474
|
-
}
|
|
1475
|
-
/** Get client-safe representation */
|
|
1476
|
-
toClientError() {
|
|
1477
|
-
if (this.clientSafe) {
|
|
1478
|
-
return { code: this.code, message: this.message };
|
|
1479
|
-
}
|
|
1480
|
-
return {
|
|
1481
|
-
code: CCE_ERROR.DECRYPTION_FAILED,
|
|
1482
|
-
message: "Request processing failed"
|
|
1483
|
-
};
|
|
1484
|
-
}
|
|
1485
|
-
};
|
|
1410
|
+
// src/security/scopes.ts
|
|
1411
|
+
function hasScope(scopes, required) {
|
|
1412
|
+
if (!Array.isArray(scopes) || scopes.length === 0) {
|
|
1413
|
+
return false;
|
|
1486
1414
|
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
// src/cce/cce-derivation.service.ts
|
|
1490
|
-
function buildSalt(capsuleId, capsuleNonce, requestNonce) {
|
|
1491
|
-
const encoder = new TextEncoder();
|
|
1492
|
-
const data = encoder.encode(
|
|
1493
|
-
capsuleId + "|" + capsuleNonce + "|" + requestNonce
|
|
1494
|
-
);
|
|
1495
|
-
return (0, import_sha2.sha256)(data);
|
|
1496
|
-
}
|
|
1497
|
-
function buildInfo(contextPrefix, capsule, extraNonce) {
|
|
1498
|
-
const encoder = new TextEncoder();
|
|
1499
|
-
const parts = [
|
|
1500
|
-
contextPrefix,
|
|
1501
|
-
capsule.sub,
|
|
1502
|
-
capsule.kid,
|
|
1503
|
-
capsule.intent,
|
|
1504
|
-
capsule.aud,
|
|
1505
|
-
String(capsule.tps_from),
|
|
1506
|
-
String(capsule.tps_to),
|
|
1507
|
-
capsule.policy_hash ?? "",
|
|
1508
|
-
capsule.ver
|
|
1509
|
-
];
|
|
1510
|
-
if (extraNonce) {
|
|
1511
|
-
parts.push(extraNonce);
|
|
1415
|
+
if (scopes.includes(required)) {
|
|
1416
|
+
return true;
|
|
1512
1417
|
}
|
|
1513
|
-
|
|
1418
|
+
const [resource, id] = required.split(":");
|
|
1419
|
+
if (resource && id) {
|
|
1420
|
+
const wildcard = `${resource}:*`;
|
|
1421
|
+
if (scopes.includes(wildcard)) {
|
|
1422
|
+
return true;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
return false;
|
|
1514
1426
|
}
|
|
1515
|
-
function
|
|
1516
|
-
const
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
input.capsule.capsule_nonce,
|
|
1520
|
-
input.requestNonce
|
|
1521
|
-
);
|
|
1522
|
-
const info = buildInfo(CCE_DERIVATION.REQUEST, input.capsule);
|
|
1523
|
-
return (0, import_hkdf.hkdf)(import_sha2.sha256, ikm, salt, info, CCE_AES_KEY_BYTES);
|
|
1427
|
+
function parseScope(scope) {
|
|
1428
|
+
const parts = scope.split(":");
|
|
1429
|
+
if (parts.length !== 2) return null;
|
|
1430
|
+
return { resource: parts[0], id: parts[1] };
|
|
1524
1431
|
}
|
|
1525
|
-
function
|
|
1526
|
-
const
|
|
1527
|
-
|
|
1528
|
-
executionKey.fill(0);
|
|
1529
|
-
return {
|
|
1530
|
-
execution_key_hash: keyHash,
|
|
1531
|
-
request_id: requestId,
|
|
1532
|
-
capsule_id: input.capsule.capsule_id,
|
|
1533
|
-
sub: input.capsule.sub,
|
|
1534
|
-
kid: input.capsule.kid,
|
|
1535
|
-
intent: input.capsule.intent,
|
|
1536
|
-
aud: input.capsule.aud,
|
|
1537
|
-
tps_from: input.capsule.tps_from,
|
|
1538
|
-
tps_to: input.capsule.tps_to,
|
|
1539
|
-
policy_hash: input.capsule.policy_hash,
|
|
1540
|
-
derived_at: Math.floor(Date.now() / 1e3),
|
|
1541
|
-
valid: true
|
|
1542
|
-
};
|
|
1432
|
+
function canAccessResource(scopes, resourceType, resourceId) {
|
|
1433
|
+
const required = `${resourceType}:${resourceId}`;
|
|
1434
|
+
return hasScope(scopes, required);
|
|
1543
1435
|
}
|
|
1544
|
-
var
|
|
1545
|
-
|
|
1546
|
-
"src/cce/cce-derivation.service.ts"() {
|
|
1547
|
-
import_utils = require("@noble/hashes/utils.js");
|
|
1548
|
-
import_hkdf = require("@noble/hashes/hkdf.js");
|
|
1549
|
-
import_sha2 = require("@noble/hashes/sha2.js");
|
|
1550
|
-
init_cce_types();
|
|
1436
|
+
var init_scopes = __esm({
|
|
1437
|
+
"src/security/scopes.ts"() {
|
|
1551
1438
|
}
|
|
1552
1439
|
});
|
|
1553
1440
|
|
|
1554
|
-
// src/
|
|
1555
|
-
function
|
|
1556
|
-
if (
|
|
1557
|
-
|
|
1558
|
-
}
|
|
1559
|
-
const iv = (0, import_crypto2.randomBytes)(CCE_IV_BYTES);
|
|
1560
|
-
const cipher = (0, import_crypto2.createCipheriv)("aes-256-gcm", key, iv);
|
|
1561
|
-
if (aad) {
|
|
1562
|
-
cipher.setAAD(aad);
|
|
1441
|
+
// src/security/inline-capsule.ts
|
|
1442
|
+
function normalizeInlineCapsule(input) {
|
|
1443
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
1444
|
+
return null;
|
|
1563
1445
|
}
|
|
1564
|
-
const
|
|
1565
|
-
const
|
|
1446
|
+
const raw = input;
|
|
1447
|
+
const scopes = normalizeStringList(raw.scopes ?? raw.scope);
|
|
1566
1448
|
return {
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1449
|
+
id: normalizeScalar(raw.id),
|
|
1450
|
+
actorId: normalizeScalar(raw.actorId),
|
|
1451
|
+
intents: normalizeStringList(raw.intents),
|
|
1452
|
+
issuedAt: normalizeTimestamp(raw.issuedAt ?? raw.iat),
|
|
1453
|
+
expiresAt: normalizeTimestamp(raw.expiresAt ?? raw.exp),
|
|
1454
|
+
realm: normalizeScalar(raw.realm),
|
|
1455
|
+
node: normalizeScalar(raw.node),
|
|
1456
|
+
scopes,
|
|
1457
|
+
raw
|
|
1570
1458
|
};
|
|
1571
1459
|
}
|
|
1572
|
-
function
|
|
1573
|
-
|
|
1460
|
+
function inlineCapsuleAllowsIntent(capsule, intent) {
|
|
1461
|
+
if (!capsule.intents || capsule.intents.length === 0) {
|
|
1462
|
+
return false;
|
|
1463
|
+
}
|
|
1464
|
+
for (const pattern of capsule.intents) {
|
|
1465
|
+
if (pattern === "*" || pattern === intent) {
|
|
1466
|
+
return true;
|
|
1467
|
+
}
|
|
1468
|
+
if (pattern.endsWith(".*")) {
|
|
1469
|
+
const prefix = pattern.slice(0, -1);
|
|
1470
|
+
if (intent.startsWith(prefix)) {
|
|
1471
|
+
return true;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
return false;
|
|
1574
1476
|
}
|
|
1575
|
-
function
|
|
1576
|
-
|
|
1477
|
+
function isInlineCapsuleExpired(capsule, clockSkewMs = 3e4) {
|
|
1478
|
+
if (capsule.expiresAt === void 0) {
|
|
1479
|
+
return false;
|
|
1480
|
+
}
|
|
1481
|
+
return BigInt(Date.now()) > capsule.expiresAt + BigInt(clockSkewMs);
|
|
1577
1482
|
}
|
|
1578
|
-
function
|
|
1579
|
-
return
|
|
1483
|
+
function resolvePolicyScopes(scopes, context) {
|
|
1484
|
+
return scopes.map(
|
|
1485
|
+
(scope) => scope.replace(/\$\{([^}]+)\}/g, (_match, expression) => {
|
|
1486
|
+
const resolved = resolveTemplateExpression(expression.trim(), context);
|
|
1487
|
+
if (resolved === void 0 || resolved === null || resolved === "") {
|
|
1488
|
+
throw new Error(`CAPSULE_SCOPE_TEMPLATE_UNRESOLVED:${expression}`);
|
|
1489
|
+
}
|
|
1490
|
+
return String(resolved);
|
|
1491
|
+
})
|
|
1492
|
+
);
|
|
1580
1493
|
}
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
import_utils2 = require("@noble/hashes/utils.js");
|
|
1585
|
-
import_sha22 = require("@noble/hashes/sha2.js");
|
|
1586
|
-
import_crypto2 = require("crypto");
|
|
1587
|
-
init_cce_types();
|
|
1494
|
+
function inlineCapsuleSatisfiesScopes(capsule, requiredScopes, mode = "all") {
|
|
1495
|
+
if (!capsule.scopes || capsule.scopes.length === 0) {
|
|
1496
|
+
return false;
|
|
1588
1497
|
}
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1498
|
+
if (mode === "any") {
|
|
1499
|
+
return requiredScopes.some((scope) => hasScope(capsule.scopes, scope));
|
|
1500
|
+
}
|
|
1501
|
+
return requiredScopes.every((scope) => hasScope(capsule.scopes, scope));
|
|
1502
|
+
}
|
|
1503
|
+
function resolveTemplateExpression(expression, context) {
|
|
1504
|
+
if (expression === "intent") {
|
|
1505
|
+
return context.intent;
|
|
1506
|
+
}
|
|
1507
|
+
if (expression === "actorId") {
|
|
1508
|
+
return context.actorId;
|
|
1509
|
+
}
|
|
1510
|
+
if (expression === "chainId") {
|
|
1511
|
+
return context.chainId;
|
|
1512
|
+
}
|
|
1513
|
+
if (expression === "stepId") {
|
|
1514
|
+
return context.stepId;
|
|
1515
|
+
}
|
|
1516
|
+
if (expression.startsWith("body.")) {
|
|
1517
|
+
return getNestedValue(context.body, expression.slice(5));
|
|
1518
|
+
}
|
|
1519
|
+
return void 0;
|
|
1520
|
+
}
|
|
1521
|
+
function getNestedValue(value, path2) {
|
|
1522
|
+
if (!value || typeof value !== "object") {
|
|
1523
|
+
return void 0;
|
|
1524
|
+
}
|
|
1525
|
+
return path2.split(".").reduce((current, segment) => {
|
|
1526
|
+
if (!current || typeof current !== "object") {
|
|
1527
|
+
return void 0;
|
|
1528
|
+
}
|
|
1529
|
+
return current[segment];
|
|
1530
|
+
}, value);
|
|
1531
|
+
}
|
|
1532
|
+
function normalizeScalar(value) {
|
|
1533
|
+
if (typeof value === "string") {
|
|
1534
|
+
return value;
|
|
1535
|
+
}
|
|
1536
|
+
if (value instanceof Uint8Array) {
|
|
1537
|
+
return Buffer.from(value).toString("hex");
|
|
1538
|
+
}
|
|
1539
|
+
return void 0;
|
|
1540
|
+
}
|
|
1541
|
+
function normalizeStringList(value) {
|
|
1542
|
+
if (!value) {
|
|
1543
|
+
return void 0;
|
|
1544
|
+
}
|
|
1545
|
+
const list = Array.isArray(value) ? value : [value];
|
|
1546
|
+
const normalized = list.map((entry) => typeof entry === "string" ? entry : void 0).filter((entry) => !!entry && entry.trim().length > 0);
|
|
1547
|
+
return normalized.length > 0 ? Array.from(new Set(normalized)) : void 0;
|
|
1548
|
+
}
|
|
1549
|
+
function normalizeTimestamp(value) {
|
|
1550
|
+
if (typeof value === "bigint") {
|
|
1551
|
+
return value;
|
|
1552
|
+
}
|
|
1553
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1554
|
+
return BigInt(Math.trunc(value));
|
|
1555
|
+
}
|
|
1556
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1557
|
+
try {
|
|
1558
|
+
return BigInt(value);
|
|
1559
|
+
} catch {
|
|
1560
|
+
return void 0;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
return void 0;
|
|
1564
|
+
}
|
|
1565
|
+
var init_inline_capsule = __esm({
|
|
1566
|
+
"src/security/inline-capsule.ts"() {
|
|
1567
|
+
init_scopes();
|
|
1568
|
+
}
|
|
1569
|
+
});
|
|
1570
|
+
|
|
1571
|
+
// src/sensor/axis-sensor.ts
|
|
1572
|
+
function normalizeSensorDecision(sensorDecision) {
|
|
1573
|
+
if ("action" in sensorDecision) {
|
|
1574
|
+
switch (sensorDecision.action) {
|
|
1575
|
+
case "ALLOW":
|
|
1576
|
+
return {
|
|
1577
|
+
allow: true,
|
|
1578
|
+
riskScore: 0,
|
|
1579
|
+
reasons: [],
|
|
1580
|
+
meta: sensorDecision.meta
|
|
1581
|
+
};
|
|
1582
|
+
case "DENY":
|
|
1583
|
+
return {
|
|
1584
|
+
allow: false,
|
|
1585
|
+
riskScore: 100,
|
|
1586
|
+
reasons: [sensorDecision.code, sensorDecision.reason].filter(
|
|
1587
|
+
Boolean
|
|
1588
|
+
),
|
|
1589
|
+
meta: sensorDecision.meta,
|
|
1590
|
+
retryAfterMs: sensorDecision.retryAfterMs
|
|
1591
|
+
};
|
|
1592
|
+
case "THROTTLE":
|
|
1593
|
+
return {
|
|
1594
|
+
allow: false,
|
|
1595
|
+
riskScore: 50,
|
|
1596
|
+
reasons: ["RATE_LIMIT"],
|
|
1597
|
+
retryAfterMs: sensorDecision.retryAfterMs,
|
|
1598
|
+
meta: sensorDecision.meta
|
|
1599
|
+
};
|
|
1600
|
+
case "FLAG":
|
|
1601
|
+
return {
|
|
1602
|
+
allow: true,
|
|
1603
|
+
riskScore: sensorDecision.scoreDelta,
|
|
1604
|
+
reasons: sensorDecision.reasons,
|
|
1605
|
+
meta: sensorDecision.meta
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
return {
|
|
1610
|
+
allow: sensorDecision.allow,
|
|
1611
|
+
riskScore: sensorDecision.riskScore,
|
|
1612
|
+
reasons: sensorDecision.reasons,
|
|
1613
|
+
tags: sensorDecision.tags,
|
|
1614
|
+
meta: sensorDecision.meta,
|
|
1615
|
+
tighten: sensorDecision.tighten,
|
|
1616
|
+
retryAfterMs: sensorDecision.retryAfterMs
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
var Decision, SensorDecisions;
|
|
1620
|
+
var init_axis_sensor = __esm({
|
|
1621
|
+
"src/sensor/axis-sensor.ts"() {
|
|
1622
|
+
Decision = /* @__PURE__ */ ((Decision2) => {
|
|
1623
|
+
Decision2["ALLOW"] = "ALLOW";
|
|
1624
|
+
Decision2["DENY"] = "DENY";
|
|
1625
|
+
Decision2["THROTTLE"] = "THROTTLE";
|
|
1626
|
+
Decision2["FLAG"] = "FLAG";
|
|
1627
|
+
return Decision2;
|
|
1628
|
+
})(Decision || {});
|
|
1629
|
+
SensorDecisions = {
|
|
1630
|
+
allow(meta, tags) {
|
|
1631
|
+
return {
|
|
1632
|
+
decision: "ALLOW" /* ALLOW */,
|
|
1633
|
+
allow: true,
|
|
1634
|
+
riskScore: 0,
|
|
1635
|
+
reasons: [],
|
|
1636
|
+
tags,
|
|
1637
|
+
meta
|
|
1638
|
+
};
|
|
1639
|
+
},
|
|
1640
|
+
deny(code, reason, meta) {
|
|
1641
|
+
return {
|
|
1642
|
+
decision: "DENY" /* DENY */,
|
|
1643
|
+
allow: false,
|
|
1644
|
+
riskScore: 100,
|
|
1645
|
+
code,
|
|
1646
|
+
reasons: [code, reason].filter(Boolean),
|
|
1647
|
+
meta
|
|
1648
|
+
};
|
|
1649
|
+
},
|
|
1650
|
+
throttle(retryAfterMs, meta) {
|
|
1651
|
+
return {
|
|
1652
|
+
decision: "THROTTLE" /* THROTTLE */,
|
|
1653
|
+
allow: false,
|
|
1654
|
+
riskScore: 50,
|
|
1655
|
+
retryAfterMs,
|
|
1656
|
+
code: "RATE_LIMIT",
|
|
1657
|
+
reasons: ["RATE_LIMIT"],
|
|
1658
|
+
meta
|
|
1659
|
+
};
|
|
1660
|
+
},
|
|
1661
|
+
flag(scoreDelta, reasons, meta) {
|
|
1662
|
+
return {
|
|
1663
|
+
decision: "FLAG" /* FLAG */,
|
|
1664
|
+
allow: true,
|
|
1665
|
+
riskScore: scoreDelta,
|
|
1666
|
+
scoreDelta,
|
|
1667
|
+
reasons,
|
|
1668
|
+
meta
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
};
|
|
1672
|
+
}
|
|
1673
|
+
});
|
|
1674
|
+
|
|
1675
|
+
// src/cce/cce.types.ts
|
|
1676
|
+
var CCE_PROTOCOL_VERSION, CCE_DERIVATION, CCE_AES_KEY_BYTES, CCE_IV_BYTES, CCE_NONCE_BYTES, CCE_ERROR, CceError;
|
|
1677
|
+
var init_cce_types = __esm({
|
|
1678
|
+
"src/cce/cce.types.ts"() {
|
|
1679
|
+
CCE_PROTOCOL_VERSION = "cce-v1";
|
|
1680
|
+
CCE_DERIVATION = {
|
|
1681
|
+
/** Request execution context */
|
|
1682
|
+
REQUEST: "axis:cce:req:v1",
|
|
1683
|
+
/** Response execution context */
|
|
1684
|
+
RESPONSE: "axis:cce:resp:v1",
|
|
1685
|
+
/** Witness binding context */
|
|
1686
|
+
WITNESS: "axis:cce:witness:v1"
|
|
1687
|
+
};
|
|
1688
|
+
CCE_AES_KEY_BYTES = 32;
|
|
1689
|
+
CCE_IV_BYTES = 12;
|
|
1690
|
+
CCE_NONCE_BYTES = 32;
|
|
1691
|
+
CCE_ERROR = {
|
|
1692
|
+
// Envelope errors
|
|
1693
|
+
INVALID_ENVELOPE: "CCE_INVALID_ENVELOPE",
|
|
1694
|
+
UNSUPPORTED_VERSION: "CCE_UNSUPPORTED_VERSION",
|
|
1695
|
+
MISSING_CAPSULE: "CCE_MISSING_CAPSULE",
|
|
1696
|
+
MISSING_ENCRYPTED_KEY: "CCE_MISSING_ENCRYPTED_KEY",
|
|
1697
|
+
// Signature errors
|
|
1698
|
+
CLIENT_SIG_INVALID: "CCE_CLIENT_SIG_INVALID",
|
|
1699
|
+
CLIENT_KEY_NOT_FOUND: "CCE_CLIENT_KEY_NOT_FOUND",
|
|
1700
|
+
// Capsule errors
|
|
1701
|
+
CAPSULE_SIG_INVALID: "CCE_CAPSULE_SIG_INVALID",
|
|
1702
|
+
CAPSULE_EXPIRED: "CCE_CAPSULE_EXPIRED",
|
|
1703
|
+
CAPSULE_NOT_YET_VALID: "CCE_CAPSULE_NOT_YET_VALID",
|
|
1704
|
+
CAPSULE_REVOKED: "CCE_CAPSULE_REVOKED",
|
|
1705
|
+
CAPSULE_CONSUMED: "CCE_CAPSULE_CONSUMED",
|
|
1706
|
+
CAPSULE_NOT_VERIFIED: "CCE_CAPSULE_NOT_VERIFIED",
|
|
1707
|
+
// Binding errors
|
|
1708
|
+
AUDIENCE_MISMATCH: "CCE_AUDIENCE_MISMATCH",
|
|
1709
|
+
INTENT_MISMATCH: "CCE_INTENT_MISMATCH",
|
|
1710
|
+
TPS_WINDOW_EXPIRED: "CCE_TPS_WINDOW_EXPIRED",
|
|
1711
|
+
TPS_WINDOW_FUTURE: "CCE_TPS_WINDOW_FUTURE",
|
|
1712
|
+
// Replay / nonce errors
|
|
1713
|
+
REPLAY_DETECTED: "CCE_REPLAY_DETECTED",
|
|
1714
|
+
NONCE_REUSED: "CCE_NONCE_REUSED",
|
|
1715
|
+
// Decryption errors
|
|
1716
|
+
DECRYPTION_FAILED: "CCE_DECRYPTION_FAILED",
|
|
1717
|
+
KEY_UNWRAP_FAILED: "CCE_KEY_UNWRAP_FAILED",
|
|
1718
|
+
AEAD_TAG_MISMATCH: "CCE_AEAD_TAG_MISMATCH",
|
|
1719
|
+
PAYLOAD_TOO_LARGE: "CCE_PAYLOAD_TOO_LARGE",
|
|
1720
|
+
// Schema / validation errors
|
|
1721
|
+
PAYLOAD_SCHEMA_INVALID: "CCE_PAYLOAD_SCHEMA_INVALID",
|
|
1722
|
+
INTENT_SCHEMA_MISMATCH: "CCE_INTENT_SCHEMA_MISMATCH",
|
|
1723
|
+
// Policy errors
|
|
1724
|
+
POLICY_DENIED: "CCE_POLICY_DENIED",
|
|
1725
|
+
CONSTRAINT_VIOLATED: "CCE_CONSTRAINT_VIOLATED",
|
|
1726
|
+
// Handler errors
|
|
1727
|
+
HANDLER_NOT_FOUND: "CCE_HANDLER_NOT_FOUND",
|
|
1728
|
+
HANDLER_EXECUTION_FAILED: "CCE_HANDLER_EXECUTION_FAILED",
|
|
1729
|
+
HANDLER_TIMEOUT: "CCE_HANDLER_TIMEOUT",
|
|
1730
|
+
// Response errors
|
|
1731
|
+
RESPONSE_ENCRYPTION_FAILED: "CCE_RESPONSE_ENCRYPTION_FAILED"
|
|
1732
|
+
};
|
|
1733
|
+
CceError = class extends Error {
|
|
1734
|
+
constructor(code, message, metadata) {
|
|
1735
|
+
super(`[${code}] ${message}`);
|
|
1736
|
+
this.code = code;
|
|
1737
|
+
this.metadata = metadata;
|
|
1738
|
+
this.name = "CceError";
|
|
1739
|
+
}
|
|
1740
|
+
/** Whether this error is safe to expose to the client */
|
|
1741
|
+
get clientSafe() {
|
|
1742
|
+
const internal = [
|
|
1743
|
+
CCE_ERROR.DECRYPTION_FAILED,
|
|
1744
|
+
CCE_ERROR.KEY_UNWRAP_FAILED,
|
|
1745
|
+
CCE_ERROR.AEAD_TAG_MISMATCH,
|
|
1746
|
+
CCE_ERROR.HANDLER_EXECUTION_FAILED,
|
|
1747
|
+
CCE_ERROR.RESPONSE_ENCRYPTION_FAILED
|
|
1748
|
+
];
|
|
1749
|
+
return !internal.includes(this.code);
|
|
1750
|
+
}
|
|
1751
|
+
/** Get client-safe representation */
|
|
1752
|
+
toClientError() {
|
|
1753
|
+
if (this.clientSafe) {
|
|
1754
|
+
return { code: this.code, message: this.message };
|
|
1755
|
+
}
|
|
1756
|
+
return {
|
|
1757
|
+
code: CCE_ERROR.DECRYPTION_FAILED,
|
|
1758
|
+
message: "Request processing failed"
|
|
1759
|
+
};
|
|
1760
|
+
}
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
});
|
|
1764
|
+
|
|
1765
|
+
// src/cce/cce-derivation.service.ts
|
|
1766
|
+
function buildSalt(capsuleId, capsuleNonce, requestNonce) {
|
|
1767
|
+
const encoder = new TextEncoder();
|
|
1768
|
+
const data = encoder.encode(
|
|
1769
|
+
capsuleId + "|" + capsuleNonce + "|" + requestNonce
|
|
1770
|
+
);
|
|
1771
|
+
return (0, import_sha2.sha256)(data);
|
|
1772
|
+
}
|
|
1773
|
+
function buildInfo(contextPrefix, capsule, extraNonce) {
|
|
1774
|
+
const encoder = new TextEncoder();
|
|
1775
|
+
const parts = [
|
|
1776
|
+
contextPrefix,
|
|
1777
|
+
capsule.sub,
|
|
1778
|
+
capsule.kid,
|
|
1779
|
+
capsule.intent,
|
|
1780
|
+
capsule.aud,
|
|
1781
|
+
String(capsule.tps_from),
|
|
1782
|
+
String(capsule.tps_to),
|
|
1783
|
+
capsule.policy_hash ?? "",
|
|
1784
|
+
capsule.ver
|
|
1785
|
+
];
|
|
1786
|
+
if (extraNonce) {
|
|
1787
|
+
parts.push(extraNonce);
|
|
1788
|
+
}
|
|
1789
|
+
return encoder.encode(parts.join("|"));
|
|
1790
|
+
}
|
|
1791
|
+
function deriveRequestExecutionKey(input) {
|
|
1792
|
+
const ikm = (0, import_utils.hexToBytes)(input.axisLocalSecret);
|
|
1793
|
+
const salt = buildSalt(
|
|
1794
|
+
input.capsule.capsule_id,
|
|
1795
|
+
input.capsule.capsule_nonce,
|
|
1796
|
+
input.requestNonce
|
|
1797
|
+
);
|
|
1798
|
+
const info = buildInfo(CCE_DERIVATION.REQUEST, input.capsule);
|
|
1799
|
+
return (0, import_hkdf.hkdf)(import_sha2.sha256, ikm, salt, info, CCE_AES_KEY_BYTES);
|
|
1800
|
+
}
|
|
1801
|
+
function buildExecutionContext(input, requestId) {
|
|
1802
|
+
const executionKey = deriveRequestExecutionKey(input);
|
|
1803
|
+
const keyHash = (0, import_utils.bytesToHex)((0, import_sha2.sha256)(executionKey));
|
|
1804
|
+
executionKey.fill(0);
|
|
1805
|
+
return {
|
|
1806
|
+
execution_key_hash: keyHash,
|
|
1807
|
+
request_id: requestId,
|
|
1808
|
+
capsule_id: input.capsule.capsule_id,
|
|
1809
|
+
sub: input.capsule.sub,
|
|
1810
|
+
kid: input.capsule.kid,
|
|
1811
|
+
intent: input.capsule.intent,
|
|
1812
|
+
aud: input.capsule.aud,
|
|
1813
|
+
tps_from: input.capsule.tps_from,
|
|
1814
|
+
tps_to: input.capsule.tps_to,
|
|
1815
|
+
policy_hash: input.capsule.policy_hash,
|
|
1816
|
+
derived_at: Math.floor(Date.now() / 1e3),
|
|
1817
|
+
valid: true
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
var import_utils, import_hkdf, import_sha2;
|
|
1821
|
+
var init_cce_derivation_service = __esm({
|
|
1822
|
+
"src/cce/cce-derivation.service.ts"() {
|
|
1823
|
+
import_utils = require("@noble/hashes/utils.js");
|
|
1824
|
+
import_hkdf = require("@noble/hashes/hkdf.js");
|
|
1825
|
+
import_sha2 = require("@noble/hashes/sha2.js");
|
|
1826
|
+
init_cce_types();
|
|
1827
|
+
}
|
|
1828
|
+
});
|
|
1829
|
+
|
|
1830
|
+
// src/cce/cce-crypto.ts
|
|
1831
|
+
function aesGcmEncrypt(key, plaintext, aad) {
|
|
1832
|
+
if (key.length !== CCE_AES_KEY_BYTES) {
|
|
1833
|
+
throw new Error(`AES key must be ${CCE_AES_KEY_BYTES} bytes`);
|
|
1834
|
+
}
|
|
1835
|
+
const iv = (0, import_crypto2.randomBytes)(CCE_IV_BYTES);
|
|
1836
|
+
const cipher = (0, import_crypto2.createCipheriv)("aes-256-gcm", key, iv);
|
|
1837
|
+
if (aad) {
|
|
1838
|
+
cipher.setAAD(aad);
|
|
1839
|
+
}
|
|
1840
|
+
const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
1841
|
+
const tag = cipher.getAuthTag();
|
|
1842
|
+
return {
|
|
1843
|
+
iv: new Uint8Array(iv),
|
|
1844
|
+
ciphertext: new Uint8Array(encrypted),
|
|
1845
|
+
tag: new Uint8Array(tag)
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
function generateAesKey() {
|
|
1849
|
+
return new Uint8Array((0, import_crypto2.randomBytes)(CCE_AES_KEY_BYTES));
|
|
1850
|
+
}
|
|
1851
|
+
function base64UrlEncode(bytes2) {
|
|
1852
|
+
return Buffer.from(bytes2).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1853
|
+
}
|
|
1854
|
+
function hashPayload(payload) {
|
|
1855
|
+
return (0, import_utils2.bytesToHex)((0, import_sha22.sha256)(payload));
|
|
1856
|
+
}
|
|
1857
|
+
var import_utils2, import_sha22, import_crypto2;
|
|
1858
|
+
var init_cce_crypto = __esm({
|
|
1859
|
+
"src/cce/cce-crypto.ts"() {
|
|
1860
|
+
import_utils2 = require("@noble/hashes/utils.js");
|
|
1861
|
+
import_sha22 = require("@noble/hashes/sha2.js");
|
|
1862
|
+
import_crypto2 = require("crypto");
|
|
1863
|
+
init_cce_types();
|
|
1864
|
+
}
|
|
1865
|
+
});
|
|
1866
|
+
|
|
1867
|
+
// src/cce/cce-response.service.ts
|
|
1592
1868
|
async function buildCceResponse(options, clientKeyEncryptor, axisSigner) {
|
|
1593
1869
|
const { request, capsule, status, body, clientPublicKeyHex, witnessRef } = options;
|
|
1594
1870
|
const responseNonce = (0, import_utils3.bytesToHex)(
|
|
@@ -1765,124 +2041,20 @@ function computeExecutionContextHash(axisLocalSecret, capsule, requestNonce) {
|
|
|
1765
2041
|
return hash;
|
|
1766
2042
|
}
|
|
1767
2043
|
function hexToBytes2(hex) {
|
|
1768
|
-
const bytes2 = new Uint8Array(hex.length / 2);
|
|
1769
|
-
for (let i = 0; i < bytes2.length; i++) {
|
|
1770
|
-
bytes2[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
1771
|
-
}
|
|
1772
|
-
return bytes2;
|
|
1773
|
-
}
|
|
1774
|
-
var import_utils4, import_hkdf2, import_sha23;
|
|
1775
|
-
var init_cce_witness_observer = __esm({
|
|
1776
|
-
"src/cce/cce-witness.observer.ts"() {
|
|
1777
|
-
import_utils4 = require("@noble/hashes/utils.js");
|
|
1778
|
-
import_hkdf2 = require("@noble/hashes/hkdf.js");
|
|
1779
|
-
import_sha23 = require("@noble/hashes/sha2.js");
|
|
1780
|
-
init_cce_crypto();
|
|
1781
|
-
init_cce_types();
|
|
1782
|
-
}
|
|
1783
|
-
});
|
|
1784
|
-
|
|
1785
|
-
// src/sensor/axis-sensor.ts
|
|
1786
|
-
function normalizeSensorDecision(sensorDecision) {
|
|
1787
|
-
if ("action" in sensorDecision) {
|
|
1788
|
-
switch (sensorDecision.action) {
|
|
1789
|
-
case "ALLOW":
|
|
1790
|
-
return {
|
|
1791
|
-
allow: true,
|
|
1792
|
-
riskScore: 0,
|
|
1793
|
-
reasons: [],
|
|
1794
|
-
meta: sensorDecision.meta
|
|
1795
|
-
};
|
|
1796
|
-
case "DENY":
|
|
1797
|
-
return {
|
|
1798
|
-
allow: false,
|
|
1799
|
-
riskScore: 100,
|
|
1800
|
-
reasons: [sensorDecision.code, sensorDecision.reason].filter(
|
|
1801
|
-
Boolean
|
|
1802
|
-
),
|
|
1803
|
-
meta: sensorDecision.meta,
|
|
1804
|
-
retryAfterMs: sensorDecision.retryAfterMs
|
|
1805
|
-
};
|
|
1806
|
-
case "THROTTLE":
|
|
1807
|
-
return {
|
|
1808
|
-
allow: false,
|
|
1809
|
-
riskScore: 50,
|
|
1810
|
-
reasons: ["RATE_LIMIT"],
|
|
1811
|
-
retryAfterMs: sensorDecision.retryAfterMs,
|
|
1812
|
-
meta: sensorDecision.meta
|
|
1813
|
-
};
|
|
1814
|
-
case "FLAG":
|
|
1815
|
-
return {
|
|
1816
|
-
allow: true,
|
|
1817
|
-
riskScore: sensorDecision.scoreDelta,
|
|
1818
|
-
reasons: sensorDecision.reasons,
|
|
1819
|
-
meta: sensorDecision.meta
|
|
1820
|
-
};
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
return {
|
|
1824
|
-
allow: sensorDecision.allow,
|
|
1825
|
-
riskScore: sensorDecision.riskScore,
|
|
1826
|
-
reasons: sensorDecision.reasons,
|
|
1827
|
-
tags: sensorDecision.tags,
|
|
1828
|
-
meta: sensorDecision.meta,
|
|
1829
|
-
tighten: sensorDecision.tighten,
|
|
1830
|
-
retryAfterMs: sensorDecision.retryAfterMs
|
|
1831
|
-
};
|
|
2044
|
+
const bytes2 = new Uint8Array(hex.length / 2);
|
|
2045
|
+
for (let i = 0; i < bytes2.length; i++) {
|
|
2046
|
+
bytes2[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
2047
|
+
}
|
|
2048
|
+
return bytes2;
|
|
1832
2049
|
}
|
|
1833
|
-
var
|
|
1834
|
-
var
|
|
1835
|
-
"src/
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
return Decision2;
|
|
1842
|
-
})(Decision || {});
|
|
1843
|
-
SensorDecisions = {
|
|
1844
|
-
allow(meta, tags) {
|
|
1845
|
-
return {
|
|
1846
|
-
decision: "ALLOW" /* ALLOW */,
|
|
1847
|
-
allow: true,
|
|
1848
|
-
riskScore: 0,
|
|
1849
|
-
reasons: [],
|
|
1850
|
-
tags,
|
|
1851
|
-
meta
|
|
1852
|
-
};
|
|
1853
|
-
},
|
|
1854
|
-
deny(code, reason, meta) {
|
|
1855
|
-
return {
|
|
1856
|
-
decision: "DENY" /* DENY */,
|
|
1857
|
-
allow: false,
|
|
1858
|
-
riskScore: 100,
|
|
1859
|
-
code,
|
|
1860
|
-
reasons: [code, reason].filter(Boolean),
|
|
1861
|
-
meta
|
|
1862
|
-
};
|
|
1863
|
-
},
|
|
1864
|
-
throttle(retryAfterMs, meta) {
|
|
1865
|
-
return {
|
|
1866
|
-
decision: "THROTTLE" /* THROTTLE */,
|
|
1867
|
-
allow: false,
|
|
1868
|
-
riskScore: 50,
|
|
1869
|
-
retryAfterMs,
|
|
1870
|
-
code: "RATE_LIMIT",
|
|
1871
|
-
reasons: ["RATE_LIMIT"],
|
|
1872
|
-
meta
|
|
1873
|
-
};
|
|
1874
|
-
},
|
|
1875
|
-
flag(scoreDelta, reasons, meta) {
|
|
1876
|
-
return {
|
|
1877
|
-
decision: "FLAG" /* FLAG */,
|
|
1878
|
-
allow: true,
|
|
1879
|
-
riskScore: scoreDelta,
|
|
1880
|
-
scoreDelta,
|
|
1881
|
-
reasons,
|
|
1882
|
-
meta
|
|
1883
|
-
};
|
|
1884
|
-
}
|
|
1885
|
-
};
|
|
2050
|
+
var import_utils4, import_hkdf2, import_sha23;
|
|
2051
|
+
var init_cce_witness_observer = __esm({
|
|
2052
|
+
"src/cce/cce-witness.observer.ts"() {
|
|
2053
|
+
import_utils4 = require("@noble/hashes/utils.js");
|
|
2054
|
+
import_hkdf2 = require("@noble/hashes/hkdf.js");
|
|
2055
|
+
import_sha23 = require("@noble/hashes/sha2.js");
|
|
2056
|
+
init_cce_crypto();
|
|
2057
|
+
init_cce_types();
|
|
1886
2058
|
}
|
|
1887
2059
|
});
|
|
1888
2060
|
|
|
@@ -2134,167 +2306,6 @@ var init_axis_error = __esm({
|
|
|
2134
2306
|
}
|
|
2135
2307
|
});
|
|
2136
2308
|
|
|
2137
|
-
// src/security/scopes.ts
|
|
2138
|
-
function hasScope(scopes, required) {
|
|
2139
|
-
if (!Array.isArray(scopes) || scopes.length === 0) {
|
|
2140
|
-
return false;
|
|
2141
|
-
}
|
|
2142
|
-
if (scopes.includes(required)) {
|
|
2143
|
-
return true;
|
|
2144
|
-
}
|
|
2145
|
-
const [resource, id] = required.split(":");
|
|
2146
|
-
if (resource && id) {
|
|
2147
|
-
const wildcard = `${resource}:*`;
|
|
2148
|
-
if (scopes.includes(wildcard)) {
|
|
2149
|
-
return true;
|
|
2150
|
-
}
|
|
2151
|
-
}
|
|
2152
|
-
return false;
|
|
2153
|
-
}
|
|
2154
|
-
function parseScope(scope) {
|
|
2155
|
-
const parts = scope.split(":");
|
|
2156
|
-
if (parts.length !== 2) return null;
|
|
2157
|
-
return { resource: parts[0], id: parts[1] };
|
|
2158
|
-
}
|
|
2159
|
-
function canAccessResource(scopes, resourceType, resourceId) {
|
|
2160
|
-
const required = `${resourceType}:${resourceId}`;
|
|
2161
|
-
return hasScope(scopes, required);
|
|
2162
|
-
}
|
|
2163
|
-
var init_scopes = __esm({
|
|
2164
|
-
"src/security/scopes.ts"() {
|
|
2165
|
-
}
|
|
2166
|
-
});
|
|
2167
|
-
|
|
2168
|
-
// src/security/inline-capsule.ts
|
|
2169
|
-
function normalizeInlineCapsule(input) {
|
|
2170
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
2171
|
-
return null;
|
|
2172
|
-
}
|
|
2173
|
-
const raw = input;
|
|
2174
|
-
const scopes = normalizeStringList(raw.scopes ?? raw.scope);
|
|
2175
|
-
return {
|
|
2176
|
-
id: normalizeScalar(raw.id),
|
|
2177
|
-
actorId: normalizeScalar(raw.actorId),
|
|
2178
|
-
intents: normalizeStringList(raw.intents),
|
|
2179
|
-
issuedAt: normalizeTimestamp(raw.issuedAt ?? raw.iat),
|
|
2180
|
-
expiresAt: normalizeTimestamp(raw.expiresAt ?? raw.exp),
|
|
2181
|
-
realm: normalizeScalar(raw.realm),
|
|
2182
|
-
node: normalizeScalar(raw.node),
|
|
2183
|
-
scopes,
|
|
2184
|
-
raw
|
|
2185
|
-
};
|
|
2186
|
-
}
|
|
2187
|
-
function inlineCapsuleAllowsIntent(capsule, intent) {
|
|
2188
|
-
if (!capsule.intents || capsule.intents.length === 0) {
|
|
2189
|
-
return false;
|
|
2190
|
-
}
|
|
2191
|
-
for (const pattern of capsule.intents) {
|
|
2192
|
-
if (pattern === "*" || pattern === intent) {
|
|
2193
|
-
return true;
|
|
2194
|
-
}
|
|
2195
|
-
if (pattern.endsWith(".*")) {
|
|
2196
|
-
const prefix = pattern.slice(0, -1);
|
|
2197
|
-
if (intent.startsWith(prefix)) {
|
|
2198
|
-
return true;
|
|
2199
|
-
}
|
|
2200
|
-
}
|
|
2201
|
-
}
|
|
2202
|
-
return false;
|
|
2203
|
-
}
|
|
2204
|
-
function isInlineCapsuleExpired(capsule, clockSkewMs = 3e4) {
|
|
2205
|
-
if (capsule.expiresAt === void 0) {
|
|
2206
|
-
return false;
|
|
2207
|
-
}
|
|
2208
|
-
return BigInt(Date.now()) > capsule.expiresAt + BigInt(clockSkewMs);
|
|
2209
|
-
}
|
|
2210
|
-
function resolvePolicyScopes(scopes, context) {
|
|
2211
|
-
return scopes.map(
|
|
2212
|
-
(scope) => scope.replace(/\$\{([^}]+)\}/g, (_match, expression) => {
|
|
2213
|
-
const resolved = resolveTemplateExpression(expression.trim(), context);
|
|
2214
|
-
if (resolved === void 0 || resolved === null || resolved === "") {
|
|
2215
|
-
throw new Error(`CAPSULE_SCOPE_TEMPLATE_UNRESOLVED:${expression}`);
|
|
2216
|
-
}
|
|
2217
|
-
return String(resolved);
|
|
2218
|
-
})
|
|
2219
|
-
);
|
|
2220
|
-
}
|
|
2221
|
-
function inlineCapsuleSatisfiesScopes(capsule, requiredScopes, mode = "all") {
|
|
2222
|
-
if (!capsule.scopes || capsule.scopes.length === 0) {
|
|
2223
|
-
return false;
|
|
2224
|
-
}
|
|
2225
|
-
if (mode === "any") {
|
|
2226
|
-
return requiredScopes.some((scope) => hasScope(capsule.scopes, scope));
|
|
2227
|
-
}
|
|
2228
|
-
return requiredScopes.every((scope) => hasScope(capsule.scopes, scope));
|
|
2229
|
-
}
|
|
2230
|
-
function resolveTemplateExpression(expression, context) {
|
|
2231
|
-
if (expression === "intent") {
|
|
2232
|
-
return context.intent;
|
|
2233
|
-
}
|
|
2234
|
-
if (expression === "actorId") {
|
|
2235
|
-
return context.actorId;
|
|
2236
|
-
}
|
|
2237
|
-
if (expression === "chainId") {
|
|
2238
|
-
return context.chainId;
|
|
2239
|
-
}
|
|
2240
|
-
if (expression === "stepId") {
|
|
2241
|
-
return context.stepId;
|
|
2242
|
-
}
|
|
2243
|
-
if (expression.startsWith("body.")) {
|
|
2244
|
-
return getNestedValue(context.body, expression.slice(5));
|
|
2245
|
-
}
|
|
2246
|
-
return void 0;
|
|
2247
|
-
}
|
|
2248
|
-
function getNestedValue(value, path2) {
|
|
2249
|
-
if (!value || typeof value !== "object") {
|
|
2250
|
-
return void 0;
|
|
2251
|
-
}
|
|
2252
|
-
return path2.split(".").reduce((current, segment) => {
|
|
2253
|
-
if (!current || typeof current !== "object") {
|
|
2254
|
-
return void 0;
|
|
2255
|
-
}
|
|
2256
|
-
return current[segment];
|
|
2257
|
-
}, value);
|
|
2258
|
-
}
|
|
2259
|
-
function normalizeScalar(value) {
|
|
2260
|
-
if (typeof value === "string") {
|
|
2261
|
-
return value;
|
|
2262
|
-
}
|
|
2263
|
-
if (value instanceof Uint8Array) {
|
|
2264
|
-
return Buffer.from(value).toString("hex");
|
|
2265
|
-
}
|
|
2266
|
-
return void 0;
|
|
2267
|
-
}
|
|
2268
|
-
function normalizeStringList(value) {
|
|
2269
|
-
if (!value) {
|
|
2270
|
-
return void 0;
|
|
2271
|
-
}
|
|
2272
|
-
const list = Array.isArray(value) ? value : [value];
|
|
2273
|
-
const normalized = list.map((entry) => typeof entry === "string" ? entry : void 0).filter((entry) => !!entry && entry.trim().length > 0);
|
|
2274
|
-
return normalized.length > 0 ? Array.from(new Set(normalized)) : void 0;
|
|
2275
|
-
}
|
|
2276
|
-
function normalizeTimestamp(value) {
|
|
2277
|
-
if (typeof value === "bigint") {
|
|
2278
|
-
return value;
|
|
2279
|
-
}
|
|
2280
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2281
|
-
return BigInt(Math.trunc(value));
|
|
2282
|
-
}
|
|
2283
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
2284
|
-
try {
|
|
2285
|
-
return BigInt(value);
|
|
2286
|
-
} catch {
|
|
2287
|
-
return void 0;
|
|
2288
|
-
}
|
|
2289
|
-
}
|
|
2290
|
-
return void 0;
|
|
2291
|
-
}
|
|
2292
|
-
var init_inline_capsule = __esm({
|
|
2293
|
-
"src/security/inline-capsule.ts"() {
|
|
2294
|
-
init_scopes();
|
|
2295
|
-
}
|
|
2296
|
-
});
|
|
2297
|
-
|
|
2298
2309
|
// src/engine/intent.router.ts
|
|
2299
2310
|
var intent_router_exports = {};
|
|
2300
2311
|
__export(intent_router_exports, {
|
|
@@ -2368,23 +2379,23 @@ var import_axis_protocol3, import_dto_schema, _IntentRouter, IntentRouter;
|
|
|
2368
2379
|
var init_intent_router = __esm({
|
|
2369
2380
|
"src/engine/intent.router.ts"() {
|
|
2370
2381
|
import_axis_protocol3 = require("@nextera.one/axis-protocol");
|
|
2371
|
-
init_cce_pipeline();
|
|
2372
|
-
init_axis_error();
|
|
2373
|
-
init_constants();
|
|
2374
|
-
init_capsule_policy_decorator();
|
|
2375
|
-
init_chain_decorator();
|
|
2376
|
-
import_dto_schema = __toESM(require_dto_schema_util());
|
|
2377
2382
|
init_handler_sensors_decorator();
|
|
2378
|
-
|
|
2379
|
-
init_intent_body_decorator();
|
|
2380
|
-
init_intent_policy_decorator();
|
|
2383
|
+
init_capsule_policy_decorator();
|
|
2381
2384
|
init_intent_sensors_decorator();
|
|
2382
|
-
|
|
2385
|
+
init_intent_policy_decorator();
|
|
2386
|
+
init_intent_body_decorator();
|
|
2383
2387
|
init_observer_decorator();
|
|
2388
|
+
init_handler_decorator();
|
|
2389
|
+
init_intent_decorator();
|
|
2390
|
+
init_chain_decorator();
|
|
2391
|
+
import_dto_schema = __toESM(require_dto_schema_util());
|
|
2384
2392
|
init_inline_capsule();
|
|
2385
|
-
init_axis_sensor();
|
|
2386
2393
|
init_axis_execution_context();
|
|
2394
|
+
init_axis_sensor();
|
|
2387
2395
|
init_axis_logger();
|
|
2396
|
+
init_cce_pipeline();
|
|
2397
|
+
init_axis_error();
|
|
2398
|
+
init_constants();
|
|
2388
2399
|
_IntentRouter = class _IntentRouter {
|
|
2389
2400
|
constructor(dependencyResolver, observerDispatcher, sensorRegistry) {
|
|
2390
2401
|
this.logger = createAxisLogger(_IntentRouter.name);
|
|
@@ -2420,6 +2431,8 @@ var init_intent_router = __esm({
|
|
|
2420
2431
|
this.publicIntents = /* @__PURE__ */ new Set();
|
|
2421
2432
|
/** Intents flagged as anonymous-session accessible */
|
|
2422
2433
|
this.anonymousIntents = /* @__PURE__ */ new Set();
|
|
2434
|
+
/** Intents flagged as authorized-session accessible */
|
|
2435
|
+
this.authorizedIntents = /* @__PURE__ */ new Set();
|
|
2423
2436
|
/** Per-intent rate limit config */
|
|
2424
2437
|
this.intentRateLimits = /* @__PURE__ */ new Map();
|
|
2425
2438
|
/** CCE handler registry */
|
|
@@ -2846,6 +2859,18 @@ var init_intent_router = __esm({
|
|
|
2846
2859
|
if (isAnonMethod || isAnonClass) {
|
|
2847
2860
|
this.anonymousIntents.add(intent);
|
|
2848
2861
|
}
|
|
2862
|
+
const isAuthorizedMethod = Reflect.getMetadata(
|
|
2863
|
+
AXIS_AUTHORIZED_KEY,
|
|
2864
|
+
proto,
|
|
2865
|
+
methodName
|
|
2866
|
+
);
|
|
2867
|
+
const isAuthorizedClass = Reflect.getMetadata(
|
|
2868
|
+
AXIS_AUTHORIZED_KEY,
|
|
2869
|
+
proto.constructor
|
|
2870
|
+
);
|
|
2871
|
+
if (isAuthorizedMethod || isAuthorizedClass) {
|
|
2872
|
+
this.authorizedIntents.add(intent);
|
|
2873
|
+
}
|
|
2849
2874
|
const rateLimit = Reflect.getMetadata(
|
|
2850
2875
|
AXIS_RATE_LIMIT_KEY,
|
|
2851
2876
|
proto,
|
|
@@ -2871,6 +2896,9 @@ var init_intent_router = __esm({
|
|
|
2871
2896
|
isAnonymous(intent) {
|
|
2872
2897
|
return this.anonymousIntents.has(intent);
|
|
2873
2898
|
}
|
|
2899
|
+
isAuthorized(intent) {
|
|
2900
|
+
return this.authorizedIntents.has(intent);
|
|
2901
|
+
}
|
|
2874
2902
|
getRateLimit(intent) {
|
|
2875
2903
|
return this.intentRateLimits.get(intent);
|
|
2876
2904
|
}
|
|
@@ -12676,6 +12704,7 @@ __export(index_exports, {
|
|
|
12676
12704
|
ATS1_HDR: () => ATS1_HDR,
|
|
12677
12705
|
ATS1_SCHEMA: () => ATS1_SCHEMA,
|
|
12678
12706
|
AXIS_ANONYMOUS_KEY: () => AXIS_ANONYMOUS_KEY,
|
|
12707
|
+
AXIS_AUTHORIZED_KEY: () => AXIS_AUTHORIZED_KEY,
|
|
12679
12708
|
AXIS_EXECUTION_CONTEXT_KEY: () => AXIS_EXECUTION_CONTEXT_KEY,
|
|
12680
12709
|
AXIS_MAGIC: () => import_axis_protocol2.AXIS_MAGIC,
|
|
12681
12710
|
AXIS_META_KEY: () => AXIS_META_KEY,
|
|
@@ -12689,6 +12718,7 @@ __export(index_exports, {
|
|
|
12689
12718
|
Ats1Codec: () => ats1_exports,
|
|
12690
12719
|
Axis: () => Axis,
|
|
12691
12720
|
AxisAnonymous: () => AxisAnonymous,
|
|
12721
|
+
AxisAuthorized: () => AxisAuthorized,
|
|
12692
12722
|
AxisChainExecutor: () => AxisChainExecutor,
|
|
12693
12723
|
AxisError: () => AxisError,
|
|
12694
12724
|
AxisFrameZ: () => AxisFrameZ,
|
|
@@ -13062,6 +13092,7 @@ init_index();
|
|
|
13062
13092
|
ATS1_HDR,
|
|
13063
13093
|
ATS1_SCHEMA,
|
|
13064
13094
|
AXIS_ANONYMOUS_KEY,
|
|
13095
|
+
AXIS_AUTHORIZED_KEY,
|
|
13065
13096
|
AXIS_EXECUTION_CONTEXT_KEY,
|
|
13066
13097
|
AXIS_MAGIC,
|
|
13067
13098
|
AXIS_META_KEY,
|
|
@@ -13075,6 +13106,7 @@ init_index();
|
|
|
13075
13106
|
Ats1Codec,
|
|
13076
13107
|
Axis,
|
|
13077
13108
|
AxisAnonymous,
|
|
13109
|
+
AxisAuthorized,
|
|
13078
13110
|
AxisChainExecutor,
|
|
13079
13111
|
AxisError,
|
|
13080
13112
|
AxisFrameZ,
|