core

package
v1.18.0 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

package: core / orchestration type: orchestrator job: run a Request through the pipeline — authenticate, authorize, execute — driving the ports limits: the composition of the ports, assembled by config (-> config, adapters/*)

Core is what the endpoints drive and what drives storage, the sequencer and the signer. Handle is the pipeline: it authenticates the request's credentials to a Principal (auth), authorizes the Principal for the operation's right on its branch (access), then executes against the ports. Each stage enriches the same Request and records a line in its Report, so the object that comes back carries both the result and the trace of how it got there.

package: core / orchestration type: domain types job: the server's own domain values — merge outcome, liveness, layers, runs limits: types only; the query language is ranke-go's (-> ranke-go)

These are the typed values a Request carries in and out. What they are NOT is the graph's vocabulary: the RQL query AST and its result/report shapes were drafted here while ranke-go lacked them, and ranke-go now owns them — a Request carries a *ranke.Query and the engine answers with a ranke.ResultStream. What remains here is genuinely the server's: the outcome of a merge, liveness, the storage layers it composed, and the verification-run model it manages.

package: core / orchestration type: logic job: turn an Operation into the library call that answers it, and its result into a Stream limits: a seam, no graph behaviour; one archive snapshot per request (-> ranke-go)

Every arm is one call on the archive; an arm that grows logic is in the wrong repository.

A request resolves its snapshot once. RA_k is immutable, so answering from the one opened at the start is what keeps a streaming query consistent under a merge.

package: core / orchestration type: struct job: the one request object that flows through the server, enriched at each stage limits: transport-neutral; endpoints fill the ingress, core the rest (-> core.go)

Package core is the hexagon's center: it drives the driven ports (storage, sequencer, signer) and is driven by the driving ports (auth, endpoints). Its spine is one Request value that flows endpoint → auth → access → execution; the response comes back as a Stream (see stream.go, core.go). The endpoint fills the ingress fields from the wire; core fills the enrichment.

package: core / orchestration type: logic job: put the library's bytes on the wire — a switch on kind, plus its separator limits: transport only; it encodes no claim and shapes no result (-> github.com/flocko-motion/ranke-go)

The engine answers a query already shaped and serialised to every output axis, and tags each result with the one field carrying its payload. So serving is a switch and a separator: pull a result, write that field, frame it. Re-encoding here would put a claim's canonical form in the server's hands, and the id is a signature over exactly those bytes — the server would then be deciding identity.

The streams are lazy by construction. Each pulls one result at a time and writes it straight to the response, so a million-row query and a multi-gigabyte blob both cost one record of memory.

package: core / orchestration type: interface job: the response — a lazy byte stream that declares its own content type limits: core frames the body; the endpoint sets status and copies (-> adapters/endpoints)

Every response body — one JSON object, a json-seq or cbor-seq run, a raw blob — is bytes with a content type, so a Stream declares its ContentType and frames its body as it writes, lazily: neither a million rows nor a gigabyte blob is buffered whole.

Core owns the body, the endpoint the envelope. Per-item rendering is core's own and never crosses to the endpoint, which sees only the Stream.

package: core / orchestration type: registry job: give verification runs the identity, history and lifecycle the library's live handle has none of limits: operational state only; the walk itself is ranke-go's (-> github.com/flocko-motion/ranke-go)

The library hands back a live in-process handle — Verified, Failures, Done, Err, Wait — with no id, no persistence and no cancellation beyond the context it was started with. What an operator asks for is the other half: start a run and get an id back, list what is running, poll one by id after it has finished, stop one and keep what it found, and be refused when too many are already going. None of that is graph behaviour, so it lives here.

A run's report is retained after the walk ends, because a report is a point-in-time record: a layer repaired externally shows clean in a later run, and the earlier finding is exactly what an operator needs to still be able to read.

Index

Constants

View Source
const (
	Universe = access.Universe
	Archive  = access.Archive
	Branches = access.Branches
)

The reserved pseudo-branches, re-exported from access so a request targets them through core alone. They are the scopes a read names: Universe the privileged read under no closure, Archive the closure of the whole archive across every branch, and Branches the branch table itself.

Variables

View Source
var (
	// ErrForbidden — an authenticated principal lacks a grant for the action (403).
	// Distinct from auth.ErrUnauthenticated: identity was established, authority not.
	ErrForbidden = errors.New("core: forbidden")
	// ErrInvalidRequest — the request is malformed: a body that does not decode, or a
	// field the bound engine cannot carry (400).
	ErrInvalidRequest = errors.New("core: invalid request")
	// ErrNotFound — unknown, or outside the named scope's closure; indistinguishable (404).
	ErrNotFound = errors.New("core: not found")
	// ErrConflict — a contribution clashes with the branch's current head (409).
	ErrConflict = errors.New("core: head conflict")
	// ErrBusy — too many verification runs are active to start another (429).
	ErrBusy = errors.New("core: verification run limit reached")
	// ErrNotImplemented — a capability the stack does not yet offer (501).
	ErrNotImplemented = errors.New("core: not implemented")
)

Sentinel errors the pipeline returns, with the status an endpoint maps each to. A bad credential (401) is auth.ErrUnauthenticated, raised before these apply.

Functions

This section is empty.

Types

type Category

type Category string

Category classifies a failure transport-neutrally: core names no HTTP status, an endpoint maps the Category to its own and echoes it as the machine-readable code.

const (
	CatUnauthenticated Category = "unauthenticated" // no/invalid credential
	CatForbidden       Category = "forbidden"       // authenticated but ungranted
	CatNotFound        Category = "not_found"       // unknown/out-of-scope branch, claim, or content
	CatConflict        Category = "conflict"        // contribution clashes with the head
	CatBusy            Category = "busy"            // too many active runs
	CatInvalid         Category = "invalid"         // malformed request
	CatUnimplemented   Category = "unimplemented"   // capability not configured
	CatInternal        Category = "internal"        // anything else
)

func Categorize

func Categorize(err error) Category

Categorize walks the sentinel chain to a Category, so an endpoint translates in one place. A nil error yields the empty category.

type Content

type Content = io.ReadCloser

Content streams a blob's bytes; the read side of Contribute's io.Reader body.

type Contribution

type Contribution struct {
	Head string   `json:"head"`
	Ids  []string `json:"ids"`
}

Contribution is the outcome of a merge: the new head and the contributed ids.

type Core

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

Core composes the ports into the request pipeline. It is assembled once by config and shared by every endpoint.

func New

func New(a *auth.Set, chk *access.Checker, seq sequencer.Sequencer, store storage.Storage, opts ...Option) *Core

New assembles the core from the ports config built.

func (*Core) Handle

func (c *Core) Handle(ctx context.Context, req *Request) (Stream, error)

Handle runs a request through authenticate → authorize → execute, enriching it in place. A pre-stream failure returns the error alone; success returns a Stream.

type FailureMode

type FailureMode string

FailureMode classifies an integrity problem.

const (
	FailureCorruptBytes   FailureMode = "corrupt-bytes"   // stored bytes do not match their hash
	FailureInvalidContent FailureMode = "invalid-content" // the claim itself does not validate
)

type Health

type Health struct {
	Status string `json:"status"`           // "ok" when serving
	Signer string `json:"signer,omitempty"` // signing/contributor identity (e.g. "ed25519:…")
}

Health is liveness plus the contributor identity the stack signs merges with. The tags are the wire's: these values are served as they stand, so the names a client reads are fixed here rather than translated on the way out.

type Operation

type Operation int

Operation is what a request asks for, named Subject+Verb so it sorts hierarchically. It fixes the right the authorize stage checks (0 = none) and selects the execute branch; the pseudo-branches generalise scope, so there is no separate universe op.

const (
	OpClaimQuery         Operation = iota // query claims                           (Read)
	OpClaimGet                            // one claim by id (branch or $universe)   (Read)
	OpClaimContent                        // one claim's content                    (Read)
	OpClaimContribute                     // merge claims onto a branch             (Contribute; branch-admin is C on the branch table)
	OpClaimDelete                         // purge claims — physical removal, not a mutation (Delete)
	OpBranchHead                          // a branch's current head id             (Read)
	OpBranchInfo                          // a branch's head, height and last move  (Read)
	OpBranchList                          // list the branch table's branches       (Read on $branches)
	OpArchiveInfo                         // the branch-table head and its shape    (Read on $archive)
	OpLayerList                           // list storage layers (name + type)      (no grant)
	OpLayerInfo                           // runtime info on one storage layer      (no grant)
	OpHealthGet                           // liveness                               (no grant)
	OpVerificationStart                   // start a verification run               (no grant — verification needs none)
	OpVerificationList                    // list verification runs                 (no grant)
	OpVerificationGet                     // one verification run                   (no grant)
	OpVerificationCancel                  // cancel a run                           (no grant)
	OpVerificationDelete                  // delete a run                           (no grant)
	OpDevClockAdvance                     // steer the --dev clock forward          (no grant)
)

func (Operation) Right

func (o Operation) Right() access.Right

Right is the right this operation requires, or 0 for none. Reads need R, writes their CRUD letter; verification needs none, a core-access invariant.

type Option

type Option func(*Core)

Option supplies what only some stacks have: a signer to report an identity from, the layer names config parsed. A core assembled without them still authenticates, authorizes and reads.

func WithDevClock added in v1.15.0

func WithDevClock(advance func(time.Time) time.Time) Option

WithDevClock wires POST /dev/clock to advance, the launch's steerable clock — absent, the route answers ErrNotImplemented (§execute.go's devClockAdvance).

func WithLayers

func WithLayers(layers []StorageLayer) Option

WithLayers binds the storage layers, name and type only, that introspection reports.

func WithMaxVerificationRuns

func WithMaxVerificationRuns(n int) Option

WithMaxVerificationRuns bounds how many verification runs may walk at once. Beyond it a start is refused as busy; the server never stops a run to make room.

func WithSigner

func WithSigner(s signer.Signer) Option

WithSigner binds the signing identity health reports.

type Report

type Report struct {
	Steps []string
}

Report is the execution record that travels with the request: a human-readable trace now, and the home for the witnessed transaction window and per-stage counts as those stages are built.

type Request

type Request struct {

	// Credential is the one token the transport extracted, or the zero value (→ NoAuth);
	// more than one scheme is rejected by the endpoint before this is built.
	Credential auth.Credential
	// Op is what the caller wants; it fixes the required access right.
	Op Operation
	// Branch is the target branch, or Universe for a privileged by-id read.
	Branch string
	// Query is the read AST (OpClaimQuery) — ranke-go's RQL, answered by the Universe.
	Query *ranke.Query
	// Body is the signed-CBOR claims to merge (OpClaimContribute).
	Body io.Reader
	// ClaimID targets one claim (OpClaimGet, OpClaimContent). Content is addressed by
	// its claim, inheriting that scope and hiding whether the bytes are inline.
	ClaimID ranke.Id
	// VerConfig parameters a run (OpVerificationStart).
	VerConfig *VerificationConfig
	// VerID targets one run (OpVerificationGet, OpVerificationCancel, OpVerificationDelete).
	VerID string
	// DevClockAt is the instant to advance the dev clock to (OpDevClockAdvance).
	DevClockAt time.Time

	// Principal is who the request authenticated as (set by the authenticate stage).
	Principal access.Principal
	// Report is the running execution trace, accumulated across stages.
	Report Report
}

Request is the single object that flows through the server, enriched at each stage. Ingress fields are op-specific; the response is not a field — Handle returns a Stream.

type RunStatus

type RunStatus string

RunStatus is the lifecycle state of a verification run.

const (
	RunRunning  RunStatus = "running"
	RunComplete RunStatus = "complete"
	RunStopped  RunStatus = "stopped" // cancelled; partial findings kept
	RunError    RunStatus = "error"
)

type StorageLayer

type StorageLayer struct {
	Name string `json:"name"`
	Type string `json:"type"` // backend kind: mem, fs, sqlite, s3, postgres, neo4j, …
}

StorageLayer names one storage layer — name and type only, by design.

type Stream

type Stream interface {
	// ContentType is the MIME type of the bytes WriteTo produces.
	ContentType() string
	// WriteTo writes the framed body to w lazily, reporting bytes and the first error.
	io.WriterTo
	// Close releases the stream's resources.
	Close() error
}

Stream is a response body: framed bytes, lazily produced, plus their content type. Close must always run; a mid-stream failure surfaces from WriteTo, after the status.

type VerificationConfig

type VerificationConfig struct {
	Closure          string            `json:"closure"`                    // root — a branch name or a head id
	Layer            string            `json:"layer,omitempty"`            // optional single storage layer to check directly
	Depth            VerificationDepth `json:"depth,omitempty"`            //
	ContentThreshold int64             `json:"contentThreshold,omitempty"` // for full-content, max bytes checked per claim; 0 = all
}

VerificationConfig parameters a run.

type VerificationDepth

type VerificationDepth string

VerificationDepth is how thoroughly a run checks each claim.

const (
	DepthCompleteness      VerificationDepth = "completeness"       // every referenced claim is present
	DepthRecordCorrectness VerificationDepth = "record-correctness" // ids and signatures check out
	DepthFullContent       VerificationDepth = "full-content"       // content matches its hash too
)

type VerificationFailure

type VerificationFailure struct {
	ID     string      `json:"id"`
	Mode   FailureMode `json:"mode"`
	Layer  string      `json:"layer,omitempty"` // where it was found
	Detail string      `json:"detail,omitempty"`
}

VerificationFailure is one integrity problem a run found.

type VerificationReport

type VerificationReport struct {
	ID            string                `json:"id"`
	Config        VerificationConfig    `json:"config"`
	Head          string                `json:"head,omitempty"` // the head the run pinned at start
	Status        RunStatus             `json:"status"`
	StartedAt     time.Time             `json:"startedAt"`
	CompletedAt   time.Time             `json:"completedAt,omitzero"` // zero while running
	ClaimsChecked int64                 `json:"claimsChecked"`
	BytesRead     int64                 `json:"bytesRead"`
	OK            bool                  `json:"ok"` // true when no failures were found
	Failures      []VerificationFailure `json:"failures,omitempty"`
}

VerificationReport is a point-in-time record of a run.

Directories

Path Synopsis
package: access / policy type: checker job: decide whether a system account may exercise a CRUD right on a branch limits: pure policy from config; no ports, no ctx; core loops it for delete (-> config, core)
package: access / policy type: checker job: decide whether a system account may exercise a CRUD right on a branch limits: pure policy from config; no ports, no ctx; core loops it for delete (-> config, core)

Jump to

Keyboard shortcuts

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