@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/sensors/index.js
CHANGED
|
@@ -500,6 +500,16 @@ function AxisPublic() {
|
|
|
500
500
|
return target;
|
|
501
501
|
};
|
|
502
502
|
}
|
|
503
|
+
function AxisAuthorized() {
|
|
504
|
+
return (target, propertyKey, descriptor) => {
|
|
505
|
+
if (descriptor) {
|
|
506
|
+
Reflect.defineMetadata(AXIS_AUTHORIZED_KEY, true, target, propertyKey);
|
|
507
|
+
return descriptor;
|
|
508
|
+
}
|
|
509
|
+
Reflect.defineMetadata(AXIS_AUTHORIZED_KEY, true, target);
|
|
510
|
+
return target;
|
|
511
|
+
};
|
|
512
|
+
}
|
|
503
513
|
function AxisAnonymous() {
|
|
504
514
|
return (target, propertyKey, descriptor) => {
|
|
505
515
|
if (descriptor) {
|
|
@@ -516,7 +526,7 @@ function AxisRateLimit(config) {
|
|
|
516
526
|
return descriptor;
|
|
517
527
|
};
|
|
518
528
|
}
|
|
519
|
-
var import_reflect_metadata4, AXIS_META_KEY, SENSITIVITY_METADATA_KEY, CONTRACT_METADATA_KEY, REQUIRED_PROOF_METADATA_KEY, AXIS_PUBLIC_KEY, AXIS_ANONYMOUS_KEY, AXIS_RATE_LIMIT_KEY;
|
|
529
|
+
var import_reflect_metadata4, 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;
|
|
520
530
|
var init_intent_policy_decorator = __esm({
|
|
521
531
|
"src/decorators/intent-policy.decorator.ts"() {
|
|
522
532
|
import_reflect_metadata4 = require("reflect-metadata");
|
|
@@ -526,6 +536,7 @@ var init_intent_policy_decorator = __esm({
|
|
|
526
536
|
REQUIRED_PROOF_METADATA_KEY = "axis:required_proof";
|
|
527
537
|
AXIS_PUBLIC_KEY = "axis:public";
|
|
528
538
|
AXIS_ANONYMOUS_KEY = "axis:anonymous";
|
|
539
|
+
AXIS_AUTHORIZED_KEY = "axis:authorized";
|
|
529
540
|
AXIS_RATE_LIMIT_KEY = "axis:rateLimit";
|
|
530
541
|
}
|
|
531
542
|
});
|
|
@@ -1545,199 +1556,464 @@ var init_axis_chain_executor = __esm({
|
|
|
1545
1556
|
}
|
|
1546
1557
|
});
|
|
1547
1558
|
|
|
1548
|
-
// src/
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
CCE_PROTOCOL_VERSION = "cce-v1";
|
|
1553
|
-
CCE_DERIVATION = {
|
|
1554
|
-
/** Request execution context */
|
|
1555
|
-
REQUEST: "axis:cce:req:v1",
|
|
1556
|
-
/** Response execution context */
|
|
1557
|
-
RESPONSE: "axis:cce:resp:v1",
|
|
1558
|
-
/** Witness binding context */
|
|
1559
|
-
WITNESS: "axis:cce:witness:v1"
|
|
1560
|
-
};
|
|
1561
|
-
CCE_AES_KEY_BYTES = 32;
|
|
1562
|
-
CCE_IV_BYTES = 12;
|
|
1563
|
-
CCE_NONCE_BYTES = 32;
|
|
1564
|
-
CCE_ERROR = {
|
|
1565
|
-
// Envelope errors
|
|
1566
|
-
INVALID_ENVELOPE: "CCE_INVALID_ENVELOPE",
|
|
1567
|
-
UNSUPPORTED_VERSION: "CCE_UNSUPPORTED_VERSION",
|
|
1568
|
-
MISSING_CAPSULE: "CCE_MISSING_CAPSULE",
|
|
1569
|
-
MISSING_ENCRYPTED_KEY: "CCE_MISSING_ENCRYPTED_KEY",
|
|
1570
|
-
// Signature errors
|
|
1571
|
-
CLIENT_SIG_INVALID: "CCE_CLIENT_SIG_INVALID",
|
|
1572
|
-
CLIENT_KEY_NOT_FOUND: "CCE_CLIENT_KEY_NOT_FOUND",
|
|
1573
|
-
// Capsule errors
|
|
1574
|
-
CAPSULE_SIG_INVALID: "CCE_CAPSULE_SIG_INVALID",
|
|
1575
|
-
CAPSULE_EXPIRED: "CCE_CAPSULE_EXPIRED",
|
|
1576
|
-
CAPSULE_NOT_YET_VALID: "CCE_CAPSULE_NOT_YET_VALID",
|
|
1577
|
-
CAPSULE_REVOKED: "CCE_CAPSULE_REVOKED",
|
|
1578
|
-
CAPSULE_CONSUMED: "CCE_CAPSULE_CONSUMED",
|
|
1579
|
-
CAPSULE_NOT_VERIFIED: "CCE_CAPSULE_NOT_VERIFIED",
|
|
1580
|
-
// Binding errors
|
|
1581
|
-
AUDIENCE_MISMATCH: "CCE_AUDIENCE_MISMATCH",
|
|
1582
|
-
INTENT_MISMATCH: "CCE_INTENT_MISMATCH",
|
|
1583
|
-
TPS_WINDOW_EXPIRED: "CCE_TPS_WINDOW_EXPIRED",
|
|
1584
|
-
TPS_WINDOW_FUTURE: "CCE_TPS_WINDOW_FUTURE",
|
|
1585
|
-
// Replay / nonce errors
|
|
1586
|
-
REPLAY_DETECTED: "CCE_REPLAY_DETECTED",
|
|
1587
|
-
NONCE_REUSED: "CCE_NONCE_REUSED",
|
|
1588
|
-
// Decryption errors
|
|
1589
|
-
DECRYPTION_FAILED: "CCE_DECRYPTION_FAILED",
|
|
1590
|
-
KEY_UNWRAP_FAILED: "CCE_KEY_UNWRAP_FAILED",
|
|
1591
|
-
AEAD_TAG_MISMATCH: "CCE_AEAD_TAG_MISMATCH",
|
|
1592
|
-
PAYLOAD_TOO_LARGE: "CCE_PAYLOAD_TOO_LARGE",
|
|
1593
|
-
// Schema / validation errors
|
|
1594
|
-
PAYLOAD_SCHEMA_INVALID: "CCE_PAYLOAD_SCHEMA_INVALID",
|
|
1595
|
-
INTENT_SCHEMA_MISMATCH: "CCE_INTENT_SCHEMA_MISMATCH",
|
|
1596
|
-
// Policy errors
|
|
1597
|
-
POLICY_DENIED: "CCE_POLICY_DENIED",
|
|
1598
|
-
CONSTRAINT_VIOLATED: "CCE_CONSTRAINT_VIOLATED",
|
|
1599
|
-
// Handler errors
|
|
1600
|
-
HANDLER_NOT_FOUND: "CCE_HANDLER_NOT_FOUND",
|
|
1601
|
-
HANDLER_EXECUTION_FAILED: "CCE_HANDLER_EXECUTION_FAILED",
|
|
1602
|
-
HANDLER_TIMEOUT: "CCE_HANDLER_TIMEOUT",
|
|
1603
|
-
// Response errors
|
|
1604
|
-
RESPONSE_ENCRYPTION_FAILED: "CCE_RESPONSE_ENCRYPTION_FAILED"
|
|
1605
|
-
};
|
|
1606
|
-
CceError = class extends Error {
|
|
1607
|
-
constructor(code, message, metadata) {
|
|
1608
|
-
super(`[${code}] ${message}`);
|
|
1609
|
-
this.code = code;
|
|
1610
|
-
this.metadata = metadata;
|
|
1611
|
-
this.name = "CceError";
|
|
1612
|
-
}
|
|
1613
|
-
/** Whether this error is safe to expose to the client */
|
|
1614
|
-
get clientSafe() {
|
|
1615
|
-
const internal = [
|
|
1616
|
-
CCE_ERROR.DECRYPTION_FAILED,
|
|
1617
|
-
CCE_ERROR.KEY_UNWRAP_FAILED,
|
|
1618
|
-
CCE_ERROR.AEAD_TAG_MISMATCH,
|
|
1619
|
-
CCE_ERROR.HANDLER_EXECUTION_FAILED,
|
|
1620
|
-
CCE_ERROR.RESPONSE_ENCRYPTION_FAILED
|
|
1621
|
-
];
|
|
1622
|
-
return !internal.includes(this.code);
|
|
1623
|
-
}
|
|
1624
|
-
/** Get client-safe representation */
|
|
1625
|
-
toClientError() {
|
|
1626
|
-
if (this.clientSafe) {
|
|
1627
|
-
return { code: this.code, message: this.message };
|
|
1628
|
-
}
|
|
1629
|
-
return {
|
|
1630
|
-
code: CCE_ERROR.DECRYPTION_FAILED,
|
|
1631
|
-
message: "Request processing failed"
|
|
1632
|
-
};
|
|
1633
|
-
}
|
|
1634
|
-
};
|
|
1559
|
+
// src/security/scopes.ts
|
|
1560
|
+
function hasScope(scopes, required) {
|
|
1561
|
+
if (!Array.isArray(scopes) || scopes.length === 0) {
|
|
1562
|
+
return false;
|
|
1635
1563
|
}
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
// src/cce/cce-derivation.service.ts
|
|
1639
|
-
function buildSalt(capsuleId, capsuleNonce, requestNonce) {
|
|
1640
|
-
const encoder = new TextEncoder();
|
|
1641
|
-
const data = encoder.encode(
|
|
1642
|
-
capsuleId + "|" + capsuleNonce + "|" + requestNonce
|
|
1643
|
-
);
|
|
1644
|
-
return (0, import_sha2.sha256)(data);
|
|
1645
|
-
}
|
|
1646
|
-
function buildInfo(contextPrefix, capsule, extraNonce) {
|
|
1647
|
-
const encoder = new TextEncoder();
|
|
1648
|
-
const parts = [
|
|
1649
|
-
contextPrefix,
|
|
1650
|
-
capsule.sub,
|
|
1651
|
-
capsule.kid,
|
|
1652
|
-
capsule.intent,
|
|
1653
|
-
capsule.aud,
|
|
1654
|
-
String(capsule.tps_from),
|
|
1655
|
-
String(capsule.tps_to),
|
|
1656
|
-
capsule.policy_hash ?? "",
|
|
1657
|
-
capsule.ver
|
|
1658
|
-
];
|
|
1659
|
-
if (extraNonce) {
|
|
1660
|
-
parts.push(extraNonce);
|
|
1564
|
+
if (scopes.includes(required)) {
|
|
1565
|
+
return true;
|
|
1661
1566
|
}
|
|
1662
|
-
|
|
1567
|
+
const [resource, id] = required.split(":");
|
|
1568
|
+
if (resource && id) {
|
|
1569
|
+
const wildcard = `${resource}:*`;
|
|
1570
|
+
if (scopes.includes(wildcard)) {
|
|
1571
|
+
return true;
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
return false;
|
|
1663
1575
|
}
|
|
1664
|
-
function
|
|
1665
|
-
const
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
input.capsule.capsule_nonce,
|
|
1669
|
-
input.requestNonce
|
|
1670
|
-
);
|
|
1671
|
-
const info = buildInfo(CCE_DERIVATION.REQUEST, input.capsule);
|
|
1672
|
-
return (0, import_hkdf.hkdf)(import_sha2.sha256, ikm, salt, info, CCE_AES_KEY_BYTES);
|
|
1576
|
+
function parseScope(scope) {
|
|
1577
|
+
const parts = scope.split(":");
|
|
1578
|
+
if (parts.length !== 2) return null;
|
|
1579
|
+
return { resource: parts[0], id: parts[1] };
|
|
1673
1580
|
}
|
|
1674
|
-
function
|
|
1675
|
-
const
|
|
1676
|
-
|
|
1677
|
-
executionKey.fill(0);
|
|
1678
|
-
return {
|
|
1679
|
-
execution_key_hash: keyHash,
|
|
1680
|
-
request_id: requestId,
|
|
1681
|
-
capsule_id: input.capsule.capsule_id,
|
|
1682
|
-
sub: input.capsule.sub,
|
|
1683
|
-
kid: input.capsule.kid,
|
|
1684
|
-
intent: input.capsule.intent,
|
|
1685
|
-
aud: input.capsule.aud,
|
|
1686
|
-
tps_from: input.capsule.tps_from,
|
|
1687
|
-
tps_to: input.capsule.tps_to,
|
|
1688
|
-
policy_hash: input.capsule.policy_hash,
|
|
1689
|
-
derived_at: Math.floor(Date.now() / 1e3),
|
|
1690
|
-
valid: true
|
|
1691
|
-
};
|
|
1581
|
+
function canAccessResource(scopes, resourceType, resourceId) {
|
|
1582
|
+
const required = `${resourceType}:${resourceId}`;
|
|
1583
|
+
return hasScope(scopes, required);
|
|
1692
1584
|
}
|
|
1693
|
-
var
|
|
1694
|
-
|
|
1695
|
-
"src/cce/cce-derivation.service.ts"() {
|
|
1696
|
-
import_utils = require("@noble/hashes/utils.js");
|
|
1697
|
-
import_hkdf = require("@noble/hashes/hkdf.js");
|
|
1698
|
-
import_sha2 = require("@noble/hashes/sha2.js");
|
|
1699
|
-
init_cce_types();
|
|
1585
|
+
var init_scopes = __esm({
|
|
1586
|
+
"src/security/scopes.ts"() {
|
|
1700
1587
|
}
|
|
1701
1588
|
});
|
|
1702
1589
|
|
|
1703
|
-
// src/
|
|
1704
|
-
function
|
|
1705
|
-
if (
|
|
1706
|
-
|
|
1707
|
-
}
|
|
1708
|
-
const iv = (0, import_crypto2.randomBytes)(CCE_IV_BYTES);
|
|
1709
|
-
const cipher = (0, import_crypto2.createCipheriv)("aes-256-gcm", key, iv);
|
|
1710
|
-
if (aad) {
|
|
1711
|
-
cipher.setAAD(aad);
|
|
1590
|
+
// src/security/inline-capsule.ts
|
|
1591
|
+
function normalizeInlineCapsule(input) {
|
|
1592
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
1593
|
+
return null;
|
|
1712
1594
|
}
|
|
1713
|
-
const
|
|
1714
|
-
const
|
|
1595
|
+
const raw = input;
|
|
1596
|
+
const scopes = normalizeStringList(raw.scopes ?? raw.scope);
|
|
1715
1597
|
return {
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1598
|
+
id: normalizeScalar(raw.id),
|
|
1599
|
+
actorId: normalizeScalar(raw.actorId),
|
|
1600
|
+
intents: normalizeStringList(raw.intents),
|
|
1601
|
+
issuedAt: normalizeTimestamp(raw.issuedAt ?? raw.iat),
|
|
1602
|
+
expiresAt: normalizeTimestamp(raw.expiresAt ?? raw.exp),
|
|
1603
|
+
realm: normalizeScalar(raw.realm),
|
|
1604
|
+
node: normalizeScalar(raw.node),
|
|
1605
|
+
scopes,
|
|
1606
|
+
raw
|
|
1719
1607
|
};
|
|
1720
1608
|
}
|
|
1721
|
-
function
|
|
1722
|
-
|
|
1609
|
+
function inlineCapsuleAllowsIntent(capsule, intent) {
|
|
1610
|
+
if (!capsule.intents || capsule.intents.length === 0) {
|
|
1611
|
+
return false;
|
|
1612
|
+
}
|
|
1613
|
+
for (const pattern of capsule.intents) {
|
|
1614
|
+
if (pattern === "*" || pattern === intent) {
|
|
1615
|
+
return true;
|
|
1616
|
+
}
|
|
1617
|
+
if (pattern.endsWith(".*")) {
|
|
1618
|
+
const prefix = pattern.slice(0, -1);
|
|
1619
|
+
if (intent.startsWith(prefix)) {
|
|
1620
|
+
return true;
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
return false;
|
|
1723
1625
|
}
|
|
1724
|
-
function
|
|
1725
|
-
|
|
1626
|
+
function isInlineCapsuleExpired(capsule, clockSkewMs = 3e4) {
|
|
1627
|
+
if (capsule.expiresAt === void 0) {
|
|
1628
|
+
return false;
|
|
1629
|
+
}
|
|
1630
|
+
return BigInt(Date.now()) > capsule.expiresAt + BigInt(clockSkewMs);
|
|
1726
1631
|
}
|
|
1727
|
-
function
|
|
1728
|
-
return
|
|
1632
|
+
function resolvePolicyScopes(scopes, context) {
|
|
1633
|
+
return scopes.map(
|
|
1634
|
+
(scope) => scope.replace(/\$\{([^}]+)\}/g, (_match, expression) => {
|
|
1635
|
+
const resolved = resolveTemplateExpression(expression.trim(), context);
|
|
1636
|
+
if (resolved === void 0 || resolved === null || resolved === "") {
|
|
1637
|
+
throw new Error(`CAPSULE_SCOPE_TEMPLATE_UNRESOLVED:${expression}`);
|
|
1638
|
+
}
|
|
1639
|
+
return String(resolved);
|
|
1640
|
+
})
|
|
1641
|
+
);
|
|
1729
1642
|
}
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
import_utils2 = require("@noble/hashes/utils.js");
|
|
1734
|
-
import_sha22 = require("@noble/hashes/sha2.js");
|
|
1735
|
-
import_crypto2 = require("crypto");
|
|
1736
|
-
init_cce_types();
|
|
1643
|
+
function inlineCapsuleSatisfiesScopes(capsule, requiredScopes, mode = "all") {
|
|
1644
|
+
if (!capsule.scopes || capsule.scopes.length === 0) {
|
|
1645
|
+
return false;
|
|
1737
1646
|
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1647
|
+
if (mode === "any") {
|
|
1648
|
+
return requiredScopes.some((scope) => hasScope(capsule.scopes, scope));
|
|
1649
|
+
}
|
|
1650
|
+
return requiredScopes.every((scope) => hasScope(capsule.scopes, scope));
|
|
1651
|
+
}
|
|
1652
|
+
function resolveTemplateExpression(expression, context) {
|
|
1653
|
+
if (expression === "intent") {
|
|
1654
|
+
return context.intent;
|
|
1655
|
+
}
|
|
1656
|
+
if (expression === "actorId") {
|
|
1657
|
+
return context.actorId;
|
|
1658
|
+
}
|
|
1659
|
+
if (expression === "chainId") {
|
|
1660
|
+
return context.chainId;
|
|
1661
|
+
}
|
|
1662
|
+
if (expression === "stepId") {
|
|
1663
|
+
return context.stepId;
|
|
1664
|
+
}
|
|
1665
|
+
if (expression.startsWith("body.")) {
|
|
1666
|
+
return getNestedValue(context.body, expression.slice(5));
|
|
1667
|
+
}
|
|
1668
|
+
return void 0;
|
|
1669
|
+
}
|
|
1670
|
+
function getNestedValue(value, path2) {
|
|
1671
|
+
if (!value || typeof value !== "object") {
|
|
1672
|
+
return void 0;
|
|
1673
|
+
}
|
|
1674
|
+
return path2.split(".").reduce((current, segment) => {
|
|
1675
|
+
if (!current || typeof current !== "object") {
|
|
1676
|
+
return void 0;
|
|
1677
|
+
}
|
|
1678
|
+
return current[segment];
|
|
1679
|
+
}, value);
|
|
1680
|
+
}
|
|
1681
|
+
function normalizeScalar(value) {
|
|
1682
|
+
if (typeof value === "string") {
|
|
1683
|
+
return value;
|
|
1684
|
+
}
|
|
1685
|
+
if (value instanceof Uint8Array) {
|
|
1686
|
+
return Buffer.from(value).toString("hex");
|
|
1687
|
+
}
|
|
1688
|
+
return void 0;
|
|
1689
|
+
}
|
|
1690
|
+
function normalizeStringList(value) {
|
|
1691
|
+
if (!value) {
|
|
1692
|
+
return void 0;
|
|
1693
|
+
}
|
|
1694
|
+
const list = Array.isArray(value) ? value : [value];
|
|
1695
|
+
const normalized = list.map((entry) => typeof entry === "string" ? entry : void 0).filter((entry) => !!entry && entry.trim().length > 0);
|
|
1696
|
+
return normalized.length > 0 ? Array.from(new Set(normalized)) : void 0;
|
|
1697
|
+
}
|
|
1698
|
+
function normalizeTimestamp(value) {
|
|
1699
|
+
if (typeof value === "bigint") {
|
|
1700
|
+
return value;
|
|
1701
|
+
}
|
|
1702
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1703
|
+
return BigInt(Math.trunc(value));
|
|
1704
|
+
}
|
|
1705
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1706
|
+
try {
|
|
1707
|
+
return BigInt(value);
|
|
1708
|
+
} catch {
|
|
1709
|
+
return void 0;
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
return void 0;
|
|
1713
|
+
}
|
|
1714
|
+
var init_inline_capsule = __esm({
|
|
1715
|
+
"src/security/inline-capsule.ts"() {
|
|
1716
|
+
init_scopes();
|
|
1717
|
+
}
|
|
1718
|
+
});
|
|
1719
|
+
|
|
1720
|
+
// src/sensor/axis-sensor.ts
|
|
1721
|
+
function normalizeSensorDecision(sensorDecision) {
|
|
1722
|
+
if ("action" in sensorDecision) {
|
|
1723
|
+
switch (sensorDecision.action) {
|
|
1724
|
+
case "ALLOW":
|
|
1725
|
+
return {
|
|
1726
|
+
allow: true,
|
|
1727
|
+
riskScore: 0,
|
|
1728
|
+
reasons: [],
|
|
1729
|
+
meta: sensorDecision.meta
|
|
1730
|
+
};
|
|
1731
|
+
case "DENY":
|
|
1732
|
+
return {
|
|
1733
|
+
allow: false,
|
|
1734
|
+
riskScore: 100,
|
|
1735
|
+
reasons: [sensorDecision.code, sensorDecision.reason].filter(
|
|
1736
|
+
Boolean
|
|
1737
|
+
),
|
|
1738
|
+
meta: sensorDecision.meta,
|
|
1739
|
+
retryAfterMs: sensorDecision.retryAfterMs
|
|
1740
|
+
};
|
|
1741
|
+
case "THROTTLE":
|
|
1742
|
+
return {
|
|
1743
|
+
allow: false,
|
|
1744
|
+
riskScore: 50,
|
|
1745
|
+
reasons: ["RATE_LIMIT"],
|
|
1746
|
+
retryAfterMs: sensorDecision.retryAfterMs,
|
|
1747
|
+
meta: sensorDecision.meta
|
|
1748
|
+
};
|
|
1749
|
+
case "FLAG":
|
|
1750
|
+
return {
|
|
1751
|
+
allow: true,
|
|
1752
|
+
riskScore: sensorDecision.scoreDelta,
|
|
1753
|
+
reasons: sensorDecision.reasons,
|
|
1754
|
+
meta: sensorDecision.meta
|
|
1755
|
+
};
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
return {
|
|
1759
|
+
allow: sensorDecision.allow,
|
|
1760
|
+
riskScore: sensorDecision.riskScore,
|
|
1761
|
+
reasons: sensorDecision.reasons,
|
|
1762
|
+
tags: sensorDecision.tags,
|
|
1763
|
+
meta: sensorDecision.meta,
|
|
1764
|
+
tighten: sensorDecision.tighten,
|
|
1765
|
+
retryAfterMs: sensorDecision.retryAfterMs
|
|
1766
|
+
};
|
|
1767
|
+
}
|
|
1768
|
+
var Decision, SensorDecisions;
|
|
1769
|
+
var init_axis_sensor = __esm({
|
|
1770
|
+
"src/sensor/axis-sensor.ts"() {
|
|
1771
|
+
Decision = /* @__PURE__ */ ((Decision2) => {
|
|
1772
|
+
Decision2["ALLOW"] = "ALLOW";
|
|
1773
|
+
Decision2["DENY"] = "DENY";
|
|
1774
|
+
Decision2["THROTTLE"] = "THROTTLE";
|
|
1775
|
+
Decision2["FLAG"] = "FLAG";
|
|
1776
|
+
return Decision2;
|
|
1777
|
+
})(Decision || {});
|
|
1778
|
+
SensorDecisions = {
|
|
1779
|
+
allow(meta, tags) {
|
|
1780
|
+
return {
|
|
1781
|
+
decision: "ALLOW" /* ALLOW */,
|
|
1782
|
+
allow: true,
|
|
1783
|
+
riskScore: 0,
|
|
1784
|
+
reasons: [],
|
|
1785
|
+
tags,
|
|
1786
|
+
meta
|
|
1787
|
+
};
|
|
1788
|
+
},
|
|
1789
|
+
deny(code, reason, meta) {
|
|
1790
|
+
return {
|
|
1791
|
+
decision: "DENY" /* DENY */,
|
|
1792
|
+
allow: false,
|
|
1793
|
+
riskScore: 100,
|
|
1794
|
+
code,
|
|
1795
|
+
reasons: [code, reason].filter(Boolean),
|
|
1796
|
+
meta
|
|
1797
|
+
};
|
|
1798
|
+
},
|
|
1799
|
+
throttle(retryAfterMs, meta) {
|
|
1800
|
+
return {
|
|
1801
|
+
decision: "THROTTLE" /* THROTTLE */,
|
|
1802
|
+
allow: false,
|
|
1803
|
+
riskScore: 50,
|
|
1804
|
+
retryAfterMs,
|
|
1805
|
+
code: "RATE_LIMIT",
|
|
1806
|
+
reasons: ["RATE_LIMIT"],
|
|
1807
|
+
meta
|
|
1808
|
+
};
|
|
1809
|
+
},
|
|
1810
|
+
flag(scoreDelta, reasons, meta) {
|
|
1811
|
+
return {
|
|
1812
|
+
decision: "FLAG" /* FLAG */,
|
|
1813
|
+
allow: true,
|
|
1814
|
+
riskScore: scoreDelta,
|
|
1815
|
+
scoreDelta,
|
|
1816
|
+
reasons,
|
|
1817
|
+
meta
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
};
|
|
1821
|
+
}
|
|
1822
|
+
});
|
|
1823
|
+
|
|
1824
|
+
// src/cce/cce.types.ts
|
|
1825
|
+
var CCE_PROTOCOL_VERSION, CCE_DERIVATION, CCE_AES_KEY_BYTES, CCE_IV_BYTES, CCE_NONCE_BYTES, CCE_ERROR, CceError;
|
|
1826
|
+
var init_cce_types = __esm({
|
|
1827
|
+
"src/cce/cce.types.ts"() {
|
|
1828
|
+
CCE_PROTOCOL_VERSION = "cce-v1";
|
|
1829
|
+
CCE_DERIVATION = {
|
|
1830
|
+
/** Request execution context */
|
|
1831
|
+
REQUEST: "axis:cce:req:v1",
|
|
1832
|
+
/** Response execution context */
|
|
1833
|
+
RESPONSE: "axis:cce:resp:v1",
|
|
1834
|
+
/** Witness binding context */
|
|
1835
|
+
WITNESS: "axis:cce:witness:v1"
|
|
1836
|
+
};
|
|
1837
|
+
CCE_AES_KEY_BYTES = 32;
|
|
1838
|
+
CCE_IV_BYTES = 12;
|
|
1839
|
+
CCE_NONCE_BYTES = 32;
|
|
1840
|
+
CCE_ERROR = {
|
|
1841
|
+
// Envelope errors
|
|
1842
|
+
INVALID_ENVELOPE: "CCE_INVALID_ENVELOPE",
|
|
1843
|
+
UNSUPPORTED_VERSION: "CCE_UNSUPPORTED_VERSION",
|
|
1844
|
+
MISSING_CAPSULE: "CCE_MISSING_CAPSULE",
|
|
1845
|
+
MISSING_ENCRYPTED_KEY: "CCE_MISSING_ENCRYPTED_KEY",
|
|
1846
|
+
// Signature errors
|
|
1847
|
+
CLIENT_SIG_INVALID: "CCE_CLIENT_SIG_INVALID",
|
|
1848
|
+
CLIENT_KEY_NOT_FOUND: "CCE_CLIENT_KEY_NOT_FOUND",
|
|
1849
|
+
// Capsule errors
|
|
1850
|
+
CAPSULE_SIG_INVALID: "CCE_CAPSULE_SIG_INVALID",
|
|
1851
|
+
CAPSULE_EXPIRED: "CCE_CAPSULE_EXPIRED",
|
|
1852
|
+
CAPSULE_NOT_YET_VALID: "CCE_CAPSULE_NOT_YET_VALID",
|
|
1853
|
+
CAPSULE_REVOKED: "CCE_CAPSULE_REVOKED",
|
|
1854
|
+
CAPSULE_CONSUMED: "CCE_CAPSULE_CONSUMED",
|
|
1855
|
+
CAPSULE_NOT_VERIFIED: "CCE_CAPSULE_NOT_VERIFIED",
|
|
1856
|
+
// Binding errors
|
|
1857
|
+
AUDIENCE_MISMATCH: "CCE_AUDIENCE_MISMATCH",
|
|
1858
|
+
INTENT_MISMATCH: "CCE_INTENT_MISMATCH",
|
|
1859
|
+
TPS_WINDOW_EXPIRED: "CCE_TPS_WINDOW_EXPIRED",
|
|
1860
|
+
TPS_WINDOW_FUTURE: "CCE_TPS_WINDOW_FUTURE",
|
|
1861
|
+
// Replay / nonce errors
|
|
1862
|
+
REPLAY_DETECTED: "CCE_REPLAY_DETECTED",
|
|
1863
|
+
NONCE_REUSED: "CCE_NONCE_REUSED",
|
|
1864
|
+
// Decryption errors
|
|
1865
|
+
DECRYPTION_FAILED: "CCE_DECRYPTION_FAILED",
|
|
1866
|
+
KEY_UNWRAP_FAILED: "CCE_KEY_UNWRAP_FAILED",
|
|
1867
|
+
AEAD_TAG_MISMATCH: "CCE_AEAD_TAG_MISMATCH",
|
|
1868
|
+
PAYLOAD_TOO_LARGE: "CCE_PAYLOAD_TOO_LARGE",
|
|
1869
|
+
// Schema / validation errors
|
|
1870
|
+
PAYLOAD_SCHEMA_INVALID: "CCE_PAYLOAD_SCHEMA_INVALID",
|
|
1871
|
+
INTENT_SCHEMA_MISMATCH: "CCE_INTENT_SCHEMA_MISMATCH",
|
|
1872
|
+
// Policy errors
|
|
1873
|
+
POLICY_DENIED: "CCE_POLICY_DENIED",
|
|
1874
|
+
CONSTRAINT_VIOLATED: "CCE_CONSTRAINT_VIOLATED",
|
|
1875
|
+
// Handler errors
|
|
1876
|
+
HANDLER_NOT_FOUND: "CCE_HANDLER_NOT_FOUND",
|
|
1877
|
+
HANDLER_EXECUTION_FAILED: "CCE_HANDLER_EXECUTION_FAILED",
|
|
1878
|
+
HANDLER_TIMEOUT: "CCE_HANDLER_TIMEOUT",
|
|
1879
|
+
// Response errors
|
|
1880
|
+
RESPONSE_ENCRYPTION_FAILED: "CCE_RESPONSE_ENCRYPTION_FAILED"
|
|
1881
|
+
};
|
|
1882
|
+
CceError = class extends Error {
|
|
1883
|
+
constructor(code, message, metadata) {
|
|
1884
|
+
super(`[${code}] ${message}`);
|
|
1885
|
+
this.code = code;
|
|
1886
|
+
this.metadata = metadata;
|
|
1887
|
+
this.name = "CceError";
|
|
1888
|
+
}
|
|
1889
|
+
/** Whether this error is safe to expose to the client */
|
|
1890
|
+
get clientSafe() {
|
|
1891
|
+
const internal = [
|
|
1892
|
+
CCE_ERROR.DECRYPTION_FAILED,
|
|
1893
|
+
CCE_ERROR.KEY_UNWRAP_FAILED,
|
|
1894
|
+
CCE_ERROR.AEAD_TAG_MISMATCH,
|
|
1895
|
+
CCE_ERROR.HANDLER_EXECUTION_FAILED,
|
|
1896
|
+
CCE_ERROR.RESPONSE_ENCRYPTION_FAILED
|
|
1897
|
+
];
|
|
1898
|
+
return !internal.includes(this.code);
|
|
1899
|
+
}
|
|
1900
|
+
/** Get client-safe representation */
|
|
1901
|
+
toClientError() {
|
|
1902
|
+
if (this.clientSafe) {
|
|
1903
|
+
return { code: this.code, message: this.message };
|
|
1904
|
+
}
|
|
1905
|
+
return {
|
|
1906
|
+
code: CCE_ERROR.DECRYPTION_FAILED,
|
|
1907
|
+
message: "Request processing failed"
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
};
|
|
1911
|
+
}
|
|
1912
|
+
});
|
|
1913
|
+
|
|
1914
|
+
// src/cce/cce-derivation.service.ts
|
|
1915
|
+
function buildSalt(capsuleId, capsuleNonce, requestNonce) {
|
|
1916
|
+
const encoder = new TextEncoder();
|
|
1917
|
+
const data = encoder.encode(
|
|
1918
|
+
capsuleId + "|" + capsuleNonce + "|" + requestNonce
|
|
1919
|
+
);
|
|
1920
|
+
return (0, import_sha2.sha256)(data);
|
|
1921
|
+
}
|
|
1922
|
+
function buildInfo(contextPrefix, capsule, extraNonce) {
|
|
1923
|
+
const encoder = new TextEncoder();
|
|
1924
|
+
const parts = [
|
|
1925
|
+
contextPrefix,
|
|
1926
|
+
capsule.sub,
|
|
1927
|
+
capsule.kid,
|
|
1928
|
+
capsule.intent,
|
|
1929
|
+
capsule.aud,
|
|
1930
|
+
String(capsule.tps_from),
|
|
1931
|
+
String(capsule.tps_to),
|
|
1932
|
+
capsule.policy_hash ?? "",
|
|
1933
|
+
capsule.ver
|
|
1934
|
+
];
|
|
1935
|
+
if (extraNonce) {
|
|
1936
|
+
parts.push(extraNonce);
|
|
1937
|
+
}
|
|
1938
|
+
return encoder.encode(parts.join("|"));
|
|
1939
|
+
}
|
|
1940
|
+
function deriveRequestExecutionKey(input) {
|
|
1941
|
+
const ikm = (0, import_utils.hexToBytes)(input.axisLocalSecret);
|
|
1942
|
+
const salt = buildSalt(
|
|
1943
|
+
input.capsule.capsule_id,
|
|
1944
|
+
input.capsule.capsule_nonce,
|
|
1945
|
+
input.requestNonce
|
|
1946
|
+
);
|
|
1947
|
+
const info = buildInfo(CCE_DERIVATION.REQUEST, input.capsule);
|
|
1948
|
+
return (0, import_hkdf.hkdf)(import_sha2.sha256, ikm, salt, info, CCE_AES_KEY_BYTES);
|
|
1949
|
+
}
|
|
1950
|
+
function buildExecutionContext(input, requestId) {
|
|
1951
|
+
const executionKey = deriveRequestExecutionKey(input);
|
|
1952
|
+
const keyHash = (0, import_utils.bytesToHex)((0, import_sha2.sha256)(executionKey));
|
|
1953
|
+
executionKey.fill(0);
|
|
1954
|
+
return {
|
|
1955
|
+
execution_key_hash: keyHash,
|
|
1956
|
+
request_id: requestId,
|
|
1957
|
+
capsule_id: input.capsule.capsule_id,
|
|
1958
|
+
sub: input.capsule.sub,
|
|
1959
|
+
kid: input.capsule.kid,
|
|
1960
|
+
intent: input.capsule.intent,
|
|
1961
|
+
aud: input.capsule.aud,
|
|
1962
|
+
tps_from: input.capsule.tps_from,
|
|
1963
|
+
tps_to: input.capsule.tps_to,
|
|
1964
|
+
policy_hash: input.capsule.policy_hash,
|
|
1965
|
+
derived_at: Math.floor(Date.now() / 1e3),
|
|
1966
|
+
valid: true
|
|
1967
|
+
};
|
|
1968
|
+
}
|
|
1969
|
+
var import_utils, import_hkdf, import_sha2;
|
|
1970
|
+
var init_cce_derivation_service = __esm({
|
|
1971
|
+
"src/cce/cce-derivation.service.ts"() {
|
|
1972
|
+
import_utils = require("@noble/hashes/utils.js");
|
|
1973
|
+
import_hkdf = require("@noble/hashes/hkdf.js");
|
|
1974
|
+
import_sha2 = require("@noble/hashes/sha2.js");
|
|
1975
|
+
init_cce_types();
|
|
1976
|
+
}
|
|
1977
|
+
});
|
|
1978
|
+
|
|
1979
|
+
// src/cce/cce-crypto.ts
|
|
1980
|
+
function aesGcmEncrypt(key, plaintext, aad) {
|
|
1981
|
+
if (key.length !== CCE_AES_KEY_BYTES) {
|
|
1982
|
+
throw new Error(`AES key must be ${CCE_AES_KEY_BYTES} bytes`);
|
|
1983
|
+
}
|
|
1984
|
+
const iv = (0, import_crypto2.randomBytes)(CCE_IV_BYTES);
|
|
1985
|
+
const cipher = (0, import_crypto2.createCipheriv)("aes-256-gcm", key, iv);
|
|
1986
|
+
if (aad) {
|
|
1987
|
+
cipher.setAAD(aad);
|
|
1988
|
+
}
|
|
1989
|
+
const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
1990
|
+
const tag = cipher.getAuthTag();
|
|
1991
|
+
return {
|
|
1992
|
+
iv: new Uint8Array(iv),
|
|
1993
|
+
ciphertext: new Uint8Array(encrypted),
|
|
1994
|
+
tag: new Uint8Array(tag)
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
function generateAesKey() {
|
|
1998
|
+
return new Uint8Array((0, import_crypto2.randomBytes)(CCE_AES_KEY_BYTES));
|
|
1999
|
+
}
|
|
2000
|
+
function base64UrlEncode(bytes2) {
|
|
2001
|
+
return Buffer.from(bytes2).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
2002
|
+
}
|
|
2003
|
+
function hashPayload(payload) {
|
|
2004
|
+
return (0, import_utils2.bytesToHex)((0, import_sha22.sha256)(payload));
|
|
2005
|
+
}
|
|
2006
|
+
var import_utils2, import_sha22, import_crypto2;
|
|
2007
|
+
var init_cce_crypto = __esm({
|
|
2008
|
+
"src/cce/cce-crypto.ts"() {
|
|
2009
|
+
import_utils2 = require("@noble/hashes/utils.js");
|
|
2010
|
+
import_sha22 = require("@noble/hashes/sha2.js");
|
|
2011
|
+
import_crypto2 = require("crypto");
|
|
2012
|
+
init_cce_types();
|
|
2013
|
+
}
|
|
2014
|
+
});
|
|
2015
|
+
|
|
2016
|
+
// src/cce/cce-response.service.ts
|
|
1741
2017
|
async function buildCceResponse(options, clientKeyEncryptor, axisSigner) {
|
|
1742
2018
|
const { request, capsule, status, body, clientPublicKeyHex, witnessRef } = options;
|
|
1743
2019
|
const responseNonce = (0, import_utils3.bytesToHex)(
|
|
@@ -1914,124 +2190,20 @@ function computeExecutionContextHash(axisLocalSecret, capsule, requestNonce) {
|
|
|
1914
2190
|
return hash;
|
|
1915
2191
|
}
|
|
1916
2192
|
function hexToBytes2(hex) {
|
|
1917
|
-
const bytes2 = new Uint8Array(hex.length / 2);
|
|
1918
|
-
for (let i = 0; i < bytes2.length; i++) {
|
|
1919
|
-
bytes2[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
1920
|
-
}
|
|
1921
|
-
return bytes2;
|
|
1922
|
-
}
|
|
1923
|
-
var import_utils4, import_hkdf2, import_sha23;
|
|
1924
|
-
var init_cce_witness_observer = __esm({
|
|
1925
|
-
"src/cce/cce-witness.observer.ts"() {
|
|
1926
|
-
import_utils4 = require("@noble/hashes/utils.js");
|
|
1927
|
-
import_hkdf2 = require("@noble/hashes/hkdf.js");
|
|
1928
|
-
import_sha23 = require("@noble/hashes/sha2.js");
|
|
1929
|
-
init_cce_crypto();
|
|
1930
|
-
init_cce_types();
|
|
1931
|
-
}
|
|
1932
|
-
});
|
|
1933
|
-
|
|
1934
|
-
// src/sensor/axis-sensor.ts
|
|
1935
|
-
function normalizeSensorDecision(sensorDecision) {
|
|
1936
|
-
if ("action" in sensorDecision) {
|
|
1937
|
-
switch (sensorDecision.action) {
|
|
1938
|
-
case "ALLOW":
|
|
1939
|
-
return {
|
|
1940
|
-
allow: true,
|
|
1941
|
-
riskScore: 0,
|
|
1942
|
-
reasons: [],
|
|
1943
|
-
meta: sensorDecision.meta
|
|
1944
|
-
};
|
|
1945
|
-
case "DENY":
|
|
1946
|
-
return {
|
|
1947
|
-
allow: false,
|
|
1948
|
-
riskScore: 100,
|
|
1949
|
-
reasons: [sensorDecision.code, sensorDecision.reason].filter(
|
|
1950
|
-
Boolean
|
|
1951
|
-
),
|
|
1952
|
-
meta: sensorDecision.meta,
|
|
1953
|
-
retryAfterMs: sensorDecision.retryAfterMs
|
|
1954
|
-
};
|
|
1955
|
-
case "THROTTLE":
|
|
1956
|
-
return {
|
|
1957
|
-
allow: false,
|
|
1958
|
-
riskScore: 50,
|
|
1959
|
-
reasons: ["RATE_LIMIT"],
|
|
1960
|
-
retryAfterMs: sensorDecision.retryAfterMs,
|
|
1961
|
-
meta: sensorDecision.meta
|
|
1962
|
-
};
|
|
1963
|
-
case "FLAG":
|
|
1964
|
-
return {
|
|
1965
|
-
allow: true,
|
|
1966
|
-
riskScore: sensorDecision.scoreDelta,
|
|
1967
|
-
reasons: sensorDecision.reasons,
|
|
1968
|
-
meta: sensorDecision.meta
|
|
1969
|
-
};
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
return {
|
|
1973
|
-
allow: sensorDecision.allow,
|
|
1974
|
-
riskScore: sensorDecision.riskScore,
|
|
1975
|
-
reasons: sensorDecision.reasons,
|
|
1976
|
-
tags: sensorDecision.tags,
|
|
1977
|
-
meta: sensorDecision.meta,
|
|
1978
|
-
tighten: sensorDecision.tighten,
|
|
1979
|
-
retryAfterMs: sensorDecision.retryAfterMs
|
|
1980
|
-
};
|
|
2193
|
+
const bytes2 = new Uint8Array(hex.length / 2);
|
|
2194
|
+
for (let i = 0; i < bytes2.length; i++) {
|
|
2195
|
+
bytes2[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
2196
|
+
}
|
|
2197
|
+
return bytes2;
|
|
1981
2198
|
}
|
|
1982
|
-
var
|
|
1983
|
-
var
|
|
1984
|
-
"src/
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
return Decision2;
|
|
1991
|
-
})(Decision || {});
|
|
1992
|
-
SensorDecisions = {
|
|
1993
|
-
allow(meta, tags) {
|
|
1994
|
-
return {
|
|
1995
|
-
decision: "ALLOW" /* ALLOW */,
|
|
1996
|
-
allow: true,
|
|
1997
|
-
riskScore: 0,
|
|
1998
|
-
reasons: [],
|
|
1999
|
-
tags,
|
|
2000
|
-
meta
|
|
2001
|
-
};
|
|
2002
|
-
},
|
|
2003
|
-
deny(code, reason, meta) {
|
|
2004
|
-
return {
|
|
2005
|
-
decision: "DENY" /* DENY */,
|
|
2006
|
-
allow: false,
|
|
2007
|
-
riskScore: 100,
|
|
2008
|
-
code,
|
|
2009
|
-
reasons: [code, reason].filter(Boolean),
|
|
2010
|
-
meta
|
|
2011
|
-
};
|
|
2012
|
-
},
|
|
2013
|
-
throttle(retryAfterMs, meta) {
|
|
2014
|
-
return {
|
|
2015
|
-
decision: "THROTTLE" /* THROTTLE */,
|
|
2016
|
-
allow: false,
|
|
2017
|
-
riskScore: 50,
|
|
2018
|
-
retryAfterMs,
|
|
2019
|
-
code: "RATE_LIMIT",
|
|
2020
|
-
reasons: ["RATE_LIMIT"],
|
|
2021
|
-
meta
|
|
2022
|
-
};
|
|
2023
|
-
},
|
|
2024
|
-
flag(scoreDelta, reasons, meta) {
|
|
2025
|
-
return {
|
|
2026
|
-
decision: "FLAG" /* FLAG */,
|
|
2027
|
-
allow: true,
|
|
2028
|
-
riskScore: scoreDelta,
|
|
2029
|
-
scoreDelta,
|
|
2030
|
-
reasons,
|
|
2031
|
-
meta
|
|
2032
|
-
};
|
|
2033
|
-
}
|
|
2034
|
-
};
|
|
2199
|
+
var import_utils4, import_hkdf2, import_sha23;
|
|
2200
|
+
var init_cce_witness_observer = __esm({
|
|
2201
|
+
"src/cce/cce-witness.observer.ts"() {
|
|
2202
|
+
import_utils4 = require("@noble/hashes/utils.js");
|
|
2203
|
+
import_hkdf2 = require("@noble/hashes/hkdf.js");
|
|
2204
|
+
import_sha23 = require("@noble/hashes/sha2.js");
|
|
2205
|
+
init_cce_crypto();
|
|
2206
|
+
init_cce_types();
|
|
2035
2207
|
}
|
|
2036
2208
|
});
|
|
2037
2209
|
|
|
@@ -2283,167 +2455,6 @@ var init_axis_error = __esm({
|
|
|
2283
2455
|
}
|
|
2284
2456
|
});
|
|
2285
2457
|
|
|
2286
|
-
// src/security/scopes.ts
|
|
2287
|
-
function hasScope(scopes, required) {
|
|
2288
|
-
if (!Array.isArray(scopes) || scopes.length === 0) {
|
|
2289
|
-
return false;
|
|
2290
|
-
}
|
|
2291
|
-
if (scopes.includes(required)) {
|
|
2292
|
-
return true;
|
|
2293
|
-
}
|
|
2294
|
-
const [resource, id] = required.split(":");
|
|
2295
|
-
if (resource && id) {
|
|
2296
|
-
const wildcard = `${resource}:*`;
|
|
2297
|
-
if (scopes.includes(wildcard)) {
|
|
2298
|
-
return true;
|
|
2299
|
-
}
|
|
2300
|
-
}
|
|
2301
|
-
return false;
|
|
2302
|
-
}
|
|
2303
|
-
function parseScope(scope) {
|
|
2304
|
-
const parts = scope.split(":");
|
|
2305
|
-
if (parts.length !== 2) return null;
|
|
2306
|
-
return { resource: parts[0], id: parts[1] };
|
|
2307
|
-
}
|
|
2308
|
-
function canAccessResource(scopes, resourceType, resourceId) {
|
|
2309
|
-
const required = `${resourceType}:${resourceId}`;
|
|
2310
|
-
return hasScope(scopes, required);
|
|
2311
|
-
}
|
|
2312
|
-
var init_scopes = __esm({
|
|
2313
|
-
"src/security/scopes.ts"() {
|
|
2314
|
-
}
|
|
2315
|
-
});
|
|
2316
|
-
|
|
2317
|
-
// src/security/inline-capsule.ts
|
|
2318
|
-
function normalizeInlineCapsule(input) {
|
|
2319
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
2320
|
-
return null;
|
|
2321
|
-
}
|
|
2322
|
-
const raw = input;
|
|
2323
|
-
const scopes = normalizeStringList(raw.scopes ?? raw.scope);
|
|
2324
|
-
return {
|
|
2325
|
-
id: normalizeScalar(raw.id),
|
|
2326
|
-
actorId: normalizeScalar(raw.actorId),
|
|
2327
|
-
intents: normalizeStringList(raw.intents),
|
|
2328
|
-
issuedAt: normalizeTimestamp(raw.issuedAt ?? raw.iat),
|
|
2329
|
-
expiresAt: normalizeTimestamp(raw.expiresAt ?? raw.exp),
|
|
2330
|
-
realm: normalizeScalar(raw.realm),
|
|
2331
|
-
node: normalizeScalar(raw.node),
|
|
2332
|
-
scopes,
|
|
2333
|
-
raw
|
|
2334
|
-
};
|
|
2335
|
-
}
|
|
2336
|
-
function inlineCapsuleAllowsIntent(capsule, intent) {
|
|
2337
|
-
if (!capsule.intents || capsule.intents.length === 0) {
|
|
2338
|
-
return false;
|
|
2339
|
-
}
|
|
2340
|
-
for (const pattern of capsule.intents) {
|
|
2341
|
-
if (pattern === "*" || pattern === intent) {
|
|
2342
|
-
return true;
|
|
2343
|
-
}
|
|
2344
|
-
if (pattern.endsWith(".*")) {
|
|
2345
|
-
const prefix = pattern.slice(0, -1);
|
|
2346
|
-
if (intent.startsWith(prefix)) {
|
|
2347
|
-
return true;
|
|
2348
|
-
}
|
|
2349
|
-
}
|
|
2350
|
-
}
|
|
2351
|
-
return false;
|
|
2352
|
-
}
|
|
2353
|
-
function isInlineCapsuleExpired(capsule, clockSkewMs = 3e4) {
|
|
2354
|
-
if (capsule.expiresAt === void 0) {
|
|
2355
|
-
return false;
|
|
2356
|
-
}
|
|
2357
|
-
return BigInt(Date.now()) > capsule.expiresAt + BigInt(clockSkewMs);
|
|
2358
|
-
}
|
|
2359
|
-
function resolvePolicyScopes(scopes, context) {
|
|
2360
|
-
return scopes.map(
|
|
2361
|
-
(scope) => scope.replace(/\$\{([^}]+)\}/g, (_match, expression) => {
|
|
2362
|
-
const resolved = resolveTemplateExpression(expression.trim(), context);
|
|
2363
|
-
if (resolved === void 0 || resolved === null || resolved === "") {
|
|
2364
|
-
throw new Error(`CAPSULE_SCOPE_TEMPLATE_UNRESOLVED:${expression}`);
|
|
2365
|
-
}
|
|
2366
|
-
return String(resolved);
|
|
2367
|
-
})
|
|
2368
|
-
);
|
|
2369
|
-
}
|
|
2370
|
-
function inlineCapsuleSatisfiesScopes(capsule, requiredScopes, mode = "all") {
|
|
2371
|
-
if (!capsule.scopes || capsule.scopes.length === 0) {
|
|
2372
|
-
return false;
|
|
2373
|
-
}
|
|
2374
|
-
if (mode === "any") {
|
|
2375
|
-
return requiredScopes.some((scope) => hasScope(capsule.scopes, scope));
|
|
2376
|
-
}
|
|
2377
|
-
return requiredScopes.every((scope) => hasScope(capsule.scopes, scope));
|
|
2378
|
-
}
|
|
2379
|
-
function resolveTemplateExpression(expression, context) {
|
|
2380
|
-
if (expression === "intent") {
|
|
2381
|
-
return context.intent;
|
|
2382
|
-
}
|
|
2383
|
-
if (expression === "actorId") {
|
|
2384
|
-
return context.actorId;
|
|
2385
|
-
}
|
|
2386
|
-
if (expression === "chainId") {
|
|
2387
|
-
return context.chainId;
|
|
2388
|
-
}
|
|
2389
|
-
if (expression === "stepId") {
|
|
2390
|
-
return context.stepId;
|
|
2391
|
-
}
|
|
2392
|
-
if (expression.startsWith("body.")) {
|
|
2393
|
-
return getNestedValue(context.body, expression.slice(5));
|
|
2394
|
-
}
|
|
2395
|
-
return void 0;
|
|
2396
|
-
}
|
|
2397
|
-
function getNestedValue(value, path2) {
|
|
2398
|
-
if (!value || typeof value !== "object") {
|
|
2399
|
-
return void 0;
|
|
2400
|
-
}
|
|
2401
|
-
return path2.split(".").reduce((current, segment) => {
|
|
2402
|
-
if (!current || typeof current !== "object") {
|
|
2403
|
-
return void 0;
|
|
2404
|
-
}
|
|
2405
|
-
return current[segment];
|
|
2406
|
-
}, value);
|
|
2407
|
-
}
|
|
2408
|
-
function normalizeScalar(value) {
|
|
2409
|
-
if (typeof value === "string") {
|
|
2410
|
-
return value;
|
|
2411
|
-
}
|
|
2412
|
-
if (value instanceof Uint8Array) {
|
|
2413
|
-
return Buffer.from(value).toString("hex");
|
|
2414
|
-
}
|
|
2415
|
-
return void 0;
|
|
2416
|
-
}
|
|
2417
|
-
function normalizeStringList(value) {
|
|
2418
|
-
if (!value) {
|
|
2419
|
-
return void 0;
|
|
2420
|
-
}
|
|
2421
|
-
const list = Array.isArray(value) ? value : [value];
|
|
2422
|
-
const normalized = list.map((entry) => typeof entry === "string" ? entry : void 0).filter((entry) => !!entry && entry.trim().length > 0);
|
|
2423
|
-
return normalized.length > 0 ? Array.from(new Set(normalized)) : void 0;
|
|
2424
|
-
}
|
|
2425
|
-
function normalizeTimestamp(value) {
|
|
2426
|
-
if (typeof value === "bigint") {
|
|
2427
|
-
return value;
|
|
2428
|
-
}
|
|
2429
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2430
|
-
return BigInt(Math.trunc(value));
|
|
2431
|
-
}
|
|
2432
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
2433
|
-
try {
|
|
2434
|
-
return BigInt(value);
|
|
2435
|
-
} catch {
|
|
2436
|
-
return void 0;
|
|
2437
|
-
}
|
|
2438
|
-
}
|
|
2439
|
-
return void 0;
|
|
2440
|
-
}
|
|
2441
|
-
var init_inline_capsule = __esm({
|
|
2442
|
-
"src/security/inline-capsule.ts"() {
|
|
2443
|
-
init_scopes();
|
|
2444
|
-
}
|
|
2445
|
-
});
|
|
2446
|
-
|
|
2447
2458
|
// src/engine/intent.router.ts
|
|
2448
2459
|
var intent_router_exports = {};
|
|
2449
2460
|
__export(intent_router_exports, {
|
|
@@ -2517,23 +2528,23 @@ var import_axis_protocol4, import_dto_schema, _IntentRouter, IntentRouter;
|
|
|
2517
2528
|
var init_intent_router = __esm({
|
|
2518
2529
|
"src/engine/intent.router.ts"() {
|
|
2519
2530
|
import_axis_protocol4 = require("@nextera.one/axis-protocol");
|
|
2520
|
-
init_cce_pipeline();
|
|
2521
|
-
init_axis_error();
|
|
2522
|
-
init_constants();
|
|
2523
|
-
init_capsule_policy_decorator();
|
|
2524
|
-
init_chain_decorator();
|
|
2525
|
-
import_dto_schema = __toESM(require_dto_schema_util());
|
|
2526
2531
|
init_handler_sensors_decorator();
|
|
2527
|
-
|
|
2528
|
-
init_intent_body_decorator();
|
|
2529
|
-
init_intent_policy_decorator();
|
|
2532
|
+
init_capsule_policy_decorator();
|
|
2530
2533
|
init_intent_sensors_decorator();
|
|
2531
|
-
|
|
2534
|
+
init_intent_policy_decorator();
|
|
2535
|
+
init_intent_body_decorator();
|
|
2532
2536
|
init_observer_decorator();
|
|
2537
|
+
init_handler_decorator();
|
|
2538
|
+
init_intent_decorator();
|
|
2539
|
+
init_chain_decorator();
|
|
2540
|
+
import_dto_schema = __toESM(require_dto_schema_util());
|
|
2533
2541
|
init_inline_capsule();
|
|
2534
|
-
init_axis_sensor();
|
|
2535
2542
|
init_axis_execution_context();
|
|
2543
|
+
init_axis_sensor();
|
|
2536
2544
|
init_axis_logger();
|
|
2545
|
+
init_cce_pipeline();
|
|
2546
|
+
init_axis_error();
|
|
2547
|
+
init_constants();
|
|
2537
2548
|
_IntentRouter = class _IntentRouter {
|
|
2538
2549
|
constructor(dependencyResolver, observerDispatcher, sensorRegistry) {
|
|
2539
2550
|
this.logger = createAxisLogger(_IntentRouter.name);
|
|
@@ -2569,6 +2580,8 @@ var init_intent_router = __esm({
|
|
|
2569
2580
|
this.publicIntents = /* @__PURE__ */ new Set();
|
|
2570
2581
|
/** Intents flagged as anonymous-session accessible */
|
|
2571
2582
|
this.anonymousIntents = /* @__PURE__ */ new Set();
|
|
2583
|
+
/** Intents flagged as authorized-session accessible */
|
|
2584
|
+
this.authorizedIntents = /* @__PURE__ */ new Set();
|
|
2572
2585
|
/** Per-intent rate limit config */
|
|
2573
2586
|
this.intentRateLimits = /* @__PURE__ */ new Map();
|
|
2574
2587
|
/** CCE handler registry */
|
|
@@ -2995,6 +3008,18 @@ var init_intent_router = __esm({
|
|
|
2995
3008
|
if (isAnonMethod || isAnonClass) {
|
|
2996
3009
|
this.anonymousIntents.add(intent);
|
|
2997
3010
|
}
|
|
3011
|
+
const isAuthorizedMethod = Reflect.getMetadata(
|
|
3012
|
+
AXIS_AUTHORIZED_KEY,
|
|
3013
|
+
proto,
|
|
3014
|
+
methodName
|
|
3015
|
+
);
|
|
3016
|
+
const isAuthorizedClass = Reflect.getMetadata(
|
|
3017
|
+
AXIS_AUTHORIZED_KEY,
|
|
3018
|
+
proto.constructor
|
|
3019
|
+
);
|
|
3020
|
+
if (isAuthorizedMethod || isAuthorizedClass) {
|
|
3021
|
+
this.authorizedIntents.add(intent);
|
|
3022
|
+
}
|
|
2998
3023
|
const rateLimit = Reflect.getMetadata(
|
|
2999
3024
|
AXIS_RATE_LIMIT_KEY,
|
|
3000
3025
|
proto,
|
|
@@ -3020,6 +3045,9 @@ var init_intent_router = __esm({
|
|
|
3020
3045
|
isAnonymous(intent) {
|
|
3021
3046
|
return this.anonymousIntents.has(intent);
|
|
3022
3047
|
}
|
|
3048
|
+
isAuthorized(intent) {
|
|
3049
|
+
return this.authorizedIntents.has(intent);
|
|
3050
|
+
}
|
|
3023
3051
|
getRateLimit(intent) {
|
|
3024
3052
|
return this.intentRateLimits.get(intent);
|
|
3025
3053
|
}
|
|
@@ -10528,6 +10556,7 @@ __export(index_exports, {
|
|
|
10528
10556
|
ATS1_HDR: () => ATS1_HDR,
|
|
10529
10557
|
ATS1_SCHEMA: () => ATS1_SCHEMA,
|
|
10530
10558
|
AXIS_ANONYMOUS_KEY: () => AXIS_ANONYMOUS_KEY,
|
|
10559
|
+
AXIS_AUTHORIZED_KEY: () => AXIS_AUTHORIZED_KEY,
|
|
10531
10560
|
AXIS_EXECUTION_CONTEXT_KEY: () => AXIS_EXECUTION_CONTEXT_KEY,
|
|
10532
10561
|
AXIS_MAGIC: () => import_axis_protocol.AXIS_MAGIC,
|
|
10533
10562
|
AXIS_META_KEY: () => AXIS_META_KEY,
|
|
@@ -10541,6 +10570,7 @@ __export(index_exports, {
|
|
|
10541
10570
|
Ats1Codec: () => ats1_exports,
|
|
10542
10571
|
Axis: () => Axis,
|
|
10543
10572
|
AxisAnonymous: () => AxisAnonymous,
|
|
10573
|
+
AxisAuthorized: () => AxisAuthorized,
|
|
10544
10574
|
AxisChainExecutor: () => AxisChainExecutor,
|
|
10545
10575
|
AxisError: () => AxisError,
|
|
10546
10576
|
AxisFrameZ: () => AxisFrameZ,
|