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

serve

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package serve answers read-only questions about a warehouse, over HTTP, so the console never holds a warehouse credential.

Everything here runs on the far side of that line. The console forwards a request; this decides what may run, bounds it, runs it and says what it did. A limit the console could change is not a limit, which is why none of them live there.

Index

Constants

View Source
const CodeNoConnection = "no-connection"

CodeNoConnection is what the console matches on. See ErrNoConnection.

View Source
const EnvLocal = "local"

EnvLocal is the one environment where an open endpoint is allowed.

Variables

View Source
var ErrNoConnection = errors.New("no connection is declared for that destination")

ErrNoConnection is what an opener returns when nothing is DECLARED for a destination, as opposed to declared and unreachable.

THE DIFFERENCE IS THE WHOLE POINT. "Unreachable" is an incident and says nothing a reader can act on; "nobody has declared where that database is" is a sentence with an action in it, and V4 puts it on the screen. A 502 would bury the second inside the first.

Functions

func BytesText

func BytesText(n int64) string

BytesText is a byte count somebody can judge at a glance.

A refusal saying "10737418240 bytes" is one somebody has to count the digits of, and the number IS the content of that message: it is the difference between a typo and a query worth waiting for.

func ReadOnly

func ReadOnly(dialect, statement string) error

ReadOnly refuses any statement that is not a single query.

THIS IS THE FUNCTION BETWEEN A BROWSER AND A CUSTOMER'S WAREHOUSE, and it is written to be read by somebody deciding whether to trust it.

OVER A TOKENISER AND NOT A REGEX, which is the whole reason `sqltok` exists as its own package. A pattern matching `DELETE` cannot tell code from a string literal or a comment, so it refuses `WHERE note = 'please DELETE this row'` -- a legitimate query -- and it accepts `/* SELECT */ DROP TABLE t`. Both of those are cases below.

WHAT IT CANNOT DO, said plainly so nobody discovers it as a bug: a function call writes whatever the function writes. `SELECT nextval('s')` advances a sequence and `SELECT dblink_exec(...)` runs anything at all, and no classifier that is not a planner can see inside them. THE READ-ONLY ROLE IS THE DEFENCE THERE, not this -- which is exactly the question CHECKPOINT B exists to answer before this is deployed anywhere.

WHEN IT CANNOT FOLLOW THE STATEMENT, IT REFUSES. A parser that gives up and allows is a parser that can be made to give up on purpose.

Types

type Caller

type Caller struct {
	// Name is what the audit line carries. It reaches a JSON document and
	// somebody's grep, so it is checked at boot rather than escaped later.
	Name string

	// Token is the bearer this caller presents.
	Token string
}

Caller is one named bearer.

CHECKPOINT B's F7: the audit line carried connection, hash, rows, bytes, duration and outcome, and nothing about WHO asked. With one operator that was a note; with two it means the log cannot answer the only question it is read for.

IDENTITY IS THE CREDENTIAL, not a header. A caller that announced its own name would be making a CLAIM, and an audit of claims is an audit of whatever an attacker typed. A token the operator issued is a FACT: the line cannot say anything the holder of that token did not actually hold.

The Name is not a secret -- it is printed at boot and written to every line. The Token is, and appears in neither.

type Options

