runtime

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package runtime is the governed control loop: a ControlServer ingests observations exactly-once, runs them through the rule pre-gate, bridges proposals into trusted *.proposed events, reconciles them through the single-writer kernel, and emits outbox invalidations + durable diagnostics. The Runtime owns the store + the single Tick driver; hosts reach it over the channel.ServerAPI port (D5). The kernel stays minimal; the rich admission semantics live here (D4).

Index

Constants

View Source
const DefaultStorePath = ".mnemon/harness/local/governed.db"

DefaultStorePath is the canonical Local Mnemon kernel-store path under the project's `.mnemon/harness` tree. Tests and dev may override it with an explicit path.

Variables

This section is empty.

Functions

func NewRuntimeHandler

func NewRuntimeHandler(rt *Runtime, auth channel.Authenticator) http.Handler

NewRuntimeHandler is the Local Mnemon HTTP channel endpoint over a Runtime. It differs from the api-only channel.NewHTTPHandler in two ways the Runtime makes possible:

  • P2.2 synchronous local mode: after a successful NEW observation, /ingest drives ONE Tick on the runtime's single driver, so a lone observe closes the governed loop. The Tick is serialized by the ControlServer's tickMu — no surface drives Tick independently. A duplicate observation is not re-ticked. A Tick error is reported in the receipt, never folded into the ingest result (the observation is durable regardless).
  • P2.3 /status: channel evidence (principal, digest, binding actor kind, store ref, mode).

Auth resolves the principal; the request body never names identity (D7/S9).

func RunHTTPServerWithBindings

func RunHTTPServerWithBindings(ctx context.Context, addr, storePath string, loaded channel.LoadedBindings, out io.Writer) error

RunHTTPServerWithBindings boots the server from a loaded channel-binding manifest (P3.2): the runtime enforces the bindings (channel.BindingSet authorizer) and serves only the subscription scopes the bindings declare, and — when the bindings carry credential refs — a channel.TokenAuthenticator resolves the principal from the bearer token (trusted-header auth remains the local/dev/httptest default when no tokens are configured). The store path is still the canonical project store.

func ServeRuntime

func ServeRuntime(ctx context.Context, addr string, rt *Runtime, auth channel.Authenticator, out io.Writer) error

ServeRuntime serves the runtime's channel over httpapi until ctx is cancelled. It is the shared boot loop for the bare and binding-configured server front doors.

Types

type Bridge

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

Bridge is the single chokepoint where a callback's INTENT becomes a TRUSTED *.proposed event. newID mints unique event ids; now stamps the (provenance-only) ts. Both are injected for deterministic tests.

func NewBridge

func NewBridge(newID, now func() string) *Bridge

func (*Bridge) Stamp

func (br *Bridge) Stamp(b ResolvedBinding, dispatchedOn projection.Projection, trigger contract.Event, intent contract.ProposedEvent) (contract.Event, error)

Stamp turns intent into a trusted *.proposed event, OR returns an error if any proposed write targets a ref outside the actor's DISPATCHED SCOPE (write-scope, R11 — the kernel's authz is actor/kind only). Trusted fields come from the binding (write identity), the dispatched projection (read-set + provenance), and the trigger (correlation + lineage) — NEVER from the intent payload, even if a hostile callback stuffs "actor"/"based_on" into it (R1/R2). Only Payload (the write set) rides through proposer-controlled; the kernel validates it. An empty/undecodable write set PASSES the bridge (the kernel rejects it as a malformed/empty op, preserving the audit trail); only a DECODED, out-of-scope write is blocked here.

type ControlServer

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

ControlServer is the one single-writer governed loop. Tick is its deterministic, restart-safe driver.

func New

func New(s *store.Store, k *kernel.Kernel, rules rule.RuleSet, subs map[contract.ActorID]contract.Subscription, modes contract.Modes, newID, now func() string) *ControlServer

func (*ControlServer) Ingest

func (cs *ControlServer) Ingest(principal contract.ActorID, env contract.ObservationEnvelope) (int64, bool, error)

Ingest records an observation exactly-once (S1). Source and Event.Actor are stamped from the AUTHENTICATED principal — the client's payload claim is overwritten, never trusted (D7/S9).

Trust boundary (R11/S9/S10): the wire admits ONLY observations. A *.proposed / *.diagnostic is an INTERNAL, trusted event class — a *.proposed is minted EXCLUSIVELY by the bridge after the rule pre-gate + write-scope check, a *.diagnostic only by the server. The reconciler trusts every *.proposed in the log, and dispatchOne SKIPS reserved types (so they bypass the rule pre-gate, bridge write-scope, and readback). Admitting a client-supplied one would let an edge write any resource of an authorized KIND outside its dispatched scope (a within-kind cross-resource / cross-principal escalation) and dodge the S10 content digest. Reject it at the door, before it can enter the canonical log.

