agent-comms 8.4.1 → 8.6.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +33 -3
- package/dist/bridges/cc-peer/front-runtime.d.ts.map +1 -1
- package/dist/bridges/cc-peer/front-runtime.js +4 -2
- package/dist/bridges/cc-peer/front-runtime.js.map +1 -1
- package/dist/bridges/user/controller.d.ts.map +1 -1
- package/dist/bridges/user/controller.js +4 -1
- package/dist/bridges/user/controller.js.map +1 -1
- package/dist/bridges/user/web/contract.d.ts +12 -0
- package/dist/bridges/user/web/contract.d.ts.map +1 -1
- package/dist/bridges/user/web/contract.js +9 -0
- package/dist/bridges/user/web/contract.js.map +1 -1
- package/dist/bridges/user/web/dist/bundle.js +1 -1
- package/dist/bridges/user/web/dist/mesh-worker.js +1 -1
- package/dist/bridges/user/web/dist/sw.js +1 -1
- package/dist/bridges/user/web/frontend/components/MeshGraphView.d.ts +3 -1
- package/dist/bridges/user/web/frontend/components/MeshGraphView.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/components/MeshGraphView.js +2 -4
- package/dist/bridges/user/web/frontend/components/MeshGraphView.js.map +1 -1
- package/dist/bridges/user/web/frontend/components/MeshPanel.d.ts +1 -1
- package/dist/bridges/user/web/frontend/components/MeshPanel.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/components/MeshPanel.js +6 -1
- package/dist/bridges/user/web/frontend/components/MeshPanel.js.map +1 -1
- package/dist/bridges/user/web/frontend/components/MeshTraceView.d.ts +3 -1
- package/dist/bridges/user/web/frontend/components/MeshTraceView.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/components/MeshTraceView.js +2 -4
- package/dist/bridges/user/web/frontend/components/MeshTraceView.js.map +1 -1
- package/dist/bridges/user/web/frontend/main.js +6 -13
- package/dist/bridges/user/web/frontend/main.js.map +1 -1
- package/dist/bridges/user/web/frontend/mesh-client.d.ts +2 -0
- package/dist/bridges/user/web/frontend/mesh-client.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/mesh-client.js +1 -0
- package/dist/bridges/user/web/frontend/mesh-client.js.map +1 -1
- package/dist/bridges/user/web/frontend/mesh-invalidation.d.ts +11 -0
- package/dist/bridges/user/web/frontend/mesh-invalidation.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/mesh-invalidation.js +26 -0
- package/dist/bridges/user/web/frontend/mesh-invalidation.js.map +1 -0
- package/dist/bridges/user/web/frontend/mesh-worker.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/mesh-worker.js +1 -0
- package/dist/bridges/user/web/frontend/mesh-worker.js.map +1 -1
- package/dist/bridges/user/web/frontend/tab-contract.d.ts +5 -0
- package/dist/bridges/user/web/frontend/tab-contract.d.ts.map +1 -1
- package/dist/bridges/user/web/reads.d.ts +3 -0
- package/dist/bridges/user/web/reads.d.ts.map +1 -1
- package/dist/bridges/user/web/reads.js +4 -0
- package/dist/bridges/user/web/reads.js.map +1 -1
- package/dist/bridges/user/web/router.d.ts +5 -0
- package/dist/bridges/user/web/router.d.ts.map +1 -1
- package/dist/bridges/user/web/router.js +2 -1
- package/dist/bridges/user/web/router.js.map +1 -1
- package/dist/core/agent-registry.d.ts.map +1 -1
- package/dist/core/agent-registry.js +20 -6
- package/dist/core/agent-registry.js.map +1 -1
- package/dist/core/agent-table.d.ts +18 -0
- package/dist/core/agent-table.d.ts.map +1 -0
- package/dist/core/agent-table.js +38 -0
- package/dist/core/agent-table.js.map +1 -0
- package/dist/core/atomic-file.d.ts +12 -0
- package/dist/core/atomic-file.d.ts.map +1 -0
- package/dist/core/atomic-file.js +37 -0
- package/dist/core/atomic-file.js.map +1 -0
- package/dist/core/bridge-mesh.d.ts.map +1 -1
- package/dist/core/bridge-mesh.js +7 -0
- package/dist/core/bridge-mesh.js.map +1 -1
- package/dist/core/bridge.d.ts +5 -0
- package/dist/core/bridge.d.ts.map +1 -1
- package/dist/core/bridge.js +26 -1
- package/dist/core/bridge.js.map +1 -1
- package/dist/core/delivery-engine.d.ts.map +1 -1
- package/dist/core/delivery-engine.js +4 -0
- package/dist/core/delivery-engine.js.map +1 -1
- package/dist/core/device-membership-verification.d.ts +23 -9
- package/dist/core/device-membership-verification.d.ts.map +1 -1
- package/dist/core/device-membership-verification.js +38 -11
- package/dist/core/device-membership-verification.js.map +1 -1
- package/dist/core/device-membership.d.ts +12 -3
- package/dist/core/device-membership.d.ts.map +1 -1
- package/dist/core/device-membership.js +10 -7
- package/dist/core/device-membership.js.map +1 -1
- package/dist/core/directory-admission.d.ts +5 -3
- package/dist/core/directory-admission.d.ts.map +1 -1
- package/dist/core/directory-admission.js +55 -32
- package/dist/core/directory-admission.js.map +1 -1
- package/dist/core/display-name.d.ts +29 -0
- package/dist/core/display-name.d.ts.map +1 -0
- package/dist/core/display-name.js +57 -0
- package/dist/core/display-name.js.map +1 -0
- package/dist/core/gateway-trust-actions.d.ts +7 -9
- package/dist/core/gateway-trust-actions.d.ts.map +1 -1
- package/dist/core/gateway-trust-actions.js +82 -16
- package/dist/core/gateway-trust-actions.js.map +1 -1
- package/dist/core/gateway-trust.d.ts +38 -17
- package/dist/core/gateway-trust.d.ts.map +1 -1
- package/dist/core/gateway-trust.js +86 -37
- package/dist/core/gateway-trust.js.map +1 -1
- package/dist/core/gossip-directory.d.ts +25 -3
- package/dist/core/gossip-directory.d.ts.map +1 -1
- package/dist/core/gossip-directory.js +53 -5
- package/dist/core/gossip-directory.js.map +1 -1
- package/dist/core/gossip-extensions.d.ts +4 -0
- package/dist/core/gossip-extensions.d.ts.map +1 -1
- package/dist/core/gossip-extensions.js +4 -0
- package/dist/core/gossip-extensions.js.map +1 -1
- package/dist/core/group-proofs.d.ts +49 -0
- package/dist/core/group-proofs.d.ts.map +1 -0
- package/dist/core/group-proofs.js +102 -0
- package/dist/core/group-proofs.js.map +1 -0
- package/dist/core/identity-store.d.ts +5 -4
- package/dist/core/identity-store.d.ts.map +1 -1
- package/dist/core/identity-store.js +13 -16
- package/dist/core/identity-store.js.map +1 -1
- package/dist/core/issuer-identity-file.d.ts +25 -0
- package/dist/core/issuer-identity-file.d.ts.map +1 -0
- package/dist/core/issuer-identity-file.js +124 -0
- package/dist/core/issuer-identity-file.js.map +1 -0
- package/dist/core/machine-grouping.d.ts +47 -0
- package/dist/core/machine-grouping.d.ts.map +1 -0
- package/dist/core/machine-grouping.js +102 -0
- package/dist/core/machine-grouping.js.map +1 -0
- package/dist/core/machine-identity.d.ts +19 -0
- package/dist/core/machine-identity.d.ts.map +1 -0
- package/dist/core/machine-identity.js +42 -0
- package/dist/core/machine-identity.js.map +1 -0
- package/dist/core/machine-list-groups.d.ts +13 -0
- package/dist/core/machine-list-groups.d.ts.map +1 -0
- package/dist/core/machine-list-groups.js +41 -0
- package/dist/core/machine-list-groups.js.map +1 -0
- package/dist/core/machine-name-claim.d.ts +22 -0
- package/dist/core/machine-name-claim.d.ts.map +1 -0
- package/dist/core/machine-name-claim.js +52 -0
- package/dist/core/machine-name-claim.js.map +1 -0
- package/dist/core/membership-proof.d.ts +20 -9
- package/dist/core/membership-proof.d.ts.map +1 -1
- package/dist/core/membership-proof.js +41 -15
- package/dist/core/membership-proof.js.map +1 -1
- package/dist/core/membership-proofs.d.ts +16 -8
- package/dist/core/membership-proofs.d.ts.map +1 -1
- package/dist/core/membership-proofs.js +24 -12
- package/dist/core/membership-proofs.js.map +1 -1
- package/dist/core/mesh-graph-trace-tool.d.ts +3 -2
- package/dist/core/mesh-graph-trace-tool.d.ts.map +1 -1
- package/dist/core/mesh-graph-trace-tool.js +8 -5
- package/dist/core/mesh-graph-trace-tool.js.map +1 -1
- package/dist/core/mesh-store-shared.d.ts +4 -1
- package/dist/core/mesh-store-shared.d.ts.map +1 -1
- package/dist/core/mesh-store-shared.js.map +1 -1
- package/dist/core/mesh-store.d.ts +20 -10
- package/dist/core/mesh-store.d.ts.map +1 -1
- package/dist/core/mesh-store.js +45 -38
- package/dist/core/mesh-store.js.map +1 -1
- package/dist/core/name-claim.d.ts +38 -0
- package/dist/core/name-claim.d.ts.map +1 -0
- package/dist/core/name-claim.js +93 -0
- package/dist/core/name-claim.js.map +1 -0
- package/dist/core/naming-actions.d.ts +21 -0
- package/dist/core/naming-actions.d.ts.map +1 -0
- package/dist/core/naming-actions.js +58 -0
- package/dist/core/naming-actions.js.map +1 -0
- package/dist/core/naming.d.ts +50 -0
- package/dist/core/naming.d.ts.map +1 -0
- package/dist/core/naming.js +81 -0
- package/dist/core/naming.js.map +1 -0
- package/dist/core/network-interfaces.d.ts +7 -0
- package/dist/core/network-interfaces.d.ts.map +1 -0
- package/dist/core/network-interfaces.js +23 -0
- package/dist/core/network-interfaces.js.map +1 -0
- package/dist/core/peer-versions.d.ts +6 -0
- package/dist/core/peer-versions.d.ts.map +1 -1
- package/dist/core/peer-versions.js +17 -0
- package/dist/core/peer-versions.js.map +1 -1
- package/dist/core/petnames.d.ts +22 -0
- package/dist/core/petnames.d.ts.map +1 -0
- package/dist/core/petnames.js +102 -0
- package/dist/core/petnames.js.map +1 -0
- package/dist/core/room-path.d.ts +2 -0
- package/dist/core/room-path.d.ts.map +1 -1
- package/dist/core/room-path.js +5 -1
- package/dist/core/room-path.js.map +1 -1
- package/dist/core/store.d.ts +4 -0
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +19 -2
- package/dist/core/store.js.map +1 -1
- package/dist/core/tool.d.ts +16 -5
- package/dist/core/tool.d.ts.map +1 -1
- package/dist/core/tool.js +59 -13
- package/dist/core/tool.js.map +1 -1
- package/dist/core/types.d.ts +28 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +18 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-identity.d.ts +4 -6
- package/dist/core/user-identity.d.ts.map +1 -1
- package/dist/core/user-identity.js +9 -113
- package/dist/core/user-identity.js.map +1 -1
- package/dist/core/wire-mesh-transport-options.d.ts +2 -2
- package/dist/core/wire-mesh-transport-options.d.ts.map +1 -1
- package/dist/core/wire-mesh-transport.d.ts.map +1 -1
- package/dist/core/wire-mesh-transport.js +7 -7
- package/dist/core/wire-mesh-transport.js.map +1 -1
- package/dist/test/agent-table.unit.test.d.ts +5 -0
- package/dist/test/agent-table.unit.test.d.ts.map +1 -0
- package/dist/test/agent-table.unit.test.js +53 -0
- package/dist/test/agent-table.unit.test.js.map +1 -0
- package/dist/test/delivery-engine-delivery.unit.test.js +2 -0
- package/dist/test/delivery-engine-delivery.unit.test.js.map +1 -1
- package/dist/test/delivery-engine-directed-notify.unit.test.js +2 -0
- package/dist/test/delivery-engine-directed-notify.unit.test.js.map +1 -1
- package/dist/test/delivery-engine-own-agent.unit.test.js +2 -0
- package/dist/test/delivery-engine-own-agent.unit.test.js.map +1 -1
- package/dist/test/delivery-engine.unit.test.js +2 -0
- package/dist/test/delivery-engine.unit.test.js.map +1 -1
- package/dist/test/device-membership-verification.unit.test.js +25 -25
- package/dist/test/device-membership-verification.unit.test.js.map +1 -1
- package/dist/test/device-membership.unit.test.js +6 -6
- package/dist/test/device-membership.unit.test.js.map +1 -1
- package/dist/test/directory-admission.unit.test.js +103 -7
- package/dist/test/directory-admission.unit.test.js.map +1 -1
- package/dist/test/display-name.unit.test.d.ts +5 -0
- package/dist/test/display-name.unit.test.d.ts.map +1 -0
- package/dist/test/display-name.unit.test.js +65 -0
- package/dist/test/display-name.unit.test.js.map +1 -0
- package/dist/test/gateway-trust-tool.integration.test.js +117 -4
- package/dist/test/gateway-trust-tool.integration.test.js.map +1 -1
- package/dist/test/gateway-trust.unit.test.js +62 -13
- package/dist/test/gateway-trust.unit.test.js.map +1 -1
- package/dist/test/gossip-directory.unit.test.js +14 -1
- package/dist/test/gossip-directory.unit.test.js.map +1 -1
- package/dist/test/hub-exposure.integration.test.js +1 -1
- package/dist/test/hub-exposure.integration.test.js.map +1 -1
- package/dist/test/identity-restart.integration.test.js +3 -0
- package/dist/test/identity-restart.integration.test.js.map +1 -1
- package/dist/test/identity-store.integration.test.js +64 -14
- package/dist/test/identity-store.integration.test.js.map +1 -1
- package/dist/test/machine-grouping.unit.test.d.ts +2 -0
- package/dist/test/machine-grouping.unit.test.d.ts.map +1 -0
- package/dist/test/machine-grouping.unit.test.js +68 -0
- package/dist/test/machine-grouping.unit.test.js.map +1 -0
- package/dist/test/machine-identity.unit.test.d.ts +5 -0
- package/dist/test/machine-identity.unit.test.d.ts.map +1 -0
- package/dist/test/machine-identity.unit.test.js +80 -0
- package/dist/test/machine-identity.unit.test.js.map +1 -0
- package/dist/test/machine-list-groups.unit.test.d.ts +5 -0
- package/dist/test/machine-list-groups.unit.test.d.ts.map +1 -0
- package/dist/test/machine-list-groups.unit.test.js +61 -0
- package/dist/test/machine-list-groups.unit.test.js.map +1 -0
- package/dist/test/machine-membership-trust.integration.test.d.ts +5 -0
- package/dist/test/machine-membership-trust.integration.test.d.ts.map +1 -0
- package/dist/test/machine-membership-trust.integration.test.js +152 -0
- package/dist/test/machine-membership-trust.integration.test.js.map +1 -0
- package/dist/test/membership-proof.unit.test.js +105 -13
- package/dist/test/membership-proof.unit.test.js.map +1 -1
- package/dist/test/name-claim.unit.test.d.ts +5 -0
- package/dist/test/name-claim.unit.test.d.ts.map +1 -0
- package/dist/test/name-claim.unit.test.js +135 -0
- package/dist/test/name-claim.unit.test.js.map +1 -0
- package/dist/test/naming.integration.test.d.ts +5 -0
- package/dist/test/naming.integration.test.d.ts.map +1 -0
- package/dist/test/naming.integration.test.js +188 -0
- package/dist/test/naming.integration.test.js.map +1 -0
- package/dist/test/petnames.unit.test.d.ts +5 -0
- package/dist/test/petnames.unit.test.d.ts.map +1 -0
- package/dist/test/petnames.unit.test.js +94 -0
- package/dist/test/petnames.unit.test.js.map +1 -0
- package/dist/test/principal-membership-trust.integration.test.js +2 -1
- package/dist/test/principal-membership-trust.integration.test.js.map +1 -1
- package/dist/test/room-join-admission.integration.test.js +3 -0
- package/dist/test/room-join-admission.integration.test.js.map +1 -1
- package/dist/test/room-lifecycle-bare-name.unit.test.js +2 -0
- package/dist/test/room-lifecycle-bare-name.unit.test.js.map +1 -1
- package/dist/test/room-lifecycle-membership.unit.test.js +2 -0
- package/dist/test/room-lifecycle-membership.unit.test.js.map +1 -1
- package/dist/test/room-lifecycle-remote.unit.test.js +2 -0
- package/dist/test/room-lifecycle-remote.unit.test.js.map +1 -1
- package/dist/test/room-lifecycle.unit.test.js +2 -0
- package/dist/test/room-lifecycle.unit.test.js.map +1 -1
- package/dist/test/room-messaging-durable-send.unit.test.js +2 -0
- package/dist/test/room-messaging-durable-send.unit.test.js.map +1 -1
- package/dist/test/room-messaging.unit.test.js +2 -0
- package/dist/test/room-messaging.unit.test.js.map +1 -1
- package/dist/test/room-protocol-notify.unit.test.js +2 -0
- package/dist/test/room-protocol-notify.unit.test.js.map +1 -1
- package/dist/test/room-protocol.helper.d.ts.map +1 -1
- package/dist/test/room-protocol.helper.js +2 -0
- package/dist/test/room-protocol.helper.js.map +1 -1
- package/dist/test/room-send-retry.integration.test.js +3 -0
- package/dist/test/room-send-retry.integration.test.js.map +1 -1
- package/dist/test/test-transport.d.ts +3 -0
- package/dist/test/test-transport.d.ts.map +1 -1
- package/dist/test/test-transport.js +8 -1
- package/dist/test/test-transport.js.map +1 -1
- package/dist/test/user-identity.unit.test.js +40 -14
- package/dist/test/user-identity.unit.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Which gossiped directory entries from the hub a gateway merges (agent-comms#156, widened by #187 and #
|
|
2
|
+
* Which gossiped directory entries from the hub a gateway merges (agent-comms#156, widened by #187, #266 and #343). Split out of WireMeshTransport, which hands it the two collaborators it needs.
|
|
3
3
|
*
|
|
4
|
-
* A membership proof shows that a trusted principal vouches for a device id. It does not show that whoever sent the advert is that device: the id and the proof both arrive in the same unauthenticated advert, and anyone who has read one can repeat it. So it earns only what GatewayTrust.isReachable grants (a directory entry and a route), never isTrusted, and everything a request to such a device carries is authenticated by the end-to-end session inside the relay. Verifying a proof is cryptography, so the work is bounded here: verdicts are remembered, a batch verifies only so many new proofs, and a verifier that throws refuses the entry rather than breaking the merge.
|
|
4
|
+
* A membership proof shows that a trusted principal or machine vouches for a device id. It does not show that whoever sent the advert is that device: the id and the proof both arrive in the same unauthenticated advert, and anyone who has read one can repeat it. So it earns only what GatewayTrust.isReachable grants (a directory entry and a route), never isTrusted, and everything a request to such a device carries is authenticated by the end-to-end session inside the relay. Verifying a proof is cryptography, so the work is bounded here: verdicts are remembered, a batch verifies only so many new proofs, and a verifier that throws refuses the entry rather than breaking the merge.
|
|
5
5
|
*/
|
|
6
6
|
import type { DirectoryEntry } from "wire-mesh-core/domain/mesh-session";
|
|
7
7
|
import type { GatewayTrustReader } from "./gateway-trust.js";
|
|
@@ -15,6 +15,8 @@ export interface DirectoryAdmissionDeps {
|
|
|
15
15
|
/** Absent when this side cannot verify proofs, in which case a proof is never enough. */
|
|
16
16
|
verifyMembership: WireMeshTransportOptions["verifyMembership"];
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
18
|
+
/** Whether an entry this side has already merged from the hub would still be admitted now, with no new proof to judge: its device is reachable (trusted by id, or vouched for by a proof that has not lapsed from an issuer still trusted) or is itself a trusted principal's own device. The read-time counterpart of directoryAdmission, which KnownDevices uses to drop a device as soon as the trust that let it in is withdrawn or lapses. */
|
|
19
|
+
export declare function staysAdmitted(gatewayTrust: Readonly<Pick<GatewayTrustReader, "isReachable" | "isTrustedPrincipal">>, deviceHex: string): boolean;
|
|
20
|
+
/** Builds the admission check for a transport's directory merge: given a batch of entries, the ones to merge. An entry is merged if its device is trusted by id, is itself a trusted principal's own device, or carries a proof that a trusted principal or machine vouches for it; each proof an entry carries is judged on its own, and every one that verifies records the device in gatewayTrust under that kind until the proof lapses or its issuer stops being trusted. A remembered good verdict is reused only while that kind's record is still live, and a device's newer proof is verified as it arrives, which is how its trust is renewed before the old one lapses. */
|
|
19
21
|
export declare function directoryAdmission(deps: Readonly<DirectoryAdmissionDeps>): (entries: readonly DirectoryEntry[]) => Promise<DirectoryEntry[]>;
|
|
20
22
|
//# sourceMappingURL=directory-admission.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory-admission.d.ts","sourceRoot":"","sources":["../../src/core/directory-admission.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"directory-admission.d.ts","sourceRoot":"","sources":["../../src/core/directory-admission.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,kBAAkB,EAAa,MAAM,oBAAoB,CAAC;AAKxE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAEjF,mOAAmO;AACnO,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAI7C,qOAAqO;AACrO,eAAO,MAAM,uBAAuB,QACU,CAAC;AAc/C,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAC3C,yFAAyF;IACzF,gBAAgB,EAAE,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;CAChE;AASD,mbAAmb;AACnb,wBAAgB,aAAa,CAC3B,YAAY,EAAE,QAAQ,CACpB,IAAI,CAAC,kBAAkB,EAAE,aAAa,GAAG,oBAAoB,CAAC,CAC/D,EACD,SAAS,EAAE,MAAM,GAChB,OAAO,CAKT;AAED,spBAAspB;AACtpB,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,QAAQ,CAAC,sBAAsB,CAAC,GACrC,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CA2FnE"}
|
|
@@ -1,44 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Which gossiped directory entries from the hub a gateway merges (agent-comms#156, widened by #187 and #
|
|
2
|
+
* Which gossiped directory entries from the hub a gateway merges (agent-comms#156, widened by #187, #266 and #343). Split out of WireMeshTransport, which hands it the two collaborators it needs.
|
|
3
3
|
*
|
|
4
|
-
* A membership proof shows that a trusted principal vouches for a device id. It does not show that whoever sent the advert is that device: the id and the proof both arrive in the same unauthenticated advert, and anyone who has read one can repeat it. So it earns only what GatewayTrust.isReachable grants (a directory entry and a route), never isTrusted, and everything a request to such a device carries is authenticated by the end-to-end session inside the relay. Verifying a proof is cryptography, so the work is bounded here: verdicts are remembered, a batch verifies only so many new proofs, and a verifier that throws refuses the entry rather than breaking the merge.
|
|
4
|
+
* A membership proof shows that a trusted principal or machine vouches for a device id. It does not show that whoever sent the advert is that device: the id and the proof both arrive in the same unauthenticated advert, and anyone who has read one can repeat it. So it earns only what GatewayTrust.isReachable grants (a directory entry and a route), never isTrusted, and everything a request to such a device carries is authenticated by the end-to-end session inside the relay. Verifying a proof is cryptography, so the work is bounded here: verdicts are remembered, a batch verifies only so many new proofs, and a verifier that throws refuses the entry rather than breaking the merge.
|
|
5
5
|
*/
|
|
6
6
|
import { deviceIdToHex } from "wire-mesh-core/domain/device-id";
|
|
7
|
-
import { readMembershipProof } from "./gossip-directory.js";
|
|
7
|
+
import { readMembershipProof, } from "./gossip-directory.js";
|
|
8
8
|
/** How many new proofs one batch of entries may verify. Trusted devices and proofs already judged cost nothing against it, so a flood of fresh adverts costs a bounded amount of work per batch and the rest wait for the next. */
|
|
9
9
|
export const MAX_VERIFICATIONS_PER_BATCH = 8;
|
|
10
10
|
const MS_PER_SECOND = 1000;
|
|
11
11
|
const NEGATIVE_VERDICT_TTL_SECONDS = 60;
|
|
12
12
|
/** How long a refused proof is remembered before it is worth checking again: long enough that a repeated bad proof is not re-verified on every frame, short enough that a principal trusted a moment later takes effect promptly. */
|
|
13
13
|
export const NEGATIVE_VERDICT_TTL_MS = NEGATIVE_VERDICT_TTL_SECONDS * MS_PER_SECOND;
|
|
14
|
-
/** The most
|
|
14
|
+
/** The most proofs whose last verdict is remembered. */
|
|
15
15
|
const VERDICT_CACHE_LIMIT = 1024;
|
|
16
|
-
/**
|
|
16
|
+
/** Each advert field that can carry a proof, and the kind of issuer whose trusted set it is checked against. */
|
|
17
|
+
const PROOF_SOURCES = [
|
|
18
|
+
{ field: "membership", kind: "principal" },
|
|
19
|
+
{ field: "machine", kind: "machine" },
|
|
20
|
+
];
|
|
21
|
+
/** Whether an entry this side has already merged from the hub would still be admitted now, with no new proof to judge: its device is reachable (trusted by id, or vouched for by a proof that has not lapsed from an issuer still trusted) or is itself a trusted principal's own device. The read-time counterpart of directoryAdmission, which KnownDevices uses to drop a device as soon as the trust that let it in is withdrawn or lapses. */
|
|
22
|
+
export function staysAdmitted(gatewayTrust, deviceHex) {
|
|
23
|
+
return (gatewayTrust.isReachable(deviceHex) ||
|
|
24
|
+
gatewayTrust.isTrustedPrincipal(deviceHex));
|
|
25
|
+
}
|
|
26
|
+
/** Builds the admission check for a transport's directory merge: given a batch of entries, the ones to merge. An entry is merged if its device is trusted by id, is itself a trusted principal's own device, or carries a proof that a trusted principal or machine vouches for it; each proof an entry carries is judged on its own, and every one that verifies records the device in gatewayTrust under that kind until the proof lapses or its issuer stops being trusted. A remembered good verdict is reused only while that kind's record is still live, and a device's newer proof is verified as it arrives, which is how its trust is renewed before the old one lapses. */
|
|
17
27
|
export function directoryAdmission(deps) {
|
|
18
28
|
const { gatewayTrust, verifyMembership } = deps;
|
|
29
|
+
/** Keyed by kind and device, since a device can carry one proof of each kind. */
|
|
19
30
|
const verdicts = new Map();
|
|
20
|
-
const remember = (
|
|
21
|
-
verdicts.delete(
|
|
22
|
-
verdicts.set(
|
|
31
|
+
const remember = (key, verdict) => {
|
|
32
|
+
verdicts.delete(key);
|
|
33
|
+
verdicts.set(key, verdict);
|
|
23
34
|
if (verdicts.size > VERDICT_CACHE_LIMIT) {
|
|
24
35
|
const oldest = verdicts.keys().next();
|
|
25
36
|
if (oldest.done !== true)
|
|
26
37
|
verdicts.delete(oldest.value);
|
|
27
38
|
}
|
|
28
39
|
};
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
const trustedIssuers = (kind) => kind === "principal"
|
|
41
|
+
? gatewayTrust.listPrincipals()
|
|
42
|
+
: gatewayTrust.listMachines();
|
|
43
|
+
/** The first trusted issuer of the given kind that vouches for the proof, with the proof's expiry, or undefined. An issuer the verifier throws on (a malformed id, or no identity attached yet) is skipped, so one bad issuer never blocks the others. */
|
|
44
|
+
const vouchedFor = async (proof, deviceHex, kind) => {
|
|
31
45
|
if (verifyMembership === undefined)
|
|
32
46
|
return undefined;
|
|
33
|
-
for (const
|
|
47
|
+
for (const issuer of trustedIssuers(kind)) {
|
|
34
48
|
try {
|
|
35
49
|
const verdict = await verifyMembership({
|
|
36
50
|
proof,
|
|
37
51
|
deviceHex,
|
|
38
|
-
|
|
52
|
+
issuerHex: issuer,
|
|
39
53
|
});
|
|
40
54
|
if (verdict.ok)
|
|
41
|
-
return {
|
|
55
|
+
return { issuer, expires: verdict.expires };
|
|
42
56
|
}
|
|
43
57
|
catch {
|
|
44
58
|
continue;
|
|
@@ -56,31 +70,40 @@ export function directoryAdmission(deps) {
|
|
|
56
70
|
admitted.push(entry);
|
|
57
71
|
continue;
|
|
58
72
|
}
|
|
59
|
-
|
|
60
|
-
if (proof === undefined || verifyMembership === undefined)
|
|
73
|
+
if (verifyMembership === undefined)
|
|
61
74
|
continue;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
75
|
+
// Every proof the entry carries is judged, not just the first that passes, so a device vouched for by both a trusted principal and a trusted machine holds a record of each and stays reachable when either issuer is untrusted.
|
|
76
|
+
let vouched = false;
|
|
77
|
+
for (const { field, kind } of PROOF_SOURCES) {
|
|
78
|
+
const proof = readMembershipProof(entry.advert, field);
|
|
79
|
+
if (proof === undefined)
|
|
66
80
|
continue;
|
|
81
|
+
const key = `${kind}:${deviceHex}`;
|
|
82
|
+
const known = verdicts.get(key);
|
|
83
|
+
if (known?.proof === proof) {
|
|
84
|
+
if (known.ok && gatewayTrust.isVouchedBy(deviceHex, kind)) {
|
|
85
|
+
vouched = true;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (!known.ok && known.until > Date.now())
|
|
89
|
+
continue;
|
|
67
90
|
}
|
|
68
|
-
if (
|
|
91
|
+
if (budget === 0)
|
|
69
92
|
continue;
|
|
93
|
+
budget -= 1;
|
|
94
|
+
const vouch = await vouchedFor(proof, deviceHex, kind);
|
|
95
|
+
remember(key, {
|
|
96
|
+
proof,
|
|
97
|
+
ok: vouch !== undefined,
|
|
98
|
+
until: Date.now() + NEGATIVE_VERDICT_TTL_MS,
|
|
99
|
+
});
|
|
100
|
+
if (vouch !== undefined) {
|
|
101
|
+
gatewayTrust.noteVerifiedMember(deviceHex, { kind, issuer: vouch.issuer }, vouch.expires);
|
|
102
|
+
vouched = true;
|
|
103
|
+
}
|
|
70
104
|
}
|
|
71
|
-
if (
|
|
72
|
-
continue;
|
|
73
|
-
budget -= 1;
|
|
74
|
-
const vouch = await vouchedFor(proof, deviceHex);
|
|
75
|
-
remember(deviceHex, {
|
|
76
|
-
proof,
|
|
77
|
-
ok: vouch !== undefined,
|
|
78
|
-
until: Date.now() + NEGATIVE_VERDICT_TTL_MS,
|
|
79
|
-
});
|
|
80
|
-
if (vouch !== undefined) {
|
|
81
|
-
gatewayTrust.noteVerifiedMember(deviceHex, vouch.principal, vouch.expires);
|
|
105
|
+
if (vouched)
|
|
82
106
|
admitted.push(entry);
|
|
83
|
-
}
|
|
84
107
|
}
|
|
85
108
|
return admitted;
|
|
86
109
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory-admission.js","sourceRoot":"","sources":["../../src/core/directory-admission.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAGhE,OAAO,
|
|
1
|
+
{"version":3,"file":"directory-admission.js","sourceRoot":"","sources":["../../src/core/directory-admission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one display convention for anything identified by a device-id (agent-comms#345): your own petname for it first, then the name it asserts for itself, then a short id. Every surface that shows an agent, a machine, a principal or a trusted device formats it here, so the CLI, the tool output and the dashboard read the same; wire-mesh's web console follows the same order (ExaDev/wire-mesh#295).
|
|
3
|
+
*
|
|
4
|
+
* A petname is yours: set locally, never gossiped, so it needs no trust decision and has no collision problem. A self-asserted name is whatever the subject's own key signed (an agent's registered name, a machine's name claim), so it is shown quoted, as the subject's claim rather than a fact. Where the full id is already printed beside the name, formatNames gives the names alone, since the short id would only repeat its start. The short id is the stable reference when neither name exists, and the fallback that tells two same-named subjects apart. It is a prefix of the full id, never a replacement for it: every tool action takes the full id, so a surface whose entries are acted on also prints the full id.
|
|
5
|
+
*
|
|
6
|
+
* Pure and dependency-free, so the browser bundle imports it as it is.
|
|
7
|
+
*/
|
|
8
|
+
/** How many leading hex characters of a device-id the short id keeps: 48 bits, enough that two devices a person deals with never share one by chance, and short enough to read and compare at a glance. */
|
|
9
|
+
export declare const SHORT_ID_LENGTH = 12;
|
|
10
|
+
/** Everything a display name is built from. Both names are optional; the id never is. */
|
|
11
|
+
export interface DisplayNameParts {
|
|
12
|
+
/** The full device-id (hex). */
|
|
13
|
+
id: string;
|
|
14
|
+
/** The viewer's own label for this id, if they set one. */
|
|
15
|
+
petname?: string | undefined;
|
|
16
|
+
/** The name the subject asserts for itself, if it has one. */
|
|
17
|
+
selfName?: string | undefined;
|
|
18
|
+
}
|
|
19
|
+
/** The leading SHORT_ID_LENGTH characters of id. */
|
|
20
|
+
export declare function shortId(id: string): string;
|
|
21
|
+
/** The names in parts, in display order: the petname, then the self-asserted name quoted (left out when it only repeats the petname), separated by a space, or the empty string when neither is set. Each name is checked with parseDisplayName first and left out when it fails, so a name that slipped past every other check (a hand-edited file, a peer that does not validate) still never reaches a terminal; the self-asserted name is quoted as a JSON string, so a quote inside it is escaped and cannot close the quotes early to pass the rest off as a separate, unquoted label. */
|
|
22
|
+
export declare function formatNames(parts: Readonly<DisplayNameParts>): string;
|
|
23
|
+
/** parts in display order: formatNames, then the short id. */
|
|
24
|
+
export declare function formatDisplayName(parts: Readonly<DisplayNameParts>): string;
|
|
25
|
+
/** The longest display name, petname or self-asserted, that is accepted: room for a descriptive label ("Joe's work laptop, office"), short enough that one never swamps a listing row. */
|
|
26
|
+
export declare const MAX_DISPLAY_NAME_LENGTH = 64;
|
|
27
|
+
/** raw trimmed, when it is usable as a display name: not empty, at most MAX_DISPLAY_NAME_LENGTH characters, and free of control characters. Undefined otherwise. Applied to a petname as it is set, to an agent's name as it is registered or received in an advert, to a machine's name claim as it is verified, and once more by formatNames as any name is shown, so none can carry anything a terminal would interpret. */
|
|
28
|
+
export declare function parseDisplayName(raw: string): string | undefined;
|
|
29
|
+
//# sourceMappingURL=display-name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-name.d.ts","sourceRoot":"","sources":["../../src/core/display-name.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2MAA2M;AAC3M,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,yFAAyF;AACzF,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED,oDAAoD;AACpD,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED,gkBAAgkB;AAChkB,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,MAAM,CASrE;AAED,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAI3E;AAMD,0LAA0L;AAC1L,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAW1C,+ZAA+Z;AAC/Z,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUhE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one display convention for anything identified by a device-id (agent-comms#345): your own petname for it first, then the name it asserts for itself, then a short id. Every surface that shows an agent, a machine, a principal or a trusted device formats it here, so the CLI, the tool output and the dashboard read the same; wire-mesh's web console follows the same order (ExaDev/wire-mesh#295).
|
|
3
|
+
*
|
|
4
|
+
* A petname is yours: set locally, never gossiped, so it needs no trust decision and has no collision problem. A self-asserted name is whatever the subject's own key signed (an agent's registered name, a machine's name claim), so it is shown quoted, as the subject's claim rather than a fact. Where the full id is already printed beside the name, formatNames gives the names alone, since the short id would only repeat its start. The short id is the stable reference when neither name exists, and the fallback that tells two same-named subjects apart. It is a prefix of the full id, never a replacement for it: every tool action takes the full id, so a surface whose entries are acted on also prints the full id.
|
|
5
|
+
*
|
|
6
|
+
* Pure and dependency-free, so the browser bundle imports it as it is.
|
|
7
|
+
*/
|
|
8
|
+
/** How many leading hex characters of a device-id the short id keeps: 48 bits, enough that two devices a person deals with never share one by chance, and short enough to read and compare at a glance. */
|
|
9
|
+
export const SHORT_ID_LENGTH = 12;
|
|
10
|
+
/** The leading SHORT_ID_LENGTH characters of id. */
|
|
11
|
+
export function shortId(id) {
|
|
12
|
+
return id.slice(0, SHORT_ID_LENGTH);
|
|
13
|
+
}
|
|
14
|
+
/** The names in parts, in display order: the petname, then the self-asserted name quoted (left out when it only repeats the petname), separated by a space, or the empty string when neither is set. Each name is checked with parseDisplayName first and left out when it fails, so a name that slipped past every other check (a hand-edited file, a peer that does not validate) still never reaches a terminal; the self-asserted name is quoted as a JSON string, so a quote inside it is escaped and cannot close the quotes early to pass the rest off as a separate, unquoted label. */
|
|
15
|
+
export function formatNames(parts) {
|
|
16
|
+
const petname = usableName(parts.petname);
|
|
17
|
+
const selfName = usableName(parts.selfName);
|
|
18
|
+
const labels = [];
|
|
19
|
+
if (petname !== undefined)
|
|
20
|
+
labels.push(petname);
|
|
21
|
+
if (selfName !== undefined && selfName !== petname) {
|
|
22
|
+
labels.push(JSON.stringify(selfName));
|
|
23
|
+
}
|
|
24
|
+
return labels.join(" ");
|
|
25
|
+
}
|
|
26
|
+
/** parts in display order: formatNames, then the short id. */
|
|
27
|
+
export function formatDisplayName(parts) {
|
|
28
|
+
const names = formatNames(parts);
|
|
29
|
+
const id = shortId(parts.id);
|
|
30
|
+
return names === "" ? id : `${names} ${id}`;
|
|
31
|
+
}
|
|
32
|
+
function usableName(raw) {
|
|
33
|
+
return raw === undefined ? undefined : parseDisplayName(raw);
|
|
34
|
+
}
|
|
35
|
+
/** The longest display name, petname or self-asserted, that is accepted: room for a descriptive label ("Joe's work laptop, office"), short enough that one never swamps a listing row. */
|
|
36
|
+
export const MAX_DISPLAY_NAME_LENGTH = 64;
|
|
37
|
+
/** The last C0 control character; everything at or below it, DEL, and the C1 range are refused, since a name is printed straight into terminals and a control sequence in one could rewrite what the viewer sees. */
|
|
38
|
+
const LAST_C0_CONTROL = 0x1f;
|
|
39
|
+
const DEL = 0x7f;
|
|
40
|
+
const LAST_C1_CONTROL = 0x9f;
|
|
41
|
+
function isControlCharacter(code) {
|
|
42
|
+
return code <= LAST_C0_CONTROL || (code >= DEL && code <= LAST_C1_CONTROL);
|
|
43
|
+
}
|
|
44
|
+
/** raw trimmed, when it is usable as a display name: not empty, at most MAX_DISPLAY_NAME_LENGTH characters, and free of control characters. Undefined otherwise. Applied to a petname as it is set, to an agent's name as it is registered or received in an advert, to a machine's name claim as it is verified, and once more by formatNames as any name is shown, so none can carry anything a terminal would interpret. */
|
|
45
|
+
export function parseDisplayName(raw) {
|
|
46
|
+
const name = raw.trim();
|
|
47
|
+
if (name.length === 0 || name.length > MAX_DISPLAY_NAME_LENGTH) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
for (const char of name) {
|
|
51
|
+
const code = char.codePointAt(0);
|
|
52
|
+
if (code !== undefined && isControlCharacter(code))
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
return name;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=display-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-name.js","sourceRoot":"","sources":["../../src/core/display-name.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2MAA2M;AAC3M,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAYlC,oDAAoD;AACpD,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;AACtC,CAAC;AAED,gkBAAgkB;AAChkB,MAAM,UAAU,WAAW,CAAC,KAAiC;IAC3D,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,iBAAiB,CAAC,KAAiC;IACjE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC7B,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,EAAE,EAAE,CAAC;AAC9C,CAAC;AAED,SAAS,UAAU,CAAC,GAAuB;IACzC,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,0LAA0L;AAC1L,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAE1C,qNAAqN;AACrN,MAAM,eAAe,GAAG,IAAI,CAAC;AAC7B,MAAM,GAAG,GAAG,IAAI,CAAC;AACjB,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO,IAAI,IAAI,eAAe,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,eAAe,CAAC,CAAC;AAC7E,CAAC;AAED,+ZAA+Z;AAC/Z,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,uBAAuB,EAAE,CAAC;QAC/D,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,IAAI,KAAK,SAAS,IAAI,kBAAkB,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;IACvE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CommsTool's gateway-trust action handlers (agent-comms#156, extended by agent-comms#187's principal-keyed allowlist and agent-comms#193's tool-level `principal` flag) -- split out of tool.ts purely to keep that file under the repo's max-lines cap, the same reason agent-registry.ts, delivery-engine.ts, and their siblings were split from mesh-store.ts. Free functions over MeshOnlyFeatures's own gateway-trust methods rather than class methods, since CommsTool owns no state of its own for this concern -- every one of these is a pure translation from a CommsAction to a CommsResult against whatever store methods are present.
|
|
3
|
-
*/
|
|
4
1
|
import type { CommsAction } from "./types.js";
|
|
5
2
|
import type { CommsResult, MeshOnlyFeatures } from "./tool.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import { type Namer } from "./naming.js";
|
|
4
|
+
/** The slice of MeshOnlyFeatures the three functions below actually need, named so this file doesn't repeat the same Pick inline at every signature. */
|
|
5
|
+
export type GatewayTrustStore = Pick<MeshOnlyFeatures, "addTrustedGateway" | "removeTrustedGateway" | "listTrustedGateways" | "addTrustedGatewayPrincipal" | "removeTrustedGatewayPrincipal" | "listTrustedGatewayPrincipals" | "addTrustedGatewayMachine" | "removeTrustedGatewayMachine" | "listTrustedGatewayMachines" | "listVerifiedMembers">;
|
|
6
|
+
/** Trusts action.device: as a user principal (GatewayTrust.addPrincipal, agent-comms#187) when action.principal is true, as a machine (GatewayTrust.addMachine, agent-comms#343) when action.machine is true, or as a bare remote device-id (the original agent-comms#156 behaviour) otherwise. */
|
|
9
7
|
export declare function gatewayTrust(store: Readonly<GatewayTrustStore>, action: CommsAction & {
|
|
10
8
|
action: "gateway_trust";
|
|
11
9
|
}): CommsResult;
|
|
12
|
-
/** Withdraws trust from action.device: from the principal allowlist (GatewayTrust.removePrincipal, agent-comms#187) when action.principal is true, or from the bare-device allowlist (the original agent-comms#156 behaviour) otherwise. */
|
|
10
|
+
/** Withdraws trust from action.device: from the principal allowlist (GatewayTrust.removePrincipal, agent-comms#187) when action.principal is true, from the machine allowlist (GatewayTrust.removeMachine, agent-comms#343, revoking every device it vouches for at once) when action.machine is true, or from the bare-device allowlist (the original agent-comms#156 behaviour) otherwise. */
|
|
13
11
|
export declare function gatewayUntrust(store: Readonly<GatewayTrustStore>, action: CommsAction & {
|
|
14
12
|
action: "gateway_untrust";
|
|
15
13
|
}): CommsResult;
|
|
16
|
-
/** Reports every currently trusted remote device-id
|
|
17
|
-
export declare function gatewayListTrusted(store: Readonly<GatewayTrustStore
|
|
14
|
+
/** Reports every currently trusted remote device-id, principal (agent-comms#187) and machine (agent-comms#343) together, and the devices reachable through a trusted principal or machine. Listing is never mutually exclusive between the sets, so, unlike gatewayTrust/gatewayUntrust above, this needs no flag of its own. Each entry shows the full id, which gateway_untrust takes, then the display name namer gives it (agent-comms#345). */
|
|
15
|
+
export declare function gatewayListTrusted(store: Readonly<GatewayTrustStore>, namer: Namer): CommsResult;
|
|
18
16
|
//# sourceMappingURL=gateway-trust-actions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-trust-actions.d.ts","sourceRoot":"","sources":["../../src/core/gateway-trust-actions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gateway-trust-actions.d.ts","sourceRoot":"","sources":["../../src/core/gateway-trust-actions.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEtD,wJAAwJ;AACxJ,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,gBAAgB,EACd,mBAAmB,GACnB,sBAAsB,GACtB,qBAAqB,GACrB,4BAA4B,GAC5B,+BAA+B,GAC/B,8BAA8B,GAC9B,0BAA0B,GAC1B,6BAA6B,GAC7B,4BAA4B,GAC5B,qBAAqB,CACxB,CAAC;AA0BF,mSAAmS;AACnS,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,EAClC,MAAM,EAAE,WAAW,GAAG;IAAE,MAAM,EAAE,eAAe,CAAA;CAAE,GAChD,WAAW,CA6Bb;AAED,gYAAgY;AAChY,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,EAClC,MAAM,EAAE,WAAW,GAAG;IAAE,MAAM,EAAE,iBAAiB,CAAA;CAAE,GAClD,WAAW,CAgCb;AAgBD,obAAob;AACpb,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,EAClC,KAAK,EAAE,KAAK,GACX,WAAW,CA6Cb"}
|
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CommsTool's gateway-trust action handlers (agent-comms#156, extended by agent-comms#187's principal-keyed allowlist, agent-comms#193's tool-level `principal` flag and agent-comms#343's `machine` flag), split out of tool.ts to keep that file under the repo's max-lines cap, the same reason agent-registry.ts, delivery-engine.ts, and their siblings were split from mesh-store.ts. Free functions over MeshOnlyFeatures's own gateway-trust methods rather than class methods, since CommsTool owns no state of its own for this concern: every one of these is a pure translation from a CommsAction to a CommsResult against whatever store methods are present.
|
|
3
|
+
*/
|
|
4
|
+
import { isDeviceIdHex } from "./room-path.js";
|
|
5
|
+
import { idWithNames } from "./naming.js";
|
|
6
|
+
/** The result for an id named as both a principal and a machine: the two are different kinds of issuer, so one id is at most one of them. */
|
|
7
|
+
function principalOrMachine() {
|
|
8
|
+
return {
|
|
9
|
+
content: "Pass principal or machine, not both.",
|
|
10
|
+
isError: true,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** The result for an id that is not a full device-id. Trusting one would persist an entry that matches no real device, principal or machine, yet still count towards hasAny and so start this side advertising on the hub. */
|
|
14
|
+
function notADeviceId(device) {
|
|
15
|
+
return {
|
|
16
|
+
content: `${JSON.stringify(device)} is not a device-id: pass the full 64-character hex id (whoami prints this side's).`,
|
|
17
|
+
isError: true,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
1
20
|
/** Uniform "gateway trust isn't available on this store" result, mirroring tool.ts's own notMeshBacked helper for the other MeshOnlyFeatures methods. */
|
|
2
21
|
function gatewayTrustUnavailable() {
|
|
3
22
|
return {
|
|
@@ -5,8 +24,23 @@ function gatewayTrustUnavailable() {
|
|
|
5
24
|
isError: true,
|
|
6
25
|
};
|
|
7
26
|
}
|
|
8
|
-
/** Trusts action.device: as a user principal (GatewayTrust.addPrincipal, agent-comms#187) when action.principal is true, or as a bare remote device-id (the original agent-comms#156 behaviour) otherwise. */
|
|
27
|
+
/** Trusts action.device: as a user principal (GatewayTrust.addPrincipal, agent-comms#187) when action.principal is true, as a machine (GatewayTrust.addMachine, agent-comms#343) when action.machine is true, or as a bare remote device-id (the original agent-comms#156 behaviour) otherwise. */
|
|
9
28
|
export function gatewayTrust(store, action) {
|
|
29
|
+
if (action.principal === true && action.machine === true) {
|
|
30
|
+
return principalOrMachine();
|
|
31
|
+
}
|
|
32
|
+
if (!isDeviceIdHex(action.device.toLowerCase())) {
|
|
33
|
+
return notADeviceId(action.device);
|
|
34
|
+
}
|
|
35
|
+
if (action.machine === true) {
|
|
36
|
+
if (!store.addTrustedGatewayMachine)
|
|
37
|
+
return gatewayTrustUnavailable();
|
|
38
|
+
store.addTrustedGatewayMachine(action.device);
|
|
39
|
+
return {
|
|
40
|
+
content: `Trusted remote machine ${action.device}: every device it vouches for is now reachable.`,
|
|
41
|
+
isError: false,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
10
44
|
if (action.principal === true) {
|
|
11
45
|
if (!store.addTrustedGatewayPrincipal)
|
|
12
46
|
return gatewayTrustUnavailable();
|
|
@@ -24,8 +58,24 @@ export function gatewayTrust(store, action) {
|
|
|
24
58
|
isError: false,
|
|
25
59
|
};
|
|
26
60
|
}
|
|
27
|
-
/** Withdraws trust from action.device: from the principal allowlist (GatewayTrust.removePrincipal, agent-comms#187) when action.principal is true, or from the bare-device allowlist (the original agent-comms#156 behaviour) otherwise. */
|
|
61
|
+
/** Withdraws trust from action.device: from the principal allowlist (GatewayTrust.removePrincipal, agent-comms#187) when action.principal is true, from the machine allowlist (GatewayTrust.removeMachine, agent-comms#343, revoking every device it vouches for at once) when action.machine is true, or from the bare-device allowlist (the original agent-comms#156 behaviour) otherwise. */
|
|
28
62
|
export function gatewayUntrust(store, action) {
|
|
63
|
+
if (action.principal === true && action.machine === true) {
|
|
64
|
+
return principalOrMachine();
|
|
65
|
+
}
|
|
66
|
+
if (!isDeviceIdHex(action.device.toLowerCase()) &&
|
|
67
|
+
!listedForUntrust(store, action)) {
|
|
68
|
+
return notADeviceId(action.device);
|
|
69
|
+
}
|
|
70
|
+
if (action.machine === true) {
|
|
71
|
+
if (!store.removeTrustedGatewayMachine)
|
|
72
|
+
return gatewayTrustUnavailable();
|
|
73
|
+
store.removeTrustedGatewayMachine(action.device);
|
|
74
|
+
return {
|
|
75
|
+
content: `Untrusted remote machine ${action.device}: no device is reachable through it any more.`,
|
|
76
|
+
isError: false,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
29
79
|
if (action.principal === true) {
|
|
30
80
|
if (!store.removeTrustedGatewayPrincipal)
|
|
31
81
|
return gatewayTrustUnavailable();
|
|
@@ -43,29 +93,45 @@ export function gatewayUntrust(store, action) {
|
|
|
43
93
|
isError: false,
|
|
44
94
|
};
|
|
45
95
|
}
|
|
46
|
-
/**
|
|
47
|
-
|
|
96
|
+
/** Whether action.device is already in the set gateway_untrust would remove it from, so an entry an earlier version persisted without checking its shape can still be withdrawn through the tool. */
|
|
97
|
+
function listedForUntrust(store, action) {
|
|
98
|
+
const listed = action.machine === true
|
|
99
|
+
? store.listTrustedGatewayMachines?.()
|
|
100
|
+
: action.principal === true
|
|
101
|
+
? store.listTrustedGatewayPrincipals?.()
|
|
102
|
+
: store.listTrustedGateways?.();
|
|
103
|
+
return listed?.includes(action.device.toLowerCase()) === true;
|
|
104
|
+
}
|
|
105
|
+
/** Reports every currently trusted remote device-id, principal (agent-comms#187) and machine (agent-comms#343) together, and the devices reachable through a trusted principal or machine. Listing is never mutually exclusive between the sets, so, unlike gatewayTrust/gatewayUntrust above, this needs no flag of its own. Each entry shows the full id, which gateway_untrust takes, then the display name namer gives it (agent-comms#345). */
|
|
106
|
+
export function gatewayListTrusted(store, namer) {
|
|
48
107
|
if (!store.listTrustedGateways)
|
|
49
108
|
return gatewayTrustUnavailable();
|
|
50
109
|
const devices = store.listTrustedGateways();
|
|
51
110
|
const principals = store.listTrustedGatewayPrincipals?.() ?? [];
|
|
111
|
+
const machines = store.listTrustedGatewayMachines?.() ?? [];
|
|
52
112
|
const members = store.listVerifiedMembers?.() ?? [];
|
|
53
|
-
|
|
113
|
+
const sections = [];
|
|
114
|
+
const section = (title, lines) => {
|
|
115
|
+
if (lines.length > 0) {
|
|
116
|
+
sections.push(`${title}:\n${lines.map((line) => ` ${line}`).join("\n")}`);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const entry = (id) => idWithNames(id, namer);
|
|
120
|
+
section("Trusted remote gateway devices", devices.map(entry));
|
|
121
|
+
section("Trusted remote gateway principals", principals.map(entry));
|
|
122
|
+
section("Trusted remote machines", machines.map(entry));
|
|
123
|
+
section("Devices trusted through a principal", members
|
|
124
|
+
.filter((member) => member.kind === "principal")
|
|
125
|
+
.map((member) => `${entry(member.device)} (vouched for by ${namer(member.issuer)})`));
|
|
126
|
+
section("Devices trusted through a machine", members
|
|
127
|
+
.filter((member) => member.kind === "machine")
|
|
128
|
+
.map((member) => `${entry(member.device)} (runs on ${namer(member.issuer)})`));
|
|
129
|
+
if (sections.length === 0) {
|
|
54
130
|
return {
|
|
55
|
-
content: "No remote gateway devices or
|
|
131
|
+
content: "No remote gateway devices, principals or machines are trusted.",
|
|
56
132
|
isError: false,
|
|
57
133
|
};
|
|
58
134
|
}
|
|
59
|
-
const sections = [];
|
|
60
|
-
if (devices.length > 0) {
|
|
61
|
-
sections.push(`Trusted remote gateway devices:\n${devices.map((device) => ` ${device}`).join("\n")}`);
|
|
62
|
-
}
|
|
63
|
-
if (principals.length > 0) {
|
|
64
|
-
sections.push(`Trusted remote gateway principals:\n${principals.map((principal) => ` ${principal}`).join("\n")}`);
|
|
65
|
-
}
|
|
66
|
-
if (members.length > 0) {
|
|
67
|
-
sections.push(`Devices trusted through a principal:\n${members.map((member) => ` ${member.device} (vouched for by ${member.principal})`).join("\n")}`);
|
|
68
|
-
}
|
|
69
135
|
return {
|
|
70
136
|
content: sections.join("\n"),
|
|
71
137
|
isError: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-trust-actions.js","sourceRoot":"","sources":["../../src/core/gateway-trust-actions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gateway-trust-actions.js","sourceRoot":"","sources":["../../src/core/gateway-trust-actions.ts"],"names":[],"mappings":"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"}
|