policy: scope seed-boundary slicing to delegation children
Review fix (ds-review-bot on #623): the unconditional slice regressed the public SessionStore.fork path — a generic fork child gets seedLength but no policy baseline, so slicing discarded its seed-carried sandbox/approval switches and silently widened it to the deployment defaults (a forked read-only/never parent produced a workspace-write/ask child). overrideOf now branches on baseline presence: with a header baseline (a delegation child) the fold covers only own post-seed switches — the baseline captured from the parent's FULL log subsumes seed history; without one, the whole log — seeded switches ARE the replayed inherited truth. The permission preset fold scopes the same way. Red-first: generic-fork seed-carried override tests in both policy suites.
This commit is contained in:
@@ -143,10 +143,11 @@ export class PermissionService extends Service {
|
||||
* override chains execution reads (own post-seed switches, else the
|
||||
* inherited header baseline, else the composition defaults), so a
|
||||
* delegated child's inherited knobs derive its real preset. A
|
||||
* still-matching last OWN selection wins shared-bundle ties (a seed-carried
|
||||
* selection is stale parent history, subsumed by the baseline); otherwise
|
||||
* the first table match wins, or {@link CUSTOM_PRESET} when no entry
|
||||
* matches.
|
||||
* still-matching last selection wins shared-bundle ties, scoped like the
|
||||
* knob chains: a delegation child (header baselines present) ignores
|
||||
* seed-carried selections as stale parent history, while a generic fork
|
||||
* child keeps them alongside its seed-carried knobs; otherwise the first
|
||||
* table match wins, or {@link CUSTOM_PRESET} when no entry matches.
|
||||
* @param session - the session whose preset to derive.
|
||||
* @returns the effective preset name, or `custom` when nothing matches.
|
||||
*/
|
||||
@@ -154,7 +155,8 @@ export class PermissionService extends Service {
|
||||
const sandbox = sandboxOverrideOf(session) ?? this.ctx.bash.sandboxMode
|
||||
const approval = approvalOverrideOf(session) ?? this.ctx.approval.config.policy ?? 'ask'
|
||||
const matches = (spec: PresetSpec): boolean => spec.sandbox === sandbox && spec.approval === approval
|
||||
const folded = effectivePermissionPreset(session.events.slice(session.header.seedLength ?? 0))
|
||||
const delegated = session.header.sandboxMode !== undefined || session.header.approvalPolicy !== undefined
|
||||
const folded = effectivePermissionPreset(delegated ? session.events.slice(session.header.seedLength ?? 0) : session.events)
|
||||
if (folded !== undefined) {
|
||||
const spec = this.presets[folded]
|
||||
if (spec !== undefined && matches(spec)) return folded
|
||||
|
||||
Reference in New Issue
Block a user