func (*ControlServer) PullProjection

func (cs *ControlServer) PullProjection(principal contract.ActorID, sub contract.Subscription) (projection.Projection, error)

PullProjection serves an actor's scoped, server-built view. The subscription's actor MUST equal the authenticated principal (S9/D7): a client can never name another actor's scope on the wire.

func (*ControlServer) Tick

func (cs *ControlServer) Tick() ([]contract.Decision, error)

Tick runs one governed cycle:

  1. DISPATCH: scan events past the durable dispatch cursor; for each OBSERVED event, build its actor's scoped view, run the rule pre-gate, turn the verdict into trusted events — a propose -> bridged *.proposed event; a deny / rule-error -> a *.diagnostic event (S7, no silent drop). The proposed + diagnostic events AND the cursor advance are ONE atomic DispatchTx (S2).
  2. RECONCILE: the kernel decides the pending *.proposed events (the kernel is the only writer).
  3. INVALIDATE: each Accepted decision enqueues an outbox invalidation (downstream projections are stale).

type ResolvedBinding

type ResolvedBinding struct {
	Actor contract.ActorID
	Emits string
}

ResolvedBinding carries the trusted write identity (Actor) and authorized emit type for a proposal: the server builds it at dispatch time from the rule (Actor()/Emits()), and Bridge.Stamp reads only these two fields. It is runtime's own stamping DTO — trusted write identity at stamp time has nothing to do with file config (where it lived before the assembler cutover).

type Runtime

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

Runtime is the server-owned governed runtime: it owns the canonical kernel store, the kernel, the ControlServer channel boundary, the single Tick driver, and shutdown. Host surfaces reach the engine through this runtime over server.Client, rather than opening the store directly.

At any instant there is exactly ONE store owner and ONE dispatch-cursor driver (S11 single-writer): the runtime holds the kernel store's single-writer lock for its lifetime, so an embedded opener and a live server can never own the same store at once.

func OpenRuntime

func OpenRuntime(storePath string, cfg RuntimeConfig) (*Runtime, error)

OpenRuntime opens (or creates) the kernel store at storePath and wires the one ControlServer over it per cfg. storePath "" defaults to DefaultStorePath. The caller MUST Close the runtime; while it is open it is the sole owner of the store (S11). A failure to create the store dir or open the store is returned, never panicked.

func (*Runtime) API

func (r *Runtime) API() channel.ServerAPI

API returns the channel boundary (channel.ServerAPI: observe via Ingest, pull via PullProjection) every surface speaks to: the bare ControlServer, or — when bindings are configured — a channel.BindingSet authorizer wrapping it (P2.1). The Tick driver and read helpers stay on the unwrapped runtime.

func (*Runtime) Close

func (r *Runtime) Close() error

Close releases the store and its single-writer lock. After Close the runtime no longer owns the store, so another owner (embedded or service) may take it (S11).

func (*Runtime) DecisionLedger

func (r *Runtime) DecisionLedger() ([]contract.Decision, error)

DecisionLedger returns the full decision log in append order — the operator-wide, cross-actor decision history that backs the Control Tower's LEDGER (accepted) and INBOX (rejected escalations) pages (P6). It is READ-ONLY (wraps Store.DecisionsAfter); it opens NO write path. This is the one operator-scoped read the channel's per-actor PullProjection cannot serve, so the Tower facade — which holds the *Runtime — reads it here rather than over the channel. The caller filters by status (Accepted -> LEDGER, Rejected -> INBOX); the ui package never touches this directly (ui↛store).

func (*Runtime) DrainOutbox

func (r *Runtime) DrainOutbox() ([]contract.ResourceRef, int, error)

DrainOutbox claims, acks, AND PRUNES the pending projection-invalidation outbox rows. It is the driver's out-of-band duty (a kind-scoped ClaimOutbox caller for the "invalidation" rows it actually delivers). It returns the DEDUPED resource refs the drained rows invalidated (the producer stamps d.NewVersions into every row's payload) so the driver can refresh selectively, plus the drained row COUNT — re-projection triggers on the count, never on the refs, so an undecodable payload loses selectivity but never the trigger. Acked rows are pruned in the same pass — nothing re-reads them.

func (*Runtime) GetCursor

func (r *Runtime) GetCursor(name string) int64

GetCursor / SetCursor expose the durable cursor surface for the SYNC cursor names only ("sync_pull:<remote>"). The dispatch/sink cursors belong to the ControlServer — driving them from outside would corrupt the governed loop; remotesync's helpers are the intended callers.

func (*Runtime) IngestTrusted

