sessioncontext

package
v0.52.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package sessioncontext owns private, durable session context and immutable input pins. Source execution and Detective evaluation remain in their existing domains.

Index

Constants

View Source
const (
	Sessions      = "sessionContextSessions"
	Bags          = "sessionContextBags"
	Entries       = "sessionContextEntries"
	Revisions     = "sessionContextEntryRevisions"
	ContextSets   = "sessionContextSets"
	Operations    = "sessionContextOperations"
	Audit         = "sessionContextAudit"
	Inputs        = "sessionContextInputs"
	Runs          = "sessionContextRuns"
	Messages      = "sessionContextMessages"
	Outbox        = "sessionContextOutbox"
	LegacyImports = "sessionContextLegacyImports"
	// MaxSnapshotBytes caps the sum of serialized session, bag, context-set, current
	// entry and current revision records returned by GetSnapshot.
	MaxSnapshotBytes = 4 * 1024 * 1024
	// MaxSnapshotEntries bounds current entry and revision reads in one snapshot.
	MaxSnapshotEntries = 400
)

Variables

View Source
var (
	ErrNotFound    = errors.New("session context: not found")
	ErrConflict    = errors.New("session context: version conflict")
	ErrInvalid     = errors.New("session context: invalid command")
	ErrForbidden   = errors.New("session context: access denied")
	ErrReadOnly    = errors.New("session context: session is read-only")
	ErrUnavailable = errors.New("session context: storage unavailable")
)

Functions

func Collections

func Collections() []string

func ManifestCollectionsYAML

func ManifestCollectionsYAML() string

ManifestCollectionsYAML is the collections block beneath schemas in an OVDB manifest.

func SQLiteSchemaStatements

func SQLiteSchemaStatements() []string

SQLiteSchemaStatements provision the private local OVDB mount before opening it. These identifiers are compile-time constants; no user SQL is interpolated.

Types

type Access

type Access struct {
	Principal Principal
	Action    string
	SessionID string
	Scope     *Scope
}

type AppliedContextSet

type AppliedContextSet struct {
	ID        string        `json:"id"`
	SessionID string        `json:"sessionId"`
	Enabled   bool          `json:"enabled"`
	Slots     []AppliedSlot `json:"slots"`
	CreatedAt time.Time     `json:"createdAt"`
}

type AppliedSlot

type AppliedSlot struct {
	Scope      Scope      `json:"scope"`
	BagID      string     `json:"bagId"`
	BagVersion int64      `json:"bagVersion"`
	Version    int64      `json:"version"`
	Entries    []EntryRef `json:"entries"`
}

A slot with an empty bagId is a cleared tombstone. Its version prevents ABA reuse.

type AuditEvent

type AuditEvent struct {
	OpID       string    `json:"opId"`
	Actor      string    `json:"actor"`
	Action     string    `json:"action"`
	SessionID  string    `json:"sessionId"`
	ResourceID string    `json:"resourceId,omitempty"`
	Count      int       `json:"count"`
	At         time.Time `json:"at"`
}

type Authorizer

type Authorizer func(context.Context, Access) error

type Bag

type Bag struct {
	ID           string   `json:"id"`
	SessionID    string   `json:"sessionId"`
	Title        string   `json:"title"`
	Scope        Scope    `json:"scope"`
	Version      int64    `json:"version"`
	ClearVersion int64    `json:"clearVersion,omitempty"`
	EntryIDs     []string `json:"entryIds"`
}

type Command

type Command struct {
	OpID                 string         `json:"opId"`
	Action               string         `json:"action"`
	SessionID            string         `json:"sessionId"`
	ExpectedVersion      int64          `json:"expectedVersion,omitempty"`
	DatabaseID           string         `json:"databaseId,omitempty"`
	ProjectID            string         `json:"projectId,omitempty"`
	BagID                string         `json:"bagId,omitempty"`
	ExpectedBagVersion   int64          `json:"expectedBagVersion,omitempty"`
	ExpectedSlotVersion  int64          `json:"expectedSlotVersion,omitempty"`
	ExpectedContextSetID string         `json:"expectedContextSetId,omitempty"`
	EntryID              string         `json:"entryId,omitempty"`
	ExpectedEntryVersion int64          `json:"expectedEntryVersion,omitempty"`
	RevisionID           string         `json:"revisionId,omitempty"`
	Title                string         `json:"title,omitempty"`
	Alias                string         `json:"alias,omitempty"`
	Scope                *Scope         `json:"scope,omitempty"`
	Subject              *Subject       `json:"subject,omitempty"`
	Value                *ValueEnvelope `json:"value,omitempty"`
	Selection            []EntryRef     `json:"selection,omitempty"`
	Enabled              *bool          `json:"enabled,omitempty"`
	Transition           string         `json:"transition,omitempty"`
	// M3 input pins and durable run routing. Result rows remain in the existing result store.
	InputSnapshotID    string          `json:"inputSnapshotId,omitempty"`
	RunID              string          `json:"runId,omitempty"`
	Kind               string          `json:"kind,omitempty"`
	DefinitionID       string          `json:"definitionId,omitempty"`
	DefinitionRevision string          `json:"definitionRevision,omitempty"`
	DefinitionDocument json.RawMessage `json:"definitionDocument,omitempty"`
	ExecutionDocument  json.RawMessage `json:"executionDocument,omitempty"`
	Attachments        []EntryRef      `json:"attachments,omitempty"`
	Text               string          `json:"text,omitempty"`
	ExpectedRunVersion int64           `json:"expectedRunVersion,omitempty"`
	// reportClientRun accepts outcome-unknown only with the fixed
	// CLIENT_OUTCOME_UNKNOWN code and no result payload. It records uncertainty
	// after client interruption; it does not assert source failure or cancellation.
	RunState           string                            `json:"runState,omitempty"`
	Widgets            []WidgetOutcome                   `json:"widgets,omitempty"`
	ResultRefs         []string                          `json:"resultRefs,omitempty"`
	ErrorCode          string                            `json:"errorCode,omitempty"`
	CaseID             string                            `json:"caseId,omitempty"`
	DetectiveRunID     string                            `json:"detectiveRunId,omitempty"`
	ResolvedParameters map[string]apicontract.TypedValue `json:"resolvedParameters,omitempty"`
	LegacyImport       *LegacyImport                     `json:"legacyImport,omitempty"`
}

Command is shared by HTTP/terminal adapters. IDs are opaque, path-safe and stable. expectedVersion is the session version. expectedEntryVersion=0 creates an entry.

type CommandResult

type CommandResult struct {
	Receipt Receipt `json:"receipt"`
}

type DALRepository

type DALRepository struct {
	// contains filtered or unexported fields
}

func NewDALRepository

func NewDALRepository(mounted MountedDatabase, parent *record.Key) (*DALRepository, error)

func (*DALRepository) DatabaseID

func (r *DALRepository) DatabaseID() string

func (*DALRepository) Transact

func (r *DALRepository) Transact(ctx context.Context, f func(Transaction) error) error

Transact queues every write until the worker has completed all reads. Firestore transactions prohibit reads after writes, so this ordering is part of the contract.

func (*DALRepository) View

func (r *DALRepository) View(ctx context.Context, f func(Reader) error) error

type EntityKey

type EntityKey struct {
	Components []KeyComponent `json:"components"`
}

type Entry

type Entry struct {
	ID                string  `json:"id"`
	SessionID         string  `json:"sessionId"`
	BagID             string  `json:"bagId"`
	Alias             string  `json:"alias,omitempty"`
	Subject           Subject `json:"subject"`
	CurrentRevisionID string  `json:"currentRevisionId"`
	Version           int64   `json:"version"`
}

type EntryRef

type EntryRef struct {
	EntryID    string `json:"entryId"`
	RevisionID string `json:"revisionId"`
}

type EntryRevision

type EntryRevision struct {
	ID               string        `json:"id"`
	EntryID          string        `json:"entryId"`
	BagID            string        `json:"bagId"`
	ParentRevisionID string        `json:"parentRevisionId,omitempty"`
	Subject          Subject       `json:"subject"`
	Value            ValueEnvelope `json:"value"`
	CreatedAt        time.Time     `json:"createdAt"`
	Provenance       string        `json:"provenance,omitempty"`
	LegacySourceID   string        `json:"legacySourceId,omitempty"`
	SourceDigest     string        `json:"sourceDigest,omitempty"`
}

type EvidenceHandoff

type EvidenceHandoff struct {
	ID              string `json:"id"`
	SessionID       string `json:"sessionId"`
	RunID           string `json:"runId"`
	InputSnapshotID string `json:"inputSnapshotId"`
	CaseID          string `json:"caseId"`
	DetectiveRunID  string `json:"detectiveRunId"`
	State           string `json:"state"`
	ErrorCode       string `json:"errorCode,omitempty"`
}

EvidenceHandoff cannot replace Detective's native CaseRunLink transaction. A worker finalizes the native Detective operation, then marks this handoff delivered.

type InputSnapshot

type InputSnapshot struct {
	ID                 string                            `json:"id"`
	SessionID          string                            `json:"sessionId"`
	ContextSetID       string                            `json:"contextSetId"`
	Scope              Scope                             `json:"scope"`
	Entries            []EntryRef                        `json:"entries"`
	DefinitionDigest   string                            `json:"definitionDigest"`
	DefinitionDocument json.RawMessage                   `json:"definitionDocument"`
	ResolvedParameters map[string]apicontract.TypedValue `json:"resolvedParameters,omitempty"`
	ParametersOrigin   string                            `json:"parametersOrigin,omitempty"`
	CreatedAt          time.Time                         `json:"createdAt"`
}

type KeyComponent

type KeyComponent struct {
	Field string                 `json:"field"`
	Value apicontract.TypedValue `json:"value"`
}

type LegacyChatMessage

type LegacyChatMessage struct {
	ID        string    `json:"id"`
	Role      string    `json:"role"`
	Text      string    `json:"text"`
	CreatedAt time.Time `json:"createdAt,omitempty"`
}

type LegacyEntry

type LegacyEntry struct {
	ID        string        `json:"id"`
	Alias     string        `json:"alias,omitempty"`
	Subject   Subject       `json:"subject"`
	Value     ValueEnvelope `json:"value"`
	CreatedAt time.Time     `json:"createdAt,omitempty"`
}

type LegacyImport

type LegacyImport struct {
	SourceID string              `json:"sourceId"`
	Title    string              `json:"title,omitempty"`
	Scope    Scope               `json:"scope"`
	Entries  []LegacyEntry       `json:"entries,omitempty"`
	Messages []LegacyChatMessage `json:"messages,omitempty"`
}

LegacyImport is a bounded, read-only migration payload. It imports saved context values and historical chat turns; it never creates executable runs.

type LegacyImportManifest

type LegacyImportManifest struct {
	ID           string    `json:"id"`
	SessionID    string    `json:"sessionId"`
	BagID        string    `json:"bagId"`
	SourceID     string    `json:"sourceId"`
	SourceDigest string    `json:"sourceDigest"`
	Scope        Scope     `json:"scope"`
	CreatedAt    time.Time `json:"createdAt"`
}

LegacyImportManifest is private idempotency state keyed by a digest of the source identity, actor, project, and execution scope.

type Message

type Message struct {
	ID              string    `json:"id"`
	SessionID       string    `json:"sessionId"`
	InputSnapshotID string    `json:"inputSnapshotId"`
	Role            string    `json:"role"`
	Text            string    `json:"text"`
	CreatedAt       time.Time `json:"createdAt"`
	Provenance      string    `json:"provenance,omitempty"`
	LegacySourceID  string    `json:"legacySourceId,omitempty"`
	SourceDigest    string    `json:"sourceDigest,omitempty"`
	HistoricalAt    time.Time `json:"historicalAt,omitempty"`
	SourceScope     Scope     `json:"sourceScope,omitempty"`
}

