mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-30 01:06:11 +00:00
fix(gateway): gate agent model overrides by admin scope
Keep plugin subagent provider/model overrides working for synthetic admin dispatch, but stop forwarding those overrides for plain operator.write gateway callers. Add regressions for both the admin-allowed and write-scoped paths. Regeneration-Prompt: | After the first fix for PR #48277, Codex flagged that gateway agent requests were now forwarding provider/model overrides for every operator.write caller. Verify that claim against the current gateway trust model and method scopes. Preserve the plugin subagent use case, which dispatches with the synthetic admin gateway client, but restore least-privilege behavior for normal write-scoped agent RPC callers. The boundary should be enforced at the gateway handler so the core agent command path can still support trusted callers. Add focused tests proving admin callers keep override forwarding while write-scoped callers do not.
This commit is contained in:
@@ -303,7 +303,7 @@ describe("gateway agent handler", () => {
|
||||
expect(capturedEntry?.acp).toEqual(existingAcpMeta);
|
||||
});
|
||||
|
||||
it("forwards provider and model overrides to ingress agent runs", async () => {
|
||||
it("forwards provider and model overrides for admin-scoped callers", async () => {
|
||||
primeMainAgentRun();
|
||||
|
||||
await invokeAgent(
|
||||
@@ -315,7 +315,14 @@ describe("gateway agent handler", () => {
|
||||
model: "claude-haiku-4-6",
|
||||
idempotencyKey: "test-idem-model-override",
|
||||
},
|
||||
{ reqId: "test-idem-model-override" },
|
||||
{
|
||||
reqId: "test-idem-model-override",
|
||||
client: {
|
||||
connect: {
|
||||
scopes: ["operator.admin"],
|
||||
},
|
||||
} as AgentHandlerArgs["client"],
|
||||
},
|
||||
);
|
||||
|
||||
const lastCall = mocks.agentCommand.mock.calls.at(-1);
|
||||
@@ -327,6 +334,37 @@ describe("gateway agent handler", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("does not forward provider and model overrides for write-scoped callers", async () => {
|
||||
primeMainAgentRun();
|
||||
|
||||
await invokeAgent(
|
||||
{
|
||||
message: "test override",
|
||||
agentId: "main",
|
||||
sessionKey: "agent:main:main",
|
||||
provider: "anthropic",
|
||||
model: "claude-haiku-4-6",
|
||||
idempotencyKey: "test-idem-model-override-write",
|
||||
},
|
||||
{
|
||||
reqId: "test-idem-model-override-write",
|
||||
client: {
|
||||
connect: {
|
||||
scopes: ["operator.write"],
|
||||
},
|
||||
} as AgentHandlerArgs["client"],
|
||||
},
|
||||
);
|
||||
|
||||
const lastCall = mocks.agentCommand.mock.calls.at(-1);
|
||||
expect(lastCall?.[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
provider: undefined,
|
||||
model: undefined,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves cliSessionIds from existing session entry", async () => {
|
||||
const existingCliSessionIds = { "claude-cli": "abc-123-def" };
|
||||
const existingClaudeCliSessionId = "abc-123-def";
|
||||
|
||||
@@ -194,6 +194,8 @@ export const agentHandlers: GatewayRequestHandlers = {
|
||||
inputProvenance?: InputProvenance;
|
||||
};
|
||||
const senderIsOwner = resolveSenderIsOwnerFromClient(client);
|
||||
const providerOverride = senderIsOwner ? request.provider : undefined;
|
||||
const modelOverride = senderIsOwner ? request.model : undefined;
|
||||
const cfg = loadConfig();
|
||||
const idem = request.idempotencyKey;
|
||||
const normalizedSpawned = normalizeSpawnedRunMetadata({
|
||||
@@ -586,8 +588,8 @@ export const agentHandlers: GatewayRequestHandlers = {
|
||||
ingressOpts: {
|
||||
message,
|
||||
images,
|
||||
provider: request.provider,
|
||||
model: request.model,
|
||||
provider: providerOverride,
|
||||
model: modelOverride,
|
||||
to: resolvedTo,
|
||||
sessionId: resolvedSessionId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
|
||||
Reference in New Issue
Block a user