func (r *Runtime) IngestTrusted(principal contract.ActorID, env contract.ObservationEnvelope) (int64, bool, error)

IngestTrusted is the in-process OWNER's intake: the co-hosted sync worker imports pulled commits under contract.SyncImportActor through it. It bypasses ONLY the channel-binding authorizer — sync@local is a platform actor, never a wire principal, so it holds no binding — while the full intake trust boundary still applies unchanged (observed-type grammar, internal-only suffix reject, exactly-once dedupe, rule pre-gate, kernel authority). Never exposed on the wire.

func (*Runtime) MarkSyncCommitStatus

func (r *Runtime) MarkSyncCommitStatus(originReplicaID, localDecisionID string, ref contract.ResourceRef, status, remotePeerID, at, diagnostic string) error

MarkSyncCommitStatus mirrors a hub verdict into the local sync ledger (pusher-side attribution).

func (*Runtime) PendingEvents

func (r *Runtime) PendingEvents(afterSeq int64) ([]contract.Event, error)

PendingEvents exposes the durable event log past seq for the owning surface (e.g. recovering a refusal diagnostic after a denied apply). Read-only.

func (*Runtime) PendingSyncCommits

func (r *Runtime) PendingSyncCommits() ([]contract.LocalCommit, error)

PendingSyncCommits reads the outbound sync ledger's pending rows.

func (*Runtime) ReplicaID

func (r *Runtime) ReplicaID() (string, error)

ReplicaID is this store's durable replica identity (minted on first read).

func (*Runtime) Resource

func (r *Runtime) Resource(ref contract.ResourceRef) (contract.Version, map[string]any, error)

Resource reads one canonical resource's version + fields directly from the store. It is a read-after-decision helper for the OWNING surface (read-only — never a second writer).

func (*Runtime) SetCursor

func (r *Runtime) SetCursor(name string, seq int64) error

func (*Runtime) Status

func (r *Runtime) Status(principal contract.ActorID) (contract.ChannelStatus, error)

Status builds the principal's channel status. When bindings are configured it is gated on the binding's channel.VerbStatus (a grant distinct from pull). The digest is the principal's server-configured scope, read through the kernel store directly (the server owns the runtime), so status does not require the pull verb.

func (*Runtime) StorePath

func (r *Runtime) StorePath() string

StorePath is the canonical store path this runtime owns (status/diagnostic evidence).

func (*Runtime) SyncPull

func (*Runtime) SyncPush

func (*Runtime) SyncStatus

func (r *Runtime) SyncStatus(principal contract.ActorID) (contract.SyncStatusResponse, error)

func (*Runtime) Tick

func (r *Runtime) Tick() ([]contract.Decision, error)

Tick drives one governed cycle. The runtime owns the SINGLE dispatch-cursor driver — no surface drives Tick independently against the store.

type RuntimeConfig

type RuntimeConfig struct {
	Rules     rule.RuleSet
	Authority kernel.AuthorityRules
	Subs      map[contract.ActorID]contract.Subscription
	Modes     contract.Modes
	NewID     func() string
	Now       func() string

	// SchemaGuard is the kernel's per-kind required-fields guard. The assembler builds it from the
	// governance kinds plus each enabled capability's declared required header (PD2), so a declared
	// user kind's required set has ONE source — the capability. The zero value (nil Required) falls
	// back to kernel.DefaultSchemaGuard for callers that do not assemble a catalog.
	SchemaGuard kernel.SchemaGuard

	// Bindings, when non-empty, gates the runtime's channel API with a channel.BindingSet authorizer (P2.1):
	// every principal must have a binding granting the verb / observed type / pull scope it uses. The
	// zero (nil) leaves the API unbound — correct for a trusted in-process owner (embedded coreengine).
	Bindings []channel.ChannelBinding

	// SyncableKinds names the resource kinds this replica PRODUCES Remote Workspace sync commits for —
	// the produce surface (sync-abi-v2 §4). The assembler injects the catalog's importable kinds
	// (capability.ImportableKinds), so the produce set is descriptor-derived, never a hardcoded
	// constant (PD6 replaced contract.SyncableResourceKinds). The zero (nil) produces no sync commits
	// — correct for a runtime with no Remote Workspace. The runtime stays capability-free: this is a
	// plain contract.ResourceKind slice the app layer fills.
	SyncableKinds []contract.ResourceKind
}

RuntimeConfig selects the runtime's policy: the rule pre-gate set, the kernel authority, the per-principal subscription scopes, the reconcile modes, and the id/clock generators. The zero config boots a bare channel endpoint with no rules or preconfigured actors. NewID/Now default to uuid/RFC3339; Modes defaults to reject + projection-read-set + strict authz.

Jump to

Keyboard shortcuts

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