@ouro.bot/cli 0.1.0-alpha.660 → 0.1.0-alpha.661
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/changelog.json +7 -0
- package/dist/mind/friends/resolver.js +42 -2
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.661",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Default the local machine owner (the OS user running the daemon) to family trust when first encountered as a friend, instead of stranger. The Workbench boss check-in resolves the machine owner as a `local` friend; because MCP tool calls are trust-gated, a stranger-level owner caused the boss's own runtime-injected `ouro_workbench` machine-introspection tools to be rejected with the trust guardrail (\"i'd need a closer friend to vouch for you\"). The person running the daemon owns the agent and its bundle, so they are family, not a stranger.",
|
|
8
|
+
"Adds the pure `isLocalMachineOwnerIdentity` predicate and an injectable `machineOwnerUsername()` detection seam so the owner default is deterministically testable; resolver friend-creation is fully covered."
|
|
9
|
+
]
|
|
10
|
+
},
|
|
4
11
|
{
|
|
5
12
|
"version": "0.1.0-alpha.660",
|
|
6
13
|
"changes": [
|
|
@@ -4,10 +4,45 @@
|
|
|
4
4
|
// Replaces the old ContextResolver: no authority checker, no separate note resolution.
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.FriendResolver = void 0;
|
|
7
|
+
exports._setMachineOwnerUsernameForTest = _setMachineOwnerUsernameForTest;
|
|
8
|
+
exports.machineOwnerUsername = machineOwnerUsername;
|
|
9
|
+
exports.isLocalMachineOwnerIdentity = isLocalMachineOwnerIdentity;
|
|
7
10
|
const crypto_1 = require("crypto");
|
|
11
|
+
const os_1 = require("os");
|
|
8
12
|
const channel_1 = require("./channel");
|
|
9
13
|
const runtime_1 = require("../../nerves/runtime");
|
|
10
14
|
const CURRENT_SCHEMA_VERSION = 1;
|
|
15
|
+
// Test seam: when set (including to null), overrides OS detection of the
|
|
16
|
+
// machine-owner username so resolver tests are deterministic.
|
|
17
|
+
let machineOwnerOverride;
|
|
18
|
+
function _setMachineOwnerUsernameForTest(value) {
|
|
19
|
+
machineOwnerOverride = value;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The OS username that owns this daemon process, or null if undetectable. The
|
|
23
|
+
* person running the daemon owns this agent + its bundle, so the local friend
|
|
24
|
+
* that names them is the machine owner (family), not a stranger.
|
|
25
|
+
*/
|
|
26
|
+
function machineOwnerUsername() {
|
|
27
|
+
if (machineOwnerOverride !== undefined)
|
|
28
|
+
return machineOwnerOverride;
|
|
29
|
+
try {
|
|
30
|
+
return (0, os_1.userInfo)().username;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* v8 ignore next -- defensive: userInfo() only throws when the running user has no passwd entry @preserve */
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* True when (provider, externalId) names the local machine owner — the OS user
|
|
39
|
+
* running the daemon. Matches the bare username or a `user@host` external id.
|
|
40
|
+
*/
|
|
41
|
+
function isLocalMachineOwnerIdentity(provider, externalId, ownerUsername) {
|
|
42
|
+
if (provider !== "local" || !ownerUsername)
|
|
43
|
+
return false;
|
|
44
|
+
return externalId === ownerUsername || externalId.startsWith(`${ownerUsername}@`);
|
|
45
|
+
}
|
|
11
46
|
class FriendResolver {
|
|
12
47
|
store;
|
|
13
48
|
params;
|
|
@@ -88,6 +123,11 @@ class FriendResolver {
|
|
|
88
123
|
}
|
|
89
124
|
const isFirstImprint = !hasAnyFriends;
|
|
90
125
|
const isA2AAgent = this.params.provider === "a2a-agent";
|
|
126
|
+
// The local friend that names the OS user running the daemon is the machine
|
|
127
|
+
// owner (family) — they own the agent + its bundle. Usually this friend already
|
|
128
|
+
// exists as a family/primary hatch imprint; this covers the un-imprinted boss
|
|
129
|
+
// path (e.g. a Workbench boss check-in on a bundle that skipped imprint).
|
|
130
|
+
const isLocalMachineOwner = isLocalMachineOwnerIdentity(this.params.provider, this.params.externalId, machineOwnerUsername());
|
|
91
131
|
// BlueBubbles group chats route through here as `imessage-handle` with an
|
|
92
132
|
// externalId of the form `group:any;+;<chatHash>`. When the harness auto-
|
|
93
133
|
// creates the group friend at stranger trust, we mark the record so that
|
|
@@ -106,8 +146,8 @@ class FriendResolver {
|
|
|
106
146
|
const friend = {
|
|
107
147
|
id: (0, crypto_1.randomUUID)(),
|
|
108
148
|
name: this.params.displayName,
|
|
109
|
-
role: isA2AAgent ? "agent-peer" : isFirstImprint ? "primary" : "stranger",
|
|
110
|
-
trustLevel: isA2AAgent ? "stranger" : isFirstImprint ? "family" : "stranger",
|
|
149
|
+
role: isA2AAgent ? "agent-peer" : isFirstImprint ? "primary" : isLocalMachineOwner ? "family" : "stranger",
|
|
150
|
+
trustLevel: isA2AAgent ? "stranger" : (isFirstImprint || isLocalMachineOwner) ? "family" : "stranger",
|
|
111
151
|
connections: [],
|
|
112
152
|
externalIds: [externalId],
|
|
113
153
|
tenantMemberships,
|