Documentation
¶
Index ¶
- Constants
- func MergeBinding(path string, b ChannelBinding, credentialRef string) error
- func NewHTTPHandler(api ServerAPI) http.Handler
- func NewHTTPHandlerWithAuth(api ServerAPI, auth Authenticator) http.Handler
- func RemoveBinding(path string, principal contract.ActorID) (bool, error)
- func SubsFromBindings(bindings []ChannelBinding) map[contract.ActorID]contract.Subscription
- func UpsertBinding(path string, b ChannelBinding, credentialRef string) error
- func ValidateSyncEndpoint(endpoint string, allowInsecure bool) error
- type Authenticator
- type BindingSet
- type ChannelBinding
- func ControlAgentBinding(principal contract.ActorID, endpoint string, scope []contract.ResourceRef) ChannelBinding
- func HostAgentBinding(principal contract.ActorID, endpoint string, scope []contract.ResourceRef) ChannelBinding
- func ReplicaAgentBinding(principal contract.ActorID, endpoint string, scope []contract.ResourceRef) ChannelBinding
- type Client
- func (c *Client) Ingest(principal contract.ActorID, env contract.ObservationEnvelope) (int64, bool, error)
- func (c *Client) IngestObserve(_ contract.ActorID, env contract.ObservationEnvelope) (IngestReceipt, error)
- func (c *Client) PullProjection(_ contract.ActorID, sub contract.Subscription) (projection.Projection, error)
- func (c *Client) Status(_ contract.ActorID) (contract.ChannelStatus, error)
- func (c *Client) SyncPull(reqBody contract.SyncPullRequest) (contract.SyncPullResponse, error)
- func (c *Client) SyncPush(reqBody contract.SyncPushRequest) (contract.SyncPushResponse, error)
- func (c *Client) SyncStatus() (contract.SyncStatusResponse, error)
- type HeaderAuthenticator
- type IngestReceipt
- type LoadedBindings
- type ServerAPI
- type SyncClientConfig
- type TokenAuthenticator
- type Transport
- type Verb
Constants ¶
const DefaultBindingFile = ".mnemon/harness/channel/bindings.json"
DefaultBindingFile is the canonical channel-binding manifest path under the project root (P3.1).
const DefaultSyncTimeout = 10 * time.Second
DefaultSyncTimeout bounds every sync transport call (v1.1 #10): a hung remote can never wedge the caller — the in-process worker stays off the Tick path, but even its own goroutine must converge.
const MaxIngestBytes = 1 << 20
MaxIngestBytes caps an observation request body, so an oversize payload is rejected at the edge rather than buffered into memory. interim Phase-1 default; superseded by Phase-2 per-capability max_payload_bytes.
Variables ¶
This section is empty.
Functions ¶
func MergeBinding ¶
func MergeBinding(path string, b ChannelBinding, credentialRef string) error
UpsertBinding inserts or replaces (by principal) b in the manifest at path, creating the file (schema_version 1) when absent and PRESERVING every other entry + their order — so `setup` manages exactly its own principal and never clobbers a user-added or sibling-loop binding. credentialRef is the token-file ref to record (project-relative or absolute, "" for header auth). MergeBinding upserts b into the binding file, UNIONing the verbs / observed types / subscription scope with any existing binding for the same principal — so installing skill after memory keeps the memory grant rather than replacing it. The existing credential ref is kept when credentialRef is empty (an idempotent token). It is the additive variant of UpsertBinding (which replaces).
func NewHTTPHandler ¶
NewHTTPHandler exposes a ServerAPI over net/http with the default HeaderAuthenticator (D5: production HTTP/gRPC+mTLS is a thin adapter; this is the thin adapter, gated by httptest).
func NewHTTPHandlerWithAuth ¶
func NewHTTPHandlerWithAuth(api ServerAPI, auth Authenticator) http.Handler
NewHTTPHandlerWithAuth is NewHTTPHandler with an explicit Authenticator seam. The principal is resolved by auth; the body carries only the observation. The one ControlServer behind it stays the sole serializer — multi-execution-surface, never multi-writer.
func RemoveBinding ¶
RemoveBinding removes the principal's entry from the manifest at path, preserving all others, and reports whether an entry was removed. The file is left in place (with an empty bindings list when it held only that entry), so a user-managed manifest is never surprised away by an uninstall.
func SubsFromBindings ¶
func SubsFromBindings(bindings []ChannelBinding) map[contract.ActorID]contract.Subscription
SubsFromBindings derives the per-principal subscription scopes from the bindings, so the runtime's served scope and the binding manifest come from ONE source (the binding file).
func UpsertBinding ¶
func UpsertBinding(path string, b ChannelBinding, credentialRef string) error
func ValidateSyncEndpoint ¶
ValidateSyncEndpoint is the client half of the TLS downgrade gate: an http:// endpoint with a non-loopback host is refused unless explicitly overridden (mirroring the stage-4 listen-side loopback-only posture). https always passes; loopback plaintext stays allowed (same-machine hubs and tests are inside the T1 boundary). `sync connect` applies the same check at write time.
Types ¶
type Authenticator ¶
Authenticator resolves the authenticated edge principal from a request — the P3 seam that replaces the bare trusted X-Mnemon-Principal header. A production transport binds it to mTLS / OIDC / a local-socket peer credential; the default (HeaderAuthenticator) trusts the header, which is correct for a local/trusted transport and for httptest. The server still trusts ONLY the resolved principal, never the request body (D7/S9).
func NewBindingAuthenticator ¶
func NewBindingAuthenticator(loaded LoadedBindings) Authenticator
NewBindingAuthenticator builds the per-principal authenticator from the loaded bindings' tokens. With no tokens it is a plain header authenticator; with all-token it requires bearers; mixed is resolved per principal.
type BindingSet ¶
type BindingSet struct {
// contains filtered or unexported fields
}
BindingSet indexes the channel bindings by principal. It is the in-memory authorizer source for the walking skeleton (P2.1): the smallest runtime control that turns the ChannelBinding manifest into enforcement, without yet committing a binding-file schema (P3). The actor kind rides the binding, never a separate code path (D6) — the authorizer branches on verbs/types/scope, not on the role.
func NewBindingSet ¶
func NewBindingSet(bindings ...ChannelBinding) (*BindingSet, error)
NewBindingSet validates each binding and indexes them by principal. Duplicate principals and colliding idempotency namespaces are rejected (the namespace isolates a principal's ExternalIDs).
func (*BindingSet) Binding ¶
func (s *BindingSet) Binding(principal contract.ActorID) (ChannelBinding, bool)
Binding returns the principal's binding (and whether one exists).
type ChannelBinding ¶
type ChannelBinding struct {
Principal contract.ActorID // the authenticated identity
ActorKind contract.ActorKind // role classification (not a privilege path)
Transport Transport // wire
Endpoint string // base URL / socket path
AllowedVerbs []Verb // observe / pull / status
AllowedObservedTypes []string // observed event types this principal may Ingest ("" or "*" = any)
SubscriptionScope []contract.ResourceRef // the refs this principal may pull
IdempotencyNamespace string // prefix isolating this principal's ExternalIDs (cross-principal dedup isolation)
Budget contract.BudgetTier // context-budget tier for this endpoint's derived mirror (P4); empty = hot (full)
}
ChannelBinding is the manifest that scopes ONE principal's access to the channel (D6). The channel is the same for every binding; the binding — never a privileged code path — is what differs a HostAgent from a ControlAgent. The server still enforces the scope at runtime (S9); the binding makes the grant explicit and auditable.
func ControlAgentBinding ¶
func ControlAgentBinding(principal contract.ActorID, endpoint string, scope []contract.ResourceRef) ChannelBinding
func HostAgentBinding ¶
func HostAgentBinding(principal contract.ActorID, endpoint string, scope []contract.ResourceRef) ChannelBinding
HostAgentBinding and ControlAgentBinding are the two canonical bindings over the SAME channel — the role differs ONLY by the binding (zero new surface for the control agent, D6).
func ReplicaAgentBinding ¶
func ReplicaAgentBinding(principal contract.ActorID, endpoint string, scope []contract.ResourceRef) ChannelBinding
func (ChannelBinding) Allows ¶
func (b ChannelBinding) Allows(v Verb) bool
Allows reports whether the binding grants verb.
func (ChannelBinding) AllowsObservedType ¶
func (b ChannelBinding) AllowsObservedType(eventType string) bool
AllowsObservedType reports whether the binding permits Ingesting an observation of eventType. An empty AllowedObservedTypes (or a "*" entry) means any observed type.
func (ChannelBinding) ClampRefs ¶
func (b ChannelBinding) ClampRefs(requested []contract.ResourceRef) ([]contract.ResourceRef, error)
ClampRefs clamps a requested ref set to the binding's SubscriptionScope — the team-scale authorization ceiling, implemented ONCE for pull / sync / status (hand-rolled copies had already diverged on empty-scope handling). The one implementation is contract.ClampRefs — shared with the standalone hub (syncserver), which cannot import channel — and this method DELEGATES to it: empty requested defaults to the full scope; any explicit ref outside the scope is an error; an EMPTY scope denies every explicit ref (fail closed). The ingest path keeps its documented exception (an observation naming no refs is unconstrained) at its own call site.
func (ChannelBinding) Validate ¶
func (b ChannelBinding) Validate() error
Validate checks the binding is well-formed: a principal, a known kind, at least one verb.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a thin edge-side HTTP client bound to one authenticated credential. It satisfies ServerAPI so an edge can speak to a remote server exactly as to an in-process one. The credential is either the trusted principal header (NewClient, local/trusted transport) or a bearer token resolved by a TokenAuthenticator (NewClientWithToken) — the P3 channel client.
func NewClientWithToken ¶
NewClientWithToken binds the client to a bearer token (resolved server-side by a TokenAuthenticator) instead of the trusted principal header.
func NewSyncClient ¶
func NewSyncClient(endpoint string, cfg SyncClientConfig) (*Client, error)
NewSyncClient builds the sync client over endpoint: fail-closed on a plaintext non-loopback endpoint (the T2 downgrade gate, v1.1 #3) and always bounded by a timeout. With a CAFile the transport trusts exactly that root — nothing else.
func (*Client) Ingest ¶
func (c *Client) Ingest(principal contract.ActorID, env contract.ObservationEnvelope) (int64, bool, error)
Ingest satisfies ServerAPI by delegating to IngestObserve and dropping the processing metadata.
func (*Client) IngestObserve ¶
func (c *Client) IngestObserve(_ contract.ActorID, env contract.ObservationEnvelope) (IngestReceipt, error)
IngestObserve POSTs the observation and returns the full channel receipt (seq, dup, processing metadata). The principal argument is ignored: the client's identity is its bound credential (the trusted header / bearer token), never a per-call claim — an edge cannot forge another's id.
func (*Client) PullProjection ¶
func (c *Client) PullProjection(_ contract.ActorID, sub contract.Subscription) (projection.Projection, error)
PullProjection fetches the actor's scoped view from the server. The principal argument is ignored: the subscription's actor is sent in the body and the server cross-checks it against the bound credential header, so an edge cannot pull another actor's scope (D7/S9).
func (*Client) Status ¶
Status fetches the channel status evidence for the client's bound principal (P2.3). The principal argument is ignored: identity is the bound credential, sent as the trusted header / bearer token.
func (*Client) SyncPull ¶
func (c *Client) SyncPull(reqBody contract.SyncPullRequest) (contract.SyncPullResponse, error)
func (*Client) SyncPush ¶
func (c *Client) SyncPush(reqBody contract.SyncPushRequest) (contract.SyncPushResponse, error)
func (*Client) SyncStatus ¶
func (c *Client) SyncStatus() (contract.SyncStatusResponse, error)
SyncStatus fetches the hub's sync status evidence (counters) for the bound credential.
type HeaderAuthenticator ¶
type HeaderAuthenticator struct{}
HeaderAuthenticator trusts the X-Mnemon-Principal header. It is the default seam impl for a local/trusted transport (and what httptest uses).
func (HeaderAuthenticator) Authenticate ¶
type IngestReceipt ¶
type IngestReceipt struct {
Seq int64 `json:"seq"`
Dup bool `json:"dup"`
Ticked bool `json:"ticked"`
ProcessingError string `json:"processing_error,omitempty"`
}
IngestReceipt is the channel's reply to an observe: it tells the client the observation was recorded (Seq), whether it was a duplicate (Dup), whether the runtime attempted to process it with a synchronous Tick (Ticked, P2.2), and any processing error (the observation is durable regardless — a Tick failure is reported, not folded into the ingest result).
type LoadedBindings ¶
type LoadedBindings struct {
Bindings []ChannelBinding
Tokens map[string]contract.ActorID
}
LoadedBindings is the result of parsing a binding file: the channel bindings plus the bearer token -> principal map assembled from the bindings' credential_ref token files (for a TokenAuthenticator). The bindings feed RuntimeConfig.Bindings + SubsFromBindings; the tokens feed the server's authenticator.
func LoadBindingFile ¶
func LoadBindingFile(root, path string) (LoadedBindings, error)
LoadBindingFile reads + validates the channel-binding manifest at path and assembles the bindings and bearer-token map. Relative credential_ref token paths resolve against root (the project root, absolute ones are used verbatim. It validates each entry (principal, known actor kind / verbs / transport, http endpoint non-empty), the schema version, and cross-entry uniqueness (principal, idempotency namespace, bearer token).
type ServerAPI ¶
type ServerAPI interface {
Ingest(principal contract.ActorID, env contract.ObservationEnvelope) (seq int64, dup bool, err error)
PullProjection(principal contract.ActorID, sub contract.Subscription) (projection.Projection, error)
}
ServerAPI is the edge<->server boundary (D5). Production HTTP/gRPC+mTLS is a thin adapter over it (httpapi.go); the in-process implementation is *runtime.ControlServer. It grows by phase: Ingest (P0), PullProjection (P2). The channel owns this port; the runtime satisfies it structurally, so channel never imports runtime.
func NewAuthorizedAPI ¶
func NewAuthorizedAPI(inner ServerAPI, bindings *BindingSet) ServerAPI
NewAuthorizedAPI returns inner gated by bindings. With a nil/empty BindingSet, callers should use inner directly (an unbound, trusted in-process owner such as the embedded coreengine path).
type SyncClientConfig ¶
type SyncClientConfig struct {
Token string
Timeout time.Duration // <= 0 defaults to DefaultSyncTimeout
CAFile string // PEM bundle for the remote's TLS root (e.g. mnemon-hub --dev-selfsigned cert)
AllowInsecure bool // explicit T2 downgrade override for a plaintext non-loopback endpoint
}
SyncClientConfig configures the replica sync client (sync-abi-v1 §8): the bearer credential, a bounded transport budget, an optional CA bundle pinning the remote's TLS root, and the explicit plaintext override.
type TokenAuthenticator ¶
TokenAuthenticator resolves the principal from a bearer token via a static token->principal map — a minimal non-header seam implementation (mTLS/OIDC slot in the same way). An unknown or empty token is rejected, so the body's claimed actor is never trusted.
func (TokenAuthenticator) Authenticate ¶
type Verb ¶
type Verb string
Verb is a channel operation. The Agent Integration channel exposes observe (Ingest) + pull (PullProjection) + status. Replica sync gets separate verbs so a sync credential does not inherit Agent Integration access.
const ( VerbObserve Verb = "observe" VerbPull Verb = "pull" VerbStatus Verb = "status" // The sync verb STRINGS are ABI surface owned by contract (sync-abi-v1 §1); these aliases keep // the channel's Verb space complete without channel becoming the wire-name authority. VerbSyncPush Verb = contract.SyncVerbPush VerbSyncPull Verb = contract.SyncVerbPull VerbSyncStatus Verb = contract.SyncVerbStatus )