Documentation
¶
Overview ¶
Package sessionoverlay owns the SESSION-scoped safe-subset overlay of the agent-config control plane: the lower tier of the authorization matrix. A session-scoped (non-admin) end user may set a user-instruction prompt layer, NARROW (never widen) source/tool enablement within the admin-allowed set, and manage ephemeral personal skills. The overlay composes OVER the admin agent config at run start; it can only ever narrow a capability the admin granted, never grant a new one.
Keying — the session is the isolation boundary (CLAUDE.md §6) ¶
Unlike the admin agent-config registry (which keys by a synthetic {tenant, "__agentcfg__", agentID} identity so config is agent-level), the session overlay is keyed by the caller's REAL (tenant, user, session) triple plus the agent id in the record Kind. The StateStore is identity-scoped by the triple, so one session's overlay is invisible to another session by construction — there is no code path where session A's overlay reaches session B's run.
The safe subset is structurally narrow-only ¶
The persisted Overlay carries ONLY a user prompt layer (never a base), a source/tool DISABLE set (never an enable), and the names of the session's ephemeral personal skills. Because the shape has no base-prompt field and no enable field, a session caller PHYSICALLY cannot widen a capability or edit the operator base — the data model carries the guarantee; the projection's union-only composition is the second layer.
Concurrent reuse (the concurrent-reuse contract) ¶
A constructed Store is immutable after construction except for the closed atomic flag; every read is fresh from the StateStore (no cache). Safe to share across N concurrent goroutines; per-call state lives in arguments and locals.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrIdentityRequired — a method was called with an incomplete identity // triple or an empty agent id. Fails closed (CLAUDE.md §6). ErrIdentityRequired = errors.New("agentcfg/sessionoverlay: identity triple incomplete") // ErrInvalidConfig — NewStore was called with a nil StateStore. ErrInvalidConfig = errors.New("agentcfg/sessionoverlay: invalid configuration") // ErrClosed — a method was called after Close. ErrClosed = errors.New("agentcfg/sessionoverlay: store is closed") ErrStateUnavailable = errors.New("agentcfg/sessionoverlay: state store unavailable") // ErrInvalidInput — a method was called with an empty/invalid argument // (an empty personal-skill name on add/remove). ErrInvalidInput = errors.New("agentcfg/sessionoverlay: invalid input") )
Sentinel errors. Callers compare via errors.Is.
Functions ¶
This section is empty.
Types ¶
type Overlay ¶
type Overlay struct {
// UserPrompt is the session's user-instruction prompt layer. It composes
// ABOVE the admin base in the lower-trust `<user_instructions>` position
// (escaped); it can extend the operator's guidance but never precede,
// replace, or weaken the operator base. There is intentionally NO Base
// field — a session caller cannot write the operator base.
UserPrompt string `json:"user_prompt,omitempty"`
// DisabledServers names MCP servers the session has DISABLED. At
// projection these are UNIONED into the admin exclusion set (the session
// can only ADD to the disabled set, never remove an admin exclusion) — so
// the result can only ever NARROW the admin-allowed exposure.
DisabledServers []string `json:"disabled_servers,omitempty"`
// DisabledTools names tools the session has DISABLED. Unioned into the
// admin exclusion set at projection (narrow-only).
DisabledTools []string `json:"disabled_tools,omitempty"`
// PersonalSkills names the session's ephemeral personal skills (the
// bodies live in the session-scoped SkillStore under the same triple).
// They are added back to the session's skill view at projection and
// never promote to the agent/tenant scope.
PersonalSkills []string `json:"personal_skills,omitempty"`
}
Overlay is the session-scoped safe-subset desired state. Every field is a SAFE capability: a user prompt layer that composes ABOVE the operator base, a narrow-only source/tool disable set, and the names of the session's ephemeral personal skills.
type Store ¶
type Store interface {
// Get returns the session's overlay for the agent and whether one exists.
// No overlay returns (zero, false, nil).
Get(ctx context.Context, id identity.Quadruple, agentID string) (Overlay, bool, error)
// SetUserPrompt sets ONLY the user prompt layer, preserving the disable
// set + personal skills. An empty prompt clears the user layer.
SetUserPrompt(ctx context.Context, id identity.Quadruple, agentID, prompt string) (Overlay, error)
// SetSourceDisables replaces the narrow-only DISABLE set (servers +
// tools), preserving the user prompt + personal skills. There is no
// "enable" — the set names what the session wants OFF; the projection
// unions it into the admin exclusion set, so it can only narrow.
SetSourceDisables(ctx context.Context, id identity.Quadruple, agentID string, servers, tools []string) (Overlay, error)
// AddPersonalSkill records a personal-skill name (idempotent), preserving
// every other field.
AddPersonalSkill(ctx context.Context, id identity.Quadruple, agentID, name string) (Overlay, error)
// RemovePersonalSkill removes a personal-skill name (idempotent),
// preserving every other field.
RemovePersonalSkill(ctx context.Context, id identity.Quadruple, agentID, name string) (Overlay, error)
// Close releases resources. Idempotent.
Close(ctx context.Context) error
}
Store is the session-scoped overlay persistence surface. It is a compiled artifact: immutable after construction and safe for concurrent reuse.
func NewStore ¶
NewStore builds a session-overlay Store over a StateStore. st is mandatory — a nil fails loud with ErrInvalidConfig rather than building a store that would nil-panic on the first request (CLAUDE.md §5).
The returned Store is immutable after construction and safe for concurrent use by N goroutines.