@adapt-toolkit/a2adapt 0.11.3 → 0.11.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.
@@ -3,7 +3,7 @@
3
3
  "name": "a2adapt",
4
4
  "displayName": "a2adapt",
5
5
  "description": "Secure agent-to-agent communication channel over ADAPT: self-sovereign pubkey identity, end-to-end encryption, plan-first execution.",
6
- "version": "0.11.3",
6
+ "version": "0.11.4",
7
7
  "author": {
8
8
  "name": "Adapt Toolkit"
9
9
  },
package/dist/index.js CHANGED
@@ -22512,7 +22512,7 @@ function writeIdentityFile(target, opts, overwrite = false) {
22512
22512
  }
22513
22513
 
22514
22514
  // src/index.ts
22515
- var VERSION = true ? "0.11.3" : "0.0.0-dev";
22515
+ var VERSION = true ? "0.11.4" : "0.0.0-dev";
22516
22516
  var CONFIG = loadConfig();
22517
22517
  var STATE_DIR = CONFIG.stateDir;
22518
22518
  var BROKER_URL = CONFIG.brokerUrl;
@@ -22962,7 +22962,7 @@ async function provisionIdentity(name, opts = { exposeLocal: true, localAutoAcce
22962
22962
  const seed = randomBytes(24).toString("hex");
22963
22963
  fs2.writeFileSync(seedPath(dir), seed, { mode: 384 });
22964
22964
  const id = await createPacket(name, seed, dir);
22965
- await mutatingTx(id, "::actor::set_my_name", { name });
22965
+ await mutatingTx(id, "::a2a_messaging::set_my_name", { name });
22966
22966
  await pinRegistrar(id);
22967
22967
  if (!opts.localAutoAccept) {
22968
22968
  await mutatingTx(id, "::actor::set_local_policy", { auto_accept: false });
@@ -23174,7 +23174,7 @@ function createMcpServer(getSessionId) {
23174
23174
  if (identities.has(name)) return textResult(`create_identity failed: an identity named "${name}" already exists.`, true);
23175
23175
  try {
23176
23176
  const id = await provisionIdentity(name, { exposeLocal: expose_local, localAutoAccept: local_auto_accept });
23177
- if (bio) await mutatingTx(id, "::actor::set_my_bio", { bio });
23177
+ if (bio) await mutatingTx(id, "::a2a_messaging::set_my_bio", { bio });
23178
23178
  let hierarchy = "";
23179
23179
  const root = rootName ? identities.get(rootName) : void 0;
23180
23180
  if (root) {
@@ -23216,7 +23216,7 @@ Ask the user: do you want to arm a message monitor for "${name}"? If yes, use: M
23216
23216
  }
23217
23217
  try {
23218
23218
  const id = await provisionIdentity(name, { exposeLocal: expose_local, localAutoAccept: local_auto_accept });
23219
- if (bio) await mutatingTx(id, "::actor::set_my_bio", { bio });
23219
+ if (bio) await mutatingTx(id, "::a2a_messaging::set_my_bio", { bio });
23220
23220
  rootName = name;
23221
23221
  writeRootMarker(name);
23222
23222
  const adopted = [];
@@ -23444,7 +23444,7 @@ ${inbox.map((m) => fmtMsg(m)).join("\n")}`;
23444
23444
  try {
23445
23445
  const targ = {};
23446
23446
  if (name) targ.name = name;
23447
- const data = await mutatingTx(id, "::actor::generate_invite", targ);
23447
+ const data = await mutatingTx(id, "::a2a_messaging::generate_invite", targ);
23448
23448
  const blob = packInvite(Buffer.from(data.Reduce("invite").GetBinary()));
23449
23449
  const heading = name ? `Invite for "${name}" created.` : "Invite created \u2014 the contact will be registered under the name the recipient announces when accepting.";
23450
23450
  return textResult(
@@ -23478,7 +23478,7 @@ ${blob}`
23478
23478
  const blobValue = id.pw.packet.NewBinaryFromBuffer(buf);
23479
23479
  const targ = { invite: blobValue };
23480
23480
  if (name) targ.name = name;
23481
- const data = await mutatingTx(id, "::actor::add_contact", targ);
23481
+ const data = await mutatingTx(id, "::a2a_messaging::add_contact", targ);
23482
23482
  const added = data.Reduce("added").Visualize();
23483
23483
  const cid = data.Reduce("container_id").Visualize();
23484
23484
  const roleId = data.Reduce("role_id").Visualize();
@@ -23499,9 +23499,9 @@ ${blob}`
23499
23499
  const { id, err } = boundOr();
23500
23500
  if (err) return err;
23501
23501
  try {
23502
- const contacts = renderContacts(readonlyTx(id, "::actor::list_contacts"));
23502
+ const contacts = renderContacts(readonlyTx(id, "::a2a_messaging::list_contacts"));
23503
23503
  const pending = renderPending(readonlyTx(id, "::actor::list_pending_introductions"));
23504
- const roots = renderContactRoots(readonlyTx(id, "::actor::list_contact_roots"));
23504
+ const roots = renderContactRoots(readonlyTx(id, "::a2a_messaging::list_contact_roots"));
23505
23505
  const lines = [];
23506
23506
  lines.push(
23507
23507
  contacts.length === 0 ? "No contacts yet." : `Contacts (${contacts.length}):
@@ -23576,7 +23576,7 @@ ${lines.join("\n")}`);
23576
23576
  const { id, err } = boundOr();
23577
23577
  if (err) return err;
23578
23578
  try {
23579
- await mutatingTx(id, "::actor::set_my_bio", { bio });
23579
+ await mutatingTx(id, "::a2a_messaging::set_my_bio", { bio });
23580
23580
  let refreshed = 0;
23581
23581
  if (id.name === rootName) {
23582
23582
  for (const other of identities.values()) {
@@ -23638,7 +23638,7 @@ ${lines.join("\n")}`);
23638
23638
  const { id, err } = boundOr();
23639
23639
  if (err) return err;
23640
23640
  try {
23641
- await mutatingTx(id, "::actor::send_message", { contact, text });
23641
+ await mutatingTx(id, "::a2a_messaging::send_message", { contact, text });
23642
23642
  return textResult(`Message sent to "${contact}".`);
23643
23643
  } catch (e) {
23644
23644
  if (!/Unknown contact/.test(String(e))) {
@@ -23662,7 +23662,7 @@ ${lines.join("\n")}`);
23662
23662
  const { id, err } = boundOr();
23663
23663
  if (err) return err;
23664
23664
  try {
23665
- const data = await mutatingTx(id, "::actor::remove_contact", { contact });
23665
+ const data = await mutatingTx(id, "::a2a_messaging::remove_contact", { contact });
23666
23666
  const name = data.Reduce("removed").Visualize();
23667
23667
  const cid = data.Reduce("container_id").Visualize();
23668
23668
  return textResult(`Removed contact "${name}" (${cid}).`);
@@ -5,20 +5,39 @@
5
5
  // encrypted; the key exchange is handled for us by the stdlib `encrypted_channel`
6
6
  // library — we only ever address peers by their container id.
7
7
  //
8
- // The wire-facing shapes and shared verification logic live in the shared
9
- // a2adapt-mufl-core repo (checked out as the core/ subfolder of this
10
- // directory): libraries `a2a_protocol` and `version`. They are shared with
8
+ // The shared transaction logic lives in the a2adapt-mufl-core repo (checked
9
+ // out as the core/ subfolder of this directory): `a2a_protocol` (wire shapes +
10
+ // verification), `a2a_messaging` (contact + message wire path, addressed
11
+ // ::a2a_messaging::<name> by the host), and `version`. They are shared with
11
12
  // the web messenger — change them there, bump core_version, and recompile
12
13
  // every consumer.
13
14
  //
15
+ // This packet keeps only what is agent-specific:
16
+ // - the inbox message store with its lifecycle (unread -> processed ->
17
+ // ready_to_delete -> deleted; see get_messages / gc / defer_messages)
18
+ // - the local contact book + identity hierarchy transactions (host-fired)
19
+ // - export_state / import_state wrappers composing the core helpers with
20
+ // the app-side fields (including the legacy-blob migrations)
21
+ // - ::actor:: compat shims for the network-visible inbound transactions
22
+ // (accept_contact, receive_message) — pre-migration peers send to these
23
+ // names, and the core keeps SENDING to them too (Option A: zero network
24
+ // break; drop both only when no old clients remain)
25
+ //
26
+ // Storage is wired into the core via a2a_messaging::init hooks (see the
27
+ // hidden block): on_message_received deposits into the inbox (or the
28
+ // pending-introduction queue for unknown senders); send/remove hooks are
29
+ // agent no-ops.
30
+ //
14
31
  // User transactions (each backs one MCP tool, except gc which the host fires):
15
- // set_my_name — set the display name peers see for me
16
- // set_my_bio — set my profile bio (free-text, self-asserted)
17
- // generate_invite — make a slim personal invite blob for a named peer
18
- // add_contact — join via an invite blob, reply to the inviter
19
- // send_message — send an e2e-encrypted message to a contact
20
- // remove_contact — forget a contact (drops it from my contacts)
21
- // list_contacts — (readonly) my contacts
32
+ // ::a2a_messaging::set_my_name — set the display name peers see for me
33
+ // ::a2a_messaging::set_my_bio — set my profile bio (free-text, self-asserted)
34
+ // ::a2a_messaging::generate_invite — make an invite blob for a named peer
35
+ // ::a2a_messaging::add_contact — join via an invite blob, reply to the inviter
36
+ // ::a2a_messaging::send_message — send an e2e-encrypted message to a contact
37
+ // ::a2a_messaging::remove_contact — forget a contact
38
+ // ::a2a_messaging::list_contacts — (readonly) my contacts
39
+ // ::a2a_messaging::list_contact_roots — (readonly) verified root linkage per contact
40
+ // ::a2a_messaging::get_version — (readonly) shared-core version
22
41
  // list_incoming_messages — (readonly) my inbox, with per-message id + status
23
42
  // get_messages — return unread messages + mark them processed (sole body egress)
24
43
  // defer_messages — flip processed/ready_to_delete messages back to unread
@@ -29,7 +48,6 @@
29
48
  // export_root_profile — root-only in practice: my self-signed root profile blob
30
49
  // set_delegation — role: store my verified delegation cert + root material
31
50
  // describe_identity — (readonly) name/bio/hierarchy position
32
- // list_contact_roots — (readonly) verified root linkage per contact
33
51
  // connect_sibling — register an intra-root peer + send sibling_introduce
34
52
  //
35
53
  // Local contact book (host-fired transactions; see the design notes above
@@ -45,17 +63,10 @@
45
63
  // list_pending_introductions — (readonly) pending introductions (names + queue sizes)
46
64
  //
47
65
  // External transactions (inbound, not exposed as tools):
48
- // accept_contact — inviter learns the joiner's identity + name
49
- // receive_message — store a decrypted inbound message
66
+ // accept_contact — inviter learns the joiner's identity + name (core shim)
67
+ // receive_message — store a decrypted inbound message (core shim)
50
68
  // local_introduce — same-host peer connects via the local contact book
51
69
  // sibling_introduce — intra-root peer connects, authorized by its delegation cert
52
- //
53
- // Naming model (personal invites): generate_invite('Bob') tags a pending invite
54
- // with the peer-name "Bob"; whoever redeems it is registered under "Bob" (the
55
- // inviter's assigned name wins). Generating WITHOUT a name tags the invite with
56
- // "" — then the joiner's self-announced name wins (falling back to its container
57
- // id if the joiner never set one). The joiner, in turn, sees the inviter under
58
- // the inviter's own self-name (set via set_my_name), unless the joiner overrides it.
59
70
 
60
71
  application actor loads libraries
61
72
  identity_proof_document,
@@ -70,6 +81,7 @@ application actor loads libraries
70
81
  encrypted_channel,
71
82
  current_transaction_info,
72
83
  a2a_protocol,
84
+ a2a_messaging,
73
85
  version
74
86
  uses transactions
75
87
  {
@@ -107,27 +119,19 @@ application actor loads libraries
107
119
  encrypted_channel::init ($_read_or_abort -> _read_or_abort).
108
120
 
109
121
  // ---- packet state ---------------------------------------------------
110
- // The display name peers see for me (set via set_my_name).
111
- my_name is str = "".
112
- // Known contacts, keyed by their container id.
113
- contacts is (global_id ->> a2a_protocol::contact_t) = (,).
114
- // Invites I generated, keyed by invite id -> the name I assigned the peer.
115
- pending_invites is (global_id ->> str) = (,).
122
+ // (The shared contact/profile/hierarchy state my_name, contacts,
123
+ // pending_invites, peer_ads, my_bio, delegation_cert, root_ad,
124
+ // root_profile, contact_roots lives in a2a_messaging and is read /
125
+ // assigned as a2a_messaging::<field> below.)
126
+ //
116
127
  // Received messages. Each carries its own lifecycle status (see
117
- // message_t / get_messages / mark_processed / defer_messages), so the
128
+ // message_t / get_messages / gc / defer_messages), so the
118
129
  // packet is the single authority on what has been read or processed —
119
130
  // no host-side cursor, safe across concurrent sessions.
120
131
  inbox is message_t[] = [].
121
132
  // Monotonic source of per-message ids (the stable handle the agent uses
122
133
  // to mark a message processed or defer it).
123
134
  next_msg_seq is int = 1.
124
- // Peer address documents, captured when a contact is established. These are
125
- // self-signed, code-independent, and seed-stable, so on a code upgrade the
126
- // host re-creates this packet from the same seed and import_state replays
127
- // them through address_document::process_address_document — re-registering
128
- // every peer's keys in key_storage so encrypted channels survive the upgrade
129
- // with no re-handshake. Only peer PUBLIC keys travel here, never secrets.
130
- peer_ads is (global_id ->> address_document_types::t_address_document) = (,).
131
135
  // The host registrar's address document (pinned once at identity
132
136
  // creation / injected on upgrade) — its $identity $key_list is what
133
137
  // introduction credentials are verified against. NIL means this identity
@@ -142,18 +146,6 @@ application actor loads libraries
142
146
  // Verified-but-unapproved local introductions (when auto-accept is off),
143
147
  // each with a bounded queue of messages awaiting approval.
144
148
  pending_introductions is (global_id ->> pending_intro_t) = (,).
145
- // ---- identity hierarchy state ----
146
- // My profile bio (free-text, self-asserted; carried in role invites).
147
- my_bio is str = "".
148
- // My delegation cert. NIL == I am a root or a legacy flat identity.
149
- delegation_cert is a2a_protocol::delegation_cert_t+ = NIL.
150
- // My root's address document (set with the cert; its key list is what
151
- // sibling introductions and my own cert are verified against).
152
- root_ad is address_document_types::t_address_document+ = NIL.
153
- // My root's self-signed profile, embedded in the invites I generate.
154
- root_profile is a2a_protocol::root_profile_t+ = NIL.
155
- // Verified root linkage per contact, keyed by the contact's container id.
156
- contact_roots is (global_id ->> a2a_protocol::contact_root_t) = (,).
157
149
 
158
150
  // Signal the host to persist the packet. Only emitted at the end of a
159
151
  // complete procedure — intermediate states (e.g. channel handshake) are
@@ -162,19 +154,6 @@ application actor loads libraries
162
154
  fn _return_data (payload: any) = (transaction::action::return_data ($kind -> $data, $payload -> payload)).
163
155
  fn _notify_agent (payload: any) = (transaction::action::return_data ($kind -> $notify_agent, $payload -> payload)).
164
156
 
165
- // Resolve a contact reference (a display name or stringified container id)
166
- // to a container id; aborts if no contact matches.
167
- fn resolve_contact (ref: str) -> global_id
168
- {
169
- found is global_id+ = NIL.
170
- sc contacts -- (cid -> c) ?? found == NIL && ((c $name) == ref || (_str cid) == ref)
171
- {
172
- found -> cid.
173
- }
174
- abort "Unknown contact: " + ref when found == NIL.
175
- return found?.
176
- }
177
-
178
157
  // Append a message to the inbox under a fresh id; returns the id.
179
158
  fn deposit_message (sender_id: global_id, sender_name: str, text: str, msg_date: time) -> int
180
159
  {
@@ -203,229 +182,52 @@ application actor loads libraries
203
182
  abort "No pending introduction matches: " + ref when found == NIL.
204
183
  return found?.
205
184
  }
206
- }
207
-
208
- // ---- user transactions --------------------------------------------------
209
-
210
- trn set_my_name _:($name -> name: str)
211
- {
212
- current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::user,).
213
- my_name -> name.
214
- return transaction::success [
215
- _return_data ($name -> name),
216
- _save_state NIL
217
- ].
218
- }
219
185
 
220
- trn set_my_bio _:($bio -> bio: str)
221
- {
222
- current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::user,).
223
- my_bio -> bio.
224
- return transaction::success [
225
- _return_data ($bio -> bio),
226
- _save_state NIL
227
- ].
228
- }
229
-
230
- trn generate_invite _:($name -> name: str+)
231
- {
232
- current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::user,).
233
-
234
- invite_id = _new_id "a2adapt invite".
235
- // Remember the name I'm assigning to whoever redeems this invite. An
236
- // empty string is the "no assigned name" sentinel: accept_contact then
237
- // registers the joiner under its self-announced name instead.
238
- assigned = (name == NIL ?? "" ; name?).
239
- pending_invites invite_id -> assigned.
240
-
241
- // Carry only my signed identity (public keys) + its self-signatures. The
242
- // joiner rebuilds my address document from these (version is constant, my
243
- // container_id is the identity's own field) and stores it so it can
244
- // re-register me after a code upgrade (see peer_ads / import_state). The
245
- // identity sub-record is passed through untouched so its _value_id what
246
- // the authorizations sign over — survives the round trip unchanged.
247
- my_ad = address_document::get_my_address_document().
248
- my_identity = my_ad $identity.
249
-
250
- // A delegated role embeds its cert + the root's profile (Ring 3 of the
251
- // identity hierarchy: external peers verify the whole chain from the
252
- // invite alone). A root or legacy identity emits the original shape
253
- // byte-for-byte, so those invites stay redeemable by old clients.
254
- if delegation_cert != NIL && root_profile != NIL
255
- {
256
- role_invite is a2a_protocol::invite_role_t = (
257
- $d -> invite_id,
258
- $n -> my_name,
259
- $c -> my_identity $container_id,
260
- $k -> my_identity $key_list,
261
- $a -> my_ad $authorizations,
262
- $b -> my_bio,
263
- $dc -> delegation_cert?,
264
- $rp -> root_profile?
265
- ).
266
- return transaction::success [
267
- _return_data (
268
- $invite -> (_write role_invite),
269
- $invite_id -> invite_id,
270
- $peer_name -> assigned
271
- ),
272
- _save_state NIL
273
- ].
274
- }
275
-
276
- invite is a2a_protocol::invite_t = (
277
- $d -> invite_id,
278
- $n -> my_name,
279
- $c -> my_identity $container_id,
280
- $k -> my_identity $key_list,
281
- $a -> my_ad $authorizations
186
+ // Wire the agent's storage into the shared messaging core. The receive
187
+ // hook owns everything app-specific about an inbound message: known
188
+ // senders deposit into the inbox; an unknown sender may be a verified-
189
+ // but-unapproved local introduction messaging before approval — queue
190
+ // (bounded) inside its pending entry, approval flushes the queue into
191
+ // the inbox in order; anything else from an unknown sender is rejected.
192
+ // The notification deliberately carries NO message body — only that a
193
+ // message arrived, from whom, and its id. The body stays in the packet
194
+ // and only leaves through get_messages.
195
+ a2a_messaging::init (
196
+ $_read_or_abort -> _read_or_abort,
197
+ $on_message_received -> fn (arg: any) -> transaction::action::type[]
198
+ {
199
+ sender_id = (arg $sender_id) safe global_id.
200
+ text = (arg $text) safe str.
201
+ msg_date = (arg $date) safe time.
202
+
203
+ if (arg $sender_name) == NIL
204
+ {
205
+ p = pending_introductions sender_id.
206
+ abort "Message from an unknown sender was rejected." when p == NIL.
207
+ entry = p?.
208
+ queued = entry $messages.
209
+ abort "Pending-introduction message queue is full; awaiting approval." when (_count queued|) >= pending_queue_cap.
210
+ queued (_count queued|) -> ($text -> text, $date -> msg_date).
211
+ pending_introductions sender_id -> ($name -> entry $name, $ad -> entry $ad, $messages -> queued).
212
+ return [
213
+ _notify_agent ($event -> $pending_message, $sender_name -> entry $name, $queued -> _count queued|),
214
+ _save_state NIL
215
+ ].
216
+ }
217
+
218
+ sender_name = (arg $sender_name) safe str.
219
+ mid = deposit_message sender_id sender_name text msg_date.
220
+ return [
221
+ _notify_agent ($event -> $message_received, $sender_name -> sender_name, $msg_id -> mid, $date -> msg_date),
222
+ _save_state NIL
223
+ ].
224
+ },
225
+ $on_message_sent -> fn (_: any) -> transaction::action::type[] { return []. },
226
+ $on_contact_removed -> fn (_: any) -> transaction::action::type[] { return []. }
282
227
  ).
283
-
284
- return transaction::success [
285
- _return_data (
286
- $invite -> (_write invite),
287
- $invite_id -> invite_id,
288
- $peer_name -> assigned
289
- ),
290
- _save_state NIL
291
- ].
292
- }
293
-
294
- trn add_contact _:($invite -> invite_blob: bin, $name -> custom_name: str+)
295
- {
296
- current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::user,).
297
-
298
- // Parse field-by-field rather than via one `safe invite_t` cast: the
299
- // shared fields are identical between invite_t and invite_role_t, so
300
- // this one path redeems both the legacy shape and the role shape (the
301
- // hierarchy fields are simply NIL on a legacy invite).
302
- raw = _read_or_abort invite_blob.
303
- inviter_id = (raw $c) safe global_id.
304
- abort "This invite is your own — you cannot add yourself." when inviter_id == _get_container_id().
305
- invite_id = (raw $d) safe global_id.
306
- inviter_name = (raw $n) safe str.
307
- inviter_keys = (raw $k) safe (key_utils::t_publickey(,)).
308
- inviter_auths = (raw $a) safe (crypto_signature(,)).
309
-
310
- // Rebuild the inviter's full address document from the carried material
311
- // (see a2a_protocol::rebuild_peer_address_document — the reconstructed
312
- // identity is byte-for-byte the signed one). import_state later replays
313
- // this document through process_address_document to re-register the
314
- // inviter's keys after a code upgrade — so it must validate, and it does.
315
- inviter_ad = a2a_protocol::rebuild_peer_address_document inviter_id inviter_keys inviter_auths.
316
-
317
- // A role invite carries a delegation chain — verify it BEFORE anything
318
- // is registered (an invalid chain rejects the whole invite), and record
319
- // the root linkage. A legacy/root invite has no chain; nothing to check.
320
- inviter_root is a2a_protocol::contact_root_t+ = NIL.
321
- inviter_bio is str = "".
322
- if (raw $dc) != NIL
323
- {
324
- cert = (raw $dc) safe a2a_protocol::delegation_cert_t.
325
- rp = (raw $rp) safe a2a_protocol::root_profile_t.
326
- inviter_root -> a2a_protocol::verify_peer_delegation inviter_id (_value_id inviter_ad) cert rp.
327
- inviter_bio -> (raw $b) safe str.
328
- }
329
-
330
- // Register the inviter under my chosen name, or the name they embedded.
331
- contact_name = (custom_name == NIL ?? inviter_name ; custom_name?).
332
- contacts inviter_id -> ($name -> contact_name, $container_id -> inviter_id).
333
- // Remember the inviter's address document so I can re-register them after
334
- // an upgrade (their keys are seed-stable, so this stays valid).
335
- peer_ads inviter_id -> inviter_ad.
336
- if inviter_root != NIL
337
- {
338
- contact_roots inviter_id -> inviter_root?.
339
- }
340
-
341
- my_self_name = my_name.
342
- my_ad = address_document::get_my_address_document().
343
- // If I am a delegated role myself, carry my own chain in the reply so
344
- // the inviter learns my root linkage symmetrically.
345
- my_cert_blob is bin+ = NIL.
346
- my_rp_blob is bin+ = NIL.
347
- if delegation_cert != NIL && root_profile != NIL
348
- {
349
- my_cert_blob -> (_write delegation_cert?).
350
- my_rp_blob -> (_write root_profile?).
351
- }
352
-
353
- root_name_out is str = "".
354
- role_id_out is str = "".
355
- if inviter_root != NIL
356
- {
357
- root_name_out -> inviter_root? $root_name.
358
- role_id_out -> inviter_root? $role_id.
359
- }
360
-
361
- // Establish the encrypted channel with the inviter (handshake happens
362
- // transparently if we haven't talked before), then tell them I redeemed
363
- // their invite, what my own name is, and my address document, so they can
364
- // finish the handshake and remember me for future upgrades.
365
- return encrypted_channel::execute_transaction inviter_id (fn (_) -> transaction::results::type {
366
- return transaction::success [
367
- encrypted_channel::send_encrypted_tx inviter_id (
368
- $name -> "::actor::accept_contact",
369
- $targ -> (
370
- $invite_id -> invite_id,
371
- $joiner_name -> my_self_name,
372
- $joiner_ad -> my_ad,
373
- $joiner_cert -> my_cert_blob,
374
- $joiner_root_profile -> my_rp_blob
375
- )
376
- ),
377
- _return_data (
378
- $added -> contact_name,
379
- $container_id -> inviter_id,
380
- $root_name -> root_name_out,
381
- $role_id -> role_id_out,
382
- $bio -> inviter_bio
383
- ),
384
- _save_state NIL
385
- ].
386
- }).
387
228
  }
388
229
 
389
- trn send_message _:($contact -> contact_ref: str, $text -> text: str)
390
- {
391
- current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::user,).
392
-
393
- target_id = resolve_contact contact_ref.
394
-
395
- return encrypted_channel::execute_transaction target_id (fn (_) -> transaction::results::type {
396
- return transaction::success [
397
- encrypted_channel::send_encrypted_tx target_id (
398
- $name -> "::actor::receive_message",
399
- $targ -> ($text -> text)
400
- ),
401
- _return_data ($sent_to -> target_id, $text -> text),
402
- _save_state NIL
403
- ].
404
- }).
405
- }
406
-
407
- trn remove_contact _:($contact -> contact_ref: str)
408
- {
409
- current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::user,).
410
-
411
- target_id = resolve_contact contact_ref.
412
- removed = contacts target_id.
413
- removed_name = removed? $name.
414
-
415
- delete contacts target_id.
416
- if peer_ads target_id != NIL { delete peer_ads target_id. }
417
- if contact_roots target_id != NIL { delete contact_roots target_id. }
418
-
419
- return transaction::success [
420
- _return_data ($removed -> removed_name, $container_id -> target_id),
421
- _save_state NIL
422
- ].
423
- }
424
-
425
- trn readonly list_contacts _
426
- {
427
- return contacts.
428
- }
230
+ // ---- message store --------------------------------------------------------
429
231
 
430
232
  trn readonly list_incoming_messages _
431
233
  {
@@ -668,10 +470,10 @@ application actor loads libraries
668
470
  entry_sig = (_read_or_abort entry_sig_blob) safe crypto_signature.
669
471
  abort "Contact-book entry failed registrar verification." when key_storage::check_signature_new_container (_value_id entry) entry_sig (registrar_ad? $identity $key_list) != TRUE.
670
472
 
671
- contacts target_id -> ($name -> name, $container_id -> target_id).
672
- peer_ads target_id -> target_ad.
473
+ a2a_messaging::contacts target_id -> ($name -> name, $container_id -> target_id).
474
+ a2a_messaging::peer_ads target_id -> target_ad.
673
475
 
674
- my_self_name = my_name.
476
+ my_self_name = a2a_messaging::my_name.
675
477
  my_ad = address_document::get_my_address_document().
676
478
  return encrypted_channel::execute_transaction target_id (fn (_) -> transaction::results::type {
677
479
  return transaction::success [
@@ -691,8 +493,8 @@ application actor loads libraries
691
493
 
692
494
  pid = resolve_pending ref.
693
495
  entry = (pending_introductions pid)?.
694
- contacts pid -> ($name -> entry $name, $container_id -> pid).
695
- peer_ads pid -> entry $ad.
496
+ a2a_messaging::contacts pid -> ($name -> entry $name, $container_id -> pid).
497
+ a2a_messaging::peer_ads pid -> entry $ad.
696
498
 
697
499
  queued = entry $messages.
698
500
  flushed is int = 0.
@@ -751,7 +553,7 @@ application actor loads libraries
751
553
  trn sign_delegation _:($role_ad -> role_ad_blob: bin, $role_id -> role_id: str)
752
554
  {
753
555
  current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::user,).
754
- abort "Only a root identity can sign delegation certificates." when delegation_cert != NIL.
556
+ abort "Only a root identity can sign delegation certificates." when a2a_messaging::delegation_cert != NIL.
755
557
 
756
558
  role_ad = (_read_or_abort role_ad_blob) safe address_document_types::t_address_document.
757
559
  role_cid = role_ad $identity $container_id.
@@ -777,14 +579,14 @@ application actor loads libraries
777
579
  trn export_root_profile _
778
580
  {
779
581
  current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::user,).
780
- abort "Only a root identity can export a root profile." when delegation_cert != NIL.
582
+ abort "Only a root identity can export a root profile." when a2a_messaging::delegation_cert != NIL.
781
583
 
782
584
  my_ad = address_document::get_my_address_document().
783
585
  core is a2a_protocol::root_profile_core_t = (
784
586
  $version -> 1,
785
587
  $root_cid -> _get_container_id(),
786
- $name -> my_name,
787
- $bio -> my_bio,
588
+ $name -> a2a_messaging::my_name,
589
+ $bio -> a2a_messaging::my_bio,
788
590
  $keys -> my_ad $identity $key_list
789
591
  ).
790
592
  profile is a2a_protocol::root_profile_t = ($p -> core, $s -> key_storage::default_sign (_value_id core)).
@@ -817,9 +619,9 @@ application actor loads libraries
817
619
  abort "The root profile's key list does not match the root's address document." when (_value_id (rp $p $keys)) != (_value_id (new_root_ad $identity $key_list)).
818
620
  abort "The root profile signature is invalid." when key_storage::check_signature_new_container (_value_id (rp $p)) (rp $s) (new_root_ad $identity $key_list) != TRUE.
819
621
 
820
- delegation_cert -> cert.
821
- root_ad -> new_root_ad.
822
- root_profile -> rp.
622
+ a2a_messaging::delegation_cert -> cert.
623
+ a2a_messaging::root_ad -> new_root_ad.
624
+ a2a_messaging::root_profile -> rp.
823
625
 
824
626
  return transaction::success [
825
627
  _return_data ($delegated -> TRUE, $root_cid -> (_str (cert $c $root_cid)), $role_id -> cert $c $role_id),
@@ -829,16 +631,16 @@ application actor loads libraries
829
631
 
830
632
  trn readonly describe_identity _
831
633
  {
832
- if delegation_cert == NIL
634
+ if a2a_messaging::delegation_cert == NIL
833
635
  {
834
- return ($name -> my_name, $bio -> my_bio, $has_cert -> FALSE, $role_id -> "", $root_cid -> "", $root_name -> "").
636
+ return ($name -> a2a_messaging::my_name, $bio -> a2a_messaging::my_bio, $has_cert -> FALSE, $role_id -> "", $root_cid -> "", $root_name -> "").
835
637
  }
836
- cert = delegation_cert?.
638
+ cert = a2a_messaging::delegation_cert?.
837
639
  rname is str = "".
838
- if root_profile != NIL { rname -> root_profile? $p $name. }
640
+ if a2a_messaging::root_profile != NIL { rname -> a2a_messaging::root_profile? $p $name. }
839
641
  return (
840
- $name -> my_name,
841
- $bio -> my_bio,
642
+ $name -> a2a_messaging::my_name,
643
+ $bio -> a2a_messaging::my_bio,
842
644
  $has_cert -> TRUE,
843
645
  $role_id -> cert $c $role_id,
844
646
  $root_cid -> (_str (cert $c $root_cid)),
@@ -846,17 +648,6 @@ application actor loads libraries
846
648
  ).
847
649
  }
848
650
 
849
- trn readonly list_contact_roots _
850
- {
851
- return contact_roots.
852
- }
853
-
854
- // The shared-core version this packet was compiled with (see core/version.mm).
855
- trn readonly get_version _
856
- {
857
- return ($core -> version::get_core_version()).
858
- }
859
-
860
651
  // Connect to an intra-root sibling (Ring 1): register it as a contact and
861
652
  // introduce myself over the encrypted channel, presenting my delegation
862
653
  // cert (NIL when I am the root itself — the channel proves I control the
@@ -872,22 +663,22 @@ application actor loads libraries
872
663
  abort "This sibling is your own identity." when target_id == _get_container_id().
873
664
 
874
665
  cert_blob is bin+ = NIL.
875
- if delegation_cert != NIL { cert_blob -> (_write delegation_cert?). }
666
+ if a2a_messaging::delegation_cert != NIL { cert_blob -> (_write a2a_messaging::delegation_cert?). }
876
667
 
877
- contacts target_id -> ($name -> name, $container_id -> target_id).
878
- peer_ads target_id -> target_ad.
668
+ a2a_messaging::contacts target_id -> ($name -> name, $container_id -> target_id).
669
+ a2a_messaging::peer_ads target_id -> target_ad.
879
670
  // Record the target's root linkage: a sibling shares my root by
880
671
  // definition (the receiving side verifies the converse independently).
881
- if delegation_cert != NIL && root_profile != NIL
672
+ if a2a_messaging::delegation_cert != NIL && a2a_messaging::root_profile != NIL
882
673
  {
883
- contact_roots target_id -> ($root_cid -> delegation_cert? $c $root_cid, $root_name -> root_profile? $p $name, $role_id -> name).
674
+ a2a_messaging::contact_roots target_id -> ($root_cid -> a2a_messaging::delegation_cert? $c $root_cid, $root_name -> a2a_messaging::root_profile? $p $name, $role_id -> name).
884
675
  }
885
676
  else
886
677
  {
887
- contact_roots target_id -> ($root_cid -> _get_container_id(), $root_name -> my_name, $role_id -> name).
678
+ a2a_messaging::contact_roots target_id -> ($root_cid -> _get_container_id(), $root_name -> a2a_messaging::my_name, $role_id -> name).
888
679
  }
889
680
 
890
- my_self_name = my_name.
681
+ my_self_name = a2a_messaging::my_name.
891
682
  my_ad = address_document::get_my_address_document().
892
683
  return encrypted_channel::execute_transaction target_id (fn (_) -> transaction::results::type {
893
684
  return transaction::success [
@@ -909,27 +700,32 @@ application actor loads libraries
909
700
  //
910
701
  // The packet-level snapshot is NOT used for upgrades: it is bound to the unit
911
702
  // code hash, so a new .muflo cannot load an old snapshot. This data blob is.
703
+ //
704
+ // The blob stays FLAT with the historical field names — the core fields come
705
+ // from a2a_messaging::export_core_state / import_core_state, the app fields
706
+ // are composed in here — so a PRE-migration export imports unchanged.
912
707
 
913
708
  trn readonly export_state _
914
709
  {
710
+ core_state = a2a_messaging::export_core_state NIL.
915
711
  return (
916
- $my_name -> my_name,
917
- $contacts -> contacts,
918
- $pending_invites -> pending_invites,
712
+ $my_name -> core_state $my_name,
713
+ $contacts -> core_state $contacts,
714
+ $pending_invites -> core_state $pending_invites,
919
715
  $inbox -> inbox,
920
716
  $next_msg_seq -> next_msg_seq,
921
- $peer_ads -> peer_ads,
717
+ $peer_ads -> core_state $peer_ads,
922
718
  $registrar_ad -> registrar_ad,
923
719
  $local_auto_accept -> local_auto_accept,
924
720
  // Nonces are exported so a restart does not reopen the replay window
925
721
  // for still-fresh credentials; stale ones are purged lazily anyway.
926
722
  $seen_nonces -> seen_nonces,
927
723
  $pending_introductions -> pending_introductions,
928
- $my_bio -> my_bio,
929
- $delegation_cert -> delegation_cert,
930
- $root_ad -> root_ad,
931
- $root_profile -> root_profile,
932
- $contact_roots -> contact_roots
724
+ $my_bio -> core_state $my_bio,
725
+ $delegation_cert -> core_state $delegation_cert,
726
+ $root_ad -> core_state $root_ad,
727
+ $root_profile -> core_state $root_profile,
728
+ $contact_roots -> core_state $contact_roots
933
729
  ).
934
730
  }
935
731
 
@@ -937,12 +733,11 @@ application actor loads libraries
937
733
  {
938
734
  current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::user,).
939
735
 
940
- // The fields that did not change across the schema bump are validated the
941
- // same way for any version of the blob.
942
- my_name -> (data $my_name) safe str.
943
- contacts -> (data $contacts) safe (global_id ->> a2a_protocol::contact_t).
944
- pending_invites -> (data $pending_invites) safe (global_id ->> str).
945
- peer_ads -> (data $peer_ads) safe (global_id ->> address_document_types::t_address_document).
736
+ // Core fields (contacts/profile/hierarchy) validated and restored by
737
+ // the shared library, which also replays every peer's address document
738
+ // through process_address_document so encrypted channels keep working
739
+ // after the upgrade with no re-handshake.
740
+ a2a_messaging::import_core_state data.
946
741
 
947
742
  // The inbox + next_msg_seq are the only parts the message-lifecycle changes
948
743
  // touched. A pre-lifecycle blob has no $next_msg_seq and inbox entries with
@@ -1013,36 +808,6 @@ application actor loads libraries
1013
808
  pending_introductions -> (data $pending_introductions) safe (global_id ->> pending_intro_t).
1014
809
  }
1015
810
 
1016
- // Identity-hierarchy state arrived after the local-contact-book schema —
1017
- // same pattern: every field is optional, defaults stay when absent.
1018
- if (data $my_bio) != NIL
1019
- {
1020
- my_bio -> (data $my_bio) safe str.
1021
- }
1022
- if (data $delegation_cert) != NIL
1023
- {
1024
- delegation_cert -> (data $delegation_cert) safe a2a_protocol::delegation_cert_t.
1025
- }
1026
- if (data $root_ad) != NIL
1027
- {
1028
- root_ad -> (data $root_ad) safe address_document_types::t_address_document.
1029
- }
1030
- if (data $root_profile) != NIL
1031
- {
1032
- root_profile -> (data $root_profile) safe a2a_protocol::root_profile_t.
1033
- }
1034
- if (data $contact_roots) != NIL
1035
- {
1036
- contact_roots -> (data $contact_roots) safe (global_id ->> a2a_protocol::contact_root_t).
1037
- }
1038
-
1039
- // Re-register every peer's keys so encrypted channels keep working after
1040
- // the upgrade — no handshake needed (my own keys are unchanged, and the
1041
- // peers' self-signed address documents re-authorize on this fresh packet).
1042
- sc peer_ads -- ( -> ad)
1043
- {
1044
- address_document::process_address_document ad TRUE.
1045
- }
1046
811
  // Pending introducers' keys too: their channel to me predates approval,
1047
812
  // so it must survive an upgrade exactly like an approved contact's.
1048
813
  sc pending_introductions -- ( -> p)
@@ -1051,103 +816,24 @@ application actor loads libraries
1051
816
  }
1052
817
 
1053
818
  return transaction::success [
1054
- _return_data ($imported -> TRUE, $contacts -> _count contacts|, $peers -> _count peer_ads|),
819
+ _return_data ($imported -> TRUE, $contacts -> _count a2a_messaging::contacts|, $peers -> _count a2a_messaging::peer_ads|),
1055
820
  _save_state NIL
1056
821
  ].
1057
822
  }
1058
823
 
1059
824
  // ---- external (inbound) transactions ------------------------------------
1060
825
 
1061
- // Args are taken as `any` (not a destructured shape) so old clients — whose
1062
- // accept_contact payload has no hierarchy fields keep working unchanged.
826
+ // Compat shims (Option A): pre-migration peers address these as ::actor::*,
827
+ // and the core keeps SENDING to the ::actor:: names too. Each delegates to
828
+ // the shared handler — remove only when no old clients remain.
1063
829
  trn accept_contact args: any
1064
830
  {
1065
- current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::external,).
1066
- encrypted_channel::check_encrypted_or_abort().
1067
-
1068
- sender_id = current_transaction_info::get_external_envelope_or_abort() $from.
1069
- invite_id = (args $invite_id) safe global_id.
1070
- joiner_ad = (args $joiner_ad) safe address_document_types::t_address_document.
1071
-
1072
- // Only an invite I generated (and have not yet consumed) authorizes a
1073
- // contact registration. Without this gate any invite blob would be a
1074
- // multi-use bearer credential: anyone who ever saw one could register
1075
- // themselves as my contact with a self-chosen name.
1076
- assigned_name = pending_invites invite_id.
1077
- abort "Unknown or already-redeemed invite." when assigned_name == NIL.
1078
- // An empty assigned name means the invite was generated without one:
1079
- // the joiner's self-announced name wins (container id as a last resort
1080
- // when the joiner never set a name either).
1081
- contact_name is str = assigned_name?.
1082
- if contact_name == ""
1083
- {
1084
- joiner_self = (args $joiner_name) safe str.
1085
- contact_name -> (joiner_self == "" ?? (_str sender_id) ; joiner_self).
1086
- }
1087
-
1088
- // A delegated-role joiner carries its chain so I learn its root linkage
1089
- // symmetrically; an invalid chain rejects the redemption outright.
1090
- joiner_root is a2a_protocol::contact_root_t+ = NIL.
1091
- if (args $joiner_cert) != NIL
1092
- {
1093
- cert = (_read_or_abort ((args $joiner_cert) safe bin)) safe a2a_protocol::delegation_cert_t.
1094
- rp = (_read_or_abort ((args $joiner_root_profile) safe bin)) safe a2a_protocol::root_profile_t.
1095
- joiner_root -> a2a_protocol::verify_peer_delegation sender_id (_value_id joiner_ad) cert rp.
1096
- }
1097
-
1098
- contacts sender_id -> ($name -> contact_name, $container_id -> sender_id).
1099
- // Remember the joiner's address document for upgrade-time re-registration.
1100
- peer_ads sender_id -> joiner_ad.
1101
- if joiner_root != NIL
1102
- {
1103
- contact_roots sender_id -> joiner_root?.
1104
- }
1105
- delete pending_invites invite_id.
1106
-
1107
- return transaction::success [
1108
- _notify_agent ($event -> $contact_accepted, $name -> contact_name, $container_id -> sender_id),
1109
- _save_state NIL
1110
- ].
831
+ return a2a_messaging::handle_accept_contact args.
1111
832
  }
1112
833
 
1113
834
  trn receive_message _:($text -> text: str)
1114
835
  {
1115
- current_transaction_info::validate_origin_or_abort (transaction::envelope::origin::external,).
1116
- encrypted_channel::check_encrypted_or_abort().
1117
-
1118
- sender_id = current_transaction_info::get_external_envelope_or_abort() $from.
1119
- msg_date = (current_transaction_info::get_transaction_time())?.
1120
- sender = contacts sender_id.
1121
-
1122
- if sender == NIL
1123
- {
1124
- // A verified-but-unapproved local introduction may message me before
1125
- // approval: queue (bounded) inside its pending entry. Approval
1126
- // flushes the queue into the inbox in order; anything else from an
1127
- // unknown sender is rejected as before.
1128
- p = pending_introductions sender_id.
1129
- abort "Message from an unknown sender was rejected." when p == NIL.
1130
- entry = p?.
1131
- queued = entry $messages.
1132
- abort "Pending-introduction message queue is full; awaiting approval." when (_count queued|) >= pending_queue_cap.
1133
- queued (_count queued|) -> ($text -> text, $date -> msg_date).
1134
- pending_introductions sender_id -> ($name -> entry $name, $ad -> entry $ad, $messages -> queued).
1135
- return transaction::success [
1136
- _notify_agent ($event -> $pending_message, $sender_name -> entry $name, $queued -> _count queued|),
1137
- _save_state NIL
1138
- ].
1139
- }
1140
-
1141
- sender_name = sender? $name.
1142
- mid = deposit_message sender_id sender_name text msg_date.
1143
-
1144
- // The notification deliberately carries NO message body — only that a
1145
- // message arrived, from whom, and its id. The body stays in the packet
1146
- // and only leaves through get_messages.
1147
- return transaction::success [
1148
- _notify_agent ($event -> $message_received, $sender_name -> sender_name, $msg_id -> mid, $date -> msg_date),
1149
- _save_state NIL
1150
- ].
836
+ return a2a_messaging::handle_receive_message text.
1151
837
  }
1152
838
 
1153
839
  // A same-host peer connects via the local contact book. The credential must
@@ -1196,12 +882,12 @@ application actor loads libraries
1196
882
  abort "Too many concurrent introductions; try again shortly." when (_count seen_nonces|) >= seen_nonce_cap.
1197
883
  seen_nonces (intro $nonce) -> now.
1198
884
 
1199
- existing = contacts sender_id.
885
+ existing = a2a_messaging::contacts sender_id.
1200
886
  if existing != NIL
1201
887
  {
1202
888
  // Already a contact (idempotent re-introduction): keep my assigned
1203
889
  // name, refresh the stored address document, deliver any payload.
1204
- peer_ads sender_id -> joiner_ad.
890
+ a2a_messaging::peer_ads sender_id -> joiner_ad.
1205
891
  if text != NIL
1206
892
  {
1207
893
  mid = deposit_message sender_id (existing? $name) text? now.
@@ -1215,8 +901,8 @@ application actor loads libraries
1215
901
 
1216
902
  if local_auto_accept
1217
903
  {
1218
- contacts sender_id -> ($name -> joiner_name, $container_id -> sender_id).
1219
- peer_ads sender_id -> joiner_ad.
904
+ a2a_messaging::contacts sender_id -> ($name -> joiner_name, $container_id -> sender_id).
905
+ a2a_messaging::peer_ads sender_id -> joiner_ad.
1220
906
  if text != NIL
1221
907
  {
1222
908
  mid = deposit_message sender_id joiner_name text? now.
@@ -1267,8 +953,8 @@ application actor loads libraries
1267
953
  if cert_blob == NIL
1268
954
  {
1269
955
  // Sender claims to be my root.
1270
- abort "A certificate-less sibling introduction is only accepted from my root." when delegation_cert == NIL.
1271
- abort "Sender is not my root." when sender_id != (delegation_cert? $c $root_cid).
956
+ abort "A certificate-less sibling introduction is only accepted from my root." when a2a_messaging::delegation_cert == NIL.
957
+ abort "Sender is not my root." when sender_id != (a2a_messaging::delegation_cert? $c $root_cid).
1272
958
  link -> ($root_cid -> sender_id, $root_name -> joiner_name, $role_id -> "").
1273
959
  }
1274
960
  else
@@ -1279,14 +965,14 @@ application actor loads libraries
1279
965
  abort "Sibling certificate does not match the sender's address document." when (cert $c $role_ad_hash) != (_value_id joiner_ad).
1280
966
 
1281
967
  root_name_known is str = "".
1282
- if delegation_cert != NIL
968
+ if a2a_messaging::delegation_cert != NIL
1283
969
  {
1284
970
  // I am a role: the cert must name MY root and verify against the
1285
971
  // root key material pinned at delegation time.
1286
- abort "My root material is missing — cannot verify sibling certificates." when root_ad == NIL.
1287
- abort "Sibling certificate names a different root." when (cert $c $root_cid) != (delegation_cert? $c $root_cid).
1288
- abort "Sibling certificate was not signed by my root." when key_storage::check_signature_new_container (_value_id (cert $c)) (cert $s) (root_ad? $identity $key_list) != TRUE.
1289
- if root_profile != NIL { root_name_known -> root_profile? $p $name. }
972
+ abort "My root material is missing — cannot verify sibling certificates." when a2a_messaging::root_ad == NIL.
973
+ abort "Sibling certificate names a different root." when (cert $c $root_cid) != (a2a_messaging::delegation_cert? $c $root_cid).
974
+ abort "Sibling certificate was not signed by my root." when key_storage::check_signature_new_container (_value_id (cert $c)) (cert $s) (a2a_messaging::root_ad? $identity $key_list) != TRUE.
975
+ if a2a_messaging::root_profile != NIL { root_name_known -> a2a_messaging::root_profile? $p $name. }
1290
976
  }
1291
977
  else
1292
978
  {
@@ -1295,18 +981,18 @@ application actor loads libraries
1295
981
  abort "Sibling certificate names a different root." when (cert $c $root_cid) != _get_container_id().
1296
982
  my_ad = address_document::get_my_address_document().
1297
983
  abort "Sibling certificate was not signed by me." when key_storage::check_signature_new_container (_value_id (cert $c)) (cert $s) (my_ad $identity $key_list) != TRUE.
1298
- root_name_known -> my_name.
984
+ root_name_known -> a2a_messaging::my_name.
1299
985
  }
1300
986
  link -> ($root_cid -> cert $c $root_cid, $root_name -> root_name_known, $role_id -> cert $c $role_id).
1301
987
  }
1302
988
 
1303
- existing = contacts sender_id.
989
+ existing = a2a_messaging::contacts sender_id.
1304
990
  if existing != NIL
1305
991
  {
1306
992
  // Already a contact (idempotent re-introduction): keep my assigned
1307
993
  // name, refresh the stored material, deliver any payload.
1308
- peer_ads sender_id -> joiner_ad.
1309
- contact_roots sender_id -> link?.
994
+ a2a_messaging::peer_ads sender_id -> joiner_ad.
995
+ a2a_messaging::contact_roots sender_id -> link?.
1310
996
  if text != NIL
1311
997
  {
1312
998
  mid = deposit_message sender_id (existing? $name) text? now.
@@ -1318,9 +1004,9 @@ application actor loads libraries
1318
1004
  return transaction::success [ _save_state NIL ].
1319
1005
  }
1320
1006
 
1321
- contacts sender_id -> ($name -> joiner_name, $container_id -> sender_id).
1322
- peer_ads sender_id -> joiner_ad.
1323
- contact_roots sender_id -> link?.
1007
+ a2a_messaging::contacts sender_id -> ($name -> joiner_name, $container_id -> sender_id).
1008
+ a2a_messaging::peer_ads sender_id -> joiner_ad.
1009
+ a2a_messaging::contact_roots sender_id -> link?.
1324
1010
  if text != NIL
1325
1011
  {
1326
1012
  mid = deposit_message sender_id joiner_name text? now.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adapt-toolkit/a2adapt",
3
- "version": "0.11.3",
3
+ "version": "0.11.4",
4
4
  "description": "MCP server daemon for a2adapt — one native ADAPT wrapper hosting N self-sovereign identities, exposing secure agent-to-agent messaging tools over HTTP (Streamable HTTP). Run `a2adapt-mcp start`.",
5
5
  "type": "module",
6
6
  "license": "MIT",