server

package
v0.2.3 Latest Latest
Warning

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

Go to latest
Published: Sep 25, 2026 License: MIT Imports: 75 Imported by: 0

Documentation

Overview

Package server implements the HTTP/JSON API for any-sync-sdk.

@title			Any API
@version		1.0
@description	Local HTTP/JSON API wrapping any-sync-sdk. Localhost-only, no auth in v1.

@servers.url	http://127.0.0.1:7001/v1

Index

Constants

View Source
const DefaultAccountSelector = "default"

DefaultAccountSelector names the legacy flat-root account to FindRunning's filter, which otherwise matches account dirs by id.

View Source
const DevicesDataset = "devices"

DevicesDataset is the tech-space system dataset holding the account's device registry: one row per device (peer), row id = peerId. Like the space list it lives on the tech-space index object and is system-owned — reads go through the endpoints below, writes only through the restricted self-row surface (never the generic modify path). See docs/23-devices.md.

View Source
const SpaceListDataset = "spaces"

SpaceListDataset is the default tech-space system dataset the space-list query/subscribe endpoints read. The profile dataset is reachable via the optional `dataset` body field.

Variables

This section is empty.

Functions

func AccountID

func AccountID(ctx context.Context, p auth.Provider) (string, error)

AccountID returns the anytype account identifier derived from the provider's account key — the string health exposes as "account".

func NewIndexRegistry

func NewIndexRegistry() *index.Registry

NewIndexRegistry builds the chunker registry — one chunker per indexed dataset, paralleling the Types list above. The indexer (internal/indexer) drives it.

Indexed: editor blocks (coalesced windows), chat messages, and object properties (name / description under "basic"; user values default-on under "props", meta.index overriding — see internal/index/prop.go). Deliberately NOT indexed: saved views (`dataviews` / `views` — navigation chrome, not knowledge) have no chunker. Agent data, enrichments, programs and mini apps are harness-declared runtime datasets: indexed via the schema chunker under their declared search scope, or not at all when the declaration carries no `search` mapping (program source and mini-app HTML are code, not knowledge — anybao ADR-010 §5).

func OpenIndexer

func OpenIndexer(ctx context.Context, cfg config.Index, dataDir, modelsDir string, sdk *anysyncsdk.SDK, chunkers *index.Registry, onProcess func(indexer.ProcessUpdate), onLinks func(spaceId string, targets []string)) (*indexer.Indexer, error)

OpenIndexer builds the search indexer: embedder (per config), local index store under <dataDir>/index, and the service over the chunker registry. modelsDir is the shared (cross-account) model cache; a model already downloaded to the legacy <dataDir>/index/models keeps being used from there. There is no boot-time embedder probe: an unreachable embedder never blocks the boot or the FTS pipeline — text-bearing docs queue as pending and the embed loop picks them up once the embedder responds (the dimension is learned from the first successful batch unless index.vector.dim pins it). A misconfigured embedder (bad name, missing model) is still a hard error. onProcess (nil = off) receives indexing lifecycle updates (fts / embed / model download) for the process view — see deps.indexerProcess.

func OpenSDK

func OpenSDK(ctx context.Context, cfg config.Config, nodeconf []byte, dataDir string, provider auth.Provider) (*anysyncsdk.SDK, error)

OpenSDK boots the SDK against the wallet provider and the project config, joining the network nodeconf names (resolved by the caller, which pins it). Storage lives under <dataDir>/sdk so the SDK's any-store and any-sync state are isolated from other process state in the data dir.

Topology defaults to Shared; only "shared" is supported in v1 (per-space topology is on the SDK side but not yet exercised here).

func OpenWallet

func OpenWallet(path, passkey, mnemonic string, index uint32) (provider *auth.FileProvider, firstRun bool, err error)

OpenWallet loads or creates the file-backed wallet at path. A non-empty mnemonic seeds creation (restore / second-device path; the device key is always fresh) and must match an already-existing wallet; index is the account-derivation index applied on creation — fresh generation included — and read back from the file otherwise. On first generation the returned firstRun flag is true, and the caller is expected to display Mnemonic() once.

func PrintMnemonic

func PrintMnemonic(phrase string)

PrintMnemonic writes the first-run warning and BIP-39 phrase to stderr. Stderr (not stdout) so it doesn't contaminate piped output, and only on the wallet's first generation.

func Run

func Run(ctx context.Context, cfg config.Config) error

Run starts the HTTP server and blocks until ctx is cancelled or POST /v1/shutdown is called. Caller is responsible for installing signal handlers and cancelling ctx accordingly.

When the data dir resolves to an account (root wallet, sole per-account dir, or an explicit selector) its engine — wallet, SDK, indexer — boots before the listener binds, so failures surface before any request is accepted. With no account to boot the server starts UNAUTHORIZED: every /v1 route except health/shutdown/auth returns 401 auth.required until POST /v1/auth creates or selects an account and boots the engine in place.

func RunWith

func RunWith(ctx context.Context, cfg config.Config, opts RunOptions) error

RunWith is Run plus a hook surface. Embedders (gomobile) use this to learn the bound address synchronously and surface bind / wallet / SDK errors before returning.

func StopRunning

func StopRunning(r Running, wait time.Duration) error

StopRunning asks the holder to exit (SIGTERM — the same graceful path Ctrl-C takes) and waits for its lock to be released. Windows has no signal to send; stopping there is the user's job.

func ValidateCatalog

func ValidateCatalog(src []byte) catalog.Problems

ValidateCatalog runs every check on a catalog source — the pure ones and the server-side gate — and returns every problem found. Nil means valid. Offline: nothing here touches a space or the SDK.

func ValidateLoopback

func ValidateLoopback(addr string) error

ValidateLoopback rejects non-loopback bind addresses. v1 is loopback-only on purpose (see docs/02-server.md).

Types

type ErrLocked

type ErrLocked struct {
	PID  int
	Path string
}

ErrLocked is returned when Acquire finds another process holding the lock. PID is 0 when the holder's pid file is missing or unreadable — the holder writes it just after acquiring, so a racing Acquire can arrive first.

func (*ErrLocked) Error

func (e *ErrLocked) Error() string

type ErrNetworkMismatch

type ErrNetworkMismatch struct {
	Pinned     string
	Configured string
}

ErrNetworkMismatch refuses a boot whose configured network is not the one the account dir is pinned to.

func (*ErrNetworkMismatch) Error

func (e *ErrNetworkMismatch) Error() string

type ErrNoIdentity

type ErrNoIdentity struct {
	// Accounts lists the per-account dirs found (empty = fresh root).
	Accounts []string
}

ErrNoIdentity is the resolution outcome "nothing to boot": no wallet selected and none unambiguously present. `run` starts unauthorized and waits for POST /v1/auth; CLI paths print the hint instead.

func (*ErrNoIdentity) Error

func (e *ErrNoIdentity) Error() string

type Identity

type Identity struct {
	// Account is the expected account id. Empty when it can only be
	// learned by opening the wallet (root wallet / explicit override);
	// when non-empty the caller verifies the derived id against it.
	Account string
	// Dir holds this account's server.pid, sdk/ and index/ — and, under
	// managed custody, the cached device.key.
	Dir string
	// WalletPath is the wallet file to open. Empty under managed
	// custody, where the account key never touches disk.
	WalletPath string
}

Identity names the wallet a server boots with and where that account's data lives. Dir is the per-account data dir (the root itself for the legacy flat layout and for an explicit walletPath override).

func ResolveIdentity

func ResolveIdentity(cfg config.Config, root string) (*Identity, error)

ResolveIdentity decides which wallet to boot for the given root:

  1. auth.walletPath / --wallet override → that wallet, data flat at the root (manual mode, no per-account nesting).
  2. --account / ANY_ACCOUNT / account: selector → <root>/<id>/ if it exists, else the root wallet (verified against the selector after opening), else an error.
  3. No selector: root wallet.key → the default flat account; else a sole per-account dir; else *ErrNoIdentity (none or several).

type Lock

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

Lock is the single-instance lock on an account dir: an exclusive OS file lock on <dir>/server.lock (flock(2) on unix, LockFileEx with LOCKFILE_FAIL_IMMEDIATELY on Windows), plus <dir>/server.pid naming the holder for error messages.

The kernel releases the lock when the process exits by any means, so there is no stale-lock reclaim and no liveness probe: a crashed holder blocks nobody. server.pid is advisory — it never decides who holds the lock, and it can name a dead process whenever the lock is free.

Neither file is removed, on release or on crash. Unlinking a file under an OS lock lets the next process create a fresh inode and lock THAT, so both would hold "the" lock.

The lock file is opened only here: on aix/solaris/illumos gofrs/flock falls back to POSIX fcntl records, which any close of any descriptor to the file drops. Those aren't platforms we ship, but a second opener would be a trap on the ones that are, too.

func Acquire

func Acquire(dir string) (*Lock, error)

Acquire takes the single-instance lock for an account dir. Returns ErrLocked when another process holds it.

func (*Lock) Release

func (l *Lock) Release() error

Release drops the OS lock and closes the lock file. Safe to call from a defer — no-op on a nil Lock (the mobile build's bypass). The lock and pid files stay on disk by design.

type RunOptions

type RunOptions struct {
	// Ready, if non-nil, is invoked once the TCP listener has bound but
	// before Echo starts serving. It receives the actually-bound address
	// (resolving "127.0.0.1:0" to the OS-picked host:port) so embedders
	// like the gomobile wrapper can hand the real port back to the
	// caller. The hook runs on the goroutine that called Run, so keep it
	// quick — long work blocks server startup.
	Ready func(addr string)
	// ControlToken is the managed-mode control token an in-process host
	// supplies. Empty on a managed server means "mint one and announce
	// it on stdout" (the CLI / sidecar path). Ignored in standalone.
	ControlToken string
}

RunOptions tweaks server.Run behaviour without bloating its signature. All fields are optional and zero-valued by default.

type Running

type Running struct {
	// Account is the dir name (the account id); "" for the legacy
	// flat-root account.
	Account string
	Dir     string
	// PID is the holder's pid from server.pid; 0 when unknown.
	PID int
	// Addr is the holder's bound address from server.addr; "" when
	// unknown (a server older than the file, or one that never bound).
	Addr string
}

Running describes a server process holding an account's instance lock under a root. Found by probing the lock itself, so it is proof of life: a crashed holder's lock is released by the kernel and the dir reads as not running, whatever server.pid says.

func FindRunning

func FindRunning(root, account string) ([]Running, error)

FindRunning lists the servers currently serving accounts under root: the root itself (legacy layout) and every account dir, filtered to account when non-empty (DefaultAccountSelector picks the root). Neither a wallet nor a device key is consulted — only a held server.lock counts — so it finds standalone and managed servers alike, and never an unauthorized one (an engine that has not booted holds no lock). The probe takes and releases each lock for microseconds; Acquire retries briefly so a booting server never mistakes a probe for a holder.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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