Documentation
¶
Overview ¶
Package opcore is the urfave/cli-free engine core of the spec-driven verb design: the per-operation descriptor, the request runtime, and the self-guarding Operation.Execute entrypoint. specverb projects this core onto a urfave/cli tree; a non-CLI consumer (ward-mcp) drives Operation.Execute directly and is still fully gated. See docs/specverb.md for the projection shape.
Index ¶
- Constants
- Variables
- func AnyItem(token string) any
- func AssembleBody(d Descriptor, body map[string]any) ([]byte, error)
- func ChainSources(chain guardfile.ValueChain) []valuesource.Source
- func CheckFlagCollisions(desc Descriptor) error
- func CheckProxyRules(allow, deny []ProxyRule, args map[string]any) error
- func CoerceItems(items string, tokens []string) ([]any, error)
- func CoerceScalar(fieldType, token string) (any, error)
- func DefaultScheme(baseURL string) string
- func DestructiveVerb(verb string) bool
- func FillPath(template string, values []string) string
- func MatchesAnyGlob(val string, globs []string) bool
- func MethodForVerb(verb string) (string, bool)
- func ParseInline(src []byte) ([]Descriptor, RuntimeConfig, error)
- func ParseInlineWithOptions(src []byte, opts InlineOptions) ([]Descriptor, RuntimeConfig, []string, error)
- func ParseInlineWithWarnings(src []byte) ([]Descriptor, RuntimeConfig, []string, error)
- func PathParamsInOrder(path string) []string
- func ValidMethod(m string) bool
- type ArgBinder
- type Args
- type BodyMapping
- type Database
- type Descriptor
- type Field
- type GraphQL
- type InlineOptions
- type MCPCall
- type MCPEnv
- type MCPUpstream
- type Operation
- type Property
- type PropertyVariant
- type Provider
- type Proxy
- type ProxyRule
- type Request
- type Response
- type Runtime
- func (rt *Runtime) Authorize(ctx context.Context, req *http.Request) error
- func (rt *Runtime) BaseForRequest(ctx context.Context, dry bool) (string, error)
- func (rt *Runtime) CheckRestrictions(pathParams, values []string) error
- func (rt *Runtime) FireCapture(ctx context.Context, method, url string, body []byte, contentType string) (decoded any, raw []byte, status string, err error)
- func (rt *Runtime) FireCaptureRaw(ctx context.Context, method, url string, body []byte, contentType string) (raw []byte, status string, err error)
- func (rt *Runtime) MetaAllowed(param string) bool
- type RuntimeConfig
- type SQL
- type Schema
- type UpstreamTool
- type Variant
Constants ¶
const ( LocationPath = "path" LocationQuery = "query" LocationBody = "body" LocationForm = "form" )
Location constants label where a Property lowers onto the outgoing request.
const DefaultUserAgent = "umbra/1.0 (+https://github.com/coilyco/umbra)"
DefaultUserAgent names this client when nothing else does. Go's default is refused outright by some APIs; see docs/specverb-request.md (umbra#303).
const ItemsAny = "any"
ItemsAny marks an array whose swagger `items` schema is empty: the spec says the list carries more than one type. Forgejo labels. agentic-os#1047
const OwnerRepoArg = "owner-repo"
OwnerRepoArg is the documented `args` sugar: a single `owner/name` value split across the leaf's `owner` and `repo` path params.
Variables ¶
var ReservedFlagNames = map[string]bool{ "dry-run": true, "query": true, "output": true, "body-file": true, }
ReservedFlagNames are the universal per-leaf engine flags no promoted input (query, body, or form field) may shadow. See docs/specverb-request.md.
Functions ¶
func AnyItem ¶
AnyItem lowers one token of an empty-`items` array: all digits becomes a JSON number, anything else stays a string.
func AssembleBody ¶
func AssembleBody(d Descriptor, body map[string]any) ([]byte, error)
AssembleBody builds one descriptor's outgoing JSON body. Exported so a caller assembling a request by hand cannot order the body modes differently.
func ChainSources ¶
func ChainSources(chain guardfile.ValueChain) []valuesource.Source
ChainSources lowers a guardfile.ValueChain to the []valuesource.Source the shared resolver walks, keeping guardfile free of the resolution layer.
func CheckFlagCollisions ¶
func CheckFlagCollisions(desc Descriptor) error
CheckFlagCollisions rejects reserved or duplicate local inputs and duplicate outgoing query names. Both descriptor sources share this fail-closed check.
func CheckProxyRules ¶
CheckProxyRules enforces request-side allow and deny guards over one argument map. Exported so the MCP Apps host refuses on identical regex semantics.
func CoerceItems ¶
CoerceItems lowers CLI tokens to the JSON element type an array field declares. An empty `items` (ItemsAny) resolves per token, the only both-types encoding.
func CoerceScalar ¶
CoerceScalar lowers one CLI token to the JSON type a body field declares, the scalar sibling of CoerceItems. Unknown or empty types stay strings. #328.
func DefaultScheme ¶
DefaultScheme prepends https:// to a base-url that carries no scheme, so a Guardfile may write `base-url "host/api/v1"` and rely on TLS by default.
func DestructiveVerb ¶
DestructiveVerb reports whether a verb mutates irreversibly, so both the resolved and the inline source flag the same leaves. See docs/specverb.md.
func FillPath ¶
FillPath substitutes the i-th positional value into the i-th `{...}` slot. The caller has already enforced len(values) == number of slots.
func MatchesAnyGlob ¶
MatchesAnyGlob reports whether val matches at least one filepath.Match glob. A malformed pattern matches nothing (fail closed), never errors out.
func MethodForVerb ¶
MethodForVerb returns the HTTP method a verb maps to by convention; ok is false only for the bare-unknown-verb POST default. See specverb-resolution.md.
func ParseInline ¶
func ParseInline(src []byte) ([]Descriptor, RuntimeConfig, error)
ParseInline states the ward-mcp inline grammar as the same []Descriptor the OpenAPI source feeds, plus the request RuntimeConfig. See docs/opcore-inline.md.
func ParseInlineWithOptions ¶ added in v0.247.0
func ParseInlineWithOptions(src []byte, opts InlineOptions) ([]Descriptor, RuntimeConfig, []string, error)
ParseInlineWithOptions is ParseInlineWithWarnings for a consumer stating its options.
func ParseInlineWithWarnings ¶
func ParseInlineWithWarnings(src []byte) ([]Descriptor, RuntimeConfig, []string, error)
ParseInlineWithWarnings is ParseInline plus the non-fatal notes a caller should surface, one per grant whose method was inferred rather than known.
func PathParamsInOrder ¶
PathParamsInOrder returns the `{...}` names in path-template order, the order the leaf takes them positionally. Shared with the CLI projection's binder.
func ValidMethod ¶
ValidMethod reports whether m is an HTTP method the grammar accepts.
Types ¶
type ArgBinder ¶
type ArgBinder struct {
PathVals []string
Query neturl.Values
BodyObj map[string]any
// contains filtered or unexported fields
}
ArgBinder routes one poll arg onto a path param (by name or owner-repo sugar), a query param, or a body field, keeping leaf-request assembly flat.
func NewArgBinder ¶
func NewArgBinder(leaf Descriptor) *ArgBinder
NewArgBinder builds a binder over one leaf's path/query/body flag surface.
func (*ArgBinder) Bind ¶
Bind routes one resolved arg value; the caller has already proved every arg targets something, so an unmatched name here is a no-op, not an error.
func (*ArgBinder) BindSlice ¶
BindSlice routes one resolved arg whose value is a list. A query target repeats the parameter, a body or form target lands a JSON array in the leaf's own type.
func (*ArgBinder) FieldFor ¶
FieldFor returns the leaf's declared query/body/form field of that name.
func (*ArgBinder) RequireAllPaths ¶
RequireAllPaths fails closed if any path param went unbound, so a poll tick never fires an under-bound URL.
type Args ¶
type Args struct {
Path map[string]string
Query map[string]string
QueryValues map[string]any
Body map[string]any
}
Args splits an Operation's inputs by URL and body location. Query is the compatible scalar surface, while QueryValues carries typed values and arrays.
type BodyMapping ¶
type BodyMapping struct {
SourcePath []string
Target string
// Type is the JSON type the leaf projects, defaulting to string. A mapped
// leaf used to be string-only in every configuration. See umbra#312.
Type string
// Items is the element type when Type is "array".
Items string
}
BodyMapping projects one required nested string input path onto one top-level outgoing JSON key. Unmapped input is never forwarded.
type Database ¶
type Database struct {
Driver string
DSN guardfile.ValueChain
}
Database is the wrap-level `database <driver> { value ... }` declaration: a registered database/sql driver name and the chain its DSN resolves through.
type Descriptor ¶
type Descriptor struct {
VerbName string // dotted audit name, e.g. ward.ops.forgejo.repo.create
Group string // CLI group noun, e.g. repo
Leaf string // CLI leaf verb, e.g. create
Method string // HTTP method
Path string // path template, e.g. /repos/{owner}/{repo}
PathParams []string // ordered positional args drawn from the path
BodyFlags []Field // request-body fields, including nested object/array shapes
BodyMappings []BodyMapping // required input paths projected onto fresh top-level body keys
QueryFlags []Field // query params, including typed scalar-array shapes
QueryExclusive [][]string // local query-name groups where at most one may be supplied
FormFlags []Field // formData params, where "file" types take a path
FixedBody map[string]any // pinned body keys, alone for a state toggle or seeding a mapped body
// ReturnFields is the optional `returns` declaration a successful response
// is pruned to before Execute hands it back. See docs/opcore-returns.md.
ReturnFields []Field
Destructive bool // leaf mutates irreversibly (delete)
Grant string // the authorizing grant sentence, e.g. "can delete repos"
Describe string // optional Guardfile describe "..." note, "" if none
FailWhen string // optional JMESPath response postcondition; truthy rejects a successful call
Proxy *Proxy // non-nil for an inline MCP proxy grant
GraphQL *GraphQL // non-nil for a `graphql` grant; owns the whole body
SQL *SQL // non-nil for a `sql` grant; reaches a database, not a URL
MCP *MCPCall // non-nil for an `mcp` dialect leaf; reaches a session, not a URL
// Meta is upstream `_meta`, kept verbatim and never interpreted. A served
// surface forwards it; MCP Apps addresses its widget there.
Meta map[string]any
// RawResponse marks a success response offering no JSON, written through
// untouched. See docs/specverb-request.md.
RawResponse bool
// MethodInferred marks a Method guessed from an unrecognised verb rather
// than looked up or stated. See docs/opcore-inline.md.
MethodInferred bool
}
Descriptor is the tiny per-operation payload the generic action binds to, isolated from the static request machinery.
func (Descriptor) InputSchema ¶
func (d Descriptor) InputSchema() Schema
InputSchema projects a Descriptor onto its neutral input surface: path params as required strings, query/body/form as fieldFlagsToCLI reads them, no FixedBody.
func (Descriptor) Label ¶
func (d Descriptor) Label() string
Label names the leaf in operator-facing errors, satisfying stepflow.Leaf so a resolved Descriptor can drive a complex-action step. See pkg/stepflow.
type Field ¶
type Field struct {
Name string // local input name and the default outgoing field or parameter name
UpstreamName string // outgoing query parameter name when it differs from Name
Type string // swagger type: string|boolean|integer|number|array|object
Items string // scalar element type when Type is "array" and Item is nil
Item *Field // nested element schema when Type is "array" and Item is object/array
Fields []Field
Raw bool
Required bool // required in the schema, enforced at request assembly
Desc string
Enum []any // permitted values, when the upstream schema names a closed set
Minimum *float64 // inclusive numeric lower bound
Maximum *float64 // inclusive numeric upper bound
MinItems *int // inclusive array-length lower bound
MaxItems *int // inclusive array-length upper bound
// ArrayEncode is "" or "repeat" for the bare repeated name, "brackets" for
// the []-suffixed form. docs/specverb-request.md (umbra#7013).
ArrayEncode string
// Keyed marks an object whose key set is the caller's, not a fixed
// named list. See docs/opcore-body-variants.md.
Keyed bool
EntrySchema *Field
// Variant is a discriminated union: exactly one Cases entry applies. See
// docs/opcore-body-variants.md.
Variant *Variant
}
Field is one spec input. The flat cases lower to CLI flags, while body fields may carry nested shape and query fields may carry numeric or array bounds.
func (Field) QueryName ¶
QueryName returns the outgoing query parameter name for this field. An empty UpstreamName preserves the historical Name-to-wire mapping.
func (Field) QueryWireName ¶
QueryWireName returns the outgoing parameter name including any array-encoding suffix, which is what actually reaches the URL.
type GraphQL ¶
type GraphQL struct {
Document string // the operation document, sent verbatim as `query`
Operation string // operation name, sent as `operationName`; "" when anonymous
Variables []Field // derived from the document signature, decorated by `variable`
}
GraphQL is one grant's operation: an authored document that never reaches the input schema, plus caller variables derived from its signature.
type InlineOptions ¶ added in v0.247.0
type InlineOptions struct {
// AllowReservedNames lets an input take a name the umbra CLI reserves for its flags.
// A consumer mounting no CLI sets it. Duplicate inputs stay refused.
AllowReservedNames bool
}
InlineOptions are the consumer facts the inline grammar cannot read from the file.
type MCPCall ¶
type MCPCall struct {
Tool string
// Allow and Deny guard the outgoing arguments, PostCall the returned value.
// All three match a regex against one named string field.
Allow []ProxyRule
Deny []ProxyRule
PostCall []ProxyRule
}
MCPCall marks a leaf of the mcp dialect: the exact upstream tool it fires and the guards over that call. A leaf carrying it assembles no request.
type MCPEnv ¶
type MCPEnv struct {
Name string
Value guardfile.ValueChain
}
MCPEnv is one environment injection on a stdio upstream.
type MCPUpstream ¶
type MCPUpstream struct {
Kind string // "stdio" | "http"
Command string
Argv []string
Env []MCPEnv
URL string
URLValue guardfile.ValueChain
Auth guardfile.Auth
}
MCPUpstream is the wrap-level `mcp <transport> { ... }` declaration, with its credential material still symbolic: chains resolve per call, not at parse.
func (MCPUpstream) IsZero ¶
func (u MCPUpstream) IsZero() bool
IsZero reports whether no upstream was declared.
type Operation ¶
type Operation struct {
Desc Descriptor
RT *Runtime
}
Operation is one resolved leaf plus the runtime that fires it: the unit a non-CLI consumer (ward-mcp) drives via the self-guarding Execute.
func (Operation) Execute ¶
Execute runs the leaf under the full security floor (gate, restrict, assemble, base-url, auth, fire) and returns the decoded response, rendering nothing.
func (Operation) Preview ¶
Preview resolves the request without firing it (same gate/restrict/assembly as Execute) for a dry-run; a value-resolved base-url stays an offline placeholder.
type Property ¶
type Property struct {
Type string // string|boolean|integer|number|array
Items string // element type when Type==array
Item *Property
Properties map[string]Property
Required []string
Raw bool
Location string // path|query|body|form (neutral hint)
UpstreamName string // outgoing query parameter when it differs from the local property name
Description string
Enum []any
Minimum *float64
Maximum *float64
MinItems *int
MaxItems *int
// Keyed marks an object whose key set is the caller's, every value shaped
// like Entry. umbra#8032.
Keyed bool
Entry *Property
Variant *PropertyVariant
}
Property is one input in a Schema: its type (or array element type), the neutral where-it-goes hint, its help text, and any nested shape.
type PropertyVariant ¶
PropertyVariant is the schema-facing form of Variant. See opcore-body-variants.md.
type Provider ¶
type Provider = valuesource.Provider
Provider resolves the value at address for one named value source: the shared valuesource.Provider, so the consumer's one registry drives both engines.
type Proxy ¶
type Proxy struct {
Name string // local served tool name
Upstream UpstreamTool // exact upstream MCP tool mapping
Allow []ProxyRule // request-time allow rules
Deny []ProxyRule // request-time deny rules
PostCall []ProxyRule // response-time checks after the upstream call
Describe string // optional human note
}
Proxy is one inline MCP proxy grant: local tool, exact upstream mapping, and request/response guards. The consumer resolves the upstream schema at runtime.
type ProxyRule ¶
ProxyRule is one simple regex guard over a string field such as url, text, content, target, element, key, or state.
type Request ¶
Request is a resolved-but-unfired call: the exact method, URL, and body the runtime would send. Preview returns one for a consumer's dry-run.
type Response ¶
Response is a fired call's outcome: the decoded JSON value, the raw bytes (for a consumer's own rendering), and the HTTP status line.
type Runtime ¶
type Runtime struct {
BaseURL string
Auth guardfile.Auth
Providers map[string]Provider
Client *http.Client
Restrict []guardfile.Restriction
// AllowMeta names the path params the wrap's `allow-metacharacters` exempts.
// Query is exempt by construction, never by this list; specverb-request.md.
AllowMeta []string
// Headers are wrap-declared request headers, applied before the default
// User-Agent. See docs/specverb-request.md.
Headers map[string]string
// BaseURLValue (zero = static BaseURL) resolves the host through the first
// available source in its chain once, caching it. See specverb-policy.md.
BaseURLValue guardfile.ValueChain
// Database backs `sql` grants. The pool opens once on first use, so a
// consumer that serves no SQL grant never opens a connection.
Database Database
// MCP is the wrap-level upstream backing `mcp` dialect leaves. Its value
// chains stay symbolic here and resolve per call, never at parse.
MCP MCPUpstream
// contains filtered or unexported fields
}
Runtime carries the per-tree request dependencies shared by every leaf, urfave/cli-free: specverb embeds it and a non-CLI consumer drives it directly.
func NewRuntime ¶
func NewRuntime(c RuntimeConfig) *Runtime
NewRuntime assembles a Runtime, defaulting the base-url scheme and the HTTP client; the wrap pipeline and step runner are CLI-layer concerns layered on top.
func (*Runtime) Authorize ¶
Authorize applies the runtime's configured auth to req. Blank auth is a no-op.
func (*Runtime) BaseForRequest ¶
BaseForRequest returns the request base-url: the static base, or (for a `base-url { value }` host) a once-resolved provider value. Dry-run stays offline.
func (*Runtime) CheckRestrictions ¶
CheckRestrictions enforces every wrap-level restriction against a leaf's bound path values, failing closed on an out-of-scope value. See docs/specverb.md.
func (*Runtime) FireCapture ¶
func (rt *Runtime) FireCapture(ctx context.Context, method, url string, body []byte, contentType string) (decoded any, raw []byte, status string, err error)
FireCapture sends one request and returns the decoded JSON value plus raw body, rendering nothing: the "fire and capture" path complex actions feed on.
func (*Runtime) FireCaptureRaw ¶
func (rt *Runtime) FireCaptureRaw(ctx context.Context, method, url string, body []byte, contentType string) (raw []byte, status string, err error)
FireCaptureRaw sends one request and returns the body undecoded, for an op declaring a non-JSON media type. See docs/specverb-request.md.
func (*Runtime) MetaAllowed ¶
MetaAllowed reports whether the wrap opted this path param out of the gate. Exported so the CLI layer's pre-gate agrees with opcore's rather than diverging.
type RuntimeConfig ¶
type RuntimeConfig struct {
BaseURL string
Auth guardfile.Auth
Providers map[string]Provider
Client *http.Client
Restrict []guardfile.Restriction
AllowMeta []string
Headers map[string]string
BaseURLValue guardfile.ValueChain
Database Database
MCP MCPUpstream
}
RuntimeConfig is the input to NewRuntime: BaseURL is raw (scheme + trim applied), a nil Client defaults to the redirect-guarding client.
type SQL ¶
type SQL struct {
Statement string // sent verbatim; parameters bind, nothing interpolates
Params []Field // ordered, binding to $1..$N or ?..? in that order
MaxRows int // result bound for a reading statement
Reads bool // true when the statement returns rows rather than a count
Placeholder byte // '$' or '?', the style the statement uses
}
SQL is one grant's declared statement: authored text that never reaches the input schema, plus the parameters a caller binds into its placeholders.
type Schema ¶
type Schema struct {
Properties map[string]Property // keyed by field name
Required []string // names that must be supplied, in a stable order
MutuallyExclusive [][]string // groups where at most one property may be supplied
}
Schema is the transport-neutral input surface of one Descriptor: every input it accepts, keyed by name, plus the subset that must be supplied. See docs.
func (Schema) JSONSchema ¶
JSONSchema emits the Schema as a generic draft-07 object, never an MCP tool type (that wrapper lives in ward-mcp). The neutral Location hint is omitted.
type UpstreamTool ¶
UpstreamTool names the proxied MCP server and upstream tool exactly.