@uuaid/pillar 0.2.0-alpha.12 → 0.2.0-alpha.13

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.
@@ -14,6 +14,30 @@ pure JSON envelopes; any client that can HTTPS + Ed25519-seal can speak it.
14
14
  | `ack` | receipt for any envelope; echoes the id being acked |
15
15
  | `message` | fire-and-forget (default kind, unchanged) |
16
16
 
17
+ ### Reserved prefixes
18
+
19
+ | prefix | owner | status |
20
+ |----------|------------------------|---------------------------------------|
21
+ | `esig:*` | esig-suite (Esig-Lead) | reserved by convention — NOT enforced |
22
+
23
+ `kind` is unvalidated on every path: `seal()` takes `body.kind ?? "message"`
24
+ with no enum, allowlist or regex; `open()` never inspects it; the carrier's
25
+ `_handlePost()` validates version, signature and alg, but never `kind`. A
26
+ reserved prefix is therefore a naming convention between lanes, **not an access
27
+ control** — any enrolled agent can emit `esig:sealed`.
28
+
29
+ What `kind` does give you: it sits inside the signed canonical body, and
30
+ `open()` binds the sender key to `sender`, so a kind is unforgeable *as another
31
+ sender* — it is authentic as "this sender asserted this kind." What it does not
32
+ give you: any authorization value. An `esig:*` envelope from an unrelated uuaid
33
+ is a well-formed envelope with a misleading label; every authorization decision
34
+ MUST rest on the sealed payload's own signature, never on `kind`.
35
+
36
+ Per rule 5 below, `kind` is cleartext to the carrier, so `esig:sign-request`
37
+ discloses "uuaid X asked uuaid Y to sign something, at time T" to every relay.
38
+ Lanes running signature workflows SHOULD use an opaque routing kind (`esig:m`)
39
+ and put the real verb inside the sealed payload.
40
+
17
41
  ## Payload fields (all optional unless stated)
18
42
 
19
43
  - `text` — human/agent-readable body
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uuaid/pillar",
3
- "version": "0.2.0-alpha.12",
3
+ "version": "0.2.0-alpha.13",
4
4
  "description": "Pillar (Protocol for Inter-agent Linked Ledger And Relay) — the secure delivery layer of UACP, the Universal Agent Communication Protocol. UACP = UUAID (identity) + Envelope (signed, encrypted container) + Pillar (relay, mailbox, routing, store-and-forward). IAASO-3050 reference implementation: one command to mint an identity and join the network.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -15,6 +15,22 @@ import { randomBytes, createHash, generateKeyPairSync, sign, verify, createPubli
15
15
 
16
16
  const KEYCHAIN_VERSION = 1;
17
17
 
18
+ /**
19
+ * Derive a stable, publishable local id from a raw Ed25519 public key. This
20
+ * makes the UUAID self-authenticating: given the UUAID, anyone can
21
+ * independently check that the public key hashes to the expected local-id.
22
+ *
23
+ * Public because consumers verifying a UUAID against a public key need it
24
+ * without reaching into `Keychain._localIdFromKey`.
25
+ */
26
+ export function localIdFromKey(rawPub) {
27
+ const h = createHash("sha256").update(rawPub).digest();
28
+ // First 16 bytes -> UUID-style dash format for readability.
29
+ const b = h.slice(0, 16);
30
+ const hex = Buffer.from(b).toString("hex");
31
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
32
+ }
33
+
18
34
  export class Keychain {
19
35
  constructor(path) {
20
36
  this.path = path;
@@ -48,16 +64,17 @@ export class Keychain {
48
64
  };
49
65
  }
50
66
 
51
- static _localIdFromKey(rawPub) {
52
- // Derive a stable, publishable local id from the public key. This makes
53
- // the UUAID self-authenticating: given the UUAID, anyone can independently
54
- // check that the public key hashes to the expected local-id.
55
- const h = createHash("sha256").update(rawPub).digest();
56
- // First 16 bytes -> UUID-style dash format for readability.
57
- const b = h.slice(0, 16);
58
- const hex = Buffer.from(b).toString("hex");
59
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
60
- }
67
+ /**
68
+ * Derive the local-id from a raw Ed25519 public key.
69
+ *
70
+ * Kept on the class for the call sites that already reach for it; the
71
+ * implementation is the module-level `localIdFromKey`, which is the public
72
+ * export.
73
+ */
74
+ static localIdFromKey = localIdFromKey;
75
+
76
+ /** @deprecated Alias kept for compatibility — use `localIdFromKey`. */
77
+ static _localIdFromKey = localIdFromKey;
61
78
 
62
79
  /**
63
80
  * Load an identity from disk.
package/src/index.mjs CHANGED
@@ -7,7 +7,7 @@
7
7
  * Entry point. Not intended for import in browsers today — browser build
8
8
  * lives at @uuaid/pillar-browser (later).
9
9
  */
10
- export { Keychain } from "./identity/keychain.mjs";
10
+ export { Keychain, localIdFromKey } from "./identity/keychain.mjs";
11
11
  export { jcs } from "./identity/jcs.mjs";
12
12
  export { seal, open, decrypt, envelopeSha, keychainSeed, ENVELOPE_VERSION, E2E_ALG } from "./net/envelope.mjs";
13
13
  export { sealPayload, openPayload, edPubToX25519, edSeedToX25519 } from "./crypto/e2e.mjs";