mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-15 03:55:09 +08:00
test(goal): verify persisted approval identity for managed JSON
This commit is contained in:
parent
1931b0698e
commit
770f4e16d5
@ -60,3 +60,5 @@ Built-in shell/code execution is not OS-isolated from the service host. Selectin
|
||||
Recovery attempts receive guidance to inspect existing evidence before repeating work. If the first recovered segment is deferred before execution, its recovery context is retained for the next claim. Ordinary continuation after an executed segment does not become a new recovery.
|
||||
|
||||
From V199, queued Web input stores the authenticated account ID at enqueue time, and ordinary Web replay carries the conversation workspace. Managed operations still recheck the account, ownership and current requirements. Legacy queue items do not gain an asserted identity from a username; users must resend an authenticated request for managed JSON operations. Persistent Goal workers retain their existing attempt-owner validation when consuming input; this does not introduce an account path without a lease check.
|
||||
|
||||
Approval replay restores the persisted runtime identity; approval does not renew an expired attempt lease or override account revocation. Legacy snapshots without an authenticated account ID cannot gain managed JSON access from a display username alone.
|
||||
|
||||
@ -62,3 +62,5 @@ Web排队消息从V199起保存入队时已认证账户的内部ID,普通Web
|
||||
恢复执行会收到先核实已有证据、不要重放未知副作用的提示。首次恢复执行若在实际运行前延期,下一次领取仍保留恢复关联;已经执行过后的普通续跑不会因此变成新恢复。
|
||||
|
||||
会话归档或改绑 Agent 后,旧运行上下文不能再读取托管运行状态、发布、检查或完成目标;有权用户仍可读取已保存的证据。此检查与当前 Goal 身份和租约校验处于同一事务。
|
||||
|
||||
审批重放还原持久化的运行身份,但审批不会延长过期 attempt 租约,也不能覆盖账户撤权。缺少认证账户 ID 的旧快照不能仅凭显示用户名获得托管 JSON 权限。
|
||||
|
||||
@ -44,6 +44,7 @@ class GoalJsonAcceptanceIntegrationTest {
|
||||
@Autowired private vip.mate.goal.service.GoalRunCoordinator coordinator;
|
||||
@Autowired private vip.mate.goal.service.GoalRecoveryService recovery;
|
||||
@Autowired private vip.mate.goal.service.GoalAttemptStore attempts;
|
||||
@Autowired private vip.mate.approval.ApprovalWorkflowService approvals;
|
||||
|
||||
private String alice;
|
||||
private String bob;
|
||||
@ -687,6 +688,44 @@ class GoalJsonAcceptanceIntegrationTest {
|
||||
: goals.markRuntimeCompleted(goal.getId(), evaluation, origin);
|
||||
}
|
||||
|
||||
@ParameterizedTest @ValueSource(strings = {"account", "scheduled", "legacy"})
|
||||
void persistedApprovalOriginRetainsIdentityButCannotOverrideCurrentAuthorization(String kind) {
|
||||
GoalEntity goal = goal(kind.equals("scheduled"));
|
||||
acceptance.configure(goal.getId(), "r", request(0, "summary"), alice);
|
||||
var run = kind.equals("scheduled") ? claimed(goal) : null;
|
||||
var origin = run != null ? attemptOrigin(goal, run) : kind.equals("legacy")
|
||||
? vip.mate.agent.context.ChatOrigin.web(goal.getConversationId(), alice, 1L, null).withAgent(1L)
|
||||
: accountOrigin(goal, alice);
|
||||
String pending;
|
||||
vip.mate.agent.context.ChatOriginHolder.set(origin);
|
||||
try {
|
||||
pending = approvals.createPending(goal.getConversationId(), alice, "read_file", "{}", "offline origin fixture",
|
||||
"[]", null, "1");
|
||||
} finally { vip.mate.agent.context.ChatOriginHolder.clear(); }
|
||||
String persisted = jdbc.queryForObject("SELECT chat_origin FROM mate_tool_approval WHERE pending_id=?", String.class, pending);
|
||||
assertNotNull(persisted);
|
||||
var consumed = approvals.resolveAndConsume(pending, alice).consumedSnapshot();
|
||||
assertNotNull(consumed);
|
||||
assertEquals(persisted, consumed.getChatOrigin());
|
||||
var restored = approvals.restoreChatOrigin(consumed.getChatOrigin());
|
||||
assertEquals(origin.requesterUserId(), restored.requesterUserId());
|
||||
assertEquals(origin.executionAttribution(), restored.executionAttribution());
|
||||
var replay = restored.withApprovalId(pending);
|
||||
assertEquals(pending, replay.executionAttribution().approvalId());
|
||||
assertEquals("CONSUMED", jdbc.queryForObject("SELECT status FROM mate_tool_approval WHERE pending_id=?", String.class, pending));
|
||||
if (kind.equals("legacy")) {
|
||||
assertThrows(MateClawException.class, () -> artifacts.publishForRuntime(replay, "report", publication(0, "{\"summary\":true}")));
|
||||
assertEquals(0, jdbc.queryForObject("SELECT COUNT(*) FROM mate_goal_json_artifact WHERE goal_id=?", Integer.class, goal.getId()));
|
||||
} else {
|
||||
artifacts.publishForRuntime(replay, "report", publication(0, "{\"summary\":true}"));
|
||||
if (run != null) jdbc.update("UPDATE mate_goal_attempt SET lease_until_epoch_second=? WHERE attempt_id=?",
|
||||
java.time.Instant.now().minusSeconds(1).getEpochSecond(), run.attempt().id());
|
||||
else jdbc.update("UPDATE mate_user SET enabled=FALSE WHERE username=?", alice);
|
||||
assertThrows(MateClawException.class, () -> bindings.snapshotForRuntime(replay),
|
||||
"Persisted approval is not a replacement for the current account or attempt lease");
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@org.junit.jupiter.params.provider.CsvSource({"false,agent", "true,agent", "false,archived", "true,archived"})
|
||||
void staleConversationRuntimeCannotUseManagedOperationsAfterScopeChanges(boolean scheduled, String change) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user