agent-comms 2.21.3 → 2.21.4
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/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/ExaDev/agent-comms)
|
|
4
4
|
[](https://www.npmjs.com/package/agent-comms)
|
|
5
|
-
[](https://github.com/ExaDev/agent-comms/releases/tag/v2.21.4)
|
|
6
6
|
[](https://github.com/ExaDev/agent-comms/actions)
|
|
7
7
|
|
|
8
8
|
Cross-harness communication mesh for LLM agents: rooms, DMs, presence, and visibility over TCP with zero filesystem dependencies.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unit tests for identity.ts — cryptographic identity generation.
|
|
3
3
|
*/
|
|
4
|
-
import { describe, it, expect } from "vitest";
|
|
5
|
-
import { X509Certificate } from "node:crypto";
|
|
6
|
-
import { generateIdentity, getCertificateFingerprint } from "../identity.js";
|
|
4
|
+
import { describe, it, expect, afterEach, vi } from "vitest";
|
|
5
|
+
import { X509Certificate, generateKeyPairSync } from "node:crypto";
|
|
6
|
+
import { generateIdentity, getCertificateFingerprint, CERTIFICATE_VALIDITY_MS, rawPublicKeyFromPrivateKey, } from "../identity.js";
|
|
7
7
|
describe("generateIdentity", () => {
|
|
8
8
|
it("returns a valid PeerIdentity with all required fields", () => {
|
|
9
9
|
const identity = generateIdentity();
|
|
@@ -21,6 +21,19 @@ describe("generateIdentity", () => {
|
|
|
21
21
|
expect(certificate, "certificate should start with PEM header").toMatch(/^-----BEGIN CERTIFICATE-----/);
|
|
22
22
|
expect(certificate, "certificate should end with PEM footer").toMatch(/-----END CERTIFICATE-----\n?$/);
|
|
23
23
|
});
|
|
24
|
+
it("wraps the certificate's base64 body at 64 characters per line", () => {
|
|
25
|
+
const { certificate } = generateIdentity();
|
|
26
|
+
const bodyLines = certificate
|
|
27
|
+
.split("\n")
|
|
28
|
+
.filter((line) => line.length > 0 &&
|
|
29
|
+
line !== "-----BEGIN CERTIFICATE-----" &&
|
|
30
|
+
line !== "-----END CERTIFICATE-----");
|
|
31
|
+
expect(bodyLines.length).toBeGreaterThan(1);
|
|
32
|
+
for (const line of bodyLines.slice(0, -1)) {
|
|
33
|
+
expect(line.length).toBe(64);
|
|
34
|
+
}
|
|
35
|
+
expect(bodyLines.at(-1)?.length).toBeLessThanOrEqual(64);
|
|
36
|
+
});
|
|
24
37
|
it("produces a fingerprint that is a 95-character SHA-256 hex string with colons", () => {
|
|
25
38
|
const { fingerprint } = generateIdentity();
|
|
26
39
|
// SHA-256 = 32 bytes = 64 hex chars + 31 colons = 95 chars
|
|
@@ -52,6 +65,59 @@ describe("generateIdentity", () => {
|
|
|
52
65
|
expect(a.privateKey).not.toBe(b.privateKey);
|
|
53
66
|
expect(a.certificate).not.toBe(b.certificate);
|
|
54
67
|
});
|
|
68
|
+
it("encodes the certificate as X.509 v3 (context tag [0] EXPLICIT INTEGER 2)", () => {
|
|
69
|
+
// v3 is required for the Subject Alternative Name / Basic Constraints extensions to be legal at all -- a v1 certificate carrying extensions is malformed, so the version tag is load-bearing even though nothing else in this file reads it back.
|
|
70
|
+
const { certificate } = generateIdentity();
|
|
71
|
+
const x509 = new X509Certificate(certificate);
|
|
72
|
+
const versionField = Buffer.from([0xa0, 0x03, 0x02, 0x01, 0x02]);
|
|
73
|
+
expect(x509.raw.indexOf(versionField)).toBeGreaterThanOrEqual(0);
|
|
74
|
+
});
|
|
75
|
+
it("marks the Basic Constraints extension critical (DER BOOLEAN TRUE)", () => {
|
|
76
|
+
// RFC 5280 requires Basic Constraints to be marked critical; a non-critical CA:FALSE constraint is a spec violation that some strict X.509 validators reject outright, even though tls.createServer tolerates it.
|
|
77
|
+
const { certificate } = generateIdentity();
|
|
78
|
+
const x509 = new X509Certificate(certificate);
|
|
79
|
+
const criticalTrue = Buffer.from([0x01, 0x01, 0xff]);
|
|
80
|
+
expect(x509.raw.indexOf(criticalTrue)).toBeGreaterThanOrEqual(0);
|
|
81
|
+
});
|
|
82
|
+
it("does not systematically force the serial number's leading byte to a fixed value", () => {
|
|
83
|
+
const firstBytes = new Set();
|
|
84
|
+
for (let i = 0; i < 20; i++) {
|
|
85
|
+
const { certificate } = generateIdentity();
|
|
86
|
+
const x509 = new X509Certificate(certificate);
|
|
87
|
+
firstBytes.add(x509.serialNumber.slice(0, 2));
|
|
88
|
+
}
|
|
89
|
+
expect(firstBytes.size, "serial numbers should vary across identities, not collapse onto one leading byte").toBeGreaterThan(1);
|
|
90
|
+
});
|
|
91
|
+
describe("certificate validity window", () => {
|
|
92
|
+
afterEach(() => {
|
|
93
|
+
vi.useRealTimers();
|
|
94
|
+
});
|
|
95
|
+
it("encodes notBefore/notAfter as exact zero-padded UTCTime, CERTIFICATE_VALIDITY_MS apart", () => {
|
|
96
|
+
// 2005-03-05T07:08:09Z: every date component below 10 (year%100, month, day, minute) so a missing zero-pad or an off-by-one in month arithmetic shifts the parsed date.
|
|
97
|
+
const fixedNow = new Date(Date.UTC(2005, 2, 5, 7, 8, 9));
|
|
98
|
+
vi.useFakeTimers();
|
|
99
|
+
vi.setSystemTime(fixedNow);
|
|
100
|
+
const { certificate } = generateIdentity();
|
|
101
|
+
const x509 = new X509Certificate(certificate);
|
|
102
|
+
expect(x509.validFromDate.toISOString()).toBe(fixedNow.toISOString());
|
|
103
|
+
expect(x509.validToDate.getTime() - x509.validFromDate.getTime()).toBe(CERTIFICATE_VALIDITY_MS);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe("CERTIFICATE_VALIDITY_MS", () => {
|
|
108
|
+
it("is exactly 365 days in milliseconds", () => {
|
|
109
|
+
expect(CERTIFICATE_VALIDITY_MS).toBe(365 * 24 * 60 * 60 * 1000);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
describe("rawPublicKeyFromPrivateKey", () => {
|
|
113
|
+
it("throws for a private key whose JWK export has no EC x/y coordinates", () => {
|
|
114
|
+
const { privateKey } = generateKeyPairSync("rsa", {
|
|
115
|
+
modulusLength: 2048,
|
|
116
|
+
privateKeyEncoding: { type: "pkcs8", format: "pem" },
|
|
117
|
+
publicKeyEncoding: { type: "spki", format: "pem" },
|
|
118
|
+
});
|
|
119
|
+
expect(() => rawPublicKeyFromPrivateKey(privateKey)).toThrow("expected an EC JWK with x/y coordinates");
|
|
120
|
+
});
|
|
55
121
|
});
|
|
56
122
|
describe("getCertificateFingerprint", () => {
|
|
57
123
|
it("is deterministic — same cert always produces same fingerprint", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.unit.test.js","sourceRoot":"","sources":["../../../src/core/test/identity.unit.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"identity.unit.test.js","sourceRoot":"","sources":["../../../src/core/test/identity.unit.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED