mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 09:39:25 +00:00
fix: require declared scheduled write adapters (#151064)
Scheduled message mutations now require their saved provider/account scope and an adapter-declared live-authority contract, without changing direct or interactive actions. Fixes #151060. Refs #140978.
This commit is contained in:
parent
f6d8e23461
commit
2bbfc3c8b2
3 changed files with 38 additions and 14 deletions
|
|
@ -699,8 +699,8 @@ An opted-in adapter must honor the existing
|
|||
|
||||
This optional field keeps older adapters source-compatible. An omitted or empty
|
||||
declaration leaves newly enabled scheduled actions denied. Existing bundled
|
||||
provider-owned message-management paths keep their admission rules. To support
|
||||
the new installed-plugin path,
|
||||
provider-owned interactive paths keep their admission rules. To support the new
|
||||
installed-plugin path,
|
||||
upgrade OpenClaw and the plugin, implement the request and retry checks above,
|
||||
declare only the covered actions, and load the updated registration. Existing
|
||||
direct-operator and interactive actions retain their admission rules. Upgrading
|
||||
|
|
|
|||
|
|
@ -540,15 +540,6 @@ function prepareScheduledMessageWriteContext(
|
|||
if (!policy || !ctx.messageActionAuthorization?.scheduled) {
|
||||
return undefined;
|
||||
}
|
||||
if (
|
||||
policy === "provider" &&
|
||||
prepared.enforcement.kind === "provider-owned" &&
|
||||
prepared.enforcement.pluginTrust === "bundled" &&
|
||||
!prepared.plugin.actions?.writeAuthorityActions?.includes(action)
|
||||
) {
|
||||
// Retain existing bundled provider admission until its adapter opts into this fence.
|
||||
return undefined;
|
||||
}
|
||||
const accountId =
|
||||
ctx.accountId ?? resolveChannelDefaultAccountId({ plugin: prepared.plugin, cfg: ctx.cfg });
|
||||
const access = resolveScheduledMessageActionAccess({
|
||||
|
|
|
|||
|
|
@ -1480,16 +1480,49 @@ describe("CLI message authority integration", () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it("preserves bundled provider-owned scheduled pins without a write declaration", async () => {
|
||||
it("keeps bundled interactive pins but denies undeclared scheduled writes", async () => {
|
||||
registerChannelPlugins({ discordOrigin: "bundled" });
|
||||
const actions = expectDefined(registeredDiscordActions, "bundled Discord actions");
|
||||
delete actions.writeAuthorityActions;
|
||||
const turn = await createTurn("discord", { scheduledPolicy: accountScheduledPolicy });
|
||||
|
||||
const interactiveTurn = await createTurn("discord");
|
||||
expectSuccess(
|
||||
await turn.call({ ...messageTarget, action: "pin", target: `channel:${discordSibling}` }),
|
||||
await interactiveTurn.call({
|
||||
...messageTarget,
|
||||
action: "pin",
|
||||
target: `channel:${discordSibling}`,
|
||||
}),
|
||||
);
|
||||
const requestCount = requests.length;
|
||||
const mismatchedOriginPolicy: ScheduledToolPolicyContext = {
|
||||
...accountScheduledPolicy,
|
||||
ownerSessionKey: `agent:main:slack:channel:${channels.slack.current}`,
|
||||
ownerOrigin: { kind: "external", channel: "slack" },
|
||||
};
|
||||
|
||||
const mismatchedOriginTurn = await createTurn("discord", {
|
||||
scheduledPolicy: mismatchedOriginPolicy,
|
||||
});
|
||||
expectDenied(
|
||||
await mismatchedOriginTurn.call({
|
||||
...messageTarget,
|
||||
action: "pin",
|
||||
target: `channel:${discordSibling}`,
|
||||
}),
|
||||
/matching recorded creator origin/,
|
||||
);
|
||||
const undeclaredTurn = await createTurn("discord", {
|
||||
scheduledPolicy: accountScheduledPolicy,
|
||||
});
|
||||
expectDenied(
|
||||
await undeclaredTurn.call({
|
||||
...messageTarget,
|
||||
action: "pin",
|
||||
target: `channel:${discordSibling}`,
|
||||
}),
|
||||
/write authorization support/,
|
||||
);
|
||||
expect(requests).toHaveLength(requestCount);
|
||||
expect(requests.filter((request) => request.method !== "GET")).toEqual([
|
||||
expect.objectContaining({
|
||||
method: "PUT",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue