capgw

package
v0.2.40 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2026 License: MPL-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package capgw is the capability inlet: `POST /v1/cap/<name>` on the web head, where dispatched work — a run on a NODE, a chassis of its own that this chassis dispatched a run to — asks this chassis to do something on its behalf: call a model, note a card, finish the run. The request carries the run's grant as a token (Txco-Run-Grant) and the call's input as JSON; the grant gateway decides it (chassis/server/grantgw.Invoke) and, when it is allowed, the stack that DECLARES the capability runs it as an ordinary pipeline run (`@src == "cap"`, the call at `@cap.*`), entered at the stack's start — or at the scope its declaration names (CAPS/<name>.yaml, chassis/capdecl) — and answers at the top-level `_cap.output` — or `_cap.error {code, message}`. A name no active stack declares still runs the tenant's `_cap` stack from its first scope: the router a tenant wrote before declarations existed.

The inlet owns the transport and the identity; the stacks own the policy (`_grant`) and the work (the declaring stack). The chassis does not know what a capability does.

Answers, always JSON. The decision is answered with its status:

401 {"ok":false,"error":{"code":"unauthorized"}}   no token, or not a live grant's
403 {"ok":false,"error":{"code":"denied"}}         refused: allowlist, standing grant, budget, a rule
409 {"ok":false,"error":{"code":"held"}}           a rule held it for a person
404 {"ok":false,"error":{"code":"no_capability"}}  not a capability name
503 {"ok":false,"error":{"code":"unavailable"}}    the chassis could not decide

An ALLOWED call answers 200 at once — headers sent and flushed before the capability's run starts — and the body when the run ends. A model call can take a minute; a proxy on the way (the fleet's edge allows 20 s for response headers) must see headers, and then bytes: until the body, the inlet writes one space every keepalive interval. So what the run came to is in the body, with the status it would otherwise have carried:

200 {"ok":true,"output":…}
200 {"ok":false,"error":{"code":"no_capability","status":404}}        no rule answered
200 {"ok":false,"error":{"code":…,"message":…,"status":422}}         the stack's own error
200 {"ok":false,"error":{"code":"timeout","status":504}}             the run passed its ceiling
200 {"ok":false,"error":{"code":"unavailable","status":503}}         the run failed, or the tenant could not be routed

A refusal says only that it was refused: the trace of the `_grant` run has the reason. A client reads `error.status` as the status (the node's cap:// does); the leading whitespace is JSON's own.

Index

Constants

View Source
const (

	// Header is where the token travels. The node's web head reads the same
	// header off the dispatching request and keeps it out of its envelope.
	Header = processor.RunGrantHeader
	// CallerRIDHeader names the run that is calling, on the node: stamped
	// as `@cap.caller.rid` so a run can be followed across the two chassis.
	CallerRIDHeader = "Txco-Caller-Rid"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Decls

type Decls interface {
	Lookup(ctx context.Context, tenant, name string) (stack string, d *capdecl.Decl, err error)
}

Decls is where the inlet finds who answers a capability: the tenant's active stack that declares the name, and the declaration. It answers capdecl.ErrNotDeclared for a name no active stack declares.

type Gateway

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

Gateway is the inlet.

func New

func New(ctx context.Context, pu *processor.Unit, grants *grantgw.Gateway, decls Decls) *Gateway

New builds the inlet over the grant gateway, the capability declarations and the processor's bus. A nil decls routes every call to `_cap`.

func (*Gateway) Handle

func (g *Gateway) Handle(w http.ResponseWriter, r *http.Request)

Handle serves POST /v1/cap/{name}. Registered ahead of the web catch-all: no BasicAuth (the token is the whole authorization), no opstack render path.

Jump to

Keyboard shortcuts

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