@suveren/gateway 0.40.0 → 0.41.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/guides/6-risks.md +1 -0
- package/dist/control-plane/index.mjs +182 -37
- package/dist/mcp-server/http.mjs +357 -71
- package/dist/ui/assets/{index-C-lA_7Lt.js → index-CO-dj98E.js} +27 -27
- package/dist/ui/index.html +1 -1
- package/node_modules/@hap/core/README.md +3 -3
- package/node_modules/@hap/core/dist/index.d.mts +567 -123
- package/node_modules/@hap/core/dist/index.d.ts +567 -123
- package/node_modules/@hap/core/dist/index.js +869 -23
- package/node_modules/@hap/core/dist/index.mjs +829 -22
- package/node_modules/@hap/core/node_modules/@hpke/core/LICENSE +21 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/README.md +263 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/mod.d.ts +11 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/mod.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/mod.js +6 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/package.json +3 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/aeads/aesGcm.d.ts +80 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/aeads/aesGcm.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/aeads/aesGcm.js +167 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/aeads/exportOnly.d.ts +34 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/aeads/exportOnly.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/aeads/exportOnly.js +56 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/cipherSuiteNative.d.ts +145 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/cipherSuiteNative.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/cipherSuiteNative.js +326 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/encryptionContext.d.ts +15 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/encryptionContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/encryptionContext.js +68 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/exporterContext.d.ts +19 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/exporterContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/exporterContext.js +62 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/aeadParams.d.ts +17 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/aeadParams.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/aeadParams.js +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/cipherSuiteParams.d.ts +13 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/cipherSuiteParams.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/cipherSuiteParams.js +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/encapsulator.d.ts +8 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/encapsulator.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/encapsulator.js +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/encryptionContext.d.ts +40 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/encryptionContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/encryptionContext.js +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/exporter.d.ts +17 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/exporter.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/exporter.js +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/keyInfo.d.ts +7 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/keyInfo.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/keyInfo.js +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/responses.d.ts +10 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/responses.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/interfaces/responses.js +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemNative.d.ts +26 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemNative.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemNative.js +112 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x25519.d.ts +24 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x25519.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x25519.js +214 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x448.d.ts +24 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x448.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x448.js +214 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemX25519.d.ts +38 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemX25519.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemX25519.js +66 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemX448.d.ts +38 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemX448.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/kems/dhkemX448.js +66 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/mutex.d.ts +5 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/mutex.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/mutex.js +28 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/native.d.ts +236 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/native.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/native.js +235 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/recipientContext.d.ts +6 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/recipientContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/recipientContext.js +38 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/senderContext.d.ts +11 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/senderContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/senderContext.js +45 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/utils/emitNotSupported.d.ts +2 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/utils/emitNotSupported.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/esm/src/utils/emitNotSupported.js +6 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/package.json +46 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/mod.d.ts +11 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/mod.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/mod.js +47 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/package.json +3 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/aeads/aesGcm.d.ts +80 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/aeads/aesGcm.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/aeads/aesGcm.js +183 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/aeads/exportOnly.d.ts +34 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/aeads/exportOnly.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/aeads/exportOnly.js +70 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/cipherSuiteNative.d.ts +145 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/cipherSuiteNative.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/cipherSuiteNative.js +340 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/encryptionContext.d.ts +15 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/encryptionContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/encryptionContext.js +82 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/exporterContext.d.ts +19 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/exporterContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/exporterContext.js +78 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/aeadParams.d.ts +17 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/aeadParams.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/aeadParams.js +12 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/cipherSuiteParams.d.ts +13 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/cipherSuiteParams.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/cipherSuiteParams.js +12 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/encapsulator.d.ts +8 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/encapsulator.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/encapsulator.js +12 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/encryptionContext.d.ts +40 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/encryptionContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/encryptionContext.js +12 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/exporter.d.ts +17 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/exporter.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/exporter.js +12 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/keyInfo.d.ts +7 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/keyInfo.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/keyInfo.js +12 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/responses.d.ts +10 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/responses.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/interfaces/responses.js +12 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemNative.d.ts +26 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemNative.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemNative.js +128 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x25519.d.ts +24 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x25519.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x25519.js +228 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x448.d.ts +24 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x448.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x448.js +228 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemX25519.d.ts +38 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemX25519.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemX25519.js +80 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemX448.d.ts +38 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemX448.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/kems/dhkemX448.js +80 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/mutex.d.ts +5 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/mutex.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/mutex.js +42 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/native.d.ts +236 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/native.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/native.js +255 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/recipientContext.d.ts +6 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/recipientContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/recipientContext.js +52 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/senderContext.d.ts +11 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/senderContext.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/senderContext.js +59 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/utils/emitNotSupported.d.ts +2 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/utils/emitNotSupported.d.ts.map +1 -0
- package/node_modules/@hap/core/node_modules/@hpke/core/script/src/utils/emitNotSupported.js +19 -0
- package/node_modules/@hap/core/package.json +2 -1
- package/node_modules/@hap/core/src/canonicalize.ts +9 -0
- package/node_modules/@hap/core/src/commitment-modes.ts +21 -9
- package/node_modules/@hap/core/src/errors.ts +24 -8
- package/node_modules/@hap/core/src/gatekeeper.ts +52 -8
- package/node_modules/@hap/core/src/index.ts +5 -1
- package/node_modules/@hap/core/src/issuance.ts +250 -0
- package/node_modules/@hap/core/src/mandate.ts +52 -14
- package/node_modules/@hap/core/src/owner-signature.ts +86 -39
- package/node_modules/@hap/core/src/profile.ts +45 -0
- package/node_modules/@hap/core/src/proposal-content.ts +219 -0
- package/node_modules/@hap/core/src/ticket-projection.ts +167 -0
- package/node_modules/@hap/core/src/ticket.ts +254 -20
- package/node_modules/@hap/core/src/types.ts +33 -5
- package/node_modules/@hap/core/src/verifier-policy.ts +178 -0
- package/node_modules/@hap/core/src/versions.ts +50 -19
- package/node_modules/@hono/node-server/dist/index.cjs +31 -6
- package/node_modules/@hono/node-server/dist/index.mjs +31 -6
- package/node_modules/@hono/node-server/package.json +1 -1
- package/node_modules/@hpke/common/esm/package.json +5 -1
- package/node_modules/@hpke/common/esm/src/curve/montgomery.d.ts +2 -2
- package/node_modules/@hpke/common/esm/src/curve/montgomery.d.ts.map +1 -1
- package/node_modules/@hpke/common/esm/src/curve/montgomery.js +41 -26
- package/node_modules/@hpke/common/esm/src/hash/sha3.d.ts.map +1 -1
- package/node_modules/@hpke/common/esm/src/hash/sha3.js +0 -15
- package/node_modules/@hpke/common/esm/src/kdfs/hkdf.d.ts +2 -1
- package/node_modules/@hpke/common/esm/src/kdfs/hkdf.d.ts.map +1 -1
- package/node_modules/@hpke/common/esm/src/kdfs/hkdf.js +12 -2
- package/node_modules/@hpke/common/esm/src/kems/dhkemPrimitives/xCurve.d.ts.map +1 -1
- package/node_modules/@hpke/common/esm/src/kems/dhkemPrimitives/xCurve.js +14 -3
- package/node_modules/@hpke/common/esm/src/utils/misc.d.ts +6 -0
- package/node_modules/@hpke/common/esm/src/utils/misc.d.ts.map +1 -1
- package/node_modules/@hpke/common/esm/src/utils/misc.js +43 -10
- package/node_modules/@hpke/common/esm/src/utils/noble.d.ts +1 -1
- package/node_modules/@hpke/common/esm/src/utils/noble.d.ts.map +1 -1
- package/node_modules/@hpke/common/esm/src/utils/noble.js +21 -10
- package/node_modules/@hpke/common/package.json +5 -1
- package/node_modules/@hpke/common/script/src/curve/montgomery.d.ts +2 -2
- package/node_modules/@hpke/common/script/src/curve/montgomery.d.ts.map +1 -1
- package/node_modules/@hpke/common/script/src/curve/montgomery.js +40 -25
- package/node_modules/@hpke/common/script/src/hash/sha3.d.ts.map +1 -1
- package/node_modules/@hpke/common/script/src/hash/sha3.js +0 -15
- package/node_modules/@hpke/common/script/src/kdfs/hkdf.d.ts +2 -1
- package/node_modules/@hpke/common/script/src/kdfs/hkdf.d.ts.map +1 -1
- package/node_modules/@hpke/common/script/src/kdfs/hkdf.js +12 -2
- package/node_modules/@hpke/common/script/src/kems/dhkemPrimitives/xCurve.d.ts.map +1 -1
- package/node_modules/@hpke/common/script/src/kems/dhkemPrimitives/xCurve.js +13 -2
- package/node_modules/@hpke/common/script/src/utils/misc.d.ts +6 -0
- package/node_modules/@hpke/common/script/src/utils/misc.d.ts.map +1 -1
- package/node_modules/@hpke/common/script/src/utils/misc.js +43 -9
- package/node_modules/@hpke/common/script/src/utils/noble.d.ts +1 -1
- package/node_modules/@hpke/common/script/src/utils/noble.d.ts.map +1 -1
- package/node_modules/@hpke/common/script/src/utils/noble.js +22 -11
- package/node_modules/@hpke/core/README.md +56 -56
- package/node_modules/@hpke/core/esm/package.json +2 -1
- package/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x25519.d.ts +3 -21
- package/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x25519.d.ts.map +1 -1
- package/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x25519.js +3 -201
- package/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x448.d.ts +3 -21
- package/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x448.d.ts.map +1 -1
- package/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/x448.js +3 -201
- package/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/xCurveNative.d.ts +26 -0
- package/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/xCurveNative.d.ts.map +1 -0
- package/node_modules/@hpke/core/esm/src/kems/dhkemPrimitives/xCurveNative.js +216 -0
- package/node_modules/@hpke/core/package.json +6 -2
- package/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x25519.d.ts +3 -21
- package/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x25519.d.ts.map +1 -1
- package/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x25519.js +4 -202
- package/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x448.d.ts +3 -21
- package/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x448.d.ts.map +1 -1
- package/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/x448.js +4 -202
- package/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/xCurveNative.d.ts +26 -0
- package/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/xCurveNative.d.ts.map +1 -0
- package/node_modules/@hpke/core/script/src/kems/dhkemPrimitives/xCurveNative.js +230 -0
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/@types/node/zlib.d.ts +752 -0
- package/node_modules/encodeurl/README.md +14 -0
- package/node_modules/encodeurl/index.js +5 -10
- package/node_modules/encodeurl/package.json +10 -6
- package/node_modules/express-rate-limit/dist/index.cjs +7 -3
- package/node_modules/express-rate-limit/dist/index.mjs +7 -3
- package/node_modules/express-rate-limit/package.json +10 -10
- package/node_modules/hono/dist/cjs/adapter/bun/serve-static.js +1 -1
- package/node_modules/hono/dist/cjs/adapter/bun/websocket.js +1 -1
- package/node_modules/hono/dist/cjs/context.js +1 -1
- package/node_modules/hono/dist/cjs/helper/css/common.js +3 -5
- package/node_modules/hono/dist/cjs/hono-base.js +4 -10
- package/node_modules/hono/dist/cjs/hono.js +0 -1
- package/node_modules/hono/dist/cjs/middleware/basic-auth/index.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/bearer-auth/index.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/csrf/index.js +2 -2
- package/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +2 -2
- package/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +2 -2
- package/node_modules/hono/dist/cjs/middleware/mount/index.js +4 -4
- package/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +13 -11
- package/node_modules/hono/dist/cjs/router/reg-exp-router/prepared-router.js +4 -4
- package/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +39 -51
- package/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +15 -5
- package/node_modules/hono/dist/cjs/utils/jwt/jwt.js +2 -1
- package/node_modules/hono/dist/cjs/utils/mount.js +35 -0
- package/node_modules/hono/dist/cjs/utils/url.js +10 -0
- package/node_modules/hono/dist/cjs/validator/validator.js +1 -1
- package/node_modules/hono/dist/context.js +1 -1
- package/node_modules/hono/dist/helper/css/common.js +3 -5
- package/node_modules/hono/dist/hono-base.js +4 -10
- package/node_modules/hono/dist/hono.js +0 -1
- package/node_modules/hono/dist/middleware/basic-auth/index.js +1 -1
- package/node_modules/hono/dist/middleware/bearer-auth/index.js +1 -1
- package/node_modules/hono/dist/middleware/csrf/index.js +2 -2
- package/node_modules/hono/dist/middleware/jwk/jwk.js +2 -2
- package/node_modules/hono/dist/middleware/jwt/jwt.js +2 -2
- package/node_modules/hono/dist/middleware/language/language.js +1 -1
- package/node_modules/hono/dist/middleware/mount/index.js +4 -4
- package/node_modules/hono/dist/router/reg-exp-router/node.js +13 -11
- package/node_modules/hono/dist/router/reg-exp-router/prepared-router.js +5 -5
- package/node_modules/hono/dist/router/reg-exp-router/router.js +40 -52
- package/node_modules/hono/dist/router/reg-exp-router/trie.js +15 -5
- package/node_modules/hono/dist/types/middleware/mount/index.d.ts +1 -0
- package/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +3 -3
- package/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +1 -1
- package/node_modules/hono/dist/types/utils/mount.d.ts +4 -0
- package/node_modules/hono/dist/types/utils/url.d.ts +1 -0
- package/node_modules/hono/dist/utils/jwt/jwt.js +2 -1
- package/node_modules/hono/dist/utils/mount.js +34 -0
- package/node_modules/hono/dist/utils/url.js +10 -1
- package/node_modules/hono/dist/validator/validator.js +1 -1
- package/node_modules/hono/package.json +1 -1
- package/node_modules/ip-address/README.md +39 -39
- package/node_modules/ip-address/dist/ipv6.js +1 -1
- package/node_modules/ip-address/dist/ipv6.js.map +1 -1
- package/node_modules/ip-address/package.json +1 -1
- package/node_modules/jose/dist/types/jwt/decrypt.d.ts +3 -0
- package/node_modules/jose/dist/types/jwt/unsecured.d.ts +2 -0
- package/node_modules/jose/dist/types/jwt/verify.d.ts +3 -0
- package/node_modules/jose/dist/types/types.d.ts +8 -0
- package/node_modules/jose/dist/types/util/decode_jwt.d.ts +1 -0
- package/node_modules/jose/dist/webapi/jwks/remote.js +3 -1
- package/node_modules/jose/dist/webapi/lib/deflate.js +2 -1
- package/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +2 -1
- package/node_modules/jose/package.json +1 -1
- package/node_modules/qs/CHANGELOG.md +29 -22
- package/node_modules/qs/dist/qs.js +14 -14
- package/node_modules/qs/eslint.config.mjs +6 -0
- package/node_modules/qs/lib/stringify.js +1 -1
- package/node_modules/qs/package.json +5 -5
- package/node_modules/qs/test/stringify.js +74 -0
- package/package.json +2 -2
package/dist/mcp-server/http.mjs
CHANGED
|
@@ -744,12 +744,19 @@ async function postInternal(path, body) {
|
|
|
744
744
|
clearTimeout(timer);
|
|
745
745
|
}
|
|
746
746
|
}
|
|
747
|
-
async function cpEncryptContent(toolArgs, recipientUserIds) {
|
|
748
|
-
const data = await postInternal("/internal/encrypt-content", { toolArgs, recipientUserIds });
|
|
747
|
+
async function cpEncryptContent(toolArgs, recipientUserIds, readers) {
|
|
748
|
+
const data = await postInternal("/internal/encrypt-content", { toolArgs, recipientUserIds, ...readers ? { readers } : {} });
|
|
749
749
|
return data;
|
|
750
750
|
}
|
|
751
751
|
async function cpDecryptContent(wire) {
|
|
752
|
-
const data = await postInternal("/internal/decrypt-content", {
|
|
752
|
+
const data = await postInternal("/internal/decrypt-content", {
|
|
753
|
+
ciphertext: wire.ciphertext,
|
|
754
|
+
// Both names: under a 0.8 mandate `encrypted_keys` is keyed by DID and
|
|
755
|
+
// `keys` by account id; the control plane finds this user's wrap by either.
|
|
756
|
+
keys: { ...wire.keys ?? {}, ...wire.encrypted_keys ?? {} },
|
|
757
|
+
// v0.8 rule 8: the control plane checks the decrypted content against the fingerprint.
|
|
758
|
+
...wire.proposalContentHash ? { proposalContentHash: wire.proposalContentHash } : wire.hash ? { hash: wire.hash } : {}
|
|
759
|
+
});
|
|
753
760
|
return data.plaintext;
|
|
754
761
|
}
|
|
755
762
|
|
|
@@ -983,7 +990,10 @@ var SPClient = class {
|
|
|
983
990
|
const { proposalContentHash, ...rest } = data;
|
|
984
991
|
const body = JSON.stringify({
|
|
985
992
|
...rest,
|
|
986
|
-
|
|
993
|
+
// v0.8 wire name is `proposalContentHash`; today's AS reads the
|
|
994
|
+
// Suveren-internal `proposal_content_hash`. Both are sent through the
|
|
995
|
+
// transition (same value); the AS of Track B reads the normative one.
|
|
996
|
+
...proposalContentHash ? { proposal_content_hash: proposalContentHash, proposalContentHash } : {}
|
|
987
997
|
});
|
|
988
998
|
const maxAttempts = data.idempotencyKey || data.proposalId ? this.receiptRetry.maxAttempts : 1;
|
|
989
999
|
let lastError;
|
|
@@ -1037,7 +1047,7 @@ var SPClient = class {
|
|
|
1037
1047
|
* read it; the caller reports who cannot.
|
|
1038
1048
|
*/
|
|
1039
1049
|
async submitProposal(data) {
|
|
1040
|
-
const { content, unreadableFor } = await cpEncryptContent(data.toolArgs, data.recipientUserIds);
|
|
1050
|
+
const { content, unreadableFor } = await cpEncryptContent(data.toolArgs, data.recipientUserIds, data.readers);
|
|
1041
1051
|
const res = await this.fetch("/api/proposals", {
|
|
1042
1052
|
method: "POST",
|
|
1043
1053
|
body: JSON.stringify({
|
|
@@ -1046,8 +1056,18 @@ var SPClient = class {
|
|
|
1046
1056
|
path: data.path,
|
|
1047
1057
|
pending_domains: data.pendingDomains,
|
|
1048
1058
|
tool: data.tool,
|
|
1059
|
+
// v0.8 normative object, beside the Suveren-internal fields today's AS
|
|
1060
|
+
// reads: `content` carries `encrypted_keys`/`readers`/`unreadable` with
|
|
1061
|
+
// the legacy `keys`/`hash`; the fingerprint travels as
|
|
1062
|
+
// `proposalContentHash`; the operation as `action` + `actionType`.
|
|
1049
1063
|
content,
|
|
1064
|
+
proposalContentHash: content.hash,
|
|
1065
|
+
action: data.tool,
|
|
1066
|
+
...data.actionType ? { actionType: data.actionType } : {},
|
|
1067
|
+
...data.mandateId ? { mandateId: data.mandateId } : {},
|
|
1068
|
+
...data.boundsHash ? { boundsHash: data.boundsHash } : {},
|
|
1050
1069
|
execution_context: data.executionContext,
|
|
1070
|
+
executionContext: data.executionContext,
|
|
1051
1071
|
// Phase 6
|
|
1052
1072
|
...data.pendingApprovers && data.pendingApprovers.length > 0 ? { pending_approvers: data.pendingApprovers } : {},
|
|
1053
1073
|
...data.createdBy ? { created_by: data.createdBy } : {}
|
|
@@ -1331,6 +1351,7 @@ var AttestationCache = class {
|
|
|
1331
1351
|
}
|
|
1332
1352
|
let signedCommitmentMode;
|
|
1333
1353
|
let subjects;
|
|
1354
|
+
let mandateId;
|
|
1334
1355
|
const firstBlob = result.attestations[0]?.blob;
|
|
1335
1356
|
if (firstBlob) {
|
|
1336
1357
|
try {
|
|
@@ -1341,6 +1362,39 @@ var AttestationCache = class {
|
|
|
1341
1362
|
signedCommitmentMode = void 0;
|
|
1342
1363
|
}
|
|
1343
1364
|
}
|
|
1365
|
+
const mandateIds = [];
|
|
1366
|
+
let mandateVersion;
|
|
1367
|
+
const nowSec4 = Math.floor(Date.now() / 1e3);
|
|
1368
|
+
for (const a of result.attestations) {
|
|
1369
|
+
if (!a.blob) continue;
|
|
1370
|
+
try {
|
|
1371
|
+
const id = decodeMandateBlob(a.blob).payload.mandate_id;
|
|
1372
|
+
if (typeof id !== "string") continue;
|
|
1373
|
+
if (!mandateIds.includes(id)) mandateIds.push(id);
|
|
1374
|
+
if (mandateId === void 0 && a.expires_at > nowSec4) {
|
|
1375
|
+
mandateId = id;
|
|
1376
|
+
const v = decodeMandateBlob(a.blob).payload.version;
|
|
1377
|
+
if (typeof v === "string") mandateVersion = v;
|
|
1378
|
+
}
|
|
1379
|
+
} catch {
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
mandateId ??= mandateIds[0];
|
|
1383
|
+
let proposalReaders;
|
|
1384
|
+
let latestIssuedAt = -Infinity;
|
|
1385
|
+
for (const a of result.attestations) {
|
|
1386
|
+
if (!a.blob) continue;
|
|
1387
|
+
try {
|
|
1388
|
+
const p = decodeMandateBlob(a.blob).payload;
|
|
1389
|
+
const ownerDid = p.mandate_owners?.[0]?.did;
|
|
1390
|
+
if (typeof p.version !== "string" || typeof ownerDid !== "string") continue;
|
|
1391
|
+
const issuedAt = typeof p.issued_at === "number" ? p.issued_at : 0;
|
|
1392
|
+
if (issuedAt < latestIssuedAt) continue;
|
|
1393
|
+
latestIssuedAt = issuedAt;
|
|
1394
|
+
proposalReaders = { version: p.version, ownerDid, deciders: [...p.above_cap_approvers ?? []] };
|
|
1395
|
+
} catch {
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1344
1398
|
const auth = {
|
|
1345
1399
|
authorizationId: result.authorization_id,
|
|
1346
1400
|
boundsHash: result.bounds_hash,
|
|
@@ -1362,6 +1416,10 @@ var AttestationCache = class {
|
|
|
1362
1416
|
attestedDomains: result.attested_domains ?? [],
|
|
1363
1417
|
deferredCommitmentDomains: result.deferred_commitment_domains ?? [],
|
|
1364
1418
|
signedCommitmentMode,
|
|
1419
|
+
mandateId,
|
|
1420
|
+
mandateIds,
|
|
1421
|
+
mandateVersion,
|
|
1422
|
+
proposalReaders,
|
|
1365
1423
|
subjects,
|
|
1366
1424
|
complete: result.complete,
|
|
1367
1425
|
groupId
|
|
@@ -2169,17 +2227,69 @@ var ExecutionJournal = class {
|
|
|
2169
2227
|
}
|
|
2170
2228
|
/** Look a ticket up. Always reads from disk — another process may have written. */
|
|
2171
2229
|
get(ticketId) {
|
|
2172
|
-
return this.load().entries.find((e) => e.ticketId === ticketId);
|
|
2230
|
+
return this.load().entries.find((e) => e.ticketId === ticketId && ticketId !== "");
|
|
2231
|
+
}
|
|
2232
|
+
/** The row for a request (idempotencyKey / proposalId), whatever its state. */
|
|
2233
|
+
getByRequest(requestKey) {
|
|
2234
|
+
return this.load().entries.find((e) => e.requestKey === requestKey);
|
|
2235
|
+
}
|
|
2236
|
+
/**
|
|
2237
|
+
* v0.8 — record that a ticket is about to be REQUESTED for this request,
|
|
2238
|
+
* before the request leaves the machine (*One execution per ticket*, rule 1).
|
|
2239
|
+
* A lost response then leaves a `requested` row: "the ticket never arrived,
|
|
2240
|
+
* so the action cannot have started" — the one case a replayed ticket may
|
|
2241
|
+
* run (rule 2). Idempotent for the same request key: a retry of the request
|
|
2242
|
+
* itself keeps the one row.
|
|
2243
|
+
*/
|
|
2244
|
+
requested(entry) {
|
|
2245
|
+
const file = this.load();
|
|
2246
|
+
if (file.entries.some((e) => e.requestKey === entry.requestKey)) return;
|
|
2247
|
+
file.entries.push({
|
|
2248
|
+
ticketId: "",
|
|
2249
|
+
...entry,
|
|
2250
|
+
state: "requested",
|
|
2251
|
+
startedAt: nowSec(),
|
|
2252
|
+
pid: process.pid
|
|
2253
|
+
});
|
|
2254
|
+
this.persist(file);
|
|
2173
2255
|
}
|
|
2174
2256
|
/**
|
|
2175
|
-
*
|
|
2176
|
-
*
|
|
2177
|
-
|
|
2257
|
+
* Close a `requested` row whose ticket was never issued (the AS refused).
|
|
2258
|
+
* Nothing ran; the row records that the request was judged and refused.
|
|
2259
|
+
*/
|
|
2260
|
+
refusedBeforeTicket(requestKey, outcome, detail) {
|
|
2261
|
+
const file = this.load();
|
|
2262
|
+
const row = file.entries.find((e) => e.requestKey === requestKey && e.state === "requested");
|
|
2263
|
+
if (!row) return;
|
|
2264
|
+
row.state = "failed";
|
|
2265
|
+
row.outcome = outcome;
|
|
2266
|
+
if (detail !== void 0) row.detail = detail.length > DETAIL_CAP ? detail.slice(0, DETAIL_CAP) : detail;
|
|
2267
|
+
row.finishedAt = nowSec();
|
|
2268
|
+
this.persist(file);
|
|
2269
|
+
}
|
|
2270
|
+
/**
|
|
2271
|
+
* Claim the ticket for execution — the atomic move to `intent` ("started")
|
|
2272
|
+
* BEFORE the downstream call (*One execution per ticket*, rule 2). Refuses
|
|
2273
|
+
* if a row for that ticket already exists, whatever its state — deciding
|
|
2274
|
+
* what an existing row means is the caller's job, and it differs by state
|
|
2275
|
+
* (see commitments.ts). With a `requestKey`, a row for the SAME request that
|
|
2276
|
+
* is already `intent`/`done`/`failed` refuses too — a second ticket with a
|
|
2277
|
+
* new id for the same request is not executed again; a `requested` row is
|
|
2278
|
+
* upgraded in place.
|
|
2178
2279
|
*/
|
|
2179
2280
|
begin(entry) {
|
|
2180
2281
|
const file = this.load();
|
|
2181
|
-
const existing = file.entries.find((e) => e.ticketId === entry.ticketId);
|
|
2282
|
+
const existing = file.entries.find((e) => e.ticketId === entry.ticketId && e.ticketId !== "");
|
|
2182
2283
|
if (existing) return { ok: false, existing };
|
|
2284
|
+
if (entry.requestKey) {
|
|
2285
|
+
const sameRequest = file.entries.find((e) => e.requestKey === entry.requestKey);
|
|
2286
|
+
if (sameRequest && sameRequest.state !== "requested") return { ok: false, existing: sameRequest };
|
|
2287
|
+
if (sameRequest) {
|
|
2288
|
+
Object.assign(sameRequest, entry, { state: "intent", startedAt: nowSec(), pid: process.pid });
|
|
2289
|
+
this.persist(file);
|
|
2290
|
+
return { ok: true };
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2183
2293
|
file.entries.push({
|
|
2184
2294
|
...entry,
|
|
2185
2295
|
state: "intent",
|
|
@@ -2431,7 +2541,8 @@ var ProposalSubmissionStore = class {
|
|
|
2431
2541
|
authorizationId: entry.authorizationId,
|
|
2432
2542
|
profileId: entry.profileId,
|
|
2433
2543
|
submittedAt: nowSec3(),
|
|
2434
|
-
...entry.previewHash ? { previewHash: entry.previewHash } : {}
|
|
2544
|
+
...entry.previewHash ? { previewHash: entry.previewHash } : {},
|
|
2545
|
+
...entry.actionType ? { actionType: entry.actionType } : {}
|
|
2435
2546
|
});
|
|
2436
2547
|
this.persist(file);
|
|
2437
2548
|
}
|
|
@@ -3230,7 +3341,7 @@ var ReportStore = class {
|
|
|
3230
3341
|
};
|
|
3231
3342
|
|
|
3232
3343
|
// src/lib/shared-state.ts
|
|
3233
|
-
import {
|
|
3344
|
+
import { SUPPORTED_VERSIONS } from "@hap/core";
|
|
3234
3345
|
var SharedState = class {
|
|
3235
3346
|
spClient;
|
|
3236
3347
|
cache;
|
|
@@ -3259,7 +3370,7 @@ var SharedState = class {
|
|
|
3259
3370
|
* again whenever the AS URL this process pairs with changes — which, in
|
|
3260
3371
|
* practice, only happens across a restart; see bin/http.ts's
|
|
3261
3372
|
* `repairIfAsUrlChanged`). Non-null means the AS this gateway is paired
|
|
3262
|
-
* with
|
|
3373
|
+
* with shares no version with SUPPORTED_VERSIONS among its
|
|
3263
3374
|
* `supportedVersions` — every gated tool call MUST refuse with this
|
|
3264
3375
|
* message rather than reach the AS at all (checked in tool-proxy.ts,
|
|
3265
3376
|
* before anything else). `null` until the first check completes, which
|
|
@@ -3269,6 +3380,16 @@ var SharedState = class {
|
|
|
3269
3380
|
* unreachable at boot must not permanently brick the gateway).
|
|
3270
3381
|
*/
|
|
3271
3382
|
asVersionRefusal = null;
|
|
3383
|
+
/** v0.8: whether the paired Authority Server lists 0.8 among its supportedVersions —
|
|
3384
|
+
* read once at start-up ({@link checkAsCompat}); false until known. Where the wire
|
|
3385
|
+
* shape differs between a 0.7 and a 0.8 AS (today: nothing), this is the switch. */
|
|
3386
|
+
asSpeaks08 = false;
|
|
3387
|
+
/** v0.8: the paired AS's supportedVersions as read at start-up; null until
|
|
3388
|
+
* known. A mandate whose signed version is not in it can no longer be
|
|
3389
|
+
* exercised (protocol.md → Version negotiation, rule 3: a v0.8 AS issues no
|
|
3390
|
+
* ticket against a v0.7 mandate) and is shown as needing to be signed again
|
|
3391
|
+
* before any call is refused for it. */
|
|
3392
|
+
asSupportedVersions = null;
|
|
3272
3393
|
/**
|
|
3273
3394
|
* @param dataDir Passed to the AttestationCache so it can enforce AS key
|
|
3274
3395
|
* pinning (as-pairing.ts), and to the SPClient so it can enforce opt-in
|
|
@@ -3309,8 +3430,11 @@ var SharedState = class {
|
|
|
3309
3430
|
return;
|
|
3310
3431
|
}
|
|
3311
3432
|
const supported = Array.isArray(compat.supportedVersions) ? compat.supportedVersions : [];
|
|
3312
|
-
|
|
3313
|
-
|
|
3433
|
+
const common = SUPPORTED_VERSIONS.filter((v) => supported.includes(v));
|
|
3434
|
+
this.asSpeaks08 = supported.includes("0.8");
|
|
3435
|
+
this.asSupportedVersions = supported.filter((v) => typeof v === "string");
|
|
3436
|
+
if (common.length === 0) {
|
|
3437
|
+
this.asVersionRefusal = supported.length > 0 ? `This Authority Server supports protocol version(s) [${supported.join(", ")}], none of [${SUPPORTED_VERSIONS.join(", ")}] this gateway speaks. Update the gateway or the Authority Server so the two agree, then restart. No gated action can run until then.` : `This Authority Server's /api/as/compat does not name a supportedVersions list (it answered ${JSON.stringify(compat.protocolVersion ?? "unknown")}), so it cannot be confirmed to support any of protocol [${SUPPORTED_VERSIONS.join(", ")}]. Update the gateway or the Authority Server, then restart. No gated action can run until then.`;
|
|
3314
3438
|
console.error(`[Suveren MCP] ${this.asVersionRefusal}`);
|
|
3315
3439
|
} else {
|
|
3316
3440
|
this.asVersionRefusal = null;
|
|
@@ -3400,7 +3524,7 @@ var SharedState = class {
|
|
|
3400
3524
|
gateContent: gateEntry?.gateContent ?? null,
|
|
3401
3525
|
context: auth.context ?? gateEntry?.context,
|
|
3402
3526
|
contextHash: auth.contextHash ?? gateEntry?.contextHash,
|
|
3403
|
-
needsReapproval: this.cache.needsReapproval(auth.authorizationId)
|
|
3527
|
+
needsReapproval: this.cache.needsReapproval(auth.authorizationId) || this.asSupportedVersions !== null && this.asSupportedVersions.length > 0 && typeof auth.mandateVersion === "string" && !this.asSupportedVersions.includes(auth.mandateVersion)
|
|
3404
3528
|
};
|
|
3405
3529
|
}).filter((auth) => auth.gateContent !== null);
|
|
3406
3530
|
}
|
|
@@ -6418,7 +6542,13 @@ function attachTicketId(tool, args, ticketId) {
|
|
|
6418
6542
|
}
|
|
6419
6543
|
|
|
6420
6544
|
// src/lib/ticket-verify.ts
|
|
6421
|
-
import {
|
|
6545
|
+
import {
|
|
6546
|
+
verifyTicketSignature,
|
|
6547
|
+
verifyTicketAgainstRequest,
|
|
6548
|
+
verifyTicketApprovals,
|
|
6549
|
+
decodeMandateBlob as decodeMandateBlob2,
|
|
6550
|
+
HapError
|
|
6551
|
+
} from "@hap/core";
|
|
6422
6552
|
var TicketBindingMismatchError = class extends Error {
|
|
6423
6553
|
constructor(message) {
|
|
6424
6554
|
super(message);
|
|
@@ -6427,6 +6557,17 @@ var TicketBindingMismatchError = class extends Error {
|
|
|
6427
6557
|
};
|
|
6428
6558
|
var TICKET_MAX_AGE_SECONDS = 5 * 60;
|
|
6429
6559
|
var TICKET_MAX_CLOCK_SKEW_SECONDS = 30;
|
|
6560
|
+
function mandateForTicket(attestations, ticketMandateId) {
|
|
6561
|
+
if (typeof ticketMandateId !== "string") return void 0;
|
|
6562
|
+
for (const a of attestations ?? []) {
|
|
6563
|
+
try {
|
|
6564
|
+
const m = decodeMandateBlob2(a.blob);
|
|
6565
|
+
if (m.payload.mandate_id === ticketMandateId) return m;
|
|
6566
|
+
} catch {
|
|
6567
|
+
}
|
|
6568
|
+
}
|
|
6569
|
+
return void 0;
|
|
6570
|
+
}
|
|
6430
6571
|
async function verifyTicket(cache, receipt, expected) {
|
|
6431
6572
|
const trustedIssuer = await cache.getTrustedIssuer();
|
|
6432
6573
|
if (typeof receipt.signature !== "string" || !receipt.signature) {
|
|
@@ -6485,20 +6626,70 @@ async function verifyTicket(cache, receipt, expected) {
|
|
|
6485
6626
|
if (typeof timestamp !== "number" || !Number.isFinite(timestamp)) {
|
|
6486
6627
|
throw new TicketBindingMismatchError("Ticket carries no valid timestamp \u2014 refusing to execute.");
|
|
6487
6628
|
}
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6629
|
+
if (expected.replay !== true) {
|
|
6630
|
+
const nowSec4 = Math.floor(Date.now() / 1e3);
|
|
6631
|
+
const ageSec = nowSec4 - timestamp;
|
|
6632
|
+
if (ageSec > TICKET_MAX_AGE_SECONDS) {
|
|
6633
|
+
throw new TicketBindingMismatchError(
|
|
6634
|
+
`Ticket is ${ageSec}s old, older than the ${TICKET_MAX_AGE_SECONDS}s freshness window \u2014 refusing to execute.`
|
|
6635
|
+
);
|
|
6636
|
+
}
|
|
6637
|
+
if (ageSec < -TICKET_MAX_CLOCK_SKEW_SECONDS) {
|
|
6638
|
+
throw new TicketBindingMismatchError(
|
|
6639
|
+
`Ticket is timestamped ${-ageSec}s in the future, beyond the ${TICKET_MAX_CLOCK_SKEW_SECONDS}s clock-skew tolerance \u2014 refusing to execute.`
|
|
6640
|
+
);
|
|
6641
|
+
}
|
|
6494
6642
|
}
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6643
|
+
const ticket = receipt;
|
|
6644
|
+
let acceptedMandateId = expected.mandateId;
|
|
6645
|
+
if (expected.mandateIds && expected.mandateIds.length > 0) {
|
|
6646
|
+
if (typeof ticket.mandateId !== "string" || !expected.mandateIds.includes(ticket.mandateId)) {
|
|
6647
|
+
throw new TicketBindingMismatchError(
|
|
6648
|
+
`TICKET_REQUEST_MISMATCH: ticket mandateId ${String(ticket.mandateId)} is not a mandate of this grant \u2014 refusing to execute.`
|
|
6649
|
+
);
|
|
6650
|
+
}
|
|
6651
|
+
acceptedMandateId = ticket.mandateId;
|
|
6652
|
+
}
|
|
6653
|
+
try {
|
|
6654
|
+
verifyTicketAgainstRequest(
|
|
6655
|
+
ticket,
|
|
6656
|
+
{
|
|
6657
|
+
profileId: expected.profileId ?? ticket.profileId,
|
|
6658
|
+
actionType: expected.actionType ?? ticket.actionType,
|
|
6659
|
+
boundsHash: expected.boundsHash ?? ticket.boundsHash,
|
|
6660
|
+
executionContext: expected.executionContext ?? ticket.executionContext ?? {},
|
|
6661
|
+
mandateId: acceptedMandateId,
|
|
6662
|
+
idempotencyKey: expected.idempotencyKey,
|
|
6663
|
+
contentHash: expected.contentHash ?? ticket.contentHash,
|
|
6664
|
+
contentBinding: expected.contentBinding !== void 0 ? expected.contentBinding : ticket.contentBinding,
|
|
6665
|
+
proposalId: expected.proposalId ?? ticket.proposalId,
|
|
6666
|
+
// A v0.7 ticket has no `proposalContentHash` (today's Authority Server
|
|
6667
|
+
// binds the fingerprint on the request only); a v0.8 ticket MUST carry
|
|
6668
|
+
// the one this call sent.
|
|
6669
|
+
proposalContentHash: ticket.version === "0.7" ? ticket.proposalContentHash : expected.proposalContentHash ?? ticket.proposalContentHash
|
|
6670
|
+
},
|
|
6671
|
+
{ mandate: expected.mandate, replay: expected.replay === true }
|
|
6498
6672
|
);
|
|
6673
|
+
} catch (err) {
|
|
6674
|
+
if (err instanceof HapError) {
|
|
6675
|
+
throw new TicketBindingMismatchError(`${err.message} \u2014 refusing to execute.`);
|
|
6676
|
+
}
|
|
6677
|
+
throw err;
|
|
6678
|
+
}
|
|
6679
|
+
if (expected.mandate && (ticket.approvalSignature || (ticket.approvalSignatures?.length ?? 0) > 0)) {
|
|
6680
|
+
try {
|
|
6681
|
+
await verifyTicketApprovals(ticket, expected.mandate);
|
|
6682
|
+
} catch (err) {
|
|
6683
|
+
throw new TicketBindingMismatchError(
|
|
6684
|
+
`${err instanceof Error ? err.message : String(err)} \u2014 the approval does not cover this operation; refusing to execute.`
|
|
6685
|
+
);
|
|
6686
|
+
}
|
|
6499
6687
|
}
|
|
6500
6688
|
}
|
|
6501
6689
|
|
|
6690
|
+
// src/lib/tool-proxy.ts
|
|
6691
|
+
import { wireExecutionContext as hapWireExecutionContext, checkExecutionValues, missingSumFields } from "@hap/core";
|
|
6692
|
+
|
|
6502
6693
|
// src/lib/who-label.ts
|
|
6503
6694
|
var UNKNOWN_DECIDER = "the person";
|
|
6504
6695
|
async function resolveWhoLabel(archive, domainKey, userId) {
|
|
@@ -6720,21 +6911,8 @@ function profileMatches(profileId, shortName2) {
|
|
|
6720
6911
|
}
|
|
6721
6912
|
function wireExecutionContext(profileId, execution) {
|
|
6722
6913
|
const profile = getProfile5(profileId);
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
if (fields) {
|
|
6726
|
-
for (const fieldDef of Object.values(fields)) {
|
|
6727
|
-
const bt = fieldDef.boundType;
|
|
6728
|
-
if (bt && (bt.kind === "per_transaction" || bt.kind === "cumulative_sum") && bt.of) {
|
|
6729
|
-
allowed.add(bt.of);
|
|
6730
|
-
}
|
|
6731
|
-
}
|
|
6732
|
-
}
|
|
6733
|
-
const out = {};
|
|
6734
|
-
for (const [key, value] of Object.entries(execution)) {
|
|
6735
|
-
if (allowed.has(key)) out[key] = value;
|
|
6736
|
-
}
|
|
6737
|
-
return out;
|
|
6914
|
+
if (!profile) return {};
|
|
6915
|
+
return hapWireExecutionContext(execution, profile);
|
|
6738
6916
|
}
|
|
6739
6917
|
function countBoundsFor(profileId, actionType) {
|
|
6740
6918
|
const fields = getProfile5(profileId)?.boundsSchema?.fields;
|
|
@@ -6898,7 +7076,7 @@ function isStaleMandateRefusal(err) {
|
|
|
6898
7076
|
}
|
|
6899
7077
|
function isVersionUnsupportedRefusal(err) {
|
|
6900
7078
|
const errors = err.body?.errors;
|
|
6901
|
-
return
|
|
7079
|
+
return errors?.[0]?.code === "VERSION_UNSUPPORTED";
|
|
6902
7080
|
}
|
|
6903
7081
|
function createGatedToolHandlerInner(tool, integrationManager2, state2) {
|
|
6904
7082
|
if (!tool.gating || !tool.gating.profile) {
|
|
@@ -7004,7 +7182,8 @@ function createGatedToolHandlerInner(tool, integrationManager2, state2) {
|
|
|
7004
7182
|
ageBoundField
|
|
7005
7183
|
) : null;
|
|
7006
7184
|
const isTeam = typeof state2.cache?.isTeamGroup === "function" ? state2.cache.isTeamGroup(matchingAuths[0]?.groupId) : void 0;
|
|
7007
|
-
|
|
7185
|
+
const ceilingMarked = ageBoundField !== null && boundsSchema?.fields?.[ageBoundField]?.enforcedBy === "gatekeeper" && matchingAuths.some((a) => a.mandateVersion === "0.8");
|
|
7186
|
+
readMaxAge = (ceilingMarked || isTeam === true) && signedAge !== null ? localAge !== null ? Math.min(localAge, signedAge) : signedAge : localAge ?? signedAge;
|
|
7008
7187
|
if (readMaxAge === null) {
|
|
7009
7188
|
return denyRead(
|
|
7010
7189
|
state2,
|
|
@@ -7209,6 +7388,32 @@ function createGatedToolHandlerInner(tool, integrationManager2, state2) {
|
|
|
7209
7388
|
return { content: [{ type: "text", text: noMandateRefusal(tool.namespacedName, mandateLabel) }], isError: true };
|
|
7210
7389
|
}
|
|
7211
7390
|
if (matchingAuths.length === 0) return noEligibleMandate(refusals);
|
|
7391
|
+
{
|
|
7392
|
+
const profileDefs = [...new Set(matchingAuths.map((a) => a.profileId))].map((id) => getProfile5(id)).filter((d) => d !== void 0);
|
|
7393
|
+
for (const profileDef of profileDefs) {
|
|
7394
|
+
try {
|
|
7395
|
+
checkExecutionValues(hapWireExecutionContext(execution, profileDef), profileDef);
|
|
7396
|
+
} catch (err) {
|
|
7397
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
7398
|
+
const field = /executionContext\.([A-Za-z0-9_]+)/.exec(detail)?.[1];
|
|
7399
|
+
const bounds = field ? Object.entries(profileDef.boundsSchema?.fields ?? {}).filter(([, def]) => def.boundType?.of === field).map(([name]) => name) : [];
|
|
7400
|
+
recordBlocked(state2, tool, {
|
|
7401
|
+
kind: "bound",
|
|
7402
|
+
detail,
|
|
7403
|
+
...field ? { field } : {},
|
|
7404
|
+
who: "gateway",
|
|
7405
|
+
code: "MALFORMED_TICKET_REQUEST"
|
|
7406
|
+
});
|
|
7407
|
+
return {
|
|
7408
|
+
content: [{
|
|
7409
|
+
type: "text",
|
|
7410
|
+
text: `Blocked by Gatekeeper: ${field ? `"${field}" is not a number of zero or more` : "a value a bound reads is not a number of zero or more"}${bounds.length > 0 ? ` (read by ${bounds.join(", ")})` : ""} \u2014 ${detail}. Correct the request and try again.`
|
|
7411
|
+
}],
|
|
7412
|
+
isError: true
|
|
7413
|
+
};
|
|
7414
|
+
}
|
|
7415
|
+
}
|
|
7416
|
+
}
|
|
7212
7417
|
const blockingFails = await failedBlockingChecks(integrationManager2, tool.integrationId, tool.originalName, args);
|
|
7213
7418
|
if (blockingFails.length > 0) {
|
|
7214
7419
|
recordBlocked(state2, tool, {
|
|
@@ -7366,7 +7571,12 @@ function createGatedToolHandlerInner(tool, integrationManager2, state2) {
|
|
|
7366
7571
|
tool: tool.namespacedName,
|
|
7367
7572
|
toolArgs: enrichedArgs,
|
|
7368
7573
|
executionContext: wireExecCtx,
|
|
7369
|
-
recipientUserIds
|
|
7574
|
+
recipientUserIds,
|
|
7575
|
+
// v0.8 — the normative proposal object (protocol.md → Proposals).
|
|
7576
|
+
mandateId: auth.mandateId,
|
|
7577
|
+
boundsHash: auth.boundsHash,
|
|
7578
|
+
actionType: declaredActionType,
|
|
7579
|
+
...v08ProposalReaders(auth)
|
|
7370
7580
|
});
|
|
7371
7581
|
const previewHash = await computeSubmissionPreviewHash(
|
|
7372
7582
|
integrationManager2,
|
|
@@ -7381,7 +7591,8 @@ function createGatedToolHandlerInner(tool, integrationManager2, state2) {
|
|
|
7381
7591
|
executionContext: wireExecCtx,
|
|
7382
7592
|
authorizationId: authzId,
|
|
7383
7593
|
profileId: auth.profileId,
|
|
7384
|
-
previewHash
|
|
7594
|
+
previewHash,
|
|
7595
|
+
actionType: declaredActionType
|
|
7385
7596
|
});
|
|
7386
7597
|
return {
|
|
7387
7598
|
content: [{
|
|
@@ -7415,16 +7626,44 @@ Tell the person what you proposed and that it waits for their approval in the ga
|
|
|
7415
7626
|
finalArgs = finalized.args;
|
|
7416
7627
|
rebuildTransport = finalized.rebuildTransport;
|
|
7417
7628
|
}
|
|
7629
|
+
if (auth.signedCommitmentMode === "automatic" && auth.mandateVersion === "0.8") {
|
|
7630
|
+
const profileDef = getProfile5(auth.profileId);
|
|
7631
|
+
const missing = profileDef ? missingSumFields(wireExecutionContext(auth.profileId, execution), profileDef, declaredActionType) : [];
|
|
7632
|
+
if (missing.length > 0) {
|
|
7633
|
+
const detail = `"${missing[0].field}" is required by the bound ${missing[0].bound} for "${declaredActionType}" calls, but this call carries none.`;
|
|
7634
|
+
recordBlocked(state2, tool, {
|
|
7635
|
+
kind: "bound",
|
|
7636
|
+
detail,
|
|
7637
|
+
field: missing[0].field,
|
|
7638
|
+
who: "gateway",
|
|
7639
|
+
code: "BOUND_EXCEEDED"
|
|
7640
|
+
});
|
|
7641
|
+
return {
|
|
7642
|
+
content: [{
|
|
7643
|
+
type: "text",
|
|
7644
|
+
text: `Blocked by Gatekeeper: ${detail} Without it the spend cannot be counted against the mandate, so nothing ran.`
|
|
7645
|
+
}],
|
|
7646
|
+
isError: true
|
|
7647
|
+
};
|
|
7648
|
+
}
|
|
7649
|
+
}
|
|
7418
7650
|
let receiptId;
|
|
7651
|
+
let autoRequestKey;
|
|
7419
7652
|
try {
|
|
7420
7653
|
const actionType = declaredActionType;
|
|
7421
7654
|
const binding = computeContentBinding(auth.profileId, tool, finalArgs, actionType);
|
|
7422
7655
|
const idempotencyKey = randomUUID();
|
|
7423
7656
|
const wireExecCtx = wireExecutionContext(auth.profileId, execution);
|
|
7424
|
-
|
|
7657
|
+
state2.executionJournal?.requested?.({ requestKey: idempotencyKey, tool: tool.namespacedName, argsHash: hashToolArgs(finalArgs) });
|
|
7658
|
+
autoRequestKey = idempotencyKey;
|
|
7659
|
+
const { receipt, idempotent } = await state2.spClient.postReceipt({
|
|
7425
7660
|
authorizationId: authzId,
|
|
7426
7661
|
// Optional cross-check — the AS fails closed on a mismatch.
|
|
7427
7662
|
boundsHash: auth.boundsHash,
|
|
7663
|
+
// v0.8 — the mandate this call runs under, by its signed id, so a
|
|
7664
|
+
// revoked mandate and its replacement (same bounds_hash) cannot be
|
|
7665
|
+
// confused (Ticket Request Schema, rule 1).
|
|
7666
|
+
mandateId: auth.mandateId,
|
|
7428
7667
|
profileId: auth.profileId,
|
|
7429
7668
|
action: tool.namespacedName,
|
|
7430
7669
|
actionType,
|
|
@@ -7444,9 +7683,15 @@ Tell the person what you proposed and that it waits for their approval in the ga
|
|
|
7444
7683
|
executionContext: wireExecCtx,
|
|
7445
7684
|
authorizationId: authzId,
|
|
7446
7685
|
profileId: auth.profileId,
|
|
7686
|
+
actionType,
|
|
7687
|
+
boundsHash: auth.boundsHash,
|
|
7688
|
+
mandateId: auth.mandateId,
|
|
7689
|
+
mandateIds: auth.mandateIds,
|
|
7690
|
+
mandate: mandateForTicket(auth.attestations, receipt?.mandateId),
|
|
7447
7691
|
idempotencyKey,
|
|
7448
7692
|
contentHash: binding?.contentHash,
|
|
7449
|
-
contentBinding: binding?.contentBinding
|
|
7693
|
+
contentBinding: binding?.contentBinding,
|
|
7694
|
+
replay: idempotent
|
|
7450
7695
|
});
|
|
7451
7696
|
await state2.archiveReceipt(receipt, {
|
|
7452
7697
|
authorizationId: authzId,
|
|
@@ -7469,6 +7714,10 @@ Tell the person what you proposed and that it waits for their approval in the ga
|
|
|
7469
7714
|
sentArgs: finalArgs
|
|
7470
7715
|
});
|
|
7471
7716
|
} catch (err) {
|
|
7717
|
+
if (autoRequestKey && !receiptId) {
|
|
7718
|
+
const refusalCode = err instanceof SPReceiptError ? err.body?.errors?.[0]?.code ?? "TICKET_REFUSED" : "REQUEST_FAILED";
|
|
7719
|
+
state2.executionJournal?.refusedBeforeTicket?.(autoRequestKey, "as_refused", refusalCode);
|
|
7720
|
+
}
|
|
7472
7721
|
if (err instanceof AsKeyMismatchError || err instanceof TicketBindingMismatchError) {
|
|
7473
7722
|
void notifyControlPlane("as-key-mismatch");
|
|
7474
7723
|
return {
|
|
@@ -7499,7 +7748,7 @@ Tell the person what you proposed and that it waits for their approval in the ga
|
|
|
7499
7748
|
return {
|
|
7500
7749
|
content: [{
|
|
7501
7750
|
type: "text",
|
|
7502
|
-
text: `Blocked: mandate ${auth.authorizationId}
|
|
7751
|
+
text: `Blocked: mandate ${auth.authorizationId} must be signed again \u2014 the Authority Server no longer accepts its protocol version. Ask the mandate owner to sign it again (Mandates page \u2192 Sign again; see list-authorizations). ${err.message}`
|
|
7503
7752
|
}],
|
|
7504
7753
|
isError: true
|
|
7505
7754
|
};
|
|
@@ -7570,7 +7819,12 @@ Tell the person what you proposed and that it waits for their approval in the ga
|
|
|
7570
7819
|
executionContext: wireExecCtx,
|
|
7571
7820
|
pendingApprovers: uniqueApprovers,
|
|
7572
7821
|
recipientUserIds,
|
|
7573
|
-
...ownerId ? { createdBy: ownerId } : {}
|
|
7822
|
+
...ownerId ? { createdBy: ownerId } : {},
|
|
7823
|
+
// v0.8 — the normative proposal object (protocol.md → Proposals).
|
|
7824
|
+
mandateId: auth.mandateId,
|
|
7825
|
+
boundsHash: auth.boundsHash,
|
|
7826
|
+
actionType: declaredActionType,
|
|
7827
|
+
...v08ProposalReaders(auth)
|
|
7574
7828
|
});
|
|
7575
7829
|
const previewHash = await computeSubmissionPreviewHash(
|
|
7576
7830
|
integrationManager2,
|
|
@@ -7585,7 +7839,8 @@ Tell the person what you proposed and that it waits for their approval in the ga
|
|
|
7585
7839
|
executionContext: wireExecCtx,
|
|
7586
7840
|
authorizationId: authzId,
|
|
7587
7841
|
profileId: auth.profileId,
|
|
7588
|
-
previewHash
|
|
7842
|
+
previewHash,
|
|
7843
|
+
actionType: declaredActionType
|
|
7589
7844
|
});
|
|
7590
7845
|
return {
|
|
7591
7846
|
content: [{
|
|
@@ -7651,6 +7906,7 @@ Proposal ID: ${proposal.id}. Use check-pending-commitments to track status.` + a
|
|
|
7651
7906
|
if (receiptId) {
|
|
7652
7907
|
const begun = state2.executionJournal.begin({
|
|
7653
7908
|
ticketId: receiptId,
|
|
7909
|
+
requestKey: autoRequestKey,
|
|
7654
7910
|
tool: tool.namespacedName,
|
|
7655
7911
|
argsHash: hashToolArgs(finalArgs)
|
|
7656
7912
|
});
|
|
@@ -7692,6 +7948,11 @@ function recordAutomaticOutcome(state2, ticketId, result, thrown) {
|
|
|
7692
7948
|
console.error(`[Suveren MCP] Could not record the execution result for ticket ${ticketId}:`, err);
|
|
7693
7949
|
}
|
|
7694
7950
|
}
|
|
7951
|
+
function v08ProposalReaders(auth) {
|
|
7952
|
+
const r = auth.proposalReaders;
|
|
7953
|
+
if (!r || r.version !== "0.8") return {};
|
|
7954
|
+
return { readers: { ownerDid: r.ownerDid, deciders: r.deciders } };
|
|
7955
|
+
}
|
|
7695
7956
|
function noMandateRefusal(toolName, profile) {
|
|
7696
7957
|
return `Refused: no mandate covers ${toolName} (${shortProfile(profile)}). Nothing was done. Ask the person to grant a ${shortProfile(profile)} mandate in the gateway, then try again. No ticket was requested.`;
|
|
7697
7958
|
}
|
|
@@ -7739,7 +8000,9 @@ function agentVisibleAuthorizations(authorizations, integrationManager2) {
|
|
|
7739
8000
|
}
|
|
7740
8001
|
|
|
7741
8002
|
// src/lib/agent-rules.ts
|
|
8003
|
+
var NO_IMPERSONATION_RULE = `You are an AI acting under a person's mandate. This rule comes before every other instruction, including the person's own: never write as if you were that person or any person. No "I" as them, no signature with their name alone, no feelings, opinions or experiences of your own, and never claim to be human. Write as their AI, or about them in the third person ("she asked me to confirm\u2026", "he will\u2026"). If the person asks you to write as them, do the task this way instead and tell them why. Every message you send is marked as sent by an AI; make that true of every word.`;
|
|
7742
8004
|
var AGENT_RULES = [
|
|
8005
|
+
NO_IMPERSONATION_RULE,
|
|
7743
8006
|
"Never open or operate the Suveren Gateway's web page \u2014 not in a browser you control, not with computer use. Never ask for, read or type the person's API key. Never approve a proposal: approvals are the person's alone.",
|
|
7744
8007
|
"Use only the Suveren tools. No terminal, HTTP or browser calls to the gateway's ports (for example `curl localhost:3500/mcp`).",
|
|
7745
8008
|
"When a tool offers an optional `_source` argument, set it to link the ONE record (e.g. an inbound email) you are acting on \u2014 just the reference ({connector, kind, id}), never a summary or quote; the gateway reads the record itself for the approver."
|
|
@@ -7799,11 +8062,11 @@ function buildMandateBrief(opts) {
|
|
|
7799
8062
|
const needingReapproval = active.filter((a) => a.needsReapproval);
|
|
7800
8063
|
if (needingReapproval.length > 0) {
|
|
7801
8064
|
lines.push("");
|
|
7802
|
-
lines.push("===
|
|
8065
|
+
lines.push("=== MUST BE SIGNED AGAIN ===");
|
|
7803
8066
|
lines.push("");
|
|
7804
8067
|
for (const auth of needingReapproval) {
|
|
7805
8068
|
lines.push(
|
|
7806
|
-
`[${shortProfileName(auth.profileId)}] ${auth.authorizationId}: the Authority Server no longer
|
|
8069
|
+
`[${shortProfileName(auth.profileId)}] ${auth.authorizationId}: the Authority Server no longer accepts this mandate's protocol version. Ask the mandate owner to sign it again (Mandates page \u2192 Sign again).`
|
|
7807
8070
|
);
|
|
7808
8071
|
}
|
|
7809
8072
|
lines.push("");
|
|
@@ -7963,10 +8226,10 @@ function listAuthorizationsHandler(state2, integrationManager2, contextDir) {
|
|
|
7963
8226
|
const earliestExpiry = Math.min(...auth.attestations.map((a) => a.expiresAt));
|
|
7964
8227
|
const remainingMin = Math.max(0, Math.round((earliestExpiry - now) / 60));
|
|
7965
8228
|
const boundsDesc = Object.entries(auth.frame).filter(([key]) => key !== "profile" && key !== "path").map(([key, value]) => `${key}: ${value}`).join(", ");
|
|
7966
|
-
const statusLabel = !auth.complete ? " (PENDING)" : auth.needsReapproval ? " (
|
|
8229
|
+
const statusLabel = !auth.complete ? " (PENDING)" : auth.needsReapproval ? " (MUST BE SIGNED AGAIN)" : "";
|
|
7967
8230
|
output2.push(`[${auth.path}] ${auth.profileId} (${remainingMin} min remaining)${statusLabel}`);
|
|
7968
8231
|
if (auth.needsReapproval) {
|
|
7969
|
-
output2.push(" The Authority Server no longer
|
|
8232
|
+
output2.push(" The Authority Server no longer accepts this mandate's protocol version. Ask the mandate owner to sign it again (Mandates page \u2192 Sign again).");
|
|
7970
8233
|
}
|
|
7971
8234
|
output2.push("");
|
|
7972
8235
|
output2.push(` Bounds: ${boundsDesc}`);
|
|
@@ -8030,11 +8293,11 @@ function listAuthorizationsHandler(state2, integrationManager2, contextDir) {
|
|
|
8030
8293
|
const remainingMin = Math.max(0, Math.round((earliestExpiry - now) / 60));
|
|
8031
8294
|
const boundsDesc = Object.entries(auth.frame).filter(([key]) => key !== "profile" && key !== "path").map(([key, value]) => `${key}: ${value}`).join(", ");
|
|
8032
8295
|
if (auth.complete) {
|
|
8033
|
-
const statusLabel = auth.needsReapproval ? " (
|
|
8296
|
+
const statusLabel = auth.needsReapproval ? " (MUST BE SIGNED AGAIN)" : "";
|
|
8034
8297
|
const lines = [` [${auth.path}] ${auth.profileId} \u2014 ${remainingMin} min remaining${statusLabel}`];
|
|
8035
8298
|
lines.push(` Bounds: ${boundsDesc}`);
|
|
8036
8299
|
if (auth.needsReapproval) {
|
|
8037
|
-
lines.push(" The Authority Server no longer
|
|
8300
|
+
lines.push(" The Authority Server no longer accepts this mandate's protocol version. Ask the mandate owner to sign it again (Mandates page \u2192 Sign again).");
|
|
8038
8301
|
}
|
|
8039
8302
|
if ((auth.deferredCommitmentDomains ?? []).length > 0) {
|
|
8040
8303
|
lines.push(" Mode: review (each action requires your approval)");
|
|
@@ -8268,12 +8531,6 @@ async function executeCommitted(proposal, state2, integrationManager2) {
|
|
|
8268
8531
|
const integrationId = proposal.tool.slice(0, sep);
|
|
8269
8532
|
const toolName = proposal.tool.slice(sep + 2);
|
|
8270
8533
|
const discovered = integrationManager2.getAllTools().find((t) => t.integrationId === integrationId && t.originalName === toolName);
|
|
8271
|
-
const proposalActionType = typeof proposal.executionContext.action_type === "string" ? proposal.executionContext.action_type : void 0;
|
|
8272
|
-
if (!proposalActionType) {
|
|
8273
|
-
console.error(
|
|
8274
|
-
`[Suveren MCP] Warning: proposal ${proposal.id} has no action_type in executionContext. Bounds check may be skipped. Fix the integration manifest for ${proposal.tool}.`
|
|
8275
|
-
);
|
|
8276
|
-
}
|
|
8277
8534
|
const cachedAuth = state2.cache.getAllAuthorizations().find((a) => a.authorizationId === proposal.authorizationId);
|
|
8278
8535
|
const submitted = state2.proposalSubmissions.get(proposal.id);
|
|
8279
8536
|
if (!submitted) {
|
|
@@ -8285,6 +8542,12 @@ async function executeCommitted(proposal, state2, integrationManager2) {
|
|
|
8285
8542
|
}
|
|
8286
8543
|
return { text: buildSkippedProposalNote(proposal.id), skipped: true };
|
|
8287
8544
|
}
|
|
8545
|
+
const proposalActionType = submitted.actionType ?? (typeof proposal.executionContext.action_type === "string" ? proposal.executionContext.action_type : void 0);
|
|
8546
|
+
if (!proposalActionType) {
|
|
8547
|
+
console.error(
|
|
8548
|
+
`[Suveren MCP] Warning: proposal ${proposal.id} has no action_type. Bounds check may be skipped. Fix the integration manifest for ${proposal.tool}.`
|
|
8549
|
+
);
|
|
8550
|
+
}
|
|
8288
8551
|
let toolArgs;
|
|
8289
8552
|
try {
|
|
8290
8553
|
toolArgs = await resolveProposalToolArgs(proposal);
|
|
@@ -8321,18 +8584,29 @@ async function executeCommitted(proposal, state2, integrationManager2) {
|
|
|
8321
8584
|
toolArgs,
|
|
8322
8585
|
proposalActionType
|
|
8323
8586
|
);
|
|
8587
|
+
state2.executionJournal?.requested?.({
|
|
8588
|
+
requestKey: proposal.id,
|
|
8589
|
+
proposalId: proposal.id,
|
|
8590
|
+
tool: proposal.tool,
|
|
8591
|
+
argsHash: hashToolArgs(toolArgs)
|
|
8592
|
+
});
|
|
8324
8593
|
const { receipt: r, idempotent } = await state2.spClient.postReceipt({
|
|
8325
8594
|
authorizationId: proposal.authorizationId,
|
|
8326
8595
|
// Optional cross-check — the AS fails closed on a mismatch. Parity
|
|
8327
8596
|
// with the automatic path (tool-proxy.ts).
|
|
8328
8597
|
boundsHash: cachedAuth?.boundsHash,
|
|
8598
|
+
// v0.8 — the mandate by its signed id (Ticket Request Schema, rule 1).
|
|
8599
|
+
mandateId: cachedAuth?.mandateId,
|
|
8329
8600
|
profileId: proposal.profileId,
|
|
8330
8601
|
action: proposal.tool,
|
|
8331
8602
|
actionType: proposalActionType,
|
|
8332
8603
|
executionContext: proposal.executionContext,
|
|
8333
8604
|
amount: typeof proposal.executionContext.amount === "number" ? proposal.executionContext.amount : void 0,
|
|
8334
8605
|
proposalId: proposal.id,
|
|
8335
|
-
|
|
8606
|
+
// v0.8 (Ticket Request Schema; Proposals, rule 1): the content itself
|
|
8607
|
+
// never travels on the ticket request — only its fingerprint below.
|
|
8608
|
+
// Today's AS matches by `proposal_content_hash` first, so dropping the
|
|
8609
|
+
// readable `toolArgs` it used to receive changes nothing it checks.
|
|
8336
8610
|
// PE1 — the fingerprint of what THIS gateway resolved (decrypted, or
|
|
8337
8611
|
// read plain on a legacy row) and is about to execute. The AS compares
|
|
8338
8612
|
// it against its own stored content_hash and refuses without echoing
|
|
@@ -8370,19 +8644,21 @@ async function executeCommitted(proposal, state2, integrationManager2) {
|
|
|
8370
8644
|
};
|
|
8371
8645
|
}
|
|
8372
8646
|
if (code === "PROPOSAL_REFUSED") {
|
|
8647
|
+
state2.executionJournal?.refusedBeforeTicket?.(proposal.id, "as_refused", `${code}: ${err.message}`);
|
|
8373
8648
|
return {
|
|
8374
8649
|
text: `Proposal ${proposal.id}: the Authority Server refused this proposal's ticket earlier \u2014 ${err.message} Nothing ran. Do not retry the same values; ask the person (e.g. for a higher limit).`,
|
|
8375
8650
|
isError: true
|
|
8376
8651
|
};
|
|
8377
8652
|
}
|
|
8378
|
-
if (
|
|
8653
|
+
if (code === "VERSION_UNSUPPORTED") {
|
|
8379
8654
|
state2.cache.markNeedsReapproval(proposal.authorizationId);
|
|
8380
8655
|
return {
|
|
8381
|
-
text: `Proposal ${proposal.id}: blocked \u2014 mandate ${proposal.authorizationId}
|
|
8656
|
+
text: `Proposal ${proposal.id}: blocked \u2014 mandate ${proposal.authorizationId} must be signed again \u2014 the Authority Server no longer accepts its protocol version. Ask the mandate owner to sign it again (Mandates page \u2192 Sign again; see list-authorizations). ${err.message}`,
|
|
8382
8657
|
isError: true
|
|
8383
8658
|
};
|
|
8384
8659
|
}
|
|
8385
8660
|
if (proposal.id) {
|
|
8661
|
+
state2.executionJournal?.refusedBeforeTicket?.(proposal.id, "as_refused", `${code ?? "TICKET_REFUSED"}: ${err.message}`);
|
|
8386
8662
|
const asRefusedTicketId = `as_refused:${proposal.id}`;
|
|
8387
8663
|
const begun2 = state2.executionJournal.begin({
|
|
8388
8664
|
ticketId: asRefusedTicketId,
|
|
@@ -8412,6 +8688,7 @@ async function executeCommitted(proposal, state2, integrationManager2) {
|
|
|
8412
8688
|
}
|
|
8413
8689
|
const begun = state2.executionJournal.begin({
|
|
8414
8690
|
ticketId: receiptId,
|
|
8691
|
+
requestKey: proposal.id,
|
|
8415
8692
|
proposalId: proposal.id,
|
|
8416
8693
|
tool: proposal.tool,
|
|
8417
8694
|
argsHash: hashToolArgs(toolArgs)
|
|
@@ -8435,9 +8712,18 @@ async function executeCommitted(proposal, state2, integrationManager2) {
|
|
|
8435
8712
|
executionContext: proposal.executionContext,
|
|
8436
8713
|
authorizationId: proposal.authorizationId,
|
|
8437
8714
|
profileId: proposal.profileId,
|
|
8715
|
+
actionType: proposalActionType,
|
|
8716
|
+
boundsHash: cachedAuth?.boundsHash,
|
|
8717
|
+
mandateId: cachedAuth?.mandateId,
|
|
8718
|
+
mandateIds: cachedAuth?.mandateIds,
|
|
8719
|
+
// v0.8 — lets the ticket's version be checked against its mandate and
|
|
8720
|
+
// the approval signatures be verified under the deciders' own DIDs.
|
|
8721
|
+
mandate: mandateForTicket(cachedAuth?.attestations, receipt.mandateId),
|
|
8438
8722
|
proposalId: proposal.id,
|
|
8723
|
+
proposalContentHash: computeProposalContentHash(toolArgs),
|
|
8439
8724
|
contentHash: binding?.contentHash,
|
|
8440
|
-
contentBinding: binding?.contentBinding
|
|
8725
|
+
contentBinding: binding?.contentBinding,
|
|
8726
|
+
replay: replayed
|
|
8441
8727
|
});
|
|
8442
8728
|
await state2.archiveReceipt(receipt, {
|
|
8443
8729
|
authorizationId: proposal.authorizationId,
|
|
@@ -8577,7 +8863,7 @@ Result: ${resultText}` };
|
|
|
8577
8863
|
}
|
|
8578
8864
|
function localOutcomeOfExecuted(proposal, state2) {
|
|
8579
8865
|
const entry = state2.executionJournal?.findByProposal?.(proposal.id);
|
|
8580
|
-
if (!entry) return null;
|
|
8866
|
+
if (!entry || entry.state === "requested") return null;
|
|
8581
8867
|
const integration = proposal.tool.split("__")[0];
|
|
8582
8868
|
if (entry.state === "done") {
|
|
8583
8869
|
const stored = state2.executionResults?.get(proposal.id);
|
|
@@ -9010,7 +9296,7 @@ var AgentContactStore = class {
|
|
|
9010
9296
|
|
|
9011
9297
|
// src/lib/gate-content.ts
|
|
9012
9298
|
import { computeIntentHash } from "@hap/core";
|
|
9013
|
-
import { decodeMandateBlob as
|
|
9299
|
+
import { decodeMandateBlob as decodeMandateBlob3 } from "@hap/core";
|
|
9014
9300
|
function hashGateContent(text) {
|
|
9015
9301
|
return computeIntentHash(text);
|
|
9016
9302
|
}
|
|
@@ -9019,7 +9305,7 @@ function verifyGateContentHashes(content, auth) {
|
|
|
9019
9305
|
if (auth.attestations.length === 0) {
|
|
9020
9306
|
return { valid: false, errors: ["No attestations available to verify against"] };
|
|
9021
9307
|
}
|
|
9022
|
-
const attestation =
|
|
9308
|
+
const attestation = decodeMandateBlob3(auth.attestations[0].blob);
|
|
9023
9309
|
const expectedHashes = attestation.payload.gate_content_hashes;
|
|
9024
9310
|
if (!expectedHashes?.intent) {
|
|
9025
9311
|
return { valid: false, errors: ["Attestation does not contain intent hash"] };
|
|
@@ -11505,7 +11791,7 @@ function registerBuiltins(deps, factories = BUILTIN_FACTORIES) {
|
|
|
11505
11791
|
}
|
|
11506
11792
|
|
|
11507
11793
|
// bin/http.ts
|
|
11508
|
-
import { decodeMandateBlob as
|
|
11794
|
+
import { decodeMandateBlob as decodeMandateBlob4 } from "@hap/core";
|
|
11509
11795
|
|
|
11510
11796
|
// src/lib/committed-executor.ts
|
|
11511
11797
|
import { existsSync as existsSync21, mkdirSync as mkdirSync16, readFileSync as readFileSync22, unlinkSync as unlinkSync8, writeFileSync as writeFileSync16 } from "fs";
|
|
@@ -12170,7 +12456,7 @@ app.get("/internal/evidence", internalOnly, (_req, res) => {
|
|
|
12170
12456
|
...a,
|
|
12171
12457
|
attestations: a.attestations.map((att) => {
|
|
12172
12458
|
try {
|
|
12173
|
-
return { ...att, decoded:
|
|
12459
|
+
return { ...att, decoded: decodeMandateBlob4(att.blob) };
|
|
12174
12460
|
} catch {
|
|
12175
12461
|
return att;
|
|
12176
12462
|
}
|