policy: guard adoption baselines, resolve-time validation, and inherited-delta narration

Review fixes (ds-review-bot on #623):

- Persistence adoption compares the immutable policy baselines: onCreated's
  ownerless claim and adoptLivePrefix retain the STORED header, so a
  same-id live session with a conflicting baseline now rejects as a
  collision instead of appending under read-only and resuming under the
  stored danger-full-access.
- resolve() resolves the session override BEFORE applying an explicit
  approved mode: the one-shot grant no longer bypasses the unconditional
  durable-header validation.
- The approval narrator attributes positionally over the session's OWN
  events (past the seed boundary): a fork child whose baseline delta has
  no own override narrates 'inherited from the delegating session' instead
  of misattributing a stale seed-carried switch to the user or the
  operator.

Red-first: baseline-conflict adoption in the shared coordinator contract
(both backends), resolve-with-explicit-mode validation, and the fork-child
narration attribution case.
This commit is contained in:
kingwl
2026-07-26 23:56:41 +08:00
parent 9aaa4a871f
commit 290e1acc45
9 changed files with 105 additions and 15 deletions

View File

@@ -99,8 +99,12 @@ export class SandboxPolicyService extends Service {
*/
resolve(request: SandboxPolicyRequest = {}): SandboxExecutionPolicy {
const { session } = request
// Resolve the session override FIRST even when an explicit approved mode
// outranks it: the unconditional durable-header validation must hold on
// every resolution — a one-shot grant is not a validation bypass.
const override = session === undefined ? undefined : this.overrideOf(session)
return {
mode: request.mode ?? (session === undefined ? undefined : this.overrideOf(session)) ?? this.defaultMode,
mode: request.mode ?? override ?? this.defaultMode,
workspaceRoot: resolveWorkspaceRoot(session?.header.cwd ?? this.workspaceRoot),
}
}