type MountedDatabase

type MountedDatabase interface {
	ID() string
	DB() dal.DB
}

MountedDatabase is implemented by OVDB core.Database. The identity is captured with its mounted DALgo engine; clients cannot supply a raw storage connection.

type Page

type Page[T any] struct {
	Items      []T    `json:"items"`
	NextCursor string `json:"nextCursor,omitempty"`
	HasMore    bool   `json:"hasMore"`
}

type Principal

type Principal struct {
	// Executor is set only by the server runtime when persisting an actual outcome.
	Executor   bool
	Actor      string
	DatabaseID string
	ProjectID  string
}

Principal is supplied by the authorized server boundary, never decoded from a command.

type Reader

type Reader interface {
	Load(context.Context, string, string, any) (int64, error)
	List(context.Context, string, string, string, int) ([]json.RawMessage, string, error)
}

type Receipt

type Receipt struct {
	Scope           *Scope    `json:"scope,omitempty"`
	OpID            string    `json:"opId"`
	Actor           string    `json:"actor"`
	Action          string    `json:"action"`
	PayloadDigest   string    `json:"payloadDigest"`
	SessionID       string    `json:"sessionId"`
	SessionVersion  int64     `json:"sessionVersion"`
	ResourceID      string    `json:"resourceId,omitempty"`
	ResourceVersion int64     `json:"resourceVersion,omitempty"`
	At              time.Time `json:"at"`
}

Receipt and audit contain references and counts only, never source/input values or titles.

type Repository

type Repository interface {
	View(context.Context, func(Reader) error) error
	Transact(context.Context, func(Transaction) error) error
}

Repository implementations commit heads, immutable records, receipt and audit in one authority. List pages are bounded and owner-filtered before records reach clients.

type Run

type Run struct {
	ID                 string `json:"id"`
	SessionID          string `json:"sessionId"`
	InputSnapshotID    string `json:"inputSnapshotId"`
	Kind               string `json:"kind"`
	DefinitionID       string `json:"definitionId"`
	DefinitionRevision string `json:"definitionRevision"`
	// State is accepted/completed/failed/canceled; client reportClientRun may
	// also settle uncertainty as outcome-unknown.
	State              string                            `json:"state"`
	OutcomeOrigin      string                            `json:"outcomeOrigin,omitempty"`
	ExecutionAuthority string                            `json:"executionAuthority"`
	ExecutionDigest    string                            `json:"executionDigest,omitempty"`
	ExecutionDocument  json.RawMessage                   `json:"executionDocument,omitempty"`
	ResolvedParameters map[string]apicontract.TypedValue `json:"resolvedParameters,omitempty"`
	Version            int64                             `json:"version"`
	Widgets            []WidgetOutcome                   `json:"widgets,omitempty"`
	ResultRefs         []string                          `json:"resultRefs,omitempty"`
	ErrorCode          string                            `json:"errorCode,omitempty"`
	CreatedAt          time.Time                         `json:"createdAt"`
	CompletedAt        *time.Time                        `json:"completedAt,omitempty"`
}

type Scope

type Scope struct {
	EnvironmentID  string `json:"environmentId"`
	IdentityDomain string `json:"identityDomain"`
}

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service requires a live authorization boundary. It never executes source queries on reads.

func NewService

func NewService(repo Repository, authorize Authorizer) (*Service, error)

func (*Service) Execute

func (s *Service) Execute(ctx context.Context, p Principal, c Command) (CommandResult, error)

func (*Service) GetSnapshot

func (s *Service) GetSnapshot(ctx context.Context, p Principal, id string) (Snapshot, error)

func (*Service) ListEntryRevisions

func (s *Service) ListEntryRevisions(ctx context.Context, p Principal, sessionID, entryID, cursor string, limit int) (Page[EntryRevision], error)

ListEntryRevisions exposes a stable, authorized history for one session entry.