type Options struct {
	// Env decides whether an unauthenticated service may exist. It comes from
	// BREVIS_ENV and NEVER from a configuration file -- the gateway's rule,
	// and its reason: "a config file that could declare itself local would be
	// a file that turns off authentication."
	Env string

	// Token is the bearer every request must carry, with NO NAME attached.
	// Required outside local unless Callers names one.
	//
	// It is what every deployment has today and it keeps working. Its audit
	// lines carry no caller, which is itself the finding: a shared secret
	// with nobody's name on it.
	Token string

	// Callers are named bearers, and the audit line carries whichever one
	// asked. See caller.go for why identity is the credential rather than a
	// header. Folded together with Token into one list at boot.
	Callers []Caller

	// Addr is where this will listen, and it is EVIDENCE rather than
	// configuration: see New. Empty means nobody is deploying anything --
	// a test, or something embedding this -- and no rule is drawn from it.
	Addr string

	// Rows is the ceiling. A caller may ask for fewer and cannot ask for more.
	Rows int

	// Bytes is the most a single query may SCAN. A caller cannot raise it
	// and cannot name one at all: it is money, and the browser is not the
	// place that decides how much of it to spend.
	//
	// IT BOUNDS THE PREVIEW TOO, and that was a hole rather than a choice.
	// A preview is `SELECT * FROM t LIMIT 20`, and a LIMIT does not reduce
	// what BigQuery scans -- twenty rows off a petabyte table reads the
	// petabyte and bills for it. The row ceiling bounds the screen and
	// bounds nothing else.
	Bytes int64

	// Budget is the most one CONNECTION may scan in an hour, across every
	// query. Zero is no budget, which is the default.
	//
	// A CONCURRENCY LIMIT IS NOT A BUDGET -- CHECKPOINT B's F6. Four queries
	// at a time, each under the per-query ceiling, repeated forever, is
	// unbounded: the ceiling bounds one query and nothing bounds the sum.
	// For a single authenticated operator no budget may well be the right
	// answer, but it has to be a CHOICE, and an absence is not one. The boot
	// banner states whichever it is.
	//
	// PER CONNECTION, because a connection is what pays the bill: two
	// warehouses are two accounts, and exhausting one must not close the
	// other.
	//
	// IT BOUNDS WHAT IS METERED, which is not everything. A warehouse that
	// charges for a machine by the hour reports no bytes, so a budget bounds
	// BigQuery and bounds nothing on Postgres. That is fine -- Postgres is
	// not billed by the byte -- and dangerous only if somebody believes
	// otherwise, which is why the banner says which connections it can
	// actually bound.
	Budget int64

	// Writable NAMES THE CONNECTIONS on which a statement may write. Empty
	// is the default and is every deployment that has not asked otherwise.
	//
	// IT COMES FROM BREVIS_SQL_SERVE_WRITES AND NEVER FROM A FILE, which is
	// the rule Token already follows one field up and for the same reason: a
	// config file that could declare itself local would be a file that turns
	// off authentication, and one that could declare itself writable would
	// be a file that turns off every limit on this surface at once.
	//
	// NAMES AND NOT A BOOLEAN. One service reaches several warehouses, and
	// unlocking the one somebody develops against must not unlock the one
	// beside it. The accident this exists to prevent is a development
	// service that is also pointed at a production DSN, and a switch cannot
	// tell those apart.
	//
	// A NAME HERE STANDS DOWN EVERY LAYER AT ONCE -- the tokeniser, the
	// warehouse's verdict and the warehouse's enforcement -- so on a named
	// connection this service is exactly as powerful as its credential. The
	// row ceiling bounds a screen and the byte ceiling bounds MONEY; neither
	// bounds damage, because an UPDATE scans almost nothing and changes
	// everything.
	Writable []string

	// Audit is where one line per query goes. Nil writes none, which is what
	// a test wants and never what a deployment does.
	Audit io.Writer

	// Concurrent is how many queries may run at once. Over that, a caller is
	// REFUSED rather than queued: a queue behind a browser is a browser that
	// waits with no way to know why, and every waiting request still holds a
	// connection to the warehouse.
	Concurrent int

	// Timeout bounds one query, the dry run and the read together.
	Timeout time.Duration

	// Open connects to one warehouse. A field so a test can hand over a fake
	// without a warehouse, and so this package holds no driver of its own.
	//
	// IT TAKES THE WHOLE TARGET and not just a name, because a name is not
	// unique on its own: `app` can be a BigQuery project and a Postgres
	// database at once, and the registry matches on both halves.
	Open func(ctx context.Context, t Table) (dialect.Conn, error)
}

Options is what a Service needs.

type Service

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

Service answers read-only questions about a warehouse.

func New

func New(opt Options) (*Service, error)

New builds the service, or refuses to.

REFUSING TO EXIST IS THE POINT. A service that started without a token and logged a warning would be an open endpoint onto a customer's warehouse, with a line in a log nobody reads. Failing at boot is the only refusal that cannot be ignored.

func (*Service) Handler

func (s *Service) Handler() http.Handler

Handler is the service's routes.

func (*Service) Metrics

func (s *Service) Metrics() http.Handler

Metrics is the exposition, and it is a SEPARATE HANDLER on purpose.

The rule this repository states twice, in the engine and in the gateway: a scrape endpoint on the port that answers requests would either need a session no scraper has, or publish every connection name to whoever can reach that port. `Handler` does not route /metrics at all, and a test says so.

It carries no authentication of its own, for the same reason the gateway's does not: it is bound to an address an operator chooses, and a scraper cannot hold a token.

type Table

type Table struct {
	// Connection is which warehouse: the BigQuery project.
	Connection string
	// Dialect is whose SQL this is, which the classifier needs: `#` opens a
	// comment in one of them and is an operator in the other, and reading
	// the wrong one wrong is how `# SELECT\nDROP TABLE t` gets through.
	Dialect string
	// Relation is `dataset.table`, ready to be written into SQL -- which is
	// safe only because both halves matched `identifier`.
	Relation string
}

Table is a target this service can read.

func ParseTarget

func ParseTarget(target string) (Table, error)

ParseTarget turns a catalog target into something readable, or refuses it.

THE MOST DANGEROUS FUNCTION IN THIS PACKAGE. What it returns is written into a statement, so nothing here escapes an input and then uses it: every segment must ALREADY be a name BigQuery could hold, and anything else is refused whole. A semicolon, a comment marker, a backtick or a space each turn one statement into two.

BIGQUERY ONLY, FOR NOW, and that is a shape rather than an omission: a `bigquery://` target carries its project, and the project IS the connection. `postgres://database/schema/table` carries a database name and no host, port or user -- a target is an identity and never an address -- so it cannot be reached without a connection somebody declared, which is a later slice.

`s3`, `gs`, `file` and `pubsub` are not tables. They are in the catalog because Brevis lands them, and they have no rows to preview.

Jump to

Keyboard shortcuts

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