api

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2026 License: AGPL-3.0 Imports: 33 Imported by: 0

Documentation

Overview

Package api is the HTTP interface every Wegweiser client speaks.

The web interface and the weg command line are both clients of it, and neither reaches the database any other way (architecture invariant 1). What the API accepts is described in openapi.yaml, which is the source of truth: the models, the server interface and the client in gen/ are all generated from it, so an endpoint that is not written down there does not exist.

Index

Constants

View Source
const BootstrapName = "bootstrap"

BootstrapName is the name the first token carries, so that an operator listing tokens can see which one came from the installer rather than from a person.

View Source
const TokenPrefix = "weg_"

TokenPrefix marks a secret as one of ours, so that a token pasted into the wrong field is recognisable in a log and a secret scanner has something to match on.

Variables

View Source
var ErrTokenInvalid = errors.New("api: the token is not valid")

ErrTokenInvalid is what every failed authentication returns.

Unknown, revoked and expired are one error on purpose: three would let an attacker sort guesses into "wrong" and "used to be right" (D5).

Functions

func EnsureBootstrapToken

func EnsureBootstrapToken(
	ctx context.Context, s store.Store, now time.Time,
) (secret string, err error)

EnsureBootstrapToken creates the first admin token if the database has none, and returns the secret exactly once.

An empty secret means tokens already existed and nothing was created. There is no way to ask for the secret again: what is stored is a hash, so a lost bootstrap token is replaced rather than recovered (docs/decisions.md D5).

func MintToken

func MintToken(name string, scopes []Scope, now time.Time) (secret string, tok store.Token, err error)

MintToken creates a new token and the record that stores it.

Types

type Config

type Config struct {
	// Store is the source of truth. It is read directly and written only
	// through the applier.
	Store store.Store

	// Applier is the write path. Every change goes through it, so that no
	// write bypasses the journal (architecture invariant 4).
	Applier *apply.Applier

	// Snapshots is the data plane whose view is republished after every write.
	// A nil one means the API is running without a query path, which is what a
	// test does; writes then change the database and nothing else.
	Snapshots Snapshots

	// Metrics is what /metrics exports. It is required rather than optional:
	// an endpoint that answers with an empty registry when the process forgot
	// to build one would report a server that answers no queries, which is
	// worse than no endpoint at all.
	Metrics *metrics.Metrics

	// Stream is what the live query stream subscribes to. Required for the
	// same reason as Metrics: an endpoint that opens a stream nothing feeds
	// looks like a server nobody is querying.
	Stream *stream.Hub

	// UI decides whether the embedded web interface is served alongside the
	// API. False serves only the API and answers everything else with a
	// problem document saying so (docs/decisions.md D16).
	UI bool

	// OnError is called for failures the client is not told the detail of, so
	// that they reach an operator instead of nobody. It may be nil.
	OnError func(error)

	// Now supplies the current time. Nil picks [time.Now]; tests set it.
	Now func() time.Time
}

Config is what a Server needs.

type Scope

type Scope string

Scope is a permission a token carries.

const (
	ScopeRead  Scope = "read"
	ScopeWrite Scope = "write"
	ScopeAdmin Scope = "admin"
)

The scopes a token may carry. They are ordered: admin allows everything write allows, and write allows everything read allows. Three levels rather than a permission per endpoint, because a permission model nobody can hold in their head is one that gets granted wholesale.

type Server

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

Server implements the generated API.

func New

func New(cfg Config) (*Server, http.Handler, error)

New returns a server and the handler that serves it.

func (*Server) Close

func (s *Server) Close() error

Close stops the background work the server does and writes out what it was holding.

It is safe to call more than once, and a server that is closed still serves: the handler does not depend on any of this, so a request arriving during shutdown is answered rather than dropped.

func (*Server) CreateRecord

CreateRecord adds a record to a zone.

What adding it caused comes back with it. An address record may generate a PTR, may find that the address already answers with another name, or may find no reverse zone to put anything in, and the last two are not errors. They are decisions for a person, so they travel as data (docs/decisions.md D3 and D6).

func (*Server) CreateSession

CreateSession exchanges a token for a browser session.

func (*Server) CreateToken

CreateToken mints a token and shows its secret for the only time.

func (*Server) CreateZone

CreateZone brings a zone into existence.

func (*Server) DeleteRecord

DeleteRecord removes a record, and whatever was generated from it.

func (*Server) DeleteSession

DeleteSession ends the session, if the request came with one.

func (*Server) DeleteZone

DeleteZone removes a zone and everything in it.

func (*Server) DetachRecord

DetachRecord turns a generated record into an authored one.

This is the way out of "a generated record cannot be edited" (D4). A record that is already authored comes back unchanged rather than as an error, which makes calling this twice harmless.

func (*Server) ExportZone

ExportZone writes a zone out in the format every other authoritative server reads.

func (*Server) GetCommit

GetCommit returns one commit with everything it changed.

func (*Server) GetHealth

GetHealth reports whether the server is fit to answer queries.

func (*Server) GetMetrics

GetMetrics writes the current values in the Prometheus text exposition format.

func (*Server) GetRecord

GetRecord returns one record.

func (*Server) GetSession

GetSession reports who the request is authenticated as.

func (*Server) GetSettings

GetSettings reports the defaults a zone that says nothing inherits.

func (*Server) GetZone

GetZone returns one zone.

func (*Server) ImportZone

ImportZone brings a whole zone in from a file in the format of RFC 1035 §5.

func (*Server) ListCommits

ListCommits returns one page of history, newest first.

func (*Server) ListRecords

ListRecords returns one page of a zone's records.

func (*Server) ListTokens

ListTokens returns every token, revoked and expired ones included.

func (*Server) ListZones

ListZones returns one page of zones.

func (*Server) ReplaceRRsets

ReplaceRRsets makes the named RRsets exactly what the client sent.

func (*Server) RevokeToken

RevokeToken withdraws a token.

func (*Server) RollbackZone

RollbackZone restores a zone to the state it had at a serial.

func (*Server) StreamQueries

StreamQueries carries a live tail of the exchanges matching the filter, as Server-Sent Events.

func (*Server) UpdateRecord

UpdateRecord changes a record, keeping its identity.

func (*Server) UpdateSettings

UpdateSettings changes them. A field the request leaves out is left alone, so a client may send only what it means to change.

func (*Server) UpdateZone

UpdateZone changes a zone's own settings, leaving its records alone.

type Snapshots

type Snapshots interface {
	Snapshot() *dns.Snapshot
	SetSnapshot(*dns.Snapshot)
}

Snapshots is the data plane, as far as the API needs to know about it: it reports what is being answered from, and it takes what should be answered from next. A *dns.Server is one.

It is an interface so that the API can be tested without a socket, and so that the coupling stays the one pointer architecture invariant 2 allows.

Directories

Path Synopsis
Package gen provides primitives to interact with the openapi HTTP API.
Package gen 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