subagent: seed inherited policy events at creation
The parent implementation introduced sandboxMode and approvalPolicy as generic SessionHeader fields, then propagated those fields through both persistence backends, session-query indexes, collision checks, policy-specific seed-boundary folds, catalogs, and a broad test matrix. That storage plane is unnecessary: Session already accepts a validated constructor seed, and persistence captures that seed when the session is announced before committing its first batch. Capture each parent override synchronously at delegation, append source-tagged sandbox/mode and approval/policy records after the optional fork prefix, and create the child with that combined seed. Keeping header.seedLength at the original fork-prefix length preserves lineage while ordinary last-event-wins folds make the inherited records outrank stale parent history and remain subordinate to later child switches. Unswitched parents still stamp nothing, so children continue to follow deployment defaults. Remove the generic header fields and every persistence/query/schema branch built around them. Collapse the inheritance suite from ten leaking scenarios to four owned-context cases covering real filesystem confinement, stale fork precedence, delegation-time capture, and the no-override path. The assembled headless snapshot now asserts the persisted inheritance event directly. This keeps the security behavior while restoring policy ownership to the existing event log and deleting the speculative durability machinery that the original tests did not exercise.
This commit is contained in:
@@ -143,14 +143,6 @@ function snapshotSessionHeader(id: SessionId, source?: SessionHeader): SessionHe
|
||||
&& (typeof record.delegationDepth !== 'number' || !Number.isSafeInteger(record.delegationDepth) || record.delegationDepth < 0)) {
|
||||
throw new Error('session header delegationDepth must be a non-negative safe integer')
|
||||
}
|
||||
// Neutral strings only: the owning policy packages validate the values
|
||||
// against their closed vocabularies on read (durable boundary).
|
||||
if (record.sandboxMode !== undefined && typeof record.sandboxMode !== 'string') {
|
||||
throw new Error('session header sandboxMode must be a string')
|
||||
}
|
||||
if (record.approvalPolicy !== undefined && typeof record.approvalPolicy !== 'string') {
|
||||
throw new Error('session header approvalPolicy must be a string')
|
||||
}
|
||||
return deepFreeze(record as unknown as SessionHeader)
|
||||
}
|
||||
|
||||
@@ -776,8 +768,6 @@ export class SessionStore extends Service {
|
||||
...meta?.parentSession === undefined ? {} : { parentSession: meta.parentSession },
|
||||
...meta?.seedLength === undefined ? {} : { seedLength: meta.seedLength },
|
||||
...meta?.delegationDepth === undefined ? {} : { delegationDepth: meta.delegationDepth },
|
||||
...meta?.sandboxMode === undefined ? {} : { sandboxMode: meta.sandboxMode },
|
||||
...meta?.approvalPolicy === undefined ? {} : { approvalPolicy: meta.approvalPolicy },
|
||||
}
|
||||
return new Session(sessionId, seed, header)
|
||||
}
|
||||
|
||||
@@ -64,24 +64,6 @@ export interface SessionHeader {
|
||||
* resume — a runtime-only depth would reset a resumed child to top-level.
|
||||
*/
|
||||
readonly delegationDepth?: number
|
||||
/**
|
||||
* The sandbox-mode override inherited from the delegating parent at
|
||||
* creation (the delegation-inheritance baseline). A neutral string here:
|
||||
* the policy owner (`dsh-sandbox-policy`) validates it against its closed
|
||||
* vocabulary on every read, this being a durable boundary. Absent for
|
||||
* top-level sessions and for children of unswitched parents, which keep
|
||||
* following the LIVE deployment default. Header-carried (the
|
||||
* `delegationDepth` precedent) so the baseline is durable from the creation
|
||||
* moment — no first-turn event survives every crash window, because an
|
||||
* idle injection can persist a complete turn before any prompt turn opens.
|
||||
*/
|
||||
readonly sandboxMode?: string
|
||||
/**
|
||||
* The approval-policy override inherited from the delegating parent at
|
||||
* creation. Same contract as {@link SessionHeader.sandboxMode}; validated
|
||||
* by `dsh-user-approval` on read.
|
||||
*/
|
||||
readonly approvalPolicy?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +72,7 @@ export interface SessionHeader {
|
||||
* store folds into a {@link SessionHeader}.
|
||||
*/
|
||||
export interface CreateSessionOptions {
|
||||
/** Events to seed the new session with (replay/fork). */
|
||||
/** Initial log events supplied at construction (replay, fork, or creation-time facts). */
|
||||
readonly seed?: readonly SessionEvent[]
|
||||
/**
|
||||
* Storage metadata read once before publication. `seedLength` is explicit
|
||||
@@ -102,8 +84,6 @@ export interface CreateSessionOptions {
|
||||
readonly createdAt?: number
|
||||
readonly seedLength?: number
|
||||
readonly delegationDepth?: number
|
||||
readonly sandboxMode?: string
|
||||
readonly approvalPolicy?: string
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user