metadata

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package metadata defines versioned, explicitly authored Arc artifact descriptors. Runtime adapters and future generators share these identities and route decisions; no reflection discovery, invocation or network activity occurs here.

Index

Constants

View Source
const Version = 1

Version is the supported descriptor format. Readers reject other versions.

Variables

View Source
var ErrInvalidModel = errors.New("invalid model metadata")

ErrInvalidModel identifies malformed model declarations or supported field tags.

Functions

func VerifyGeneratedEndpoints

func VerifyGeneratedEndpoints(profile string, expected, actual []Endpoint) error

VerifyGeneratedEndpoints compares only identities owned by expected. Call it after Resolve on the complete catalog, including manual and excluded artifacts. Extra methods, absent artifacts and validation-path changes are mismatches. Inputs are borrowed and never modified. Profile is diagnostic provenance, not a replacement for comparing endpoints. Empty or malformed expectations fail.

Types

type Authorization

type Authorization struct {
	// AllowAnonymous explicitly permits anonymous access to this operation.
	AllowAnonymous bool `json:"allowAnonymous"`
	// Requirements combines restrictions in declaration order.
	Requirements []AuthorizationRequirement `json:"requirements,omitempty"`
}

Authorization is explicit declaration metadata. A nil declaration means undeclared; a nonnil empty declaration requires authentication. AllowAnonymous contradicts any requirements and suppresses application fallback.

type AuthorizationRequirement

type AuthorizationRequirement struct {
	// Roles lists explicit role alternatives, not comma-separated syntax.
	Roles []string `json:"roles,omitempty"`
	// Policy names a registered authorization policy.
	Policy string `json:"policy,omitempty"`
	// AuthenticationSchemes describes named schemes; native Go rejects these.
	AuthenticationSchemes []string `json:"authenticationSchemes,omitempty"`
}

AuthorizationRequirement is one conjunctive restriction. Roles within it are alternatives (OR); multiple requirements are AND. Names are exact strings. Executable validation belongs to authorization.Registry.Build, not Resolve.

type Catalog

type Catalog struct {
	// Version must equal metadata.Version; zero is not silently upgraded.
	Version int `json:"version"`
	// Commands is the complete command set for namespace conflict resolution.
	Commands []Command `json:"commands"`
	// Queries is the complete query set for namespace conflict resolution.
	Queries []Query `json:"queries"`
}

Catalog is descriptor format v1 for endpoint identity and route metadata. It is caller-owned mutable configuration. Resolve borrows it only during the call. Authorization compilation is separate from route resolution. Use keyed literals for public descriptors as optional fields may be added during v0 development.

type CollisionError

type CollisionError struct {
	// Key is the conflicting identity or HTTP method/path.
	Key string
	// First is the first owner in deterministic identity order.
	First string
	// Second is the second owner.
	Second string
}

CollisionError names both owners of a conflicting identity or method/path. Resolve sorts artifacts first so errors do not depend on registration order.

func (*CollisionError) Error

func (e *CollisionError) Error() string

Error describes a collision without silently selecting a winning performer.

type Command

type Command struct {
	// DocumentationSummary is explicit/generated documentation, never read from source at runtime.
	DocumentationSummary string `json:"documentationSummary,omitempty"`
	// Type identifies the command and supplies its conventional route location.
	Type TypeName `json:"type"`
	// Path overrides the entire route verbatim; empty uses convention.
	Path string `json:"path,omitempty"`
	// Authorization is the optional command declaration; nil uses fallback.
	Authorization *Authorization `json:"authorization,omitempty"`
	// BlockOnValidationSeverity is the optional inclusive command severity floor.
	BlockOnValidationSeverity *validation.Severity `json:"blockOnValidationSeverity,omitempty"`
	// ExcludeFromDiscovery hides catalog exposure, not execution or authorization.
	ExcludeFromDiscovery bool `json:"excludeFromDiscovery,omitempty"`
}

Command describes a model-bound command, not its executable handler.

type Endpoint

type Endpoint struct {
	// Identity is the artifact identity, unaffected by route options.
	Identity string
	// Method is POST, GET or QUERY.
	Method string
	// Path is the resolved path; explicit paths retain casing and trailing slashes.
	Path string
	// ValidateOnly identifies a command's validation endpoint.
	ValidateOnly bool
}

Endpoint is a resolved literal method/path pair. Resolve returns fresh values.

func Resolve

func Resolve(catalog Catalog, options Options) ([]Endpoint, error)

Resolve validates descriptor identities and returns routes sorted by identity and method. Conflicts are case-insensitive per HTTP method, including /validate. Commands and queries may share paths when methods differ. It never retains catalog. Only literal absolute paths are supported; templates and unsafe/ambiguous paths fail explicitly. An empty method override falls back to convention, not model path.

type GeneratedContractMismatchError

type GeneratedContractMismatchError struct {
	Profile  string
	Identity string
	Expected []Endpoint
	Actual   []Endpoint
}

GeneratedContractMismatchError reports drift between generated proxies and the complete runtime catalog. Expected and Actual are independently owned snapshots.

func (*GeneratedContractMismatchError) Error

type Model

type Model struct {
	// Kind is optional; registration supplies the expected artifact kind.
	Kind ModelKind
	// Type is the stable public identity, never derived from the import path.
	Type TypeName
	// Path is an optional literal absolute route override.
	Path string
	// Authorization is the optional explicit declaration.
	Authorization *Authorization
	// BlockOnValidationSeverity is an optional command validation floor.
	BlockOnValidationSeverity *validation.Severity
	// ExcludeFromDiscovery hides discovery metadata, not execution endpoints.
	ExcludeFromDiscovery bool
	// KeyMember names an explicitly tagged command key in wire form.
	KeyMember string
	// IdentityMember names an explicitly tagged read-model identity in wire form.
	IdentityMember string
}

Model is declaration metadata shared by handwritten and generated registration. It owns its authorization slices and severity pointer. Explicit registration options override individual fields after InspectModel; validate the merged model.

func InspectModel

func InspectModel(t reflect.Type, namespace string) (Model, error)

InspectModel reads one named struct (or its pointer), using namespace as the default and the Go type name as the default name. Source comments are not read. An optional single blank field supplies metadata without an embedded base type:

_ struct{} `json:"-" arc:"command,name=Add,path=/items/add,block-on=warning" authorize:"roles=Editor|Admin,policy=CanWrite"`

arc supports command/readmodel, name, namespace, path, block-on, authorize, allow-anonymous and exclude-from-discovery. authorize on arc requires an actor; the separate authorize tag uses semicolon-separated AND requirements, each with roles (pipe-separated OR) and/or policy. Empty authorize means authentication. Comma-separated options escape comma, equals and backslash with backslash. Unknown/duplicate options and multiple blank declarations are errors. Other tag namespaces are untouched. Field arc tags support only key and identity.

func (Model) Validate

func (m Model) Validate() error

Validate checks the same declaration rules for generated and manual metadata. Policy existence is checked later by authorization.Registry.Build.

type ModelKind

type ModelKind string

ModelKind identifies explicit model opt-in; empty leaves selection to registration.

const (
	// CommandModel identifies a command declaration.
	CommandModel ModelKind = "command"
	// ReadModel identifies a read-model declaration.
	ReadModel ModelKind = "readmodel"
)

type Options

type Options struct {
	// RoutePrefix is trimmed of leading/trailing slashes before conventional routing.
	RoutePrefix string
	// SegmentsToSkip removes leading namespace segments; negative values are invalid.
	SegmentsToSkip int
	// IncludeCommandName adds the kebab-cased command name even without conflicts.
	IncludeCommandName bool
	// IncludeQueryName adds the kebab-cased query method name even without conflicts.
	IncludeQueryName bool
	// EnableQueryHTTPMethod adds QUERY beside GET.
	EnableQueryHTTPMethod bool
}

Options mirrors ApiEndpointOptions. Use DefaultOptions for C# defaults; zero deliberately means an empty prefix, omitted names and disabled QUERY support.

func DefaultOptions

func DefaultOptions() Options

DefaultOptions returns independent C# defaults: api, no skips, names and QUERY.

type Query

type Query struct {
	// DocumentationSummary is explicit/generated method documentation.
	DocumentationSummary string `json:"documentationSummary,omitempty"`
	// ReadModel identifies the containing read model.
	ReadModel TypeName `json:"readModel"`
	// Name is the method name, not the read model name.
	Name string `json:"name"`
	// Path is the method override. A non-nil empty value disables the model override.
	Path *string `json:"path,omitempty"`
	// ReadModelPath is the model-level route override.
	ReadModelPath string `json:"readModelPath,omitempty"`
	// Observable indicates an observable return shape; it does not start a stream.
	Observable bool `json:"observable"`
	// Authorization replaces the read-model declaration when nonnil.
	Authorization *Authorization `json:"authorization,omitempty"`
	// ReadModelAuthorization applies only when no method declaration exists.
	ReadModelAuthorization *Authorization `json:"readModelAuthorization,omitempty"`
	// HTTPMethod restricts the route method; empty retains the existing defaults.
	HTTPMethod QueryHTTPMethod `json:"httpMethod,omitempty"`
	// ExcludeFromDiscovery hides query exposure without disabling execution.
	ExcludeFromDiscovery bool `json:"excludeFromDiscovery,omitempty"`
	// ReadModelIdentityMember is the optional wire field for later delta support.
	ReadModelIdentityMember string `json:"readModelIdentityMember,omitempty"`
}

Query describes a method on a read model. Its identity includes the model name, but its conventional route includes only the namespace and method name.

func (Query) Identity

func (q Query) Identity() string

Identity returns the stable fully qualified query name used by subscriptions.

type QueryHTTPMethod

type QueryHTTPMethod string

QueryHTTPMethod selects an explicit query transport; zero retains route defaults.

const (
	// QueryHTTPDefault follows Options.EnableQueryHTTPMethod.
	QueryHTTPDefault QueryHTTPMethod = ""
	// QueryHTTPGet exposes GET only.
	QueryHTTPGet QueryHTTPMethod = "GET"
	// QueryHTTPQuery exposes QUERY only (and requires it enabled in route options).
	QueryHTTPQuery QueryHTTPMethod = "QUERY"
)

type QueryTags

type QueryTags struct {
	// Required distinguishes required input from a supplied zero value.
	Required bool
	// Default is raw scalar text; HasDefault distinguishes default= from absence.
	Default string
	// HasDefault reports an explicitly supplied default.
	HasDefault bool
	// PreservePresence retains missing/null/empty distinctions.
	PreservePresence bool
}

QueryTags describes explicit query input options. Scalar conversion and Optional compatibility are validated by query registration, not this parser.

func ParseQueryTags

func ParseQueryTags(text string) (QueryTags, error)

ParseQueryTags accepts required, default=value and preservePresence. Options use comma separation and backslash escaping for comma, equals and backslash. Required/default is contradictory; a default may preserve raw presence while supplying a separate effective value.

type TypeName

type TypeName struct {
	// Namespace is the logical namespace; empty denotes the global namespace.
	Namespace string `json:"namespace"`
	// Name is the simple model or command name.
	Name string `json:"name"`
}

TypeName is a stable logical type identity, independent of Go package relocation. Namespace uses dot-separated C#-compatible segments; Name is a simple type name. Both are supplied explicitly rather than inferred from runtime Go type names.

func (TypeName) Identity

func (t TypeName) Identity() string

Identity returns the namespace-qualified type name without route normalization.

Jump to

Keyboard shortcuts

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