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
- func NewRuntimeHandler(rt *Runtime, auth channel.Authenticator) http.Handler
- func RunHTTPServerWithBindings(ctx context.Context, addr, storePath string, loaded channel.LoadedBindings, ...) error
- func ServeRuntime(ctx context.Context, addr string, rt *Runtime, auth channel.Authenticator, ...) error
- type Bridge
- type ControlServer
- func (cs *ControlServer) Ingest(principal contract.ActorID, env contract.ObservationEnvelope) (int64, bool, error)
- func (cs *ControlServer) PullProjection(principal contract.ActorID, sub contract.Subscription) (projection.Projection, error)
- func (cs *ControlServer) Tick() ([]contract.Decision, error)
- type ResolvedBinding
- type Runtime
- func (r *Runtime) API() channel.ServerAPI
- func (r *Runtime) Close() error
- func (r *Runtime) DecisionLedger() ([]contract.Decision, error)
- func (r *Runtime) DrainOutbox() ([]contract.ResourceRef, int, error)
- func (r *Runtime) GetCursor(name string) int64
- func (r *Runtime) IngestTrusted(principal contract.ActorID, env contract.ObservationEnvelope) (int64, bool, error)
- func (r *Runtime) MarkSyncCommitStatus(originReplicaID, localDecisionID string, ref contract.ResourceRef, ...) error
- func (r *Runtime) PendingEvents(afterSeq int64) ([]contract.Event, error)
- func (r *Runtime) PendingSyncCommits() ([]contract.LocalCommit, error)
- func (r *Runtime) ReplicaID() (string, error)
- func (r *Runtime) Resource(ref contract.ResourceRef) (contract.Version, map[string]any, error)
- func (r *Runtime) SetCursor(name string, seq int64) error
- func (r *Runtime) Status(principal contract.ActorID) (contract.ChannelStatus, error)
- func (r *Runtime) StorePath() string
- func (r *Runtime) SyncPull(principal contract.ActorID, req contract.SyncPullRequest) (contract.SyncPullResponse, error)
- func (r *Runtime) SyncPush(principal contract.ActorID, req contract.SyncPushRequest) (contract.SyncPushResponse, error)
- func (r *Runtime) SyncStatus(principal contract.ActorID) (contract.SyncStatusResponse, error)
- func (r *Runtime) Tick() ([]contract.Decision, error)
- type RuntimeConfig
Constants ¶
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.
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 (*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 (*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:
- 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).
- RECONCILE: the kernel decides the pending *.proposed events (the kernel is the only writer).
- INVALIDATE: each Accepted decision enqueues an outbox invalidation (downstream projections are stale).
type ResolvedBinding ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
ReplicaID is this store's durable replica identity (minted on first read).
func (*Runtime) Resource ¶
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) Status ¶
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 ¶
StorePath is the canonical store path this runtime owns (status/diagnostic evidence).
func (*Runtime) SyncPull ¶
func (r *Runtime) SyncPull(principal contract.ActorID, req contract.SyncPullRequest) (contract.SyncPullResponse, error)
func (*Runtime) SyncPush ¶
func (r *Runtime) SyncPush(principal contract.ActorID, req contract.SyncPushRequest) (contract.SyncPushResponse, error)
func (*Runtime) SyncStatus ¶
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.