@ouro.bot/cli 0.1.0-alpha.886 → 0.1.0-alpha.888

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.
Files changed (35) hide show
  1. package/changelog.json +27 -0
  2. package/deploy/unraid/README.txt +7 -5
  3. package/deploy/unraid/sanctuary-butler-upgrade.mjs +87 -30
  4. package/deploy/unraid/sanctuary-replay-gate.mjs +473 -74
  5. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +1 -0
  6. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +1 -1
  7. package/deploy/unraid/sanctuary.xml +2 -1
  8. package/dist/a2a/client.js +16 -4
  9. package/dist/a2a/delegated-command-grants.js +93 -0
  10. package/dist/a2a/delegated-command.js +57 -11
  11. package/dist/a2a/escalation-grants.js +37 -75
  12. package/dist/a2a/identity.js +54 -0
  13. package/dist/a2a/operator-trust.js +382 -0
  14. package/dist/a2a/outbox-wire.js +2 -2
  15. package/dist/a2a/replay-grant-holders.js +33 -0
  16. package/dist/a2a/server.js +12 -7
  17. package/dist/a2a/trust-commands.js +203 -0
  18. package/dist/a2a/trusted-files.js +113 -26
  19. package/dist/heart/core.js +60 -33
  20. package/dist/heart/daemon/cli-exec.js +38 -37
  21. package/dist/heart/daemon/cli-parse.js +45 -5
  22. package/dist/heart/daemon/container-spec-auditor.js +3 -0
  23. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1 -1
  24. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +1 -1
  25. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +4 -47
  26. package/dist/heart/failure-reports.js +5 -5
  27. package/dist/mind/prompt.js +31 -1
  28. package/dist/repertoire/guardrails.js +89 -7
  29. package/dist/repertoire/house-sweep.js +4 -1
  30. package/dist/senses/a2a-entry.js +2 -1
  31. package/dist/senses/private-runtime.js +11 -4
  32. package/dist/senses/shared-turn.js +5 -1
  33. package/dist/senses/telegram.js +5 -3
  34. package/npm-shrinkwrap.json +2 -2
  35. package/package.json +1 -1
@@ -60,6 +60,8 @@ const tools_1 = require("../repertoire/tools");
60
60
  const tools_base_1 = require("../repertoire/tools-base");
61
61
  const tools_awaiting_1 = require("../repertoire/tools-awaiting");
62
62
  const delegated_command_1 = require("../a2a/delegated-command");
63
+ const delegated_command_grants_1 = require("../a2a/delegated-command-grants");
64
+ const resolution_proof_1 = require("../a2a/resolution-proof");
63
65
  const relationship_authorization_1 = require("../repertoire/relationship-authorization");
64
66
  const run_ledger_1 = require("../heart/run-ledger");
65
67
  const bundle_manifest_1 = require("../mind/bundle-manifest");
@@ -157,12 +159,17 @@ function relationshipAwaitCoordinates(awaitFile) {
157
159
  }
158
160
  /**
159
161
  * An A2A peer is reactive-only: it cannot be pushed to, and on its own it has no authority to be followed up with.
160
- * Only a peer still holding the operator-set principal-command grant keeps follow-up authority, and that authority
161
- * is the delegating owner's, resolved exactly as the delegated command resolved it. Revoking the grant ends it.
162
+ * Only a peer still holding the operator's trusted principal-command grant keeps follow-up authority (the same shared
163
+ * check admission used), and that authority is the delegating owner's, resolved exactly as the delegated command
164
+ * resolved it. Revoking the grant, or an expired one, ends it.
162
165
  */
163
166
  async function resolveA2APrincipal(agentRoot, store, peer, requestId) {
164
- if (peer.delegationGrant?.scope !== "principal_commands" || peer.trustLevel !== "family")
165
- throw new StaleRelationshipAwaitError("A2A peer no longer holds a delegation grant");
167
+ // TODO(phase 2 of the friends trust-layer hardening): the signer DID here is the one the friend record names, which the agent
168
+ // can write, so follow-up authority still trusts the record's key. Phase 2 re-verifies the signed envelope stored with the
169
+ // await against the grant's pinned DID instead.
170
+ const granted = (0, delegated_command_grants_1.checkDelegatedCommandGrant)(agentRoot, peer, (0, resolution_proof_1.friendDid)(peer));
171
+ if (!granted.ok)
172
+ throw new StaleRelationshipAwaitError(`A2A peer no longer holds a delegation grant (${granted.reason})`);
166
173
  // listAll() swallows an unreadable directory or record as "no friend": only a verified complete read may end an await.
167
174
  const entries = fs.readdirSync(path.join(agentRoot, "friends")).filter((entry) => entry.endsWith(".json"));
168
175
  const friends = await store.listAll();
@@ -47,6 +47,7 @@ exports.runSenseTurn = runSenseTurn;
47
47
  const os = __importStar(require("os"));
48
48
  const path = __importStar(require("path"));
49
49
  const fs = __importStar(require("fs"));
50
+ const delegated_command_1 = require("../a2a/delegated-command");
50
51
  const core_1 = require("../heart/core");
51
52
  const identity_1 = require("../heart/identity");
52
53
  const config_1 = require("../heart/config");
@@ -360,8 +361,11 @@ async function runSenseTurn(options) {
360
361
  });
