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:
@@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,4 +229,13 @@ describe('delegation inheritance (overrideOf over the header baseline)', () => {
|
||||
|
||||
expect(() => ctx.sandboxPolicy.overrideOf(child)).toThrow(/seedLength/)
|
||||
})
|
||||
|
||||
it('resolve() validates the durable header even when an explicit approved mode is supplied', async () => {
|
||||
const ctx = await mounted()
|
||||
const child = inheritedSession('sess-resolve-invalid', { sandboxMode: 'yolo' })
|
||||
|
||||
// The explicit one-shot grant must not become a validation bypass: the
|
||||
// unconditional durable-header contract holds on EVERY resolution.
|
||||
expect(() => ctx.sandboxPolicy.resolve({ session: child, mode: 'workspace-write' })).toThrow(/sandboxMode/)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user