Files
buzz/desktop/src/features/agents/lib/useAgentsDataRefresh.test.mjs
Wes f716eef437 fix(desktop): enforce shared agent access across devices (#6086)
## Summary

- discover shared managed agents from authenticated relay directory
records instead of treating channel membership as sufficient proof
- publish and refresh access-policy changes immediately so running
clients converge across machines without a restart or five-minute poll
- route profile edits through the exact managed instance and
stop/restart runtimes around access changes so unrelated edits cannot
silently widen access
- keep mention send-time revalidation and Block owner-only build
enforcement fail closed
- explain invalid custom provider/model configuration instead of leaving
Save silently disabled

### Related issue

Fixes #3204

### Known residuals

- a brand-new remote agent's first policy record can wait for the
bounded directory poll when no authenticated directory coordinate exists
yet; send-time mention revalidation remains fail closed
- a failed remote-provider policy redeploy is recorded but cannot
undeploy the older provider instance until the provider protocol gains
the destructor tracked by #5570

### Testing

- full Desktop unit suite: 4,961 tests passed
- focused profile editor Playwright workflow passed, including Customize
access edits and prompt-only edits after tightening an instance
- Desktop TypeScript, Biome formatting, file-size ratchet, Tauri checks,
and pre-push suites passed
- independently reviewed for authenticated directory trust, live
subscription teardown, runtime revocation ordering, fail-open edit
paths, and per-agent provider deployment serialization

---------

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Signed-off-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@buzz.block.builderlab.xyz>
Co-authored-by: diegorumo <diegorumo@gmail.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@buzz.block.builderlab.xyz>
2026-08-17 09:51:00 -07:00

102 lines
2.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import assert from "node:assert/strict";
import test, { mock } from "node:test";
import { relayClient } from "@/shared/api/relayClient";
import { KIND_MANAGED_AGENT } from "@/shared/constants/kinds";
import { startRelayAgentPolicyRefresh } from "./useAgentsDataRefresh.ts";
const coordinates = [
{ ownerPubkey: "owner-a", agentPubkey: "agent-a" },
{ ownerPubkey: "owner-b", agentPubkey: "agent-b" },
];
function event(pubkey, dTag) {
return {
id: "id",
pubkey,
created_at: 1,
kind: KIND_MANAGED_AGENT,
tags: dTag ? [["d", dTag]] : [],
content: "{}",
sig: "sig",
};
}
test("remote managed policy refresh accepts only exact authenticated coordinates", async () => {
let onEvent;
let filter;
let unsubscribeCalls = 0;
mock.method(relayClient, "subscribeLive", (nextFilter, listener) => {
filter = nextFilter;
onEvent = listener;
return Promise.resolve(() => {
unsubscribeCalls += 1;
return Promise.resolve();
});
});
let refreshes = 0;
const stop = startRelayAgentPolicyRefresh(coordinates, () => {
refreshes += 1;
});
await new Promise((resolve) => setImmediate(resolve));
assert.deepEqual(filter, {
kinds: [KIND_MANAGED_AGENT],
authors: ["owner-a", "owner-b"],
"#d": ["agent-a", "agent-b"],
limit: 0,
});
onEvent(event("owner-a", "agent-a"));
assert.equal(refreshes, 1);
for (const irrelevant of [
event("owner-x", "agent-a"),
event("owner-a", "agent-x"),
event("owner-a", "agent-b"), // authors×d cross-product
event("owner-a", null),
]) {
onEvent(irrelevant);
}
assert.equal(refreshes, 1, "irrelevant coordinates must not refresh");
stop();
assert.equal(unsubscribeCalls, 1);
mock.reset();
});
test("stopping before subscription readiness still closes the live query", async () => {
let resolveSubscription;
let unsubscribeCalls = 0;
mock.method(
relayClient,
"subscribeLive",
() =>
new Promise((resolve) => {
resolveSubscription = resolve;
}),
);
const stop = startRelayAgentPolicyRefresh(coordinates, () => {});
stop();
resolveSubscription(() => {
unsubscribeCalls += 1;
return Promise.resolve();
});
await new Promise((resolve) => setImmediate(resolve));
assert.equal(unsubscribeCalls, 1);
mock.reset();
});
test("no authenticated coordinates creates no global subscription", () => {
let subscriptions = 0;
mock.method(relayClient, "subscribeLive", () => {
subscriptions += 1;
return Promise.resolve(() => Promise.resolve());
});
startRelayAgentPolicyRefresh([], () => {})();
assert.equal(subscriptions, 0);
mock.reset();
});