Documentation
¶
Overview ¶
Package metadata implements structural derivation for AssemblyMeta and related types. Derivation fills in omitted fields (entrypoint, binary, deployTemplate, maxConsistencyLevel) from declared field values and peer metadata.
ref: parser.parseSlice G-7 belongsToCell auto-derive / parser.parseContract ownerCell auto-derive — same auto-derive pattern applied to assembly build fields and cross-cell consistency aggregation.
Package metadata — contract syntactic constraints (single source of truth).
JSON Schemas under kernel/metadata/schemas/ retain literal pattern/enum expressions for IDE / editor / standalone tooling consumption. The constants below are the authoritative Go-side source: TestSchemaConstants MatchSchemaLiterals (under kernel/metadata/schemas) asserts the schema literals match these constants byte-for-byte.
Adding a new syntactic constraint:
- add a const here;
- update the corresponding schema file with the same literal;
- wire the const into the governance validator (and into typed-identifier boundary types where applicable, e.g. GoIdentifier);
- extend TestSchemaConstantsMatchSchemaLiterals to compare the new pair.
Runtime is single-source: parsers do not validate values; governance is the sole gatekeeper, importing the constants here. Schema literals are the authoritative form on disk; the test guard prevents drift.
Package metadata — derived.go provides secondary projections built on top of ProjectMeta. Currently: per-cell wire summary used by /api/v1/devtools/catalog to expose listener / route / subscribe surface for ops visibility.
Derived data is stateless (no caching); callers re-derive on each request. Cost is O(cells) string copy — under 1ms for ~10 cells, no premature optimization.
Decoupling note: this file does NOT import tools/codegen/markergen. Callers that own a markergen.WireBundle (e.g. runtime/http/devtools) convert it to CellWireBundle before calling DeriveCellWireSummaries. This keeps kernel/metadata dependency-free from the tools/ layer.
Package metadata provides a parser that loads all GoCell YAML descriptors (cell.yaml, slice.yaml, contract.yaml, assembly.yaml, journey.yaml) from a project root and produces a validated ProjectMeta model.
metadata is the single source of truth for the metadata schema (see KERNEL-METADATA-NO-WIRE-01 archtest, which forbids wire-format symbol names from appearing here — those belong to runtime/devtools/catalog).
Package metadata: Locator abstracts metadata YAML discovery from parser internals. It is the single funnel through which all path-prefix knowledge about GoCell's filesystem topology must flow.
Two modes:
- Conventional — walks the hardcoded 5-pattern layout plus 2 workspace-level singletons (actors.yaml, journeys/status-board.yaml) (cells/*/cell.yaml, cells/*/slices/*/slice.yaml, contracts/{kind}/.../contract.yaml, journeys/J-*.yaml, assemblies/*/assembly.yaml). examples/ subtree follows the same patterns with one extra prefix.
- Manifest — reads .gocell/manifest.yaml and walks the modules: entries it declares. Single-module entry covers Operator-SDK external repo; multi-module entries cover Workspace mode aggregation.
Auto-detection: NewLocator without WithLocatorMode probes the root for .gocell/manifest.yaml; presence selects Manifest mode, absence selects Conventional. Override with WithLocatorMode(LocatorConventional) for CI determinism.
ref: bufbuild/buf buf.yaml v2 modules: schema — single manifest expressing both single-module and workspace-aggregate forms. ref: kubernetes-sigs/kubebuilder PROJECT — manifest-driven resource registration. ref: kubernetes-sigs/kustomize kustomization.yaml resources: field.
Funnel: LOCATOR-DISCOVERY-FUNNEL-01 (Hard downstream, Medium upstream). All path-prefix string comparisons against {cells/, contracts/, journeys/, assemblies/, examples/} must live inside locator_conventional.go or locator_manifest.go. fs.WalkDir / filepath.Walk / fs.ReadDir callsites in kernel/metadata/** must reside inside Locator.discoverConventional or Locator.discoverManifest. The upstream Medium ceiling is the Go language limit: cross-package sealed-interface-with-private-constructor is structurally unreachable — see SPAN-SETATTR-HOLDER-SEAL-01 (#851) won't-do for the precedent.
Package metadata defines the Go struct types for GoCell YAML metadata files and provides a file-system-based parser to load them into a unified ProjectMeta.
Index ¶
- Constants
- Variables
- func AssemblyGeneratedDir(asm *AssemblyMeta) string
- func AuthComboLegal(auth HTTPAuthMeta) bool
- func CellIDs(refs []AssemblyCellRef) []string
- func ContractDirFromMeta(c *ContractMeta) string
- func Find(root *yaml.Node, path string) (*yaml.Node, error)
- func GRPCProtoRepoRelPath(contractFile, proto string) string
- func GRPCServiceGoName(service string) (string, error)
- func IsAdminHTTPPath(path string) bool
- func IsBootstrapPath(path string) bool
- func IsConventionalAssemblyPath(p string) bool
- func IsInExamplesSubtree(p string) bool
- func IsInternalHTTPPath(path string) bool
- func IsKnownCapability(s string) bool
- func IsKnownDeployTemplate(s string) bool
- func IsKnownTransport(s string) bool
- func IsPublicHTTPPath(path string) bool
- func IsValidMetadataText(value string) bool
- func IterateAuthBoolCombos(fn func(auth HTTPAuthMeta, name string))
- func MatchAssemblyID(s string) bool
- func MatchAssemblyModulePath(s string) bool
- func MatchCellID(s string) bool
- func MatchGoStructName(s string) bool
- func OwnershipDeclarationRequired(auth HTTPAuthMeta) bool
- func OwnershipPathValid(expr string) bool
- func ReadManifestModulePaths(fsys fs.FS, manifestPath string) ([]string, error)
- func ReadManifestModulePathsRoot(root, manifestPath string) ([]string, error)
- func ValidateGRPCProtoPath(proto string) error
- type ActorMeta
- type AssemblyCellRef
- type AssemblyMeta
- type BuildMeta
- type CellMeta
- type CellVerifyMeta
- type CellWireBundle
- type CellWireSummary
- type ContractMeta
- type ContractOwner
- type ContractSchemaRef
- type ContractUsage
- type EndpointsMeta
- type GRPCTransportMeta
- type GoIdentifier
- type HTTPAuthMeta
- type HTTPIdempotencyMeta
- type HTTPOwnershipMeta
- type HTTPResponseMeta
- type HTTPTransportMeta
- type HeaderViolation
- type HeaderViolationKind
- type JourneyMeta
- type L0DepMeta
- type Locator
- type LocatorMode
- type LocatorOption
- type ManifestIncludes
- type ManifestModule
- type ManifestSpec
- type MetadataSource
- type OwnerMeta
- type ParamSchema
- type Parser
- type PassCriterion
- type Position
- type ProjectMeta
- type ResolvedSchemaRef
- type SagaMeta
- type SagaRetryMeta
- type SagaStepMeta
- type SchemaMeta
- type SchemaRefError
- type SchemaRefScope
- type SchemaRefsMeta
- type SliceMeta
- type SliceVerifyMeta
- type SourceKind
- type StatusBoardEntry
- type WaiverMeta
- type WebhookInboundMeta
- type WebhookPayloadMeta
- type WebhookSignatureMeta
- type WireBundleListener
- type WireBundleRoute
- type WireBundleSubscribe
- type WireListenerView
- type WireRouteView
- type WireSubscribeView
Constants ¶
const ( // AssemblyIDPattern restricts assembly ids to lowercase ASCII letters // + digits, ≥2 chars, must start with a letter. Mirrors // schemas/assembly.schema.json properties.id.pattern. Reverse-aliased // from pkg/scaffoldid.IdentifierPattern — pkg/scaffoldid owns the // single-source pattern so typed-identifier funnel (ScaffoldID) and // YAML schema validator stay in lock-step. kernel/ may depend on pkg/ // (architecture rule). AssemblyIDPattern = scaffoldid.IdentifierPattern // CellIDPattern is identical to AssemblyIDPattern by design — both share // the no-dash concatenation convention enforced by FMT-16 / FMT-C1. // Same single-source reverse-alias as AssemblyIDPattern. CellIDPattern = scaffoldid.IdentifierPattern // GoStructNamePattern restricts cell.GoStructName to a Go-exported // identifier shape (uppercase first letter, ASCII letters + digits). // Mirrors schemas/cell.schema.json properties.goStructName.pattern. GoStructNamePattern = `^[A-Z][A-Za-z0-9]*$` // SagaStepNamePattern restricts saga.steps[].name to a Go-identifier-safe // camelCase token (letters + digits, leading letter). It is STRICTER than a // generic SafeID because the step name flows through contractgen's // goPascalCase into generated Go identifiers (Run<Name> / <Name>Output); a // '.', ':' or '/' would emit uncompilable Go. Single source for the saga // step-name shape: schemas/contract.schema.json saga.steps[].name.pattern is // byte-locked to this const by TestSchemaConstantsMatchSchemaLiterals, and // kernel/governance SAGA-CONTRACT-STEP-NAME-VALID-01 compiles it (replacing // the prior hand-duplicated literal). SagaStepNamePattern = `^[a-zA-Z][a-zA-Z0-9]*$` // AssemblyModulePathPattern is the single source for assembly.yaml cell // `module` hygiene (the cross-module Go module path, #1086): a non-empty // string carrying no rune that could break out of the generated // "<module>/cellmodules/<id>" import string literal. The negated character // class is exactly the blocklist enforced by metadata.MatchAssemblyModulePath // (and consumed by AssemblyCellRef.decodeMapping): the control+space range // \x00-\x20, DEL \x7f, double-quote, backtick (\x60), and backslash (\\). // Mirrors schemas/assembly.schema.json // cells.items.oneOf[1].properties.module.pattern, byte-locked by // TestAssemblyCellRefSchemaPatternsMatchConstants. Defense-in-depth on top of // the %q-quoting + Go-compiler import-resolvability gate (ADR §D3). AssemblyModulePathPattern = "^[^\\x00-\\x20\\x7f\"\\x60\\\\]+$" )
const AuthComboMatrixSize = 1 << HTTPAuthMetaBoolFields
AuthComboMatrixSize is the size of the auth bool combination space (2 ** HTTPAuthMetaBoolFields). Tests iterate from 0 to this value.
const DefaultManifestPath = ".gocell/manifest.yaml"
DefaultManifestPath is the forward-slash path Locator probes during auto mode and reads during Manifest mode unless WithManifestPath overrides it.
const FrameworkOwnerSentinel = "_framework"
FrameworkOwnerSentinel is the reserved ownerCell value that marks a contract as FRAMEWORK-owned rather than cell-owned. It names the framework/control-plane as the contract's definition owner — the SPIFFE/cert-manager/k8s-SIG pattern where a neutral, provider-agnostic contract (whose correctness requires interchangeable providers) is owned by the framework, never by a single consumer cell. The leading underscore mirrors the metrics _runtime sentinel and is not a legal cell id (cells are no-dash concat ids), so it can never collide with a real ownerCell.
A framework-owned contract is governed by the FRAMEWORK-OWNED-CONTRACT-SCOPED rule (not the cell-owner reference rules REF-03/REF-13): it is structurally excluded from cell-owner validation by ContractOwner.Cell returning ok=false, not by per-rule string escapes.
const GRPCProtoPathPrefix = "contracts/grpc/"
GRPCProtoPathPrefix is the required leading path component for endpoints.grpc.proto: every .proto reference must be a contracts-relative path rooted under contracts/grpc/. The schema literal at schemas/contract.schema.json (...grpc.properties.proto.pattern) is kept equal to "^"+GRPCProtoPathPrefix by TestSchemaConstantsMatchSchemaLiterals (the prefix contains no regex metacharacters, so the anchored pattern is a literal prefix match). Single source shared by governance FMT-37 and runtime kernel/contractspec.validateGRPC.
const HTTPAuthMetaBoolFields = 5
HTTPAuthMetaBoolFields is the count of bool fields on HTTPAuthMeta. It is the authoritative source of the matrix size used by IterateAuthBoolCombos (1 << HTTPAuthMetaBoolFields = 32 currently). TestHTTPAuthMetaFieldCount in auth_combo_test.go reflects on HTTPAuthMeta and fails CI when the actual bool field count drifts from this constant — adding a 6th bool field forces every consumer (IterateAuthBoolCombos, AuthComboLegal, the whitelist in TestAuthComboLegal_AgainstWhitelist) to be updated together.
Variables ¶
var CapabilityEnum = []string{"postgres", "redis", "rabbitmq"}
CapabilityEnum lists the canonical values accepted for cell.requires items. Order matches the schema enum order at schemas/cell.schema.json properties.requires.items.enum; do not reorder without updating the schema in lockstep. TestSchemaConstantsMatchSchemaLiterals (kernel/metadata/schemas) asserts byte-level parity between this slice and the schema enum array. The assembly's provisioned set is the derived union of its cells' requires (Design Y, #855) — there is no assembly-level capabilities enum.
var DeployTemplateEnum = []string{"k8s", "compose", "binary"}
DeployTemplateEnum lists the canonical values accepted for assembly.build.deployTemplate. Order matches the schema enum order; do not reorder without updating schemas/assembly.schema.json in lockstep.
var LegalAuthComboNames = map[string]struct{}{
"p-r-s-b-c": {},
"P-r-s-b-c": {},
"p-R-s-b-c": {},
"p-r-S-b-c": {},
"p-r-s-B-c": {},
"p-r-s-b-C": {},
"p-R-S-b-c": {},
}
LegalAuthComboNames is the hand-maintained extensional statement of FMT-27 auth bool mutex semantics (encoded by encodeAuthCombo). AuthComboLegal is the algorithmic (intensional) statement; the two must agree on all 32 combos — TestAuthComboLegal_AgainstWhitelist enforces parity between them.
Matrix tests at the schema and governance layers consume this whitelist (rather than calling AuthComboLegal) so they detect implementation divergence instead of colluding with the oracle. Single-source by design, dual-form by intent: the algorithm runs in production, the whitelist audits the algorithm.
7 legal combinations (out of 32):
"p-r-s-b-c" default authenticated route (all flags off) "P-r-s-b-c" public only "p-R-s-b-c" passwordResetExempt only "p-r-S-b-c" serviceOwned only "p-r-s-B-c" bootstrap only "p-r-s-b-C" clientsOnly only "p-R-S-b-c" serviceOwned + passwordResetExempt
HTTP-idempotency exemption is NOT part of this matrix — it moved to the sibling endpoints.http.idempotency block (#1469 review F7), so the auth-combo space is back to 2^5 = 32 with 7 legal combos.
When a rule evolves (e.g. allowing a new pair to coexist), update both this whitelist AND AuthComboLegal in the same change; CI fails otherwise.
INVARIANT: AUTH-SCHEMA-GOVERNANCE-BOOL-SEMANTICS-01.
var ParamTypes = map[string]bool{ "string": true, "integer": true, "number": true, "boolean": true, }
ParamTypes lists the accepted `type` values for ParamSchema. Governance rule FMT-13 enforces membership.
var TransportEnum = transportEnumStrings()
TransportEnum lists the canonical wire transports accepted for contract.yaml `transports[]`. It is the string projection of cellvocab.AllTransports() (the typed single source); ordering matches that slice and, in lockstep, the schemas/contract.schema.json transports enum (byte-locked by TestSchemaConstantsMatchSchemaLiterals#transportEnum). Membership is enforced at the DECLARATION layer only — governance FMT-39 (via IsKnownTransport) plus the schema enum. Runtime kernel/contractspec.Validate deliberately does NOT re-check transport membership (a production ContractSpec.Transport is trusted as codegen/contractbuild-derived; declaration-layer enforcement, see ADR #1389 D6), so schema and governance — not the runtime value type — own this set.
Functions ¶
func AssemblyGeneratedDir ¶
func AssemblyGeneratedDir(asm *AssemblyMeta) string
AssemblyGeneratedDir returns the project-relative path of the generated/ directory for an assembly. It is derived uniformly as path.Dir(asm.File) + "/generated", which works for the conventional assemblies/<id>/ layout, the examples/<id>/ subtree, and arbitrary paths emitted by Locator manifest mode.
This is the single source of truth shared by:
- kernel/assembly Generator.appendGeneratedFiles (boundary.yaml write path)
- cmd/gocell/app generateOneAssembly (boundary.yaml + modules_gen cmd)
- cmd/gocell/app generateMetricsSchema (metrics-schema.yaml write path)
- kernel/governance validateREF16 (boundary.yaml existence check)
asm.File is the path as loaded by the parser — relative to the project root, with forward slashes (parser already normalised via filepath.ToSlash).
func AuthComboLegal ¶
func AuthComboLegal(auth HTTPAuthMeta) bool
AuthComboLegal returns true iff the bool combination on auth is permitted by FMT-27 semantics. This function is the single source of truth shared by:
- kernel/metadata/schemas/contract.schema.json (compile-time schema validation via if/then const:true rules — see TestContractSchemaAuthBoolMatrix)
- kernel/governance/rules_fmt.go validateFMT27 (runtime governance check — hasFMT27AuthModeConflict delegates to !AuthComboLegal)
- kernel/metadata/auth_combo_test.go (oracle whitelist test)
Rules:
- Core modes {Public, PasswordResetExempt, Bootstrap, ClientsOnly}: at most one may be true.
- ServiceOwned: may combine with PasswordResetExempt; mutually exclusive with Public, Bootstrap, and ClientsOnly.
INVARIANT: AUTH-SCHEMA-GOVERNANCE-BOOL-SEMANTICS-01 ref: kubernetes/kubernetes pkg/securitycontext/util.go (capability mode mutex)
func CellIDs ¶
func CellIDs(refs []AssemblyCellRef) []string
CellIDs projects an []AssemblyCellRef to the bare cell-id slice, dropping module attribution. Used where only identity matters (entrypoint cell-id list, boundary cell set, devtools catalog wire shape).
func ContractDirFromMeta ¶
func ContractDirFromMeta(c *ContractMeta) string
ContractDirFromMeta returns the contract directory relative to the project root. Returns "" when c is nil or c.Dir is unset. c.Dir is populated by the Locator funnel during ParseFS — callers that hit "" should treat it as a parsed-meta-missing condition, not as an opportunity to derive a default path from the ID. The prior ContractDirFromID-based fallback was removed when M1 (#1082) made layout discovery go through Locator: a derived "contracts/<id>" path is wrong in manifest mode and was masking real bugs when c.Dir was unexpectedly empty.
func Find ¶
Find walks `root` (a yaml.Node, typically a *DocumentNode returned by yaml.Decoder) along the dotted path and returns the matching leaf node.
Path grammar (a restricted subset of JSONPath):
path = segment ("." segment)*
segment = ident ("[" uint "]")*
ident = [A-Za-z_][A-Za-z0-9_-]*
[N] on a SequenceNode selects the N-th element (0-based). [N] on a MappingNode matches the decimal string form of N as a key, which allows addressing YAML mappings with integer keys such as "endpoints.http.responses[200].schemaRef".
Examples: "id", "owner.team", "slices[0].contractUsages[1].contract", "matrix[0][1]", "endpoints.http.responses[200].schemaRef".
Unsupported (by design): leading "$", wildcards "[*]", recursive "..", quoted identifiers. We walk the minimum grammar the validator needs.
Error conditions: empty/invalid path, missing field, index out of range, mapping key not found, keying a scalar, empty document. The path prefix that reached the offending step is included in the error.
func GRPCProtoRepoRelPath ¶
GRPCProtoRepoRelPath converts a module-relative endpoints.grpc.proto path (rooted at GRPCProtoPathPrefix, as declared in contract.yaml and validated by ValidateGRPCProtoPath) into a path relative to the workspace root, by prefixing the contract's module base.
contractFile is the contract.yaml path relative to the workspace root (metadata.ContractMeta.File). The proto and the contract both live under the same module's contracts/grpc/ tree, so the module base is the portion of contractFile preceding the first GRPCProtoPathPrefix segment:
- repo-root contract: File "contracts/grpc/d/v1/contract.yaml" → base "" → proto returned unchanged ("contracts/grpc/d/v1/x.proto").
- satellite-module contract: File "examples/iotdevice/contracts/grpc/d/v1/contract.yaml" → base "examples/iotdevice/" → "examples/iotdevice/contracts/grpc/d/v1/x.proto".
Every filesystem reader of the proto (contractgen collision pre-pass, cellgen grpc-serve enrich) MUST resolve through this before filepath.Join with the absolute workspace root. Joining the raw module-relative proto against the workspace root silently resolves to the wrong (repo-root) location for satellite modules such as examples/iotdevice — the gap the first real example-owned grpc contract surfaced (#1151). The result is slash-form.
func GRPCServiceGoName ¶
GRPCServiceGoName extracts the proto service's simple name (last dotted segment of the fully-qualified service name, e.g. "device.command.v1.DeviceCommandService" → "DeviceCommandService") and validates that it is an exported Go identifier.
The protoc-gen-go-grpc generator derives Register<Name>Server from the service's Go name, which for valid proto service declarations equals the last FQN segment. An unexported or syntactically invalid segment would cause cellgen to emit a lowercase RegisterfooServer selector that the Go compiler cannot resolve. This function is the single source for that derivation: both cellgen (RegisterFunc derivation) and contractgen (service-name validation) must call it rather than duplicating the logic.
Returns an error when the name is empty, not a valid Go identifier, or not exported (uppercase first letter). It is intentionally FS-free so it can run inside governance and codegen without reading the proto file.
func IsAdminHTTPPath ¶
IsAdminHTTPPath reports whether path targets the admin HTTP listener (operator control-plane) prefix /admin/v1. This is GoCell's single admin-path predicate; the runtime router's listener-route affinity check and kernel/cell.AuthRouteMeta.IsAdmin call it exclusively, so the prefix never drifts across layers (mirrors IsInternalHTTPPath).
Accepted:
/admin/v1 /admin/v1/projection/ordercell/orders/rebuild
Rejected (fail-closed):
"" (empty string) "admin/v1/foo" (missing leading /) "/adminx/v1/foo" (prefix must be /admin/v1 or /admin/v1/, not /adminx) "/api/v1/foo" (public listener, not admin)
func IsBootstrapPath ¶
IsBootstrapPath reports whether path matches the bootstrap admin endpoint `/api/v{N}/{cell}/setup/admin` (version-agnostic).
Matching uses exact segment comparison, not substring, to prevent false positives on paths like /foo/setup/admin/bar or /api/v1/setup/admin/foo. This is GoCell's single bootstrap-path predicate; all judgment points (FMT-28, archtest, runtime FinalizeAuth) must call this function exclusively.
Accepted:
/api/v1/access/setup/admin /api/v2/access/setup/admin /api/v1/anycell/setup/admin
Rejected (fail-closed):
"" (empty string) "api/v1/access/setup/admin" (missing leading /) "/api/v1/setup/admin/foo" (substring guard: missing cell segment) "/foo/setup/admin/bar" (substring guard) "/api/v1/access/setup/admin/foo" (trailing extra segment)
ref: postmortem 202605060030 §5.3 / ADR §D4
func IsConventionalAssemblyPath ¶
IsConventionalAssemblyPath reports whether p is an assembly YAML file under the conventional assemblies/<id>/ directory (e.g. "assemblies/corebundle/assembly.yaml"). Exposed here so the "assemblies/" path-prefix literal stays inside the Locator funnel — see LOCATOR-DISCOVERY-FUNNEL-01.A2a.
Returns false for examples/, Manifest-mode custom paths, and an empty string. Callers (e.g. deriveAssembly) check for empty file before calling and apply convention-default behavior for that case.
Intended for internal derivation logic only (deriveAssembly entrypoint heuristic); governance rules should consume AssemblyMeta.File via path.Dir instead of calling this directly.
func IsInExamplesSubtree ¶
IsInExamplesSubtree reports whether p is a YAML / Go file under the GoCell monorepo's examples/ subtree. This is a conventional-layout query exposed here (rather than open-coded in governance rules) so that the path-prefix literal "examples/" stays inside the Locator funnel — see LOCATOR-DISCOVERY-FUNNEL-01. External-repo callers under Manifest mode without an examples/ subtree always get false; this function is intended for gocell-self-repo skip-style rules.
func IsInternalHTTPPath ¶
IsInternalHTTPPath reports whether path targets the internal HTTP listener prefix where caller-cell identity can be enforced.
func IsKnownCapability ¶
IsKnownCapability reports whether s is one of CapabilityEnum.
func IsKnownDeployTemplate ¶
IsKnownDeployTemplate reports whether s is one of DeployTemplateEnum.
func IsKnownTransport ¶
IsKnownTransport reports whether s is one of TransportEnum (the closed set of wire transports GoCell sanctions). The empty string is NOT a member; callers that allow an omitted transport must guard the empty case separately. The parser defaults an OMITTED contract.yaml `transports:` per kind; an explicitly present-but-empty declaration (null / []) is left empty on purpose so governance FMT-39's non-empty guard flags it rather than silently defaulting.
func IsPublicHTTPPath ¶
IsPublicHTTPPath reports whether path targets the public-facing HTTP listener (the internet-exposed API surface). The classification covers all versioned public API prefixes — /api/vN — without locking to a specific version number, because the trust-boundary concern (public internet vs. internal control-plane) is version-agnostic: any path under /api/* is reachable by external principals and subject to the public-listener auth chain.
Contrast with IsInternalHTTPPath, which is locked to /internal/v1 because internal path versioning is tightly controlled and version-specific router wiring matters. The public oracle is deliberately version-agnostic.
Accepted:
/api
/api/v1/config/{key}
/api/v2/users
Rejected (fail-closed):
"" (empty string) "/apix/v1/foo" (prefix must be /api/ or exactly /api, not /apix) "/internal/v1/foo" (internal listener, not public) "/healthz" (framework probe, no trust-boundary flag)
ref: FMT-33 SLICE-HTTP-VISIBILITY-SEGREGATION-01; symmetric counterpart to IsInternalHTTPPath for the public trust boundary.
func IsValidMetadataText ¶
IsValidMetadataText reports whether value is free of the control characters (\n, \r, \x00, \t) that would break inline YAML scalar emission or fabricate adjacent YAML fields when interpolated into scaffold templates. All other characters — colons, dashes, unicode, punctuation — are accepted at this layer; full YAML scalar safety (quoting / escaping) is the responsibility of pkg/yamlsafe.Quote at the rendering boundary.
Tab (\t) is included because YAML 1.2 §5.1 allows tab in plain scalars, so yamlsafe.Quote would not add quotes around a tab-containing value, letting the tab pass through to the generated YAML unchanged. This matches the validateScaffoldID / validateScaffoldText tab-hardening (#8).
Predicate convention: Match* for pattern-bound checks (regex compliance); Is* for semantic free-text checks. Both return bool so callers wrap with their own errcode.
Predicate-style API mirrors MatchAssemblyID / MatchCellID — callers (kernel scaffold validation, cmd flag validation) compose their own errcode wrapping, so no errcode sentinel is introduced here.
Single-source for metadata free-text constraints; eliminates per-caller mirror copies (cf. legacy validateAssemblyTextComponent inside kernel/assembly, now deleted).
ref: kubernetes/apimachinery pkg/util/validation/validation.go — same exported-helper-only convention (pattern unexported, helper exported).
func IterateAuthBoolCombos ¶
func IterateAuthBoolCombos(fn func(auth HTTPAuthMeta, name string))
IterateAuthBoolCombos enumerates all 2 ** HTTPAuthMetaBoolFields (= 32 today) combinations of HTTPAuthMeta's bool fields. Named-field struct literals are used here for readability — Go does NOT report a compile error when a new field is added to HTTPAuthMeta, so the safety net is a separate reflect-based guard: TestHTTPAuthMetaFieldCount in auth_combo_test.go fails CI if the bool field count drifts from HTTPAuthMetaBoolFields, forcing this helper, the matrix size constant, AuthComboLegal, and the test whitelist to be updated together.
HTTPAuthMeta.Responses ([]int) is intentionally excluded: it is not a mutex-governed flag and does not participate in FMT-27 semantics.
name encodes each field as one character: uppercase = true, lowercase = false. Order P-R-S-B-C: Public / PasswordResetExempt (R) / ServiceOwned / Bootstrap / ClientsOnly. Example: "P-r-s-b-c" = Public:true, all others false.
func MatchAssemblyID ¶
MatchAssemblyID reports whether s satisfies AssemblyIDPattern. Forwards to pkg/scaffoldid.Match so the regex is compiled exactly once across the codebase (CELL-ID-PATTERN-SINGLE-SOURCE-01).
func MatchAssemblyModulePath ¶
MatchAssemblyModulePath reports whether s satisfies AssemblyModulePathPattern: a non-empty assembly cell `module` path free of runes that could break out of the generated cellmodules import string literal.
func MatchCellID ¶
MatchCellID reports whether s satisfies CellIDPattern. Same single-source forwarding as MatchAssemblyID.
func MatchGoStructName ¶
MatchGoStructName reports whether s satisfies GoStructNamePattern.
func OwnershipDeclarationRequired ¶
func OwnershipDeclarationRequired(auth HTTPAuthMeta) bool
OwnershipDeclarationRequired reports whether the auth configuration mandates an ownership block declaration. Single-source predicate shared by kernel/governance FMT-32 and schema/metadata validation.
The ownership block is required when auth.ServiceOwned is true, regardless of other flags (e.g. PasswordResetExempt may coexist with ServiceOwned per FMT-27).
func OwnershipPathValid ¶
OwnershipPathValid reports whether the ownership path expression conforms to the DSL shape. Single-source predicate shared by kernel/governance FMT-32 and schema/metadata validation.
DSL: prefix is ctx or path, followed by one or more dot-separated segments where each segment starts with a lowercase letter (camelCase enforced; snake_case and PascalCase are rejected). path.<param> referential integrity (the param must be declared in the route's pathParams) is a governance-layer concern and is not checked here.
Single-segment forms:
- "path.<param>" alone is valid — the path param value itself is the owner key (e.g. DELETE /users/{id} where {id} directly identifies the owned resource). "path.<param>.<field>" selects an owner field on the located resource (e.g. "path.id.userID" fetches the userID field of the session record at path param "id").
- "ctx.<seg>" alone is valid — the caller context field itself is the owner key (e.g. "ctx.userID").
Unicode chars are rejected by the ASCII character class — intentional fail-closed. No length cap is enforced by this predicate; governance callers reject absurd lengths if needed.
func ReadManifestModulePaths ¶
ReadManifestModulePaths reads the manifest at manifestPath from fsys and returns its declared module disk paths (ManifestModule.Path), in declaration order. It runs the same loadManifest validation (schema version, path safety, singleton uniqueness), so a malformed manifest fails closed rather than yielding a partial set.
It is the exported accessor for the workspace's metadata-module set. Tooling (the archtest workspace enumerator in tools/workspace) cross-checks this set against go.work's `use` directives — every metadata module MUST be a Go module the toolchain compiles (manifest.modules ⊆ go.work.use); a manifest module absent from go.work is a drift bug surfaced fail-closed at archtest time.
func ReadManifestModulePathsRoot ¶
ReadManifestModulePathsRoot is the root-confined form of ReadManifestModulePaths for disk callers: it opens an os.Root at root (Go 1.24+ traversal-resistant fs) and reads through os.Root.FS(), so a symlinked .gocell/manifest.yaml (or a symlinked module dir) that resolves outside root is rejected at the syscall layer rather than silently read from outside the workspace. Disk callers (e.g. tools/workspace cross-check) MUST use this rather than building os.DirFS themselves — confinement is not the caller's to opt out of. Mirrors NewLocator's os.OpenRoot confinement (#1592).
func ValidateGRPCProtoPath ¶
ValidateGRPCProtoPath validates an endpoints.grpc.proto path field. It applies five guards in order:
- non-empty — a proto field is required on every grpc contract.
- must be rooted under GRPCProtoPathPrefix ("contracts/grpc/") — prevents referencing protos outside the governed contracts tree.
- no control rune — a control character would corrupt generated doc comments and file path handling.
- filepath.IsLocal — HasPrefix alone does not stop a traversal such as "contracts/grpc/../../../etc/x" escaping the repo root on os.ReadFile. This is the single-source guard shared by contractgen and governance FMT-37 (governance never runs contractgen, so without this shared function FMT-37 missed the IsLocal check — PR #1601 finding #2 / #3).
- subtree escape after lexical clean — a path like "contracts/grpc/../http/x.proto" passes guard 2 (string HasPrefix) and guard 4 (stays under repo root) but cleans to "contracts/http/x.proto", which is OUTSIDE the contracts/grpc/ subtree. Guard 5 lexically cleans the path and re-asserts the prefix so that intra-subtree ".." sequences (e.g. "contracts/grpc/device/../device/x.proto" → "contracts/grpc/device/x.proto") are accepted while cross-subtree escapes are rejected.
This is a pure lexical guard — symlink resolution is intentionally out of scope. The contracts/grpc/ tree is repo-controlled and the validator must remain FS-free so governance can run it without reading the proto.
The returned error carries a plain, path-focused message. Callers are expected to wrap it with their own contract-identity context:
if err := metadata.ValidateGRPCProtoPath(proto); err != nil {
return fmt.Errorf("contract %q: %w", id, err)
}
Types ¶
type ActorMeta ¶
type ActorMeta struct {
ID string `yaml:"id"`
MaxConsistencyLevel string `yaml:"maxConsistencyLevel"`
}
ActorMeta maps to a single entry in actors.yaml.
actors.yaml registers external systems that participate in contracts but are not modeled as cells. Membership in this file is itself the type declaration ("registered actor = external"); audience-aware governance rules (REF-17) reject any actor in this file from internal endpoints. No type field is needed — keeping it would create a parallel truth source against the cell-vs-actor distinction already implied by membership.
type AssemblyCellRef ¶
type AssemblyCellRef struct {
// yaml tags drive only marshaling (decode is the custom UnmarshalYAML below);
// module is omitempty so a round-trip of a same-module ref emits `id: x`
// rather than `module: ""` (which the decoder rejects as explicit-empty).
ID string `yaml:"id"`
Module string `yaml:"module,omitempty"`
}
AssemblyCellRef is one entry in assembly.yaml `cells:`. It accepts two YAML forms (see UnmarshalYAML):
- scalar shorthand `- configcore` → {ID: "configcore"}
- object (cross-module) `- {id: payment, module: github.com/acme/pay}`
Module empty = the cell's cellmodules/ package lives in the assembly's own Go module (the common same-module case). A non-empty Module references a cell developed in an independent Go module (#1086); codegen renders the import as "<Module>/cellmodules/<ID>" instead of "<current module>/cellmodules/<ID>". The module must be a declared dependency (go.mod require / go.work use) — that is enforced by the Go compiler when the generated modules_gen.go is built, not by a metadata governance rule (a declared-but-unresolvable module fails `go build`).
A non-empty Module also requires the owning assembly to declare `build.compositionAPI: true`; otherwise `gocell generate assembly` fails with ErrMetadataInvalid (the legacy local-CellModule form has no import path and cannot express a foreign module).
func CellRefs ¶
func CellRefs(ids ...string) []AssemblyCellRef
CellRefs builds a same-module []AssemblyCellRef from bare cell ids. It is the ergonomic constructor for the common case (every cell in the assembly's own module); cross-module entries are constructed as AssemblyCellRef{ID, Module} literals.
This function body is the single sanctioned site that embeds an AssemblyCellRef{ID: <runtime value>} composite literal; it is allowlisted by FIXTURE-CELLID-TYPED-BUILDER-01/A1 (this file). A1 does not scan CellRefs call arguments. Usage guidance by A1 scope (kernel/):
- external kernel/ test packages with static ids → prefer explicit []AssemblyCellRef{{ID: metadatatest.CellID*}} literals (A1-checked);
- internal `package metadata` tests (cannot import metadatatest — import cycle) and dynamic-id helpers (ids are runtime params, not literals) → use CellRefs (the only A1-compatible path);
- non-kernel ergonomics + production synthesis from validated runtime ids.
func (*AssemblyCellRef) UnmarshalYAML ¶
func (r *AssemblyCellRef) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML decodes the scalar-or-object union form of an assembly cell entry. The decoder's KnownFields(true) strictness does not propagate into a custom Unmarshaler, so the mapping branch enforces the {id, module} key set itself to preserve strict-decode parity with the rest of the schema.
type AssemblyMeta ¶
type AssemblyMeta struct {
ID string `yaml:"id"`
Cells []AssemblyCellRef `yaml:"cells"`
Owner OwnerMeta `yaml:"owner"`
// The assembly's provisioned capability set is NOT declared here — it is the
// derived union of its cells' CellMeta.Requires (Design Y, #855). There is no
// hand-authored assembly-level `capabilities` field; the single source is
// per-cell. kernel/assembly.GenerateModulesGen computes the union when
// rendering generatedCapabilities() in modules_gen.go.
Build BuildMeta `yaml:"build,omitempty"`
MaxConsistencyLevel string `yaml:"-"` // derived; yaml occurrence rejected by KnownFields
Dir string `yaml:"-"` // assembly directory name (parts[1]); set by parser from path, not YAML
File string `yaml:"-"` // parsed assembly.yaml path relative to project root
}
AssemblyMeta maps to assemblies/{id}/assembly.yaml (platform assemblies) or examples/{id}/assembly.yaml (example assemblies). See parser.matchAssemblyYAML for the recognized path forms.
type BuildMeta ¶
type BuildMeta struct {
Entrypoint string `yaml:"entrypoint,omitempty"`
Binary string `yaml:"binary,omitempty"`
DeployTemplate string `yaml:"deployTemplate,omitempty"`
// CompositionAPI when true instructs GenerateModulesGen to emit the
// runtime/composition.CellModule form (cellmodules/ module functions) instead
// of the legacy local-CellModule-type form used by examples/.
// Set to true in assemblies that use cellmodules/{cell}.Module() constructors
// (currently only assemblies/corebundle/assembly.yaml).
CompositionAPI bool `yaml:"compositionAPI,omitempty"`
}
BuildMeta holds the build configuration for an Assembly.
type CellMeta ¶
type CellMeta struct {
ID string `yaml:"id"`
Type string `yaml:"type"` // "core"|"edge"|"support"
ConsistencyLevel string `yaml:"consistencyLevel"` // "L0"-"L4"
DurabilityMode string `yaml:"durabilityMode"` // "demo"|"durable" (advisory for L2+)
// Lifecycle is the governance maturity phase
// (experimental|candidate|asset|maintenance|retired). Optional; empty
// defaults to experimental at BaseCell construction. Distinct from the
// runtime cellState and from a Contract's draft/active/deprecated lifecycle
// — see kernel/cellvocab.CellLifecycle. The parser stays lenient (membership
// is enforced by cell.schema.json enum + governance CELL-LIFECYCLE-01 +
// NewBaseCell's ParseCellLifecycle), matching the durabilityMode/requires
// posture.
Lifecycle string `yaml:"lifecycle,omitempty"`
Owner OwnerMeta `yaml:"owner"`
Schema SchemaMeta `yaml:"schema"`
Verify CellVerifyMeta `yaml:"verify"`
L0Dependencies []L0DepMeta `yaml:"l0Dependencies"`
// GoStructName is a schema extension consumed by tools/codegen — kernel
// itself does not interpret its value. Cells that opt into K#04 codegen
// MUST set this; non-codegen cells leave it empty. There is no reliable
// automatic mapping from a lowercased cell id to its conventional CamelCase
// Go type (e.g. "ordercell" → "OrderCell"), which is why explicit
// declaration is required.
GoStructName GoIdentifier `yaml:"goStructName,omitempty"`
// Requires lists the assembly-level shared infrastructure capabilities this
// cell consumes (postgres / redis / rabbitmq). It is the authoritative single
// source: the owning assembly's provisioned capability set is the derived
// union of its cells' Requires (see kernel/assembly.GenerateModulesGen). The
// closed value set is mirrored by CapabilityEnum + runtime/capability.Kind +
// cell.schema.json `requires` enum; unknown/duplicate values are rejected by
// `gocell validate` governance rule FMT-36 (validation-time, not by ParseFS —
// the parser stays lenient, matching Kubernetes admission-layer validation).
// "Requires" names what the cell consumes; it declares intent, not a uniform
// hardness contract. Whether a listed capability is hard-required or
// best-effort is decided per kind by the provisioner (cmd/corebundle
// provisionCapabilities): postgres is hard-required in non-memory storage
// modes (absence fails fast at the cell's nil-guard); redis is
// provision-if-available (absence degrades gracefully — e.g. accesscore's
// AUTH-CACHE-01 session cache is skipped when no redis client is configured).
Requires []string `yaml:"requires,omitempty"`
Dir string `yaml:"-"` // directory segment under cells/, set by parser
File string `yaml:"-"` // parsed cell.yaml path relative to project root
}
CellMeta maps to cells/{id}/cell.yaml.
Dir captures the filesystem directory segment under cells/ as walked by the parser. It is populated from the file path, not the YAML, so strict-mode governance rules (REF-04) can compare filesystem truth against cell.id without being fooled by a path/id split.
type CellVerifyMeta ¶
type CellVerifyMeta struct {
Smoke []string `yaml:"smoke"`
}
CellVerifyMeta holds structured verify refs for a Cell. Smoke refs use the format: smoke.{cellID}.{suffix}.
type CellWireBundle ¶
type CellWireBundle struct {
Listeners []WireBundleListener
Routes []WireBundleRoute
Subscribes []WireBundleSubscribe
}
CellWireBundle is a dependency-free mirror of markergen.WireBundle. Callers in runtime/ or cmd/ translate markergen.WireBundle → CellWireBundle so that kernel/metadata stays pure (no import of tools/codegen/*).
type CellWireSummary ¶
type CellWireSummary struct {
CellID string `json:"cellId" yaml:"cellId"`
Listeners []WireListenerView `json:"listeners" yaml:"listeners"`
Routes []WireRouteView `json:"routes" yaml:"routes"`
Subscribes []WireSubscribeView `json:"subscribes" yaml:"subscribes"`
}
CellWireSummary aggregates a cell's wire surface for catalog exposure. JSON / YAML tags follow the project camelCase convention.
func DeriveCellWireSummaries ¶
func DeriveCellWireSummaries(project *ProjectMeta, bundles map[string]CellWireBundle) []CellWireSummary
DeriveCellWireSummaries converts a per-cell CellWireBundle map into an ordered []CellWireSummary sorted by CellID for deterministic catalog output.
Only cell IDs present in both project.Cells and bundles appear in the result — cells with no bundle entry are silently omitted (they contribute an empty summary only when the caller explicitly supplies an empty CellWireBundle for that cell ID).
nil or empty bundles map → returns an empty (non-nil) slice so that callers can iterate without nil checks.
type ContractMeta ¶
type ContractMeta struct {
ID string `yaml:"id"`
Kind string `yaml:"kind"` // http|event|command|projection|webhook|grpc|saga
// Transports is the non-empty SET of wire transports this contract is
// sanctioned to bind to (e.g. [amqp, mqtt] for an event published over both
// brokers). When the contract.yaml omits `transports:`, parser.parseContract
// defaults it per kind (event/command→[amqp], http/webhook→[http],
// grpc→[grpc], projection/saga→[internal]) so every existing contract stays
// byte-identical. Each member MUST be one of cellvocab.AllTransports();
// kind↔transport compatibility is enforced by governance FMT-39. contractgen
// derives the generated ContractSpec.Transport as the primary (Transports[0])
// and emits the full exported set for multi-transport contracts.
// ref: asyncapi/spec channel.servers (transport set); k8s SetDefaults (per-kind default).
Transports []string `yaml:"transports,omitempty"`
OwnerCell string `yaml:"ownerCell"`
ConsistencyLevel string `yaml:"consistencyLevel"`
Lifecycle string `yaml:"lifecycle"` // draft|active|deprecated
// Triggers lists the outbox event topics emitted by this contract's owner
// cell when the HTTP handler succeeds. Required for L2+ HTTP contracts.
// Each value MUST be a string literal or named constant (dto.TopicX /
// domain.TopicX); dynamic expressions (fmt.Sprintf, variables) are rejected
// by CONTRACT-CONSISTENCY-EMIT-01. Validated bidirectionally against
// outbox.Emit call sites in cells/<ownerCell>/slices/**/service.go.
Triggers []string `yaml:"triggers,omitempty"`
Endpoints EndpointsMeta `yaml:"endpoints"`
SchemaRefs SchemaRefsMeta `yaml:"schemaRefs,omitempty"`
// Saga carries the orchestration definition for kind=saga contracts (steps,
// timeout, compensationOrder). Nil for all other kinds. Parsed under strict
// KnownFields decode; the declarative mirror lives in
// schemas/contract.schema.json. contractgen derives typed step I/O structs +
// an Impl interface + BuildDefinition/Register from it (PR-07).
Saga *SagaMeta `yaml:"saga,omitempty"`
Replayable *bool `yaml:"replayable,omitempty"`
IdempotencyKey string `yaml:"idempotencyKey,omitempty"`
DeliverySemantics string `yaml:"deliverySemantics,omitempty"`
// Codegen opts the contract into `gocell generate contract` output.
// When true, contractgen produces types_gen.go / iface_gen.go (and
// handler_gen.go for kind=http) under generated/contracts/<kind>/<...>/v<N>/.
//
// K#09 funnel: parser.parseContract defaults this to true when the
// contract.yaml omits the `codegen:` key (detected via yaml AST in
// contractYAMLHasKey). Explicit `codegen: false` is the only way to
// opt out. Scaffold output omits the field entirely so the funnel is
// the single source of truth (INVARIANT SCAFFOLD-BUNDLE-NO-CODEGEN-LITERAL-01).
Codegen bool `yaml:"codegen,omitempty"`
// Direction is the webhook flow direction: "inbound" (external → cell) or
// "outbound" (cell → external). Only populated for kind=webhook.
Direction string `yaml:"direction,omitempty"`
// Signature holds the webhook signature verification metadata. Only
// populated for kind=webhook contracts.
Signature *WebhookSignatureMeta `yaml:"signature,omitempty"`
// Payload holds webhook payload constraints. Only populated for
// kind=webhook contracts.
Payload *WebhookPayloadMeta `yaml:"payload,omitempty"`
// Description / DeprecatedAt are documentation only — excluded from
// structural fingerprint via fingerprint:"-".
Description string `yaml:"description,omitempty" fingerprint:"-"`
DeprecatedAt string `yaml:"deprecatedAt,omitempty" fingerprint:"-"`
// Dir / File are parsed-time fields tracking contract.yaml location relative
// to the project root; never persisted, hence yaml:"-".
Dir string `yaml:"-" fingerprint:"-"`
File string `yaml:"-" fingerprint:"-"`
}
ContractMeta maps to contracts/{kind}/{domain...}/{version}/contract.yaml.
func (*ContractMeta) Owner ¶
func (c *ContractMeta) Owner() ContractOwner
Owner resolves the raw ownerCell wire string (post G-7 auto-derivation) into a sealed ContractOwner. It is the single funnel through which all owner-kind-aware code must read a contract's owner; reading the raw OwnerCell field as a cell id is the bypass that CONTRACT-OWNER-CELL-FUNNEL-01 forbids.
func (*ContractMeta) ProviderEndpoint ¶
func (c *ContractMeta) ProviderEndpoint() string
ProviderEndpoint returns the provider cell/actor ID for this contract based on its Kind. Returns "" if Kind is unknown or provider is unset.
For kind=webhook: returns the explicitly declared ownerCell. Webhook contracts must declare ownerCell explicitly (see contracts/webhook/README.md). Unlike other kinds, the webhook provider cannot be derived from Endpoints.Receivers or Endpoints.Dispatchers at parse time because those fields are populated by deriveWebhookEndpoints, which runs after parseContract calls ProviderEndpoint for the G-7 ownerCell auto-derivation. When ownerCell is set, the G-7 if-check in parseContract (if m.OwnerCell == "") is skipped correctly; when ownerCell is empty, ProviderEndpoint returns "" and ownerCell remains empty (governance rules will flag the omission).
type ContractOwner ¶
type ContractOwner struct {
// contains filtered or unexported fields
}
ContractOwner is the sealed, resolved owner of a contract: either a platform Cell (by id) or the Framework. It is the typed union that replaces ad-hoc `ownerCell string` cell-existence assumptions.
Sealed construction (Hard, same shape as runtime/observability/metrics.CellLabel and kernel/outbox.Entry): both fields are unexported and the sole constructor is ContractMeta.Owner (via the package-private resolveContractOwner funnel), so a non-zero ContractOwner — and in particular a FRAMEWORK owner — cannot be forged outside this package by a struct literal. Code that needs the owning cell MUST go through ContractOwner.Cell; a framework owner returns ok=false there, making "treat the framework as if it were a cell" unexpressible at the type level rather than catchable only by a runtime string check.
func (ContractOwner) Cell ¶
func (o ContractOwner) Cell() (string, bool)
Cell returns the owning cell id and ok=true when the contract is cell-owned; it returns ("", false) when the contract is framework-owned. This is the only way to extract a cell from an owner: a framework owner can never be mistaken for a cell, because there is no code path that yields a cell id from one.
func (ContractOwner) IsFramework ¶
func (o ContractOwner) IsFramework() bool
IsFramework reports whether the contract is framework-owned.
type ContractSchemaRef ¶
type ContractSchemaRef struct {
Field string
Ref string
Scope SchemaRefScope
}
ContractSchemaRef is one schema reference declared by a contract.
func ContractSchemaRefs ¶
func ContractSchemaRefs(c *ContractMeta) []ContractSchemaRef
ContractSchemaRefs returns every schema reference declared by c in deterministic order. Empty refs are included so callers that need field-level completeness can still inspect them.
type ContractUsage ¶
type ContractUsage struct {
Contract string `yaml:"contract"`
Role string `yaml:"role"` // serve|call|publish|subscribe|handle|invoke|provide|read|webhook-receive|webhook-dispatch
// Handler is the consumer handler method name on the slice's service/consumer
// struct field; REQUIRED for role=subscribe and role=webhook-receive, forbidden
// otherwise (including role=webhook-dispatch). Single source for the
// reg.Subscribe / reg.RegisterWebhookReceiver handler expression that cellgen emits.
Handler string `yaml:"handler,omitempty"`
// Group is the broker consumer group for role=subscribe; optional, defaults to
// the owning cell ID when empty. Forbidden for non-subscribe roles (including
// webhook-receive and webhook-dispatch).
Group string `yaml:"group,omitempty"`
// Field optionally names the cell-struct field holding the consumer slice's
// service, disambiguating slices that own more than one *sliceID.T field
// (e.g. a route Handler plus a subscribe Consumer or a webhook receiver).
// Optional for role=subscribe, role=webhook-receive, and role=webhook-dispatch
// (cellgen resolves by package convention when empty); forbidden for all other
// roles.
Field string `yaml:"field,omitempty"`
// SourceID is the secret-isolation key identifying the webhook source (e.g.
// "stripe", "shopify"). REQUIRED for role=webhook-receive and
// role=webhook-dispatch; forbidden for all other roles. For webhook-receive,
// this value must equal contract.endpoints.inbound.sourceID.
SourceID string `yaml:"sourceID,omitempty"`
// TargetSelector is the target-URL selector method name used by the
// dispatcher to resolve the outbound webhook URL at runtime. REQUIRED for
// role=webhook-dispatch; forbidden for all other roles.
TargetSelector string `yaml:"targetSelector,omitempty"`
// Projection, when set on a role=subscribe CU, makes cellgen emit
// reg.RegisterProjection (an L3 CQRS projection) instead of reg.Subscribe.
// The value is the ProjectionID — half of the checkpoint key
// (cellID, projectionID). MUST be a snake_case probe-name identifier:
// ^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$. Optional; forbidden on every
// non-subscribe role.
Projection string `yaml:"projection,omitempty"`
// OnReset names the optional rebuild Reset-phase hook method on the same
// slice service field as Handler (cell.ProjectionResetHook). Only meaningful
// when Projection is set; exported Go identifier (^[A-Z][A-Za-z0-9_]*$).
// Optional; subscribe-only. Forbidden when Projection is empty AND forbidden
// when ProjectionSource is "saga-journal" (the saga-journal path has no rebuild
// — EPIC #1609 PR-05).
OnReset string `yaml:"onReset,omitempty"`
// ProjectionSource selects which input stream feeds the projection (EPIC #1609
// PR-05). REQUIRED whenever Projection is set; forbidden otherwise. Values:
// - "outbox": the named event contract's outbox topic (contract.kind=event).
// - "saga-journal": the GLOBAL saga journal (stream saga.journal.v1). The
// contract MUST be kind=saga, but the anchor is for LINEAGE/governance only
// — it is NOT a runtime filter: the saga-journal source is global (reads
// every saga instance/type), so the Apply hook folds the whole journal and
// must itself filter if it cares about one saga (same coarse, existence-only
// semantics as PROJECTION-PROVIDE-NEEDS-WRITE-CU-01).
// cellgen branches on this: "outbox" emits <eventpkg>.NewProjectionRequest;
// "saga-journal" emits cell.NewSagaJournalProjectionRequest.
ProjectionSource string `yaml:"projectionSource,omitempty"`
}
ContractUsage declares a Slice's participation in a Contract.
type EndpointsMeta ¶
type EndpointsMeta struct {
// HTTP (also reused by gRPC: provider=server, consumers=clients)
Server string `yaml:"server,omitempty"`
Clients []string `yaml:"clients,omitempty"`
HTTP *HTTPTransportMeta `yaml:"http,omitempty"`
// gRPC transport subtree (parallel to HTTP); server/clients above carry
// the provider/consumer cells.
GRPC *GRPCTransportMeta `yaml:"grpc,omitempty"`
// Event
Publisher string `yaml:"publisher,omitempty"`
ActorSubscribers []string `yaml:"actorSubscribers,omitempty"`
// Subscribers is derived by deriveEventSubscribers (parser post-process):
// union of ActorSubscribers + cell IDs from slice.yaml contractUsages[role=subscribe].
// yaml:"-" means hand-written "subscribers:" in YAML is rejected by KnownFields strict decode.
Subscribers []string `yaml:"-"`
// Command
Handler string `yaml:"handler,omitempty"`
Invokers []string `yaml:"invokers,omitempty"`
// Projection
Provider string `yaml:"provider,omitempty"`
Readers []string `yaml:"readers,omitempty"`
// Webhook (kind=webhook only)
Inbound *WebhookInboundMeta `yaml:"inbound,omitempty"`
// Receivers is derived by deriveWebhookEndpoints (parser post-process): cell
// IDs from slice.yaml contractUsages[role=webhook-receive].belongsToCell,
// deduped and sorted alphabetically. yaml:"-" means hand-written "receivers:"
// in YAML is rejected by KnownFields strict decode — mirrors the Subscribers
// field pattern.
Receivers []string `yaml:"-"`
// Dispatchers is derived by deriveWebhookEndpoints (parser post-process): cell
// IDs from slice.yaml contractUsages[role=webhook-dispatch].belongsToCell,
// deduped and sorted alphabetically. yaml:"-" means hand-written "dispatchers:"
// in YAML is rejected by KnownFields strict decode — mirrors the Subscribers
// field pattern.
Dispatchers []string `yaml:"-"`
}
EndpointsMeta holds the kind-specific endpoint fields for a Contract. Only the fields relevant to the contract's Kind are populated.
type GRPCTransportMeta ¶
type GRPCTransportMeta struct {
// Service is the proto fully-qualified service name,
// e.g. "device.command.v1.DeviceCommandService".
Service string `yaml:"service" json:"service"`
// Proto is the contracts-relative path to the .proto file, e.g.
// "contracts/grpc/device/command/v1/device_command.proto".
Proto string `yaml:"proto" json:"proto"`
}
GRPCTransportMeta declares a gRPC contract's service-level ownership. It lives under EndpointsMeta.GRPC, parallel to EndpointsMeta.HTTP; the provider/consumer cells reuse endpoints.server / endpoints.clients (gRPC mirrors http: roles serve/call). A single contract owns a whole proto service — the .proto file is the single source of truth for the RPC method set. Per-method field declarations have been removed (#1655): the contractgen ProtoRegistry enumerates all RPCs from the .proto via ReadProtoServiceInfo, so contract.yaml never lists individual method names.
No per-RPC auth overlay is declared here: a service-level public flag could not express per-method auth once a service owns multiple RPCs, and nothing consumed it (the runtime auth predicate is wired separately). The per-method auth model is deferred to #1675.
ref: grpc/grpc-go ServiceDesc; go-kratos/kratos protoc-gen-go-grpc service descriptor — the proto service name is the wire identity.
type GoIdentifier ¶
type GoIdentifier struct {
// contains filtered or unexported fields
}
GoIdentifier is a string statically guaranteed to satisfy GoStructNamePattern (^[A-Z][A-Za-z0-9]*$). The unexported value field forces all construction through NewGoIdentifier or UnmarshalYAML, so any GoIdentifier value reaching codegen templates has already been validated.
Raw strings cannot be coerced to GoIdentifier; downstream consumers call String() to obtain the validated text. This is the typed-identifier boundary (review §R1) preventing arbitrary cell.yaml values from being embedded into emitted Go source code.
func MustNewGoIdentifier ¶
func MustNewGoIdentifier(s string) GoIdentifier
MustNewGoIdentifier is the panic-on-misconfig variant of NewGoIdentifier for composition-root and codegen-emitted literals. cell_gen.go embeds the validated goStructName from the parsed CellMeta — if a manual edit introduces an invalid value, the resulting panic is the expected fail-fast (C-class initialization error, see error-handling.md panic taxonomy). Runtime production code must use NewGoIdentifier.
func NewGoIdentifier ¶
func NewGoIdentifier(s string) (GoIdentifier, error)
NewGoIdentifier validates s and returns a typed GoIdentifier. Empty input returns the zero value (cells that opt out of K#04 codegen leave goStructName empty in cell.yaml); callers requiring a non-empty value must check IsZero separately. Non-empty input that does not satisfy GoStructNamePattern is rejected with errcode.ErrMetadataInvalid.
func (GoIdentifier) IsZero ¶
func (g GoIdentifier) IsZero() bool
IsZero reports whether the identifier is the zero value (empty input, indicating a cell that has not opted into K#04 codegen).
func (GoIdentifier) MarshalYAML ¶
func (g GoIdentifier) MarshalYAML() (any, error)
MarshalYAML emits the underlying string so YAML round-trips preserve the original cell.yaml content.
func (GoIdentifier) String ¶
func (g GoIdentifier) String() string
String returns the underlying identifier text. Safe to embed into Go code generation templates because every constructed value has been validated.
func (*GoIdentifier) UnmarshalYAML ¶
func (g *GoIdentifier) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML is invoked by parser.go when CellMeta.GoStructName is decoded. Validation happens at parse time so downstream derivation, governance, and codegen all operate on validated values.
type HTTPAuthMeta ¶
type HTTPAuthMeta struct {
// Public marks the route as JWT-exempt. The generated NewHandler takes no
// policy argument; auth.Route{Public: true} is emitted by RegisterRoutes.
// Mutually exclusive with PasswordResetExempt, Bootstrap, ServiceOwned,
// and ClientsOnly.
Public bool `yaml:"public,omitempty" json:"public,omitempty"`
// PasswordResetExempt allows callers whose JWT carries password_reset_required=true
// to reach this route. The generated handler emits auth.Route{PasswordResetExempt: true}.
// Mutually exclusive with Public, Bootstrap, and ClientsOnly. May combine
// with ServiceOwned.
PasswordResetExempt bool `yaml:"passwordResetExempt,omitempty" json:"passwordResetExempt,omitempty"`
// ServiceOwned indicates that the listener must still authenticate the caller,
// but route-level authorization is intentionally absent because the service
// validates ownership against domain state. When true, contractgen generates a
// single-arg NewHandler(svc Service) constructor and emits auth.Route without
// a Policy field. May be combined with PasswordResetExempt. Mutually exclusive
// with Public, Bootstrap, and ClientsOnly.
ServiceOwned bool `yaml:"serviceOwned,omitempty" json:"serviceOwned,omitempty"`
// Bootstrap marks the route as protected by HTTP Basic Auth using
// GOCELL_BOOTSTRAP_ADMIN_USERNAME/PASSWORD env credentials. Listener-level
// JWT middleware skips routes flagged as Bootstrap (matcher in FinalizeAuth).
// Mutually exclusive with Public, PasswordResetExempt, ServiceOwned, and
// ClientsOnly. FMT-28 limits this flag to contracts whose path matches
// IsBootstrapPath.
Bootstrap bool `yaml:"bootstrap,omitempty" json:"bootstrap,omitempty"`
// ClientsOnly indicates that this endpoint relies solely on Contract.Clients
// caller-cell allowlist for authorization. When true, contractgen generates a
// single-arg NewHandler(svc Service) constructor and emits auth.Route without
// a Policy field. auth.Mount auto-injects RequireCallerCell guard when
// Clients is non-empty. Mutually exclusive with Public, Bootstrap,
// PasswordResetExempt, and ServiceOwned. Requires endpoints.clients to be
// non-empty and the path to match IsInternalHTTPPath (/internal/v1 or
// /internal/v1/...) where caller-cell identity is verifiable via the
// service token.
ClientsOnly bool `yaml:"clientsOnly,omitempty" json:"clientsOnly,omitempty"`
// Responses lists HTTP status codes injected by listener-mounted middleware,
// NOT emitted by the handler/adapter — so they are declared here (no typed
// response struct) rather than in the responses map. Despite the "auth" name,
// this list already spans non-auth middleware: bootstrap auth 401, rate limiter
// 429, and HTTP-idempotency 409 (ClaimBusy) / 422 (key-reused) — both required
// on non-exempt mutating routes by governance rule CH-07. CH-04 treats these as
// declared without requiring handler AST emission.
Responses []int `yaml:"responses,omitempty" json:"responses,omitempty"`
}
HTTPAuthMeta carries route-level authentication override flags for contractgen. These map to generated auth.Route wiring and handler constructor shape.
Mutex among the 5 bool fields is enforced by metadata.AuthComboLegal (the single oracle shared by contract.schema.json if/then rules and governance validateFMT27). HTTP-idempotency behavior is NOT an auth mode — it lives on the sibling HTTPIdempotencyMeta (endpoints.http.idempotency), so HTTPAuthMeta holds exactly the 5 auth-mode flags and the auth-combo matrix stays 2^5. When adding a new bool field, see auth_combo.go for the checklist of files to update in lockstep.
ref: kubernetes-sigs/controller-tools markers/registry.go (declarative auth metadata)
type HTTPIdempotencyMeta ¶
type HTTPIdempotencyMeta struct {
// Exempt, when true, instructs the HTTP idempotency middleware to never
// claim/record/replay this route's responses (credential-rotation /
// change-password whose body returns tokens). The generated handler emits
// auth.Route{IdempotencyExempt: true} (see runtime/auth/route.go).
// Mandatory for any route whose response schema carries a
// pkg/redaction.IsSensitiveKey field — codegen rejects generation without it
// (CREDENTIAL-RESPONSE-IDEMPOTENCY-EXEMPT-FUNNEL-01).
Exempt bool `yaml:"exempt,omitempty" json:"exempt,omitempty"`
}
HTTPIdempotencyMeta carries route-level HTTP-idempotency behavior, orthogonal to authentication. It is a first-class sibling of HTTPAuthMeta rather than a folded-in auth flag (#1469 review F7): idempotency is a middleware concern, so it does not participate in the FMT-27 auth-mode mutex matrix. Keeping it out of HTTPAuthMeta also keeps the auth-combo space at 2^5 instead of 2^6.
type HTTPOwnershipMeta ¶
type HTTPOwnershipMeta struct {
SubjectPath string `yaml:"subjectPath" json:"subjectPath"`
ResourcePath string `yaml:"resourcePath" json:"resourcePath"`
}
HTTPOwnershipMeta declares object-level authorization subject/resource paths. Required when auth.serviceOwned=true (governance FMT-32 + schema if/then enforces this). Pointer field tri-state: nil = block absent, non-nil with empty fields = declared but incomplete; both forms are rejected by FMT-32.
type HTTPResponseMeta ¶
type HTTPResponseMeta struct {
Description string `yaml:"description" json:"description" fingerprint:"-"`
SchemaRef string `yaml:"schemaRef" json:"schemaRef"`
}
HTTPResponseMeta describes a declared error response for a specific HTTP status code. It references a JSON Schema file, relative to the contract directory, that describes the error response body.
type HTTPTransportMeta ¶
type HTTPTransportMeta struct {
Method string `yaml:"method" json:"method"`
Path string `yaml:"path" json:"path"`
PathParams map[string]ParamSchema `yaml:"pathParams,omitempty" json:"pathParams,omitempty"`
QueryParams map[string]ParamSchema `yaml:"queryParams,omitempty" json:"queryParams,omitempty"`
// Headers declares inbound HTTP request headers this endpoint consumes
// (keyed by canonical header name, e.g. "X-Tenant-ID"). It is the single
// source for request-header consumption: contractgen merges each declared
// header into the generated Request DTO as a typed field populated from
// r.Header.Get — see archtest HTTP-REQUEST-HEADER-READ-FUNNEL-01 (cells /
// examples may not read inbound headers raw; the generated handler is the
// sole reader).
//
// Headers are POPULATE-ONLY at codegen: the generated handler emits no
// required / length / format gate. Per-endpoint fail behavior (e.g. the
// X-Tenant-ID anti-enumeration matrix in ADR 1160 — login→401, setup/admin→400,
// setup/status→200 fail-soft) is owned by the cell adapter/service via
// tenant.ParseTenantID, not derivable from a uniform codegen gate. `required`
// is documentation / governance / client-gen metadata only. Governance FMT-40
// rejects unenforced minLength/maxLength/minimum/maximum on header schemas so a
// declared constraint can never silently no-op. ref: goadesign/goa v3
// expr/http_endpoint.go Headers; go-kratos/kratos transport/http header binding.
Headers map[string]ParamSchema `yaml:"headers,omitempty" json:"headers,omitempty"`
SuccessStatus int `yaml:"successStatus" json:"successStatus"`
NoContent bool `yaml:"noContent" json:"noContent"`
Responses map[int]HTTPResponseMeta `yaml:"responses,omitempty" json:"responses,omitempty"`
// Auth declares route-level authentication overrides for contractgen.
// When set, the generated handler emits the corresponding auth.Route flags
// instead of the default Policy-only wiring. Omit for standard authenticated routes.
Auth HTTPAuthMeta `yaml:"auth,omitempty" json:"auth,omitempty"`
// Ownership declares object-level authorization subject/resource paths.
// Required when auth.serviceOwned=true (governance FMT-32 enforces presence).
Ownership *HTTPOwnershipMeta `yaml:"ownership,omitempty" json:"ownership,omitempty"`
// Idempotency declares route-level HTTP-idempotency behavior. It is a
// first-class sibling of Auth (not folded into the auth-mode mutex matrix):
// idempotency is a middleware concern, not an authentication mode (#1469
// review F7). Omit for default idempotent-eligible routes.
Idempotency HTTPIdempotencyMeta `yaml:"idempotency,omitempty" json:"idempotency,omitempty"`
// ResponseProjection declares that this endpoint's success response `data`
// resource is served through the sealed pkg/projection.ResourceProjection
// carrier (epic #1337 PR-12, FR-016). When set, contractgen rewrites the
// generated Response.Data field type to projection.ResourceProjection (single
// object) or []projection.ResourceProjection (array), forcing the handler to
// build the wire data through the column-masking funnel
// (projection.NewProjection / NewProjectionList). A full, un-masked view is not
// assignable to the field, so column masking cannot be bypassed at the handler
// callsite (RESOURCE-PROJECTION-CALLSITE-LOCK-01). Every GET read endpoint
// carrying a `data` resource MUST set this (RESOURCE-PROJECTION-COVERAGE-01);
// an empty FieldMask obligation yields the identity projection so the wire
// field set is unchanged. Default false leaves the response type untouched.
// See contracts/http/audit/list/v1/contract.yaml for a worked example.
ResponseProjection bool `yaml:"responseProjection,omitempty" json:"responseProjection,omitempty"`
}
HTTPTransportMeta holds transport-level details for HTTP contracts. It elevates the wire-level contract (method, path, path/query parameters, status codes, bodyless semantics) to first-class metadata so static tooling (codegen, trace span labels, contract-health) can derive the full API shape from contract.yaml alone without inspecting JSON Schema files.
ref: goadesign/goa v3 expr/http_endpoint.go - Params modeled as a typed attribute map; path params derived from the path template at parse time. ref: go-kratos/kratos cmd/protoc-gen-go-http - path params parsed via regex on the path template string.
func (*HTTPTransportMeta) IdempotencyFrameworkStatuses ¶
func (h *HTTPTransportMeta) IdempotencyFrameworkStatuses() []int
IdempotencyFrameworkStatuses returns the HTTP status codes the idempotency middleware can emit for this route as a framework-injected set, analogous to HTTPAuthMeta.Responses (401/429). When idempotency is default-on, a mutating route (POST/PUT/PATCH/DELETE) that is not Idempotency.Exempt can return 409 on an in-flight key (ClaimBusy) or 422 on a reused key with a mismatched body fingerprint (ErrIdempotencyKeyReused, per IETF idempotency-key draft §2.7). Returns nil for GET/HEAD and exempt routes.
This is the single-source oracle for the CH-07 governance rule (#1537 review F4): CH-07 requires every contract this returns a non-empty set for to declare those statuses in auth.responses, so the declaration surface cannot drift from the middleware and a future mutating route is forced to declare 409/422 or set idempotency.exempt. These are NOT folded into declaredErrorStatuses (that would make CH-07 vacuous and has no effect on CH-04, which checks handler-emitted statuses — the middleware injects 409/422, not the handler).
The {409, 422} set is re-declared here as an integer literal because kernel/ must not import runtime/ (layering); it is bound to the single runtime source runtime/http/idempotency.FrameworkStatuses() by archtest IDEMPOTENCY-FRAMEWORK-STATUS-ORACLE-ALIGN-01, which fails if the two diverge.
Known reachability gap: this oracle keys only on method + Idempotency.Exempt, so it also requires 409/422 on mutating routes the middleware never claims for — public / bootstrap / service-token routes, whose non-PrincipalUser principals are bypassed by middleware.extractIdentity. Those routes therefore declare statuses they cannot emit (a pre-existing property of the 409 leg, not introduced by 422). Making the oracle auth-shape-aware is tracked at gh #1591.
type HeaderViolation ¶
type HeaderViolation struct {
// Header is the offending declared header name (the contract.yaml map key).
Header string
// Kind classifies the violation.
Kind HeaderViolationKind
// Message is a human-readable description of the problem.
Message string
}
HeaderViolation is one endpoints.http.headers schema problem.
func ValidateHTTPHeaders ¶
func ValidateHTTPHeaders(headers map[string]ParamSchema) []HeaderViolation
ValidateHTTPHeaders is the SINGLE SOURCE OF TRUTH for endpoints.http.headers schema validity. Headers are populate-only at codegen — the generated handler emits `req.X = r.Header.Get("<name>")` with no validation gate — so the declarable shape is restricted to what that accessor can express:
- name: a canonical HTTP token (httpHeaderNameRe)
- type: "string" only — r.Header.Get returns string; integer/number/boolean would generate an uncompilable typed field (#1494 review F1)
- no minLength/maxLength/minimum/maximum — no gate is generated, so they would silently no-op
- no case-insensitive duplicate name — HTTP header names are case-insensitive (#1494 review F3)
Both governance FMT-40 (validate-time) and contractgen buildHTTPSpec (codegen-time, fail-closed) call this so the two gates cannot drift: a header that governance would reject can never reach the generator, and the generator fails closed even if `gocell validate` is skipped (#1494 review F4).
Returns violations in a deterministic order (by header name, then kind); an empty slice means the header set is valid.
type HeaderViolationKind ¶
type HeaderViolationKind int
HeaderViolationKind classifies an endpoints.http.headers schema violation.
const ( // HeaderViolationName — header name is not a canonical HTTP token. HeaderViolationName HeaderViolationKind = iota // HeaderViolationType — type is missing or not "string". Headers are // populate-only at codegen (the generated handler emits // req.X = r.Header.Get(name), which yields a string); a non-string type // would generate an uncompilable typed field assignment (#1494 review F1). HeaderViolationType // HeaderViolationConstraint — minLength/maxLength/minimum/maximum declared. // Headers emit no validation gate, so a length/numeric constraint would // silently no-op; reject it rather than mislead. HeaderViolationConstraint // HeaderViolationDuplicate — case-insensitive duplicate header name. HTTP // header names are case-insensitive, so two keys folding to the same // canonical name collide (#1494 review F3). HeaderViolationDuplicate )
type JourneyMeta ¶
type JourneyMeta struct {
ID string `yaml:"id"`
Goal string `yaml:"goal"`
Lifecycle string `yaml:"lifecycle"` // "active"|"experimental"
Owner OwnerMeta `yaml:"owner"`
Cells []string `yaml:"cells"`
Contracts []string `yaml:"contracts"`
PassCriteria []PassCriterion `yaml:"passCriteria"`
File string `yaml:"-"` // parsed journey YAML path relative to project root
}
JourneyMeta maps to journeys/J-*.yaml.
type L0DepMeta ¶
L0DepMeta declares a direct dependency on an L0 (LocalOnly) Cell.
L0 Cell status: sanctioned future extension point
L0 (LocalOnly, pure-compute library cell) is a first-class member of the consistency-level model (L0-L4). An L0 Cell has no state machine, no outbox, and no contracts; it exposes shared pure-computation logic (e.g. hashing, validation algorithms, encoding helpers) that other cells in the same Assembly may import directly.
As of this writing there is no L0 Cell instance in the platform cells (accesscore / auditcore / configcore). Every platform cell.yaml therefore carries `l0Dependencies: []` — this empty slice is expected and correct; it is not a schema defect or dead-code path.
When a future L0 Cell is created (e.g. a shared pure-compute package elevated to a first-class Cell), consuming cells would add an entry here:
l0Dependencies:
- cell: sharedcrypto
reason: deterministic hashing for cursor tokens
Decision record: C-06-L0-CELL-DECISION — user chose doc-only (option b) over elevating an existing package to a concrete L0 instance (option a).
type Locator ¶
type Locator struct {
// contains filtered or unexported fields
}
Locator discovers metadata YAML files from a filesystem root and emits one MetadataSource per file, sorted by path for deterministic test fixtures.
func NewLocator ¶
func NewLocator(root string, opts ...LocatorOption) (*Locator, error)
NewLocator constructs a Locator backed by the on-disk root directory.
The filesystem is rooted via os.OpenRoot(root).FS(), which confines EVERY access (Stat / WalkDir / ReadFile) to the directory tree at root. Per the os.Root contract, it FOLLOWS symlinks that resolve within root and REJECTS those that escape it (absolute targets, or `..`/symlink chains leaving root) with "path escapes from parent" at the syscall layer. This is the root-confinement that prevents a manifest module path (or any subpath) that is a symlink escaping the workspace from making discovery read cells/contracts outside the repo (#1592). Discovery additionally skips symlink *entries* during WalkDir (see discoverConventional / matchManifestGlob), so in practice no symlink is traversed; the GoCell layout has no symlinks at all, so neither behavior changes discovery output.
The root path itself may be a symlinked directory (e.g. macOS /var -> /private/var); os.OpenRoot follows the root's own symlink to open it, then confines all SUBSEQUENT accesses within the opened directory. Resolution uses filepath.Abs (not EvalSymlinks) — confinement comes from os.Root, not from pre-resolving root.
Callers must Close the returned Locator to release the underlying directory file descriptor (Parser.Parse does this for the Locator it constructs).
func NewLocatorFS ¶
func NewLocatorFS(fsys fs.FS, opts ...LocatorOption) (*Locator, error)
NewLocatorFS constructs a Locator backed by an arbitrary fs.FS. Used by tests to feed fstest.MapFS fixtures and by callers that already hold an fs.FS handle (e.g., embed.FS, virtual FS).
Unlike NewLocator, NewLocatorFS does NOT add root confinement: it uses the caller's fsys verbatim. If a caller passes os.DirFS(dir) (which follows symlinks), symlink-escape confinement is the CALLER's responsibility — either use NewLocator (os.OpenRoot-confined) for untrusted disk roots, or guarantee safety another way (conventional Discover never recurses into symlink entries; tools/workspace additionally symlink-guards its go.work `use` dirs). MapFS / embed.FS have no OS symlinks, so the test/virtual path is unaffected.
func (*Locator) Close ¶
Close releases the os.Root directory handle held by a disk-backed Locator (NewLocator). It is a no-op for an fs.FS-backed Locator (NewLocatorFS) and is safe to call more than once. Parser.Parse / ParseFS close the Locator they construct; callers that use NewLocator directly should defer Close to release the underlying directory file descriptor.
Close errors are non-retryable (closing a read-only directory fd), so deferred callers may safely ignore them: `defer func() { _ = loc.Close() }()`.
func (*Locator) Discover ¶
func (l *Locator) Discover() ([]MetadataSource, error)
Discover walks the locator root and emits one MetadataSource per metadata YAML file found, sorted by Path for deterministic output.
func (*Locator) FS ¶
FS returns the underlying fs.FS so callers that need to read file contents (parser unmarshalFile) can share the same handle.
func (*Locator) Mode ¶
func (l *Locator) Mode() LocatorMode
Mode returns the resolved locator mode (after auto-detection).
type LocatorMode ¶
type LocatorMode int
LocatorMode selects how Locator discovers metadata.
const ( // LocatorAuto selects Conventional unless .gocell/manifest.yaml exists at // root, in which case Manifest mode is used. If the manifest file is found // but fails to parse, Locator returns an error and does NOT fall back to // Conventional mode. Use WithLocatorMode(LocatorConventional) to bypass // manifest detection explicitly. LocatorAuto LocatorMode = iota // LocatorConventional walks the hardcoded 5-pattern layout. Used when no // manifest file is present, or explicitly via WithLocatorMode. LocatorConventional // LocatorManifest reads .gocell/manifest.yaml and walks the modules: // list it declares. LocatorManifest )
func ParseLocatorMode ¶
func ParseLocatorMode(s string) (LocatorMode, error)
ParseLocatorMode converts a CLI flag value to a LocatorMode. Empty string resolves to LocatorAuto. Unknown values return an error.
func (LocatorMode) String ¶
func (m LocatorMode) String() string
String returns the kebab-case name of LocatorMode.
type LocatorOption ¶
type LocatorOption func(*Locator)
LocatorOption configures NewLocator / NewLocatorFS.
func WithLocatorMode ¶
func WithLocatorMode(m LocatorMode) LocatorOption
WithLocatorMode overrides the auto-detected mode. Use this in CI to lock the locator behavior against accidental manifest detection.
func WithManifestPath ¶
func WithManifestPath(p string) LocatorOption
WithManifestPath sets an explicit manifest path. Defaults to .gocell/manifest.yaml.
Passing an empty string is a no-op (default path unchanged). Non-empty paths containing ".." segments or absolute paths cause NewLocator / NewLocatorFS to return an error.
type ManifestIncludes ¶
type ManifestIncludes struct {
// Cells corresponds to the "cells:" YAML key.
Cells []string `yaml:"cells"`
// Slices corresponds to the "slices:" YAML key.
Slices []string `yaml:"slices"`
// Contracts corresponds to the "contracts:" YAML key.
Contracts []string `yaml:"contracts"`
// Journeys corresponds to the "journeys:" YAML key.
Journeys []string `yaml:"journeys"`
// Assemblies corresponds to the "assemblies:" YAML key.
Assemblies []string `yaml:"assemblies"`
// Actors corresponds to the "actors:" YAML key (singular string, not a list).
Actors string `yaml:"actors"`
// StatusBoard corresponds to the "statusBoard:" YAML key (camelCase, not kebab-case).
StatusBoard string `yaml:"statusBoard"`
}
ManifestIncludes maps each metadata source kind to one or more glob patterns. Globs are resolved relative to the owning ManifestModule.Path. Patterns support "*" (single segment) and "**" (zero or more segments, implemented via fs.WalkDir — not filepath.Glob which has undefined "**" semantics). Ref: bufbuild/buf v2 buf.yaml includes field.
Cells / Slices / Contracts / Journeys / Assemblies accept multiple patterns (slice of strings); Actors and StatusBoard are singletons (single string).
Actors and StatusBoard are workspace-level singletons: they may only appear in Modules[0] (validated by loadManifest). Declaring them in more than one module entry causes loadManifest to return a validation error.
type ManifestModule ¶
type ManifestModule struct {
Path string `yaml:"path"`
Includes ManifestIncludes `yaml:"includes"`
Excludes []string `yaml:"excludes"`
}
ManifestModule is a single module entry inside ManifestSpec.Modules.
Path is required, must be a non-empty relative path, and must not escape outside the manifest directory (no ".." segments, no absolute paths). Use "." for the module that lives at the same level as manifest.yaml.
Includes carries per-kind glob patterns. When empty, the conventional 5-pattern defaults are used (cells/*/cell.yaml, cells/*/slices/*/slice.yaml, contracts/**/contract.yaml, journeys/J-*.yaml, assemblies/*/assembly.yaml, plus actors.yaml and journeys/status-board.yaml singletons). This lets Operator-SDK modules omit includes: entirely and still get conventional discovery.
Excludes applies path-prefix filters across all source kinds in this module. "generated/**" is always appended to the effective excludes list (additive). "vendor/**" is NOT added automatically — declare it explicitly if needed. Specifying an explicit excludes: list does not replace the generated/** guard; both the user-declared patterns and "generated/**" are applied.
type ManifestSpec ¶
type ManifestSpec struct {
Version string `yaml:"version"`
Modules []ManifestModule `yaml:"modules"`
}
ManifestSpec is the parsed .gocell/manifest.yaml file.
Corresponds to the top-level buf v2 buf.yaml modules: schema:
version: v1
modules:
- path: .
includes: { cells: ["cells/*/cell.yaml"], ... }
excludes: ["generated/**", "vendor/**"]
Version must be "v1". Modules must have at least one entry.
type MetadataSource ¶
type MetadataSource struct {
Path string
Kind SourceKind
CellID string
}
MetadataSource is one YAML file discovered by Locator.
Path is forward-slash relative to the locator root.
CellID is populated for SourceCell / SourceSlice when the locator can derive it from layout (conventional walk path parts, or manifest includes that happen to follow conventional layout). When the locator cannot derive CellID (manifest with non-conventional layout), CellID stays empty — parser will then require slice.yaml to declare belongsToCell explicitly.
To avoid empty CellID in manifest mode, callers have two options:
(a) Read the `id` field from the corresponding cell.yaml (already parsed
into ProjectMeta.Cells by Parser — use ProjectMeta.CellForSlice to
derive it after a full parse pass).
(b) Declare `belongsToCell` explicitly in each slice.yaml; Parser will
propagate that value and governance rules will validate consistency.
type ParamSchema ¶
type ParamSchema struct {
// Ref is a relative path to a shared JSON Schema mixin that single-sources
// the value shape (type/minimum/maximum/minLength/maxLength) for this param.
// It is mutually exclusive with inline type, minimum, maximum, minLength,
// maxLength, and format declarations; resolved at parse time so governance
// (FMT-25) and contractgen see a fully-resolved ParamSchema transparently.
// The Ref field is preserved after resolution for traceability.
Ref string `yaml:"$ref,omitempty" json:"$ref,omitempty"`
Type string `yaml:"type" json:"type"`
Required *bool `yaml:"required,omitempty" json:"required,omitempty"`
Format string `yaml:"format,omitempty" json:"format,omitempty"`
MinLength *int `yaml:"minLength,omitempty" json:"minLength,omitempty"`
MaxLength *int `yaml:"maxLength,omitempty" json:"maxLength,omitempty"`
Minimum *int `yaml:"minimum,omitempty" json:"minimum,omitempty"`
Maximum *int `yaml:"maximum,omitempty" json:"maximum,omitempty"`
}
ParamSchema describes a single HTTP path or query parameter.
Type must be one of the well-known primitive names in ParamTypes. UUID path parameters use `type: "string"` with `format: "uuid"` so governance and runtime parsing rules share one convention.
Required encodes three distinct states, chosen via pointer so YAML `required: false` can be distinguished from an omitted field:
- nil - not declared; for path parameters this is the only legal value (path placeholders are required by definition, see FMT-13); for query parameters it defaults to optional.
- false - explicit opt-out, legal only on query parameters; FMT-13 rejects `required: false` on path parameters.
- true - explicit required declaration, legal on query parameters.
Format is a free-form hint (e.g. "uuid", "date-time", "int64"). It does not influence FMT-13 enforcement today, but static tooling (codegen, OpenAPI export) consumes it. Governance rule FMT-25 exempts `format: "uuid"` from minLength/maxLength enforcement.
MinLength / MaxLength / Minimum / Maximum are *int (not int) for the same three-state reason as Required: nil = "not declared", non-nil = "declared, even if zero". Governance rule FMT-25 treats the facets asymmetrically:
- maxLength and numeric minimum / maximum are REQUIRED for non-uuid string and integer/number params; a missing declaration is a violation. An explicit minimum: 0 is accepted (it rejects negatives — real semantics).
- minLength is OPTIONAL (the lower string bound carries no DoS weight), but when declared it must be >= 1: an explicit no-op minLength: 0 is rejected (string length is always >= 0, so a zero lower bound constrains nothing).
Minimum / Maximum govern both integer and number parameters; use integer-valued bounds in contract.yaml until ParamSchema grows decimal bound fields.
func ResolveParamRef ¶
func ResolveParamRef( paramName, contractDir string, param ParamSchema, readMixin func(contractDir, ref string) ([]byte, error), ) (ParamSchema, error)
ResolveParamRef is the single source of param $ref resolution. It enforces $ref mutual-exclusion, fetches the referenced mixin bytes via readMixin (the caller's IO layer maps contractDir+ref → bytes and owns path-traversal guarding), then back-fills value-shape fields onto param. Both the metadata parser (fs.FS IO) and the contract test harness (fixtureload IO) call this so the resolution semantics live in exactly one place.
Mutual-exclusion is checked BEFORE the read so an author error ($ref alongside inline type/min/max) is reported regardless of whether the mixin file exists.
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser loads and parses all YAML metadata from a project root via a Locator.
The Locator funnel is the single source of truth for filesystem topology — see kernel/metadata/locator.go. Parser does NOT walk the filesystem directly; it consumes []MetadataSource from Locator and dispatches each entry to the matching parseXxx method by SourceKind.
func NewParser ¶
func NewParser(root string, opts ...LocatorOption) *Parser
NewParser creates a Parser that reads from the given filesystem root. The root should point to the project root directory (containing go.mod). Pass LocatorOption to override the auto-detected layout — e.g., WithLocatorMode(LocatorConventional) to lock CI against accidental manifest detection, or WithLocatorMode(LocatorManifest) for an external-repo layout.
func (*Parser) Parse ¶
func (p *Parser) Parse() (*ProjectMeta, error)
Parse walks the real file system via Locator and loads all metadata YAML files. Returns a fully populated ProjectMeta.
type PassCriterion ¶
type PassCriterion struct {
Text string `yaml:"text"`
Mode string `yaml:"mode"` // "auto"|"manual"
CheckRef string `yaml:"checkRef,omitempty"`
}
PassCriterion is a single acceptance criterion within a Journey.
type Position ¶
Position is a 1-based (line, column) reference into a YAML source file. A zero Position (Line==0 or Column==0) means "unknown location".
func Locate ¶
Locate is a best-effort convenience that returns the (Line, Column) of the node at `path`, or the zero Position if the path cannot be resolved. Callers that need a precise error should use Find directly.
The caller is expected to inspect pos.Known() rather than comparing Line against 0 directly: yaml.v3 emits 1-based positions, so a zero Line here unambiguously means "unresolved", never "line 0".
type ProjectMeta ¶
type ProjectMeta struct {
Cells map[string]*CellMeta // keyed by cell ID
Slices map[string]*SliceMeta // keyed by "cellID/sliceID"
Contracts map[string]*ContractMeta // keyed by contract ID
Journeys map[string]*JourneyMeta // keyed by journey ID
Assemblies map[string]*AssemblyMeta // keyed by assembly ID
StatusBoard []StatusBoardEntry
Actors []ActorMeta
// contains filtered or unexported fields
}
ProjectMeta holds all parsed metadata for the entire project.
func (*ProjectMeta) HasFileNodes ¶
func (pm *ProjectMeta) HasFileNodes() bool
HasFileNodes reports whether any file nodes have been stored.
func (*ProjectMeta) Locate ¶
func (pm *ProjectMeta) Locate(file, path string) Position
Locate returns the Position of the YAML value at the given dotted field path inside file. Returns a zero Position when any precondition is missing (nil receiver, no file nodes, file not found, path unresolvable).
func (*ProjectMeta) PrepareFileNode ¶
func (pm *ProjectMeta) PrepareFileNode(file string, yamlSource []byte) error
PrepareFileNode parses yamlSource into a document node and stores it for the given file path. This is the public entry point for test setup — callers never need to import yaml.v3 directly.
type ResolvedSchemaRef ¶
type ResolvedSchemaRef struct {
ContractSchemaRef
AbsPath string
ProjectRel string
}
ResolvedSchemaRef is a schema ref resolved against an absolute project root.
func ResolveContractSchemaRef ¶
func ResolveContractSchemaRef(projectRoot string, c *ContractMeta, ref ContractSchemaRef) (ResolvedSchemaRef, error)
ResolveContractSchemaRef resolves ref relative to c's contract directory and verifies that the target stays inside the ref's declared scope.
func ResolveContractSchemaRefs ¶
func ResolveContractSchemaRefs(projectRoot string, c *ContractMeta) ([]ResolvedSchemaRef, error)
ResolveContractSchemaRefs resolves every non-empty schema reference for c.
type SagaMeta ¶
type SagaMeta struct {
// Timeout is the saga-wide deadline as a Go duration string (e.g. "30s").
// Empty means no saga-level ceiling (per-step timeouts still apply).
Timeout string `yaml:"timeout,omitempty"`
// CompensationOrder selects the rollback walk. v1 limitation: only "reverse"
// is supported (empty is treated as "reverse"); any other value is rejected
// by governance SAGA-CONTRACT-COMPENSATION-ORDER-01. Forward/custom orders
// are not yet modeled.
CompensationOrder string `yaml:"compensationOrder,omitempty"`
// Retries is the saga-wide default retry policy; each step inherits it
// unless the step sets its own.
Retries *SagaRetryMeta `yaml:"retries,omitempty"`
// Steps lists the forward steps in execution order; must be non-empty.
Steps []SagaStepMeta `yaml:"steps"`
}
SagaMeta is the orchestration block of a kind=saga contract.yaml. Steps run in slice order; each step's typed Run input is the previous step's output. The first step takes no typed input — the runtime feeds nil prevState. There is no saga-launch input payload in v1: the orchestrating cell loads the saga's initial business context by looking up domain state keyed by the enrolled Instance.ID (the correlation id).
type SagaRetryMeta ¶
type SagaRetryMeta struct {
MaxAttempts int `yaml:"maxAttempts,omitempty"`
BaseInterval string `yaml:"baseInterval,omitempty"`
MaxInterval string `yaml:"maxInterval,omitempty"`
}
SagaRetryMeta is the declarative form of kernel/saga.RetryPolicy. Intervals are Go duration strings (e.g. "100ms"). Zero / empty fields inherit.
type SagaStepMeta ¶
type SagaStepMeta struct {
Name string `yaml:"name"`
Output string `yaml:"output"`
Timeout string `yaml:"timeout,omitempty"`
Retries *SagaRetryMeta `yaml:"retries,omitempty"`
Compensate *bool `yaml:"compensate,omitempty"`
}
SagaStepMeta is one step inside a SagaMeta. Name must be a valid idutil.SafeID and unique within the saga. Output references a JSON Schema (contract-relative) describing this step's success payload — which becomes the next step's typed input. Compensate defaults to true (the step is rolled back during the Compensating phase); set false for terminal / non-reversible steps.
type SchemaMeta ¶
type SchemaMeta struct {
Primary string `yaml:"primary"`
}
SchemaMeta holds the primary data schema reference for a Cell.
type SchemaRefError ¶
SchemaRefError reports a schema ref resolution failure.
Kind is a free-form descriptive string used only in Error(); no caller compares it. If a caller ever needs to switch on it, type it via the string-typed concept funnel pattern — tracked in #1254.
func (*SchemaRefError) Error ¶
func (e *SchemaRefError) Error() string
type SchemaRefScope ¶
type SchemaRefScope string
SchemaRefScope describes the filesystem boundary used to resolve a schema ref.
const ( // SchemaRefScopeContractDir keeps schemaRefs.* inside the owning contract dir. SchemaRefScopeContractDir SchemaRefScope = "contractDir" // SchemaRefScopeProjectRoot permits HTTP response schemas to point at shared // schemas elsewhere in the repository. SchemaRefScopeProjectRoot SchemaRefScope = "projectRoot" )
type SchemaRefsMeta ¶
type SchemaRefsMeta struct {
Request string `yaml:"request,omitempty" json:"request,omitempty"`
Response string `yaml:"response,omitempty" json:"response,omitempty"`
Payload string `yaml:"payload,omitempty" json:"payload,omitempty"`
Headers string `yaml:"headers,omitempty" json:"headers,omitempty"`
// Extra captures additional string-valued schema ref keys beyond the four
// well-known ones, via yaml:",inline". It is excluded from JSON serialization
// (json:"-") because Go's encoding/json does not support inline maps; callers
// that need JSON output should implement custom MarshalJSON if needed.
Extra map[string]string `yaml:",inline" json:"-"`
}
SchemaRefsMeta holds JSON Schema file references relative to the contract directory. Known keys are request, response, payload, headers; additional string-valued keys are captured in Extra to stay compatible with contract.schema.json's additionalProperties: {"type":"string"}.
type SliceMeta ¶
type SliceMeta struct {
ID string `yaml:"id"`
BelongsToCell string `yaml:"belongsToCell"`
// ConsistencyLevel: "L0"-"L4"; required (parser rejects empty);
// MUST be ≤ cell.ConsistencyLevel. slice.yaml is the SoR for slice
// level (codegen funnel projects to slice_gen.go.sliceMeta);
// inheritance from cell.consistencyLevel is no longer supported.
ConsistencyLevel string `yaml:"consistencyLevel"`
// Lifecycle is the slice's governance maturity phase
// (experimental|candidate|asset|maintenance|retired). Optional; MUST be ≤ the
// parent cell's lifecycle (governance CELL-LIFECYCLE-01). See
// kernel/cellvocab.CellLifecycle.
Lifecycle string `yaml:"lifecycle,omitempty"`
ContractUsages []ContractUsage `yaml:"contractUsages"`
Verify SliceVerifyMeta `yaml:"verify"`
AllowedFiles []string `yaml:"allowedFiles,omitempty"`
Dir string `yaml:"-"` // slice directory segment, set by parser
CellDir string `yaml:"-"` // parent cell directory segment, set by parser
File string `yaml:"-"` // parsed slice.yaml path relative to project root
}
SliceMeta maps to cells/{cell-id}/slices/{slice-id}/slice.yaml.
Dir / CellDir record the filesystem directory segments as walked by the parser — they are the ground truth for strict-mode governance rules (FMT-16, FMT-17, REF-05). Reading these instead of rederiving from the map key prevents a path-vs-id split from fooling the validator (e.g. a kebab directory paired with a no-dash id in slice.yaml).
func (*SliceMeta) Clone ¶
Clone returns a deep copy of s, independently owning every slice and nested struct. Used by tools/codegen-generated SliceMetadata() accessors and by kernel/cell.NewBaseSliceFromMeta to prevent caller mutation from leaking into shared state — mirroring the K8s zz_generated.deepcopy.go pattern.
nil receiver returns nil.
type SliceVerifyMeta ¶
type SliceVerifyMeta struct {
Unit []string `yaml:"unit"`
Contract []string `yaml:"contract"`
Waivers []WaiverMeta `yaml:"waivers"`
}
SliceVerifyMeta holds verification requirements for a Slice.
type SourceKind ¶
type SourceKind int
SourceKind classifies a metadata YAML file by its semantic bucket.
const ( // SourceUnknown is the zero value; never emitted by Locator. SourceUnknown SourceKind = iota // SourceCell marks a cell.yaml file. SourceCell // SourceSlice marks a slice.yaml file. SourceSlice // SourceContract marks a contract.yaml file. SourceContract // SourceJourney marks a journeys/J-*.yaml file. SourceJourney // SourceAssembly marks an assembly.yaml file. SourceAssembly // SourceActors marks the workspace-level actors.yaml singleton. SourceActors // SourceStatusBoard marks the workspace-level journeys/status-board.yaml // singleton. SourceStatusBoard )
func (SourceKind) String ¶
func (k SourceKind) String() string
String returns the kebab-case name of the SourceKind, used in errors and diagnostics.
type StatusBoardEntry ¶
type StatusBoardEntry struct {
JourneyID string `json:"journeyId" yaml:"journeyId"`
State string `json:"state" yaml:"state"`
Risk string `json:"risk" yaml:"risk"`
Blocker string `json:"blocker" yaml:"blocker"`
UpdatedAt string `json:"updatedAt" yaml:"updatedAt"`
}
StatusBoardEntry maps to a single entry in journeys/status-board.yaml.
type WaiverMeta ¶
type WaiverMeta struct {
Contract string `yaml:"contract"`
Owner string `yaml:"owner"`
Reason string `yaml:"reason"`
ExpiresAt string `yaml:"expiresAt"`
}
WaiverMeta records a temporary exemption from a contract verification.
type WebhookInboundMeta ¶
type WebhookInboundMeta struct {
// PathPattern is the HTTP path the platform exposes for receiving webhook
// callbacks from the external source (e.g. "/webhooks/stripe/events").
PathPattern string `yaml:"pathPattern"`
// SourceID is the secret-isolation key identifying the webhook source
// (e.g. "stripe"). Must match the SourceID declared in every
// webhook-receive ContractUsage for this contract. Must satisfy
// ^[a-z][a-z0-9_-]{0,63}$ (aligns with runtime kernel/webhook
// sourceIDPattern, maxLen 64).
SourceID string `yaml:"sourceID"`
}
WebhookInboundMeta holds inbound-specific routing fields for a webhook contract (direction=inbound).
type WebhookPayloadMeta ¶
type WebhookPayloadMeta struct {
// SchemaRef is an optional path to a JSON Schema file (relative to the
// contract.yaml directory) that validates the webhook payload body.
SchemaRef string `yaml:"schemaRef,omitempty"`
// ContentType is the expected MIME type of the webhook payload
// (e.g. "application/json"). Runtime rejects requests with a mismatched
// Content-Type header.
ContentType string `yaml:"contentType,omitempty"`
// MaxBodyBytes is the maximum allowed size (in bytes) of the webhook
// request body. Runtime rejects requests exceeding this limit with 413.
// A value of 0 means no limit (not recommended for production).
MaxBodyBytes int64 `yaml:"maxBodyBytes,omitempty"`
}
WebhookPayloadMeta holds payload constraints for a webhook contract.
type WebhookSignatureMeta ¶
type WebhookSignatureMeta struct {
// Algorithm is the HMAC algorithm used to verify the webhook signature
// (e.g. "hmac-sha256").
Algorithm string `yaml:"algorithm"`
// ToleranceSeconds is the bidirectional time window (in seconds) for
// replay-attack prevention. Requests whose timestamp differs from server
// time by more than this value in either direction are rejected. A value
// of 0 disables time-window checking (not recommended for production).
ToleranceSeconds int `yaml:"toleranceSeconds,omitempty"`
// DeliveryIDHeader is the HTTP header carrying the unique delivery ID
// (e.g. "svix-id"). Used as part of the signed string to prevent
// cross-delivery replay attacks.
DeliveryIDHeader string `yaml:"deliveryIDHeader"`
// TimestampHeader is the HTTP header carrying the Unix timestamp of the
// delivery (e.g. "svix-timestamp"). Must be within ToleranceSeconds of
// server time.
TimestampHeader string `yaml:"timestampHeader"`
// SignatureHeader is the HTTP header carrying the HMAC signature value
// (e.g. "svix-signature").
SignatureHeader string `yaml:"signatureHeader"`
// SignedStringForm is a template for constructing the signed string from
// delivery fields. Template variables: {deliveryID} (value of
// DeliveryIDHeader), {timestamp} (value of TimestampHeader), {body}
// (raw request body). Example: "{deliveryID}.{timestamp}.{body}".
SignedStringForm string `yaml:"signedStringForm"`
}
WebhookSignatureMeta holds HMAC signature verification parameters for an inbound webhook contract.
type WireBundleListener ¶
WireBundleListener mirrors markergen.ListenerSpec.
type WireBundleRoute ¶
type WireBundleRoute struct {
Slice string
Listener string
SubPath string
Method string // empty when marker omitted (defaults to "RegisterRoutes")
}
WireBundleRoute mirrors markergen.RouteSpec (fields relevant to catalog exposure).
type WireBundleSubscribe ¶
WireBundleSubscribe mirrors markergen.SubscribeSpec (fields relevant to catalog).
type WireListenerView ¶
type WireListenerView struct {
Ref string `json:"ref" yaml:"ref"`
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty"`
}
WireListenerView is the catalog wire view of a single listener declaration.
type WireRouteView ¶
type WireRouteView struct {
Slice string `json:"slice" yaml:"slice"`
Listener string `json:"listener" yaml:"listener"`
SubPath string `json:"subPath,omitempty" yaml:"subPath,omitempty"`
Method string `json:"method,omitempty" yaml:"method,omitempty"`
}
WireRouteView is the catalog wire view of a single route mount.
type WireSubscribeView ¶
type WireSubscribeView struct {
Slice string `json:"slice" yaml:"slice"`
Topic string `json:"topic" yaml:"topic"`
Handler string `json:"handler" yaml:"handler"`
Group string `json:"group" yaml:"group"`
}
WireSubscribeView is the catalog wire view of a single event subscription.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package metadatatest provides typed builders for constructing kernel/metadata fixtures in *_test.go files.
|
Package metadatatest provides typed builders for constructing kernel/metadata fixtures in *_test.go files. |