361
362
  }
362
363
  async function runSenseTurnExclusive(options, owner) {
363
- const { channel, sessionKey, friendId, userMessage } = options;
364
+ const { channel, sessionKey, friendId } = options;
364
365
  const { agentName, agentRoot } = owner;
366
+ // Only the A2A server writes the delegated-command banner, in front of a command it admitted (its body is shielded there). On every
367
+ // other turn, on any channel, a typed banner is marked as the sender's own words. A precommitted ingress is already stored verbatim.
368
+ const userMessage = options.precommittedIngress || options.toolContext?.delegatedCommand ? options.userMessage : (0, delegated_command_1.shieldDelegatedBanner)(options.userMessage);
365
369
  (0, runtime_1.emitNervesEvent)({
366
370
  component: "senses",
367
371
  event: "senses.shared_turn_start",
@@ -60,6 +60,7 @@ const node_async_hooks_1 = require("node:async_hooks");
60
60
  const node_fs_1 = require("node:fs");
61
61
  const path = __importStar(require("node:path"));
62
62
  const friends_1 = require("@ouro.bot/friends");
63
+ const delegated_command_1 = require("../a2a/delegated-command");
63
64
  const identity_1 = require("../heart/identity");
64
65
  const sanctuary_acceptance_marker_1 = require("../heart/daemon/sanctuary-acceptance-marker");
65
66
  const runtime_credentials_1 = require("../heart/runtime-credentials");
@@ -1384,7 +1385,7 @@ function createTelegramSenseApp(options) {
1384
1385
  const sessionKey = `telegram:${input.botId}:${input.userId}`;
1385
1386
  const reference = `telegram-admission:${input.admissionId}`;
1386
1387
  const sessionPath = (0, shared_turn_1.getSenseSessionPath)(options.agentName, input.friendId, "telegram", sessionKey, agentRoot);
1387
- const receipt = await (0, telegram_effect_adapter_1.recordTelegramEffectsInSession)({ store: getEffectJournal(), sessionPath, artifacts: [], inbound: { text: input.text, reference } });
1388
+ const receipt = await (0, telegram_effect_adapter_1.recordTelegramEffectsInSession)({ store: getEffectJournal(), sessionPath, artifacts: [], inbound: { text: (0, delegated_command_1.shieldDelegatedBanner)(input.text), reference } });
1388
1389
  return { admissionId: input.admissionId, friendId: input.friendId, sessionKey, eventId: receipt.eventId, reference };
1389
1390
  },
1390
1391
  enqueueApprovedWork: async (input) => {
@@ -1435,8 +1436,9 @@ function createTelegramSenseApp(options) {
1435
1436
  }
1436
1437
  };
1437
1438
  const hydrateAuthorizedMessage = async (message) => {
1439
+ // The one place inbound Telegram text is assembled for every turn and every stored ingress event: a typed delegated-command banner is marked here, so the stored event and the turn carry identical, shielded text.
1438
1440
  if (!message.attachments?.length)
1439
- return { text: [message.text, ...(message.attachmentNotices ?? [])].filter(Boolean).join("\n"), attachmentIds: [] };
1441
+ return { text: (0, delegated_command_1.shieldDelegatedBanner)([message.text, ...(message.attachmentNotices ?? [])].filter(Boolean).join("\n")), attachmentIds: [] };
1440
1442
  const ingested = await (0, telegram_attachments_1.ingestTelegramAttachments)({
1441
1443
  agentName: options.agentName,
1442
1444
  agentRoot,
@@ -1448,7 +1450,7 @@ function createTelegramSenseApp(options) {
1448
1450
  });
1449
1451
  const attachmentIds = ingested.attachments.map((attachment) => attachment.id);
1450
1452
  return {
1451
- text: [message.text, (0, render_1.renderAttachmentBlock)(ingested.attachments), ...(message.attachmentNotices ?? []), ...ingested.notices].filter(Boolean).join("\n"),
1453
+ text: (0, delegated_command_1.shieldDelegatedBanner)([message.text, (0, render_1.renderAttachmentBlock)(ingested.attachments), ...(message.attachmentNotices ?? []), ...ingested.notices].filter(Boolean).join("\n")),
1452
1454
  attachmentIds,
1453
1455
  };
1454
1456
  };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.886",
3
+ "version": "0.1.0-alpha.888",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@ouro.bot/cli",
9
- "version": "0.1.0-alpha.886",
9
+ "version": "0.1.0-alpha.888",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.78.0",
12
12
  "@azure/identity": "^4.13.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.886",
3
+ "version": "0.1.0-alpha.888",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },