Help us shape the future of Go! Take the 2026 Go Developer Survey

syncserver

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: 13 Imported by: 0

Documentation

Overview

Package syncserver is the hub half of Remote Workspace sync (sync-abi-v2; the accept surface is the grant scope, §4): push adjudication against the append-only sync_remote_commits log, pull serving with the ONE scope clamp, and the status counters. It is extracted from the runtime so the standalone hub binary (mnemon-hub) can host the same wire without the runtime: it imports ONLY contract + store (+stdlib) — never channel / runtime / app / hostsurface (the trust-domain import boundary, pinned by a test). Replica authorization enters through the Grants seam; the co-hosted runtime adapts its channel bindings to grants, mnemon-hub builds grants from replicas.json — same fields, same semantics (dual-form rule).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsBadRequest

func IsBadRequest(err error) bool

IsBadRequest reports whether err is (or wraps) a request-validation failure.

func NewHTTPHandler

func NewHTTPHandler(hub *Server, auth Authenticator, audit io.Writer) http.Handler

NewHTTPHandler serves the three sync verbs over the hub Server. Every request emits ONE audit line to audit (ts, principal, verb, result): result is "unauthorized" (401, principal "-"), "bad_request" (400 — bad JSON / missing field / wrong method), "denied" (403 — no grant / out-of-scope), or "ok". The "result" is the REQUEST-level outcome (auth/parse/method); the per-commit accept/reject/conflict verdicts ride the 200 response body, NOT the audit line — a request whose every commit is rejected still audits result=ok (LOW-13). nil audit discards.

Method gates pin the frozen verb→method mapping (sync-abi-v1 §1): push/pull are POST, status is GET or POST. A violation is 405 before auth (the method is request-shape, not identity).

Types

type Authenticator

type Authenticator interface {
	Authenticate(r *http.Request) (contract.ActorID, error)
}

Authenticator resolves the authenticated principal from a request. syncserver carries its OWN seam (not channel's) so the standalone hub never imports channel; mnemon-hub plugs in BearerAuthenticator, tests may plug fakes.

type BadRequestError

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

BadRequestError marks a request-VALIDATION failure (a malformed/missing field) as distinct from an AUTHORIZATION failure (no grant / out-of-scope). The HTTP layer maps it to 400; everything else from Push/Pull/Status (no replica grant, out-of-scope clamp) stays 403 (LOW-10). It is the wire layer's only error-class signal — the per-commit accept/reject/conflict verdicts ride the 200 body.

func (*BadRequestError) Error

func (e *BadRequestError) Error() string

func (*BadRequestError) Unwrap

func (e *BadRequestError) Unwrap() error

type BearerAuthenticator

type BearerAuthenticator struct {
	Tokens map[string]contract.ActorID
}

BearerAuthenticator resolves the principal from a static bearer-token map — the mnemon-hub authenticator built from replicas.json credential_refs. A missing, empty, or unknown token is rejected; the request body never names identity.

func (BearerAuthenticator) Authenticate

func (a BearerAuthenticator) Authenticate(r *http.Request) (contract.ActorID, error)

type GrantMap

type GrantMap map[contract.ActorID]ReplicaGrant

GrantMap is the static Grants form mnemon-hub builds from replicas.json: every listed replica holds all three sync verbs (a replica credential is sync-only by construction; per-verb narrowing is the co-hosted binding form's concern).

func (GrantMap) Grant

func (m GrantMap) Grant(principal contract.ActorID, verb string) (ReplicaGrant, bool)

type Grants

type Grants interface {
	Grant(principal contract.ActorID, verb string) (ReplicaGrant, bool)
}

Grants resolves an authenticated principal's replica grant for ONE sync verb (a contract.SyncVerb* string). Implementations MUST be fail-closed: an unknown principal, a non-replica principal, or an ungranted verb returns false — there is no anonymous or default grant.

type ReplicaGrant

type ReplicaGrant = contract.ReplicaGrant

ReplicaGrant aliases the contract type (the grant record is ABI surface, sync-abi-v1 §2).

type Server

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

Server is one hub over one open store. It holds no other state: adjudication and counters are durable in the store, so a restart (or a concurrent co-hosted runtime surface) sees the same hub.

func New

func New(st *store.Store, grants Grants, now func() string) *Server

New wires a hub Server over an OPEN store (the caller owns the store's single-writer lock and its lifecycle). now stamps received_at on accepted commits.

func (*Server) Pull

Pull serves accepted commits after the request cursor, excluding the puller's own origin and clamped to the grant scope (requested scopes may only narrow). It also advances the hub's serve bookkeeping (last cursor per principal + served total) for the status counters.

func (*Server) Push

Push adjudicates one batch per commit (sync-abi-v2 §4): accepted (appended, first sight of the idempotency key), rejected (structural-validation or scope-clamp failure, with diagnostic), or conflict (idempotency-key reuse with DIFFERENT content only). The accept surface is the grant scope — the ref-level clamp is the sole kind/ref gate (no global syncable-kind set; v2). Replaying an identical batch repeats the accepted results and appends nothing. The request replica_id must match every commit's origin — a mismatch rejects the whole request before any adjudication.

func (*Server) Status

func (s *Server) Status(principal contract.ActorID) (contract.SyncStatusResponse, error)

Status reports the hub-side counters (sync-abi-v1 §3, additive): commits received (= rows in the append-only log), commits served across pulls, and the last cursor served per replica principal.

Jump to

Keyboard shortcuts

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