func (*Service) ListMessages

func (s *Service) ListMessages(ctx context.Context, p Principal, sessionID, cursor string, limit int) (Page[Message], error)

ListMessages returns durable chat history in stable ID order, rechecking the source scope pinned when each message was sent.

func (*Service) ListRuns

func (s *Service) ListRuns(ctx context.Context, p Principal, sessionID, cursor string, limit int) (Page[Run], error)

ListRuns returns durable run receipts in stable ID order. Each page is scoped to the authorized session and reauthorizes every pinned source scope.

func (*Service) ListSessions

func (s *Service) ListSessions(ctx context.Context, p Principal, cursor string, limit int) (Page[Session], error)

func (*Service) ReadEntryRevision

func (s *Service) ReadEntryRevision(ctx context.Context, p Principal, sessionID, entryID, revisionID string) (EntryRevision, error)

ReadEntryRevision returns one retained revision after checking its owning session and the bag's current authorization boundary.

func (*Service) ReadInput

func (s *Service) ReadInput(ctx context.Context, p Principal, id string) (InputSnapshot, []EntryRevision, error)

ReadInput resolves exact historical revisions after fresh source-scope authorization.

func (*Service) ReadOperation

func (s *Service) ReadOperation(ctx context.Context, p Principal, id string) (Receipt, error)

func (*Service) ReadRun

func (s *Service) ReadRun(ctx context.Context, p Principal, id string) (Run, error)

type Session

type Session struct {
	SchemaVersion   int       `json:"schemaVersion"`
	ID              string    `json:"id"`
	DatabaseID      string    `json:"databaseId"`
	ProjectID       string    `json:"projectId"`
	Owner           string    `json:"owner"`
	Title           string    `json:"title"`
	State           string    `json:"state"`
	Version         int64     `json:"version"`
	DefaultBagID    string    `json:"defaultBagId"`
	ContextSetID    string    `json:"contextSetId"`
	PendingRunCount int       `json:"pendingRunCount,omitempty"`
	BagIDs          []string  `json:"bagIds"`
	CreatedAt       time.Time `json:"createdAt"`
	UpdatedAt       time.Time `json:"updatedAt"`
}

type Snapshot

type Snapshot struct {
	Session    Session           `json:"session"`
	Bags       []Bag             `json:"bags"`
	Entries    []Entry           `json:"entries"`
	Revisions  []EntryRevision   `json:"revisions"`
	ContextSet AppliedContextSet `json:"contextSet"`
}

type Subject

type Subject struct {
	ConceptID       string   `json:"conceptId"`
	FieldID         string   `json:"fieldId"`
	FieldMappingRef string   `json:"fieldMappingRef"`
	GraphResource   string   `json:"graphResource,omitempty"`
	GraphRevision   string   `json:"graphRevision,omitempty"`
	ModelRef        string   `json:"modelRef,omitempty"`
	ModelRevision   string   `json:"modelRevision,omitempty"`
	Record          string   `json:"record,omitempty"`
	Fields          []string `json:"fields,omitempty"`
}

type Transaction

type Transaction interface {
	Reader
	Save(context.Context, string, string, any, int64, string, string) error
}

type ValueEnvelope

type ValueEnvelope struct {
	SchemaVersion int                      `json:"schemaVersion"`
	Kind          string                   `json:"kind"`
	Scalar        *apicontract.TypedValue  `json:"scalar,omitempty"`
	Values        []apicontract.TypedValue `json:"values,omitempty"`
	KeyFields     []string                 `json:"keyFields,omitempty"`
	Keys          []EntityKey              `json:"keys,omitempty"`
}

ValueEnvelope keeps integers/decimals lossless and composite keys structurally typed. Sets may be empty; an empty set is never interpreted as an unfiltered source.

type WidgetOutcome

type WidgetOutcome struct {
	ID        string `json:"id"`
	State     string `json:"state"`
	ResultRef string `json:"resultRef,omitempty"`
	ErrorCode string `json:"errorCode,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL