server

package
v0.41.5 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2026 License: Apache-2.0 Imports: 53 Imported by: 0

Documentation

Overview

syscall.Flock is absent on solaris and aix, so `unix` alone claims two platforms this file cannot compile on. Excluding them says what is true; making them work would mean x/sys/unix.Flock, which neither shipped image needs.

Package server implements the aeman HTTP server: the embedded single-page application, the /api/v1 resource API and watch stream, the MCP transport, and the board store over the board's git repositories. The browser never holds a credential: identity is resolved server-side (the owner of the credential a local run resolved, or per-user OAuth sessions) and the push credential is the server's.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DataDirHold added in v0.33.0

func DataDirHold(dir string) (io.Closer, error)

DataDirHold takes the claim on a data directory and keeps it until the returned value is closed. A caller about to configure a long-running process holds it just long enough to learn the directory is free, then closes it; the answer is advisory, since it goes stale the moment it is given and the daemon takes the claim for real at its own start.

Types

type GitBackend added in v0.26.0

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

GitBackend is a git-mode store without an HTTP server — what `aeman mcp --repo` runs on: its own clone, cache, queue and push.

func OpenGitBackend added in v0.26.0

func OpenGitBackend(cfg *GitConfig, log *slog.Logger) (*GitBackend, error)

OpenGitBackend clones or reopens the configured repository and returns a backend over it. log may be nil.

func (*GitBackend) Backend added in v0.26.0

func (g *GitBackend) Backend() boardservice.Backend

Backend is the boardservice.Backend to build a service on.

func (*GitBackend) Close added in v0.33.0

func (g *GitBackend) Close() error

Close releases this process's claim on the data directory, so the next `aeman serve` or `aeman mcp` may open the clones. It does not stop the background sync, so it belongs on a process's way out rather than mid-life.

func (*GitBackend) Drain added in v0.26.0

func (g *GitBackend) Drain(ctx context.Context) error

Drain waits for the write queue and pushes — what a stdio MCP process does before it exits, so a client that closes the pipe right after a mutation loses nothing. It reports a queue that did not empty as an ERROR rather than pushing on in silence: what is left never became a commit and does not survive this process, so a caller that logs the error is the only thing standing between a lost change and nobody knowing.

func (*GitBackend) MCPActionMiddleware added in v0.40.1

func (g *GitBackend) MCPActionMiddleware() func(mcp.MethodHandler) mcp.MethodHandler

MCPActionMiddleware groups the writes of one MCP tool call into a single commit, so a fan-out tool over the loopback daemon does not write one commit per touched card (finding: MCP commit flooding). The HTTP MCP transport wires the same middleware itself.

func (*GitBackend) UnpushedAge added in v0.33.0

func (g *GitBackend) UnpushedAge() time.Duration

UnpushedAge is how long the oldest commit this process has failed to push has been waiting; zero when everything has landed. A stdio process lived one editor session and reported a failed push on the client's stderr; a daemon runs unattended for weeks, so this is what tells one that is working apart from one whose credential died a week ago.

type GitConfig added in v0.26.0

type GitConfig struct {
	// Repos are the board's domains, primary first. Only the primary is
	// served for now.
	Repos []RepoSpec
	// Token is the push/fetch credential (HTTPS basic auth) for the
	// repositories that name none of their own; empty means an
	// unauthenticated transport (local file remotes, tests).
	Token string
	// App mints the server credential per repository from a GitHub App
	// installation instead of a static token: nothing to issue by hand,
	// nothing that quietly expires in a .env file. A repository that names
	// its own Token keeps it; the App covers the rest. GitHub only.
	App *forge.GitHubApp
	// Forge is the code host the repositories live on: it says how the
	// token travels over HTTPS (the basic-auth username differs per forge).
	// GitHub when nil.
	Forge forge.Forge
	// DataDir holds the clones (<DataDir>/repos/<name>).
	DataDir string
	// History is the background deepening horizon; zero disables it.
	History time.Duration
	// HistoryMax caps on-demand deepening — a card's log cut by the horizon
	// fetches back to the card's creation, but never further than this.
	// Zero means no on-demand deepening.
	HistoryMax time.Duration
	// SyncInterval is the fetch cadence; zero disables the ticker.
	SyncInterval time.Duration
	// UnpushedWarn is the age of the oldest unpushed commit that turns
	// health red; zero means 5 minutes.
	UnpushedWarn time.Duration
	Committer    gitstore.Identity
	// AuthorEmail is the author email template ("{login}" substituted);
	// empty means <login>@aeman.
	AuthorEmail string
}

GitConfig enables git mode.

type OAuthConfig

type OAuthConfig struct {
	ClientID     string
	ClientSecret string
	// BaseURL is the public origin (e.g. https://aeman.example.com) used to
	// build the OAuth redirect URI.
	BaseURL string
	// Scopes is a space-separated OAuth scope list (defaults to the forge's).
	Scopes string
	// SessionFile, when set, persists the dynamic MCP client registry to this
	// path so registered clients survive restarts. GitHub tokens (sessions) are
	// written here only when SessionKey is set — encrypted — so without a key a
	// restart signs users out but leaks no credentials to disk.
	SessionFile string
	// SessionKey, when set, is a secret that encrypts the persisted sessions at
	// rest (AES-256-GCM, key = SHA-256 of this value). With it, sessions and
	// MCP tokens survive a restart; the on-disk file holds only ciphertext, so
	// a leak of the file alone (backup, stray volume) exposes no token. Empty =
	// sessions stay in memory only (signed out on restart).
	SessionKey string
}

OAuthConfig enables multi-user mode: each visitor signs in with GitHub and the proxy forwards requests with that user's own token.

type Options

type Options struct {
	// Addr is the listen address, e.g. "127.0.0.1:8765".
	Addr string
	// Version is reported to the frontend via /api/config.
	Version string
	// Logger receives structured logs; slog.Default() is used when nil.
	Logger *slog.Logger
	// Auth, when non-nil, enables OAuth multi-user mode: each visitor signs
	// in with the forge, and their own token decides which of the board's
	// repositories they may read and write.
	Auth *OAuthConfig
	// Git is the board's storage — its repositories (see gitmode.go). A
	// server without it serves no board; tests inject a service instead.
	Git *GitConfig
	// Forge is the code host behind the board — the identity provider,
	// the authority on repository access, the directory of names and
	// avatars, the git credential's dialect. GitHub when nil.
	Forge forge.Forge
	// CLI is where a single-user server reads its credential and the
	// person it belongs to — the environment, the OS keychain, or the
	// forge's own tool; the gh CLI when nil. Unused in OAuth mode.
	CLI forge.CLI
}

Options configures a Server.

type Problem added in v0.41.0

type Problem struct {
	// Type is always "about:blank": Code carries the identity, and there is
	// no page per problem to point at (RFC 9457 §4.2.1).
	Type      string `json:"type"`
	Title     string `json:"title"`
	Status    int    `json:"status"`
	Detail    string `json:"detail"`
	Code      string `json:"code"`
	ActionURL string `json:"actionUrl,omitempty"`
}

Problem is what the JSON surface under /api refuses with: RFC 9457 problem details, with two extension members. Code names the rule that refused for a program to branch on; Detail is the sentence a person reads; ActionURL, when set, is where the person can go to fix it.

func (Problem) Error added in v0.41.0

func (p Problem) Error() string

Error lets a handler hand back a problem it decided itself — a zone the board does not have, a gesture the board does not draw — where the only way out is an error: a strict method answers through its return value, and the response hook writes whatever problemFor makes of it.

type RepoSpec added in v0.26.0

type RepoSpec struct {
	Name string
	URL  string
	// Token is this repository's own credential — a board may span two
	// organisations, and one token narrow enough for either cannot reach
	// both. Empty falls back to GitConfig.Token.
	Token string
}

RepoSpec names one domain: a repository and its label.

type Server

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

Server is the aeman local HTTP server.

func New

func New(opts Options) (*Server, error)

New builds a Server from the given options.

func (*Server) Close added in v0.33.0

func (s *Server) Close() error

Close releases the server's claim on its data directory, so the next `aeman serve` or `aeman mcp` may open the board's clones. It does not stop the background sync, so it belongs on a process's way out rather than mid-life. A server built without git mode holds no directory and Close does nothing.

func (*Server) Run

func (s *Server) Run(ctx context.Context) error

Run starts the server and blocks until ctx is cancelled or it fails.

func (*Server) URL

func (s *Server) URL() string

URL returns the address the server can be reached on in a browser.

Directories

Path Synopsis
Package apiv1 provides primitives to interact with the openapi HTTP API.
Package apiv1 provides primitives to interact with the openapi HTTP API.

Jump to

Keyboard shortcuts

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