Merge CB-561: one public way to build a CallerResolver (PR #32)
CallerResolver had 5 public constructors and 4 public factories, and only one of them could ever produce an architect. The rest defaulted memberSlotRoles to `_ -> null`, so every architect quietly fell through to Principal.worker(). Nothing logged, nothing threw — the role was simply off. That is the same failure shape as CB-560, so the fix is structural rather than a warning: withLeadsAndMembers(.., MemberRegistry) is now the only public construction path. Two overloads with no caller at all are deleted; the rest are package-private and marked test-only. No path remains that accepts architect bindings without a slot-role lookup, so no runtime WARN is needed. Also checked and closed: the suspected slot leak on shutdown drain is not real. SessionManager.release calls memberLifecycle.released() for every removed session, and drainAll routes every session through release, SPAWNING included. Verified in code.
This commit is contained in:
@@ -315,6 +315,7 @@ class CallerResolverTest {
|
||||
|
||||
@Test
|
||||
void aBoundArchitectPaneResolvesToArchitectBeforeTheWorkerFallback() {
|
||||
// This is the production construction path used by Bridged.
|
||||
Principal p = CallerResolver.withLeadsAndMembers(workerIdentity(), false, null,
|
||||
Map::of, boundMembers("architect:lead-designer", MemberRole.ARCHITECT))
|
||||
.resolve("127.0.0.1", 42, null);
|
||||
@@ -338,9 +339,10 @@ class CallerResolverTest {
|
||||
|
||||
@Test
|
||||
void anUnboundPaneStillResolvesAsAWorker() {
|
||||
Map<String, String> arch = Map.of("term_elsewhere", "reviewer");
|
||||
MemberRegistry members = new MemberRegistry(new BridgedConfig.Fleet(Map.of(),
|
||||
Map.of("lead-designer", new BridgedConfig.Slot("sonnet")), Map.of(), Map.of(), null));
|
||||
Principal p = CallerResolver.withLeadsAndMembers(workerIdentity(), false, null,
|
||||
Map::of, () -> arch).resolve("127.0.0.1", 42, null);
|
||||
Map::of, members).resolve("127.0.0.1", 42, null);
|
||||
|
||||
assertEquals(Role.WORKER, p.role());
|
||||
assertNull(p.name());
|
||||
@@ -376,16 +378,6 @@ class CallerResolverTest {
|
||||
assertEquals("architect:lead-designer", r.members().get("term_a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void theArchitectMapFormIsCopiedSoLaterMutationCannotGrantArchitect() {
|
||||
Map<String, String> mutable = new java.util.LinkedHashMap<>();
|
||||
CallerResolver r = new CallerResolver(workerIdentity(), false, null, Map.of(), mutable);
|
||||
|
||||
mutable.put("term_a", "sneaky");
|
||||
|
||||
assertEquals(Role.WORKER, r.resolve("127.0.0.1", 42, null).role());
|
||||
}
|
||||
|
||||
@Test
|
||||
void describeNamesTheArchitectSlot() {
|
||||
assertEquals("architect:lead-designer",
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.ltms.bridged.mcp;
|
||||
|
||||
import dev.ltms.bridged.auth.Authz;
|
||||
import dev.ltms.bridged.auth.CallerResolver;
|
||||
import dev.ltms.bridged.auth.MemberRegistry;
|
||||
import dev.ltms.bridged.auth.Principal;
|
||||
import dev.ltms.bridged.auth.Role;
|
||||
import dev.ltms.bridged.config.BridgedConfig;
|
||||
@@ -69,7 +70,8 @@ class BridgeMcpAuthzTest {
|
||||
|
||||
mcp = new BridgeMcp(messages, workers, sessions, identity, sessions.asPresence(),
|
||||
new PrimaryRegistry(null),
|
||||
enforce ? new CallerResolver(identity) : null,
|
||||
enforce ? CallerResolver.withLeadsAndMembers(identity, false, null,
|
||||
Map::of, new MemberRegistry(null)) : null,
|
||||
metrics);
|
||||
return mcp;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.ltms.bridged.rest;
|
||||
|
||||
import dev.ltms.bridged.auth.CallerResolver;
|
||||
import dev.ltms.bridged.auth.MemberRegistry;
|
||||
import dev.ltms.bridged.config.BridgedConfig;
|
||||
import dev.ltms.bridged.guard.SubscriptionGuard;
|
||||
import dev.ltms.bridged.herdr.AgentControl;
|
||||
@@ -65,9 +66,8 @@ class BridgedAppAuthTest {
|
||||
MessageService messages = new MessageService(agents, injector, new Rendezvous());
|
||||
|
||||
ConnectionIdentity identity = new ConnectionIdentity(new PaneLocator(herdr), _ -> pid);
|
||||
CallerResolver callers = tokenMode
|
||||
? new CallerResolver(identity, true, token)
|
||||
: new CallerResolver(identity);
|
||||
CallerResolver callers = CallerResolver.withLeadsAndMembers(identity, tokenMode, token,
|
||||
Map::of, new MemberRegistry(null));
|
||||
metrics = BridgedMetrics.create(sessions, new dev.ltms.bridged.msg.InMemoryReplyInbox());
|
||||
|
||||
app = new BridgedApp(herdr, workers, sessions, messages, sessions.asPresence(), null,
|
||||
|
||||
Reference in New Issue
Block a user