dashboard

package
v3.1.2 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2026 License: MIT Imports: 51 Imported by: 0

Documentation

Overview

Package dashboard serves the Pacto dashboard: a REST API and web UI that aggregates contract and runtime data from multiple sources — Kubernetes (via the operator), OCI registries, local directories, and on-disk cache — into a single view of a service fleet. It computes compliance and readiness, builds dependency graphs, and diffs contract versions.

Index

Constants

View Source
const (
	SectionPresent       = "present"        // has data from an available source
	SectionEmpty         = "empty"          // applicable + source available, but nothing declared
	SectionNotApplicable = "not_applicable" // cannot apply to this contract (e.g. runtime on a reference)
	SectionUnavailable   = "unavailable"    // a source that would supply it was unreachable / not present
)

Section state values for SectionInfo.State.

View Source
const (
	SectionInterfaces      = "interfaces"
	SectionConfigurations  = "configurations"
	SectionPolicies        = "policies"
	SectionCapabilities    = "capabilities"
	SectionDependencies    = "dependencies"
	SectionReadiness       = "readiness"
	SectionDocs            = "docs"
	SectionSBOM            = "sbom"
	SectionRuntime         = "runtime"
	SectionValidation      = "validation"
	SectionObservedRuntime = "observedRuntime"
	SectionRuntimeDiff     = "runtimeDiff"
	SectionResources       = "resources"
	SectionPorts           = "ports"
	SectionEndpoints       = "endpoints"
	SectionConditions      = "conditions"
)

Section ids for SectionMeta (sections embedded in a GetService response). Version history / dependents / cross-refs are fetched separately and carry their own state on the client.

View Source
const (
	VersionPolicyTracking     = "tracking"      // follows latest (no explicit pin)
	VersionPolicyPinnedTag    = "pinned-tag"    // pinned to a specific semver tag
	VersionPolicyPinnedDigest = "pinned-digest" // pinned to an immutable digest
)

Version policy constants describe how a service tracks its contract version.

Variables

This section is empty.

Functions

func APIConfig

func APIConfig() huma.Config

APIConfig returns the Huma configuration for the dashboard API.

func ApplyLock

func ApplyLock(svc *ServiceDetails, l *lock.Lock)

ApplyLock maps a parsed lock onto a ServiceDetails: it sets svc.Lock and pins LockedDigest/LockedVersion on each matching dependency (by name), configuration reference (kind=config, by name) and policy reference (kind=policy, by name). A nil lock leaves svc untouched (backward compatible).

It is exported so out-of-package sources (e.g. the WASM demo's EmbedSource, which reads an embedded pacto.lock rather than one on disk) can surface lock pins through the same code path the on-disk LocalSource uses.

func ClassifyVersions

func ClassifyVersions(ctx context.Context, versions []BundlePair) map[string]string

ClassifyVersions computes the diff classification between consecutive versions in a descending-sorted slice (latest first). Each version (except the oldest) gets a classification relative to its predecessor: "NON_BREAKING", "POTENTIAL_BREAKING", or "BREAKING".

Classification requires materialized bundles; if either bundle in a pair is nil (e.g. not yet fetched from the registry), that pair is skipped and the version receives no classification.

This is a purely derivational function — it depends only on contract bundles and is independent of any specific data source (cache, OCI, etc.).

func CurrentKubeContext

func CurrentKubeContext() string

CurrentKubeContext returns the name of the current kubectl context by reading the kubeconfig file. Returns an empty string if the context cannot be determined.

func EmbeddedUI

func EmbeddedUI() fs.FS

EmbeddedUI returns the embedded filesystem rooted at the ui/ subdirectory. The error from fs.Sub is ignored because the ui/ directory is always present in the embedded FS at compile time.

func ExportConfigSchema

func ExportConfigSchema() ([]byte, error)

ExportConfigSchema generates a JSON Schema for DashboardConfig using Huma's schema registry. The output includes defaults and descriptions from struct tags.

func ExportOpenAPI

func ExportOpenAPI() ([]byte, error)

ExportOpenAPI builds the Huma API with all operations registered and returns the serialized OpenAPI 3.1 specification. This can be called without starting a server.

func RedetectK8s

func RedetectK8s(ctx context.Context, result *DetectResult, namespace string)

RedetectK8s performs a fresh k8s source detection, reading the current kubeconfig from disk. This is used for runtime re-detection when the user switches kubectl contexts without restarting the dashboard.

func RepoProviderFromSource

func RepoProviderFromSource(src DataSource) func(ctx context.Context) []string

RepoProviderFromSource returns a repoProvider callback that discovers OCI repos by querying a DataSource for resolvedRef / imageRef fields. Use this to wire k8s-discovered repos into OCI background scanning.

Types

type AggregatedService

type AggregatedService struct {
	Name    string              `json:"name"`
	Sources []ServiceSourceData `json:"sources"`

	// Merged is the priority-merged view: k8s for runtime, oci for versions, local for in-progress.
	Merged *ServiceDetails `json:"merged"`
}

AggregatedService groups data for the same service across multiple sources.

type BundlePair

type BundlePair struct {
	Tag    string
	Bundle *contract.Bundle
}

BundlePair associates a version tag with its parsed bundle for classification.

type CRDDiscovery

type CRDDiscovery struct {
	Found        bool
	Group        string
	Versions     []string
	Version      string // preferred or first version
	ResourceName string
}

CRDDiscovery holds the result of discovering the Pacto CRD on the cluster.

type Cache

type Cache interface {
	Get(key string) (any, bool)
	Set(key string, value any, ttl time.Duration)
	InvalidateAll()
}

Cache defines the interface for a generic key-value cache.

func NewMemoryCache

func NewMemoryCache() Cache

NewMemoryCache creates a new bounded in-memory cache.

type CacheDiagnostics

type CacheDiagnostics struct {
	CacheDir     string `json:"cacheDir"`
	Exists       bool   `json:"exists"`
	OCIDirExists bool   `json:"ociDirExists"`
	ServiceCount int    `json:"serviceCount"`
	VersionCount int    `json:"versionCount"`
	Error        string `json:"error,omitempty"`
}

CacheDiagnostics contains OCI disk cache detection details.

type CacheSource

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

CacheSource implements DataSource by reading materialized OCI bundles from the on-disk cache at ~/.cache/pacto/oci/. It is NOT a public data source — it exists solely as an internal backing store for OCISource, providing contract hash, classification, and createdAt enrichment from previously pulled bundles. It must never appear as a named source in the API or UI.

When no live OCI registry is configured, ActiveSources() maps CacheSource under the "oci" key so previously cached data is still available.

The cache layout is: <cacheDir>/<repo>/<tag>/bundle.tar.gz e.g. ~/.cache/pacto/oci/ghcr.io/org/service/1.0.0/bundle.tar.gz

func NewCacheSource

func NewCacheSource(cacheDir string) *CacheSource

NewCacheSource scans the OCI cache directory for existing bundles. If the directory doesn't exist or contains no bundles, it returns a source that reports zero services.

func (*CacheSource) GetDiff

func (s *CacheSource) GetDiff(ctx context.Context, a, b Ref) (*DiffResult, error)

GetDiff compares two versions read from the on-disk OCI cache, erroring if either version is not cached.

func (*CacheSource) GetService

func (s *CacheSource) GetService(_ context.Context, name string) (*ServiceDetails, error)

GetService returns details for the latest cached version of name from the on-disk OCI cache, or an error if it is not cached.

func (*CacheSource) GetServiceVersion

func (s *CacheSource) GetServiceVersion(_ context.Context, ref Ref) (*ServiceDetails, error)

GetServiceVersion returns details for a specific cached version from the on-disk OCI cache, or an error if that version is not cached.

func (*CacheSource) GetVersions

func (s *CacheSource) GetVersions(ctx context.Context, name string) ([]Version, error)

GetVersions returns all cached versions of name (latest first) with contract hash, classification, and the on-disk materialization time as createdAt.

func (*CacheSource) ListServices

func (s *CacheSource) ListServices(_ context.Context) ([]Service, error)

ListServices returns one entry per service found in the on-disk OCI cache, using each service's latest cached version, sorted by name.

func (*CacheSource) Rescan

func (s *CacheSource) Rescan()

Rescan re-walks the cache directory and updates the in-memory index. This must be called after new bundles are cached (e.g. after resolve or fetch-all-versions) so they become visible as first-class cached artifacts. The freshly built index is swapped in under the write lock so concurrent readers never observe a partially populated map.

func (*CacheSource) ServiceCount

func (s *CacheSource) ServiceCount() int

ServiceCount returns the number of discovered services.

func (*CacheSource) VersionCount

func (s *CacheSource) VersionCount() int

VersionCount returns the total number of cached bundle versions.

type CachedDataSource

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

CachedDataSource wraps a DataSource with an in-memory cache layer. The prefix scopes cache keys so that multiple CachedDataSource instances sharing the same Cache do not collide (e.g. k8s vs cache vs oci).

func NewCachedDataSource

func NewCachedDataSource(source DataSource, cache Cache, ttl time.Duration, prefix string) *CachedDataSource

NewCachedDataSource wraps the given source with caching. prefix must be unique per source type when sharing a Cache instance. ttl controls how long entries are cached before re-fetching.

func (*CachedDataSource) GetDiff

func (c *CachedDataSource) GetDiff(ctx context.Context, a, b Ref) (*DiffResult, error)

GetDiff returns the wrapped source's diff between a and b, served from cache within the TTL and otherwise computed and cached.

func (*CachedDataSource) GetService

func (c *CachedDataSource) GetService(ctx context.Context, name string) (*ServiceDetails, error)

GetService returns the wrapped source's details for name, served from cache within the TTL and otherwise fetched and cached.

func (*CachedDataSource) GetServiceVersion

func (c *CachedDataSource) GetServiceVersion(ctx context.Context, ref Ref) (*ServiceDetails, error)

GetServiceVersion returns the wrapped source's details for a specific ref, served from cache within the TTL and otherwise fetched and cached.

func (*CachedDataSource) GetVersions

func (c *CachedDataSource) GetVersions(ctx context.Context, name string) ([]Version, error)

GetVersions returns the wrapped source's version history for name, served from cache within the TTL and otherwise fetched and cached.

func (*CachedDataSource) ListServices

func (c *CachedDataSource) ListServices(ctx context.Context) ([]Service, error)

ListServices returns the wrapped source's service list, served from cache within the TTL and otherwise fetched and cached.

type CapabilityInfo

type CapabilityInfo struct {
	Type string `json:"type"`
	Ref  string `json:"ref,omitempty"`
}

CapabilityInfo describes a service capability.

type CapabilityTool

type CapabilityTool struct {
	Name     string `json:"name"`
	Method   string `json:"method"`
	Path     string `json:"path"`
	Summary  string `json:"summary,omitempty"`
	Mutating bool   `json:"mutating"`
}

CapabilityTool is an agent-invocable operation derived from an OpenAPI operation in an http interface. Mutating has no omitempty: false is a meaningful, displayed value (read-only operations).

type ChecksSummary

type ChecksSummary struct {
	Total  int `json:"total"`
	Passed int `json:"passed"`
	Failed int `json:"failed"`
}

ChecksSummary holds pass/fail check counts.

type ComplianceCounts

type ComplianceCounts struct {
	Total    int `json:"total"`
	Passed   int `json:"passed"`
	Failed   int `json:"failed"`
	Errors   int `json:"errors"`
	Warnings int `json:"warnings"`
	Unknown  int `json:"unknown"`
	// Secondary metrics per B-2 ruling (informational, distinguish failure from uncertainty).
	RuntimeEvaluated int `json:"runtimeEvaluated"` // Compliant + Warning + NonCompliant + Unknown
	Conclusive       int `json:"conclusive"`       // Compliant + Warning + NonCompliant
}

ComplianceCounts summarizes validation check results.

type ComplianceInfo

type ComplianceInfo struct {
	Status  ComplianceStatus  `json:"status"`
	Score   *int              `json:"score"`
	Summary *ComplianceCounts `json:"summary,omitempty"`
}

ComplianceInfo holds the computed compliance state for a service.

func ComputeCompliance

func ComputeCompliance(cs ContractStatus, conditions []Condition) *ComplianceInfo

ComputeCompliance computes the compliance status and score from contract status and conditions.

type ComplianceStatus

type ComplianceStatus string

ComplianceStatus represents the overall compliance assessment of a service.

const (
	ComplianceOK        ComplianceStatus = "OK"
	ComplianceWarning   ComplianceStatus = "WARNING"
	ComplianceError     ComplianceStatus = "ERROR"
	ComplianceReference ComplianceStatus = "REFERENCE"
	ComplianceUnknown   ComplianceStatus = "UNKNOWN"
)

type Condition

type Condition struct {
	Type              string `json:"type"`
	Status            string `json:"status"` // "True", "False", "Unknown"
	Reason            string `json:"reason,omitempty"`
	Message           string `json:"message,omitempty"`
	Severity          string `json:"severity,omitempty"` // "error", "warning"
	LastTransitionAgo string `json:"lastTransitionAgo,omitempty"`
}

Condition represents a reconciliation condition (mirroring operator CRD status.conditions).

type ConfigValue

type ConfigValue = schemax.Property

ConfigValue is a flattened key/value/type entry for display. It aliases schemax.Property so the dashboard and operator share one representation.

type ConfigurationInfo

type ConfigurationInfo struct {
	Name       string        `json:"name,omitempty"`
	HasSchema  bool          `json:"hasSchema"`
	Schema     string        `json:"schema,omitempty"`
	Ref        string        `json:"ref,omitempty"`
	ValueKeys  []string      `json:"valueKeys,omitempty"`
	SecretKeys []string      `json:"secretKeys,omitempty"`
	Values     []ConfigValue `json:"values,omitempty"`
	// ValuesAreCurrent is set when a remote ref's values were resolved from the
	// referenced service's CURRENT version (because the ref is not version-pinned,
	// or the pinned version was unavailable) while displaying a historical version.
	// The UI labels such values "(current)" to flag the temporal mismatch.
	ValuesAreCurrent bool `json:"valuesAreCurrent,omitempty"`
	// Lock pins, populated from pacto.lock references (kind=config) when present.
	LockedDigest  string `json:"lockedDigest,omitempty"`
	LockedVersion string `json:"lockedVersion,omitempty"`
}

ConfigurationInfo describes a single configuration scope.

type ContractStatus

type ContractStatus string

ContractStatus represents the contract compliance status of a service. It reflects whether the service's contract/bundle is valid and compliant, NOT the runtime health of the service itself.

const (
	StatusCompliant    ContractStatus = "Compliant"
	StatusWarning      ContractStatus = "Warning"
	StatusNonCompliant ContractStatus = "NonCompliant"
	StatusUnknown      ContractStatus = "Unknown"
	StatusReference    ContractStatus = "Reference"
	StatusInvalid      ContractStatus = "Invalid"
	StatusNotEvaluated ContractStatus = "NotEvaluated"
)

func NormalizeContractStatus

func NormalizeContractStatus(s ContractStatus) ContractStatus

NormalizeContractStatus maps any non-standard status to one of the canonical contract statuses.

type CrossReference

type CrossReference struct {
	Name           string `json:"name"`
	RefType        string `json:"refType"` // "config" or "policy"
	Ref            string `json:"ref,omitempty"`
	ContractStatus string `json:"contractStatus,omitempty"`
}

CrossReference describes a cross-reference between services via config/policy refs.

type CrossReferences

type CrossReferences struct {
	References   []CrossReference `json:"references"`
	ReferencedBy []CrossReference `json:"referencedBy"`
}

CrossReferences contains both outgoing references and incoming "referenced by".

type DashboardConfig

type DashboardConfig struct {
	Host             string `json:"PACTO_DASHBOARD_HOST" default:"127.0.0.1" doc:"Bind address for the server"`
	Port             int    `json:"PACTO_DASHBOARD_PORT" default:"3000" doc:"HTTP server port"`
	Namespace        string `json:"PACTO_DASHBOARD_NAMESPACE,omitempty" doc:"Kubernetes namespace filter (empty = all)"`
	Repo             string `json:"PACTO_DASHBOARD_REPO,omitempty" doc:"Comma-separated OCI repositories to scan"`
	Diagnostics      bool   `json:"PACTO_DASHBOARD_DIAGNOSTICS" default:"false" doc:"Enable source diagnostics panel"`
	CacheDir         string `json:"PACTO_CACHE_DIR,omitempty" doc:"OCI bundle cache directory (default: ~/.cache/pacto/oci)"`
	NoCache          bool   `json:"PACTO_NO_CACHE" default:"false" doc:"Disable OCI bundle caching"`
	NoUpdateCheck    bool   `json:"PACTO_NO_UPDATE_CHECK" default:"false" doc:"Disable update checks"`
	RegistryUsername string `json:"PACTO_REGISTRY_USERNAME,omitempty" doc:"Registry authentication username"`
	RegistryPassword string `json:"PACTO_REGISTRY_PASSWORD,omitempty" doc:"Registry authentication password"`
	RegistryToken    string `json:"PACTO_REGISTRY_TOKEN,omitempty" doc:"Registry authentication token"`
}

DashboardConfig describes the environment-variable-based configuration for the dashboard server. Huma's schema registry generates a JSON Schema from this struct, including defaults and descriptions via struct tags.

type DataSource

type DataSource interface {
	ListServices(ctx context.Context) ([]Service, error)
	GetService(ctx context.Context, name string) (*ServiceDetails, error)
	GetServiceVersion(ctx context.Context, ref Ref) (*ServiceDetails, error)
	GetVersions(ctx context.Context, name string) ([]Version, error)
	GetDiff(ctx context.Context, a, b Ref) (*DiffResult, error)
}

DataSource is the core abstraction for loading service data into the dashboard. Implementations exist for Kubernetes (CRD status), OCI registries, and local filesystem.

type DependencyGraph

type DependencyGraph struct {
	Root      *GraphNode `json:"root"`
	Cycles    [][]string `json:"cycles,omitempty"`
	Conflicts []string   `json:"conflicts,omitempty"`
}

DependencyGraph holds a resolved dependency tree for visualization.

func GraphFromResult

func GraphFromResult(r *graph.Result) *DependencyGraph

GraphFromResult maps the graph resolver's Result to the dashboard DependencyGraph.

type DependencyInfo

type DependencyInfo struct {
	Name          string `json:"name"`
	Ref           string `json:"ref"`
	Required      bool   `json:"required"`
	Compatibility string `json:"compatibility,omitempty"`
	// Lock pins, populated from pacto.lock when present (local source only).
	LockedDigest  string `json:"lockedDigest,omitempty"`
	LockedVersion string `json:"lockedVersion,omitempty"`
	// DriftStatus compares the locked digest against the dependency target's
	// runtime digest: "locked", "drift", "unlocked", "unknown". Empty when not computed.
	DriftStatus string `json:"driftStatus,omitempty"`
}

DependencyInfo describes a declared dependency.

type DependentInfo

type DependentInfo struct {
	Name           string `json:"name"`
	Version        string `json:"version,omitempty"`
	ContractStatus string `json:"contractStatus,omitempty"`
	Required       bool   `json:"required"`
	Compatibility  string `json:"compatibility,omitempty"`
}

DependentInfo describes a service that depends on another service.

type DetectOptions

type DetectOptions struct {
	Dir       string          // working directory for local detection
	Namespace string          // k8s namespace (empty = all namespaces)
	Repos     []string        // OCI repositories to scan
	Store     oci.BundleStore // OCI client (may be nil)
	CacheDir  string          // OCI cache directory (defaults to ~/.cache/pacto/oci)
	NoCache   bool            // disable the cache-based OCI source entirely
}

DetectOptions configures source auto-detection.

type DetectResult

type DetectResult struct {
	Sources []SourceInfo
	Local   *LocalSource
	OCI     *OCISource
	K8s     *K8sSource
	Cache   *CacheSource // internal: used by OCI for offline access, not a public source

	// Diagnostics collected during detection.
	Diagnostics *SourceDiagnostics
}

DetectResult holds the outcome of source detection.

func DetectSources

func DetectSources(ctx context.Context, opts DetectOptions) *DetectResult

DetectSources probes for available data sources and returns all that are reachable.

func (*DetectResult) ActiveSources

func (r *DetectResult) ActiveSources() map[string]DataSource

ActiveSources returns the DataSource instances that were successfully detected. When a live OCI registry is configured it is exposed as "oci"; when only the on-disk cache is available it is exposed under its own "cache" key (an offline baseline of previously pulled bundles) so the UI can label and date it distinctly rather than presenting stale data as a live registry pull.

func (*DetectResult) AllSources

func (r *DetectResult) AllSources() map[string]DataSource

AllSources returns all public DataSource instances. Cache is internal to OCI and never exposed as a separate named source.

func (*DetectResult) EnrichFromK8s

func (r *DetectResult) EnrichFromK8s(ctx context.Context, store oci.BundleStore, cacheDir string)

EnrichFromK8s discovers OCI repository references from K8s service statuses and creates an OCI source when no explicit OCI repos were configured. This enables the dashboard to load full contract bundles from OCI even when started in K8s-only mode (e.g. operator-served dashboard).

It also ensures a CacheSource exists so that OCI-pulled bundles can be rescanned at runtime (post-resolve, post-fetch-all).

type DiffChange

type DiffChange struct {
	Path           string `json:"path"`
	Type           string `json:"type"` // added, removed, modified
	OldValue       any    `json:"oldValue,omitempty"`
	NewValue       any    `json:"newValue,omitempty"`
	Classification string `json:"classification"`
	Reason         string `json:"reason,omitempty"`
}

DiffChange represents a single detected change.

type DiffResult

type DiffResult struct {
	From           Ref          `json:"from"`
	To             Ref          `json:"to"`
	Classification string       `json:"classification"` // NON_BREAKING, POTENTIAL_BREAKING, BREAKING
	Changes        []DiffChange `json:"changes"`
}

DiffResult holds the output of comparing two service versions.

func ComputeDiff

func ComputeDiff(ctx context.Context, from, to Ref, oldBundle, newBundle *contract.Bundle) *DiffResult

ComputeDiff runs the diff engine on two bundles and returns a dashboard DiffResult.

func DiffResultFromEngine

func DiffResultFromEngine(from, to Ref, r *diff.Result) *DiffResult

DiffResultFromEngine maps the diff engine's Result to the dashboard DiffResult.

type DocInfo

type DocInfo struct {
	Path      string `json:"path"`  // bundle-relative, e.g. docs/runbooks/payment-api.md
	Title     string `json:"title"` // first H1, else humanized filename
	Content   string `json:"content"`
	Truncated bool   `json:"truncated,omitempty"`
}

DocInfo is one in-bundle Markdown document (docs/**/*.md) surfaced in the dashboard.

type EndpointStatus

type EndpointStatus struct {
	Interface  string `json:"interface"`
	Type       string `json:"type,omitempty"` // "health", "metrics", or empty
	URL        string `json:"url,omitempty"`
	Healthy    *bool  `json:"healthy,omitempty"`
	StatusCode *int   `json:"statusCode,omitempty"`
	LatencyMs  *int64 `json:"latencyMs,omitempty"`
	Error      string `json:"error,omitempty"`
	Message    string `json:"message,omitempty"`
}

EndpointStatus describes the observed status of a service endpoint.

type EvaluationCoverage

type EvaluationCoverage struct {
	Evaluated int `json:"evaluated"` // required assertions with Outcome == Observed
	Required  int `json:"required"`  // total required assertions
}

EvaluationCoverage reports how many required assertions were evaluated.

type GlobalGraph

type GlobalGraph struct {
	Nodes []GraphNodeData `json:"nodes"`
}

GlobalGraph is the full graph of all services and their dependency edges.

func GlobalGraphFromResult

func GlobalGraphFromResult(gr *depgraph.Result, root *ServiceDetails) *GlobalGraph

GlobalGraphFromResult builds the flat D3 GlobalGraph (as served at /api/graph) from a resolved dependency graph, for the offline single-service doc export. root is the already-built snapshot for gr.Root (carries real status + lock pins); dependency nodes are built from their resolved contracts (status Unknown, since a fetched dependency node carries no RawYAML to validate).

type GraphEdge

type GraphEdge struct {
	Ref           string     `json:"ref"`
	Required      bool       `json:"required"`
	Compatibility string     `json:"compatibility,omitempty"`
	Error         string     `json:"error,omitempty"`
	Shared        bool       `json:"shared,omitempty"`
	Node          *GraphNode `json:"node,omitempty"`
	// Lock pins from pacto.lock, carried on the edge for the dependency tree view.
	LockedDigest  string `json:"lockedDigest,omitempty"`
	LockedVersion string `json:"lockedVersion,omitempty"`
	DriftStatus   string `json:"driftStatus,omitempty"`
}

GraphEdge represents an edge in the dependency graph.

type GraphEdgeData

type GraphEdgeData struct {
	TargetID      string `json:"targetId"`
	TargetName    string `json:"targetName"`
	Required      bool   `json:"required"`
	Compatibility string `json:"compatibility,omitempty"`
	Resolved      bool   `json:"resolved"`
	Type          string `json:"type"` // "dependency" or "reference"
	// Lock pins from pacto.lock, carried on dependency edges when a lockfile is present.
	LockedDigest  string `json:"lockedDigest,omitempty"`
	LockedVersion string `json:"lockedVersion,omitempty"`
	DriftStatus   string `json:"driftStatus,omitempty"`
}

GraphEdgeData is a flat representation of a graph edge for D3.

type GraphNode

type GraphNode struct {
	Name         string      `json:"name"`
	Version      string      `json:"version"`
	Ref          string      `json:"ref,omitempty"`
	Dependencies []GraphEdge `json:"dependencies,omitempty"`
}

GraphNode represents a node in the dependency graph.

type GraphNodeData

type GraphNodeData struct {
	ID          string          `json:"id"`
	ServiceName string          `json:"serviceName"`
	Status      string          `json:"status"`
	Version     string          `json:"version,omitempty"`
	Source      string          `json:"source,omitempty"`
	Reason      string          `json:"reason,omitempty"` // why unresolved: non_oci_ref, auth_failed, no_semver_tags, not_found, pull_failed, discovering
	Edges       []GraphEdgeData `json:"edges,omitempty"`
}

GraphNodeData is a flat representation of a graph node for the D3 visualization.

type Insight

type Insight struct {
	Severity    string `json:"severity"` // "critical", "warning", "info"
	Title       string `json:"title"`
	Description string `json:"description,omitempty"`
}

Insight represents a diagnostic finding (critical, warning, info).

type InterfaceEndpoint

type InterfaceEndpoint struct {
	Method  string `json:"method"`
	Path    string `json:"path"`
	Summary string `json:"summary,omitempty"`
}

InterfaceEndpoint is a single API endpoint parsed from an OpenAPI spec.

type InterfaceInfo

type InterfaceInfo struct {
	Name            string              `json:"name"`
	Type            string              `json:"type"` // openapi, asyncapi, grpc
	Visibility      string              `json:"visibility,omitempty"`
	HasContractFile bool                `json:"hasContractFile,omitempty"`
	ContractFile    string              `json:"contractFile,omitempty"`
	ContractContent string              `json:"contractContent,omitempty"`
	Endpoints       []InterfaceEndpoint `json:"endpoints,omitempty"`
}

InterfaceInfo describes a single service interface.

type K8sClient

type K8sClient interface {
	// Probe checks if the Kubernetes cluster is reachable.
	Probe(ctx context.Context) error
	// DiscoverCRD discovers the Pacto CRD group, version, and resource name.
	DiscoverCRD(ctx context.Context) (*CRDDiscovery, error)
	// ListJSON returns the raw JSON of all Pacto CRD resources.
	ListJSON(ctx context.Context, resource, namespace string) ([]byte, error)
	// GetJSON returns the raw JSON of a single Pacto CRD resource by name.
	GetJSON(ctx context.Context, resource, namespace, name string) ([]byte, error)
	// CountResources returns the number of Pacto CRD resources.
	CountResources(ctx context.Context, resource, namespace string) (int, error)
}

K8sClient abstracts Kubernetes API operations for the dashboard.

type K8sDiagnostics

type K8sDiagnostics struct {
	ClientConfigured bool     `json:"clientConfigured"`
	KubeconfigPath   string   `json:"kubeconfigPath,omitempty"`
	ClusterReachable bool     `json:"clusterReachable"`
	CRDExists        bool     `json:"crdExists"`
	Namespace        string   `json:"namespace"`
	AllNamespaces    bool     `json:"allNamespaces"`
	ResourceCount    int      `json:"resourceCount"`
	DetectedGroup    string   `json:"detectedGroup,omitempty"`
	DetectedVersions []string `json:"detectedVersions,omitempty"`
	ChosenVersion    string   `json:"chosenVersion,omitempty"`
	ResourceName     string   `json:"resourceName,omitempty"`
	Error            string   `json:"error,omitempty"`
}

K8sDiagnostics contains K8s source detection details.

type K8sSource

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

K8sSource implements DataSource by reading Pacto CRD status from a Kubernetes cluster. It uses k8s.io/client-go to communicate with the Kubernetes API server.

func NewK8sSource

func NewK8sSource(client K8sClient, namespace, resourceName string) *K8sSource

NewK8sSource creates a data source backed by Kubernetes CRDs. namespace may be empty to use all namespaces. resourceName is the CRD resource name (e.g. "pactos"), discovered dynamically.

func (*K8sSource) GetDiff

func (s *K8sSource) GetDiff(_ context.Context, _, _ Ref) (*DiffResult, error)

GetDiff is intentionally unsupported for the k8s source: it observes only the single currently-deployed revision per service, so there is no version history to diff. The diff endpoint uses the OCI/local sources (which carry history) instead; this returns an error so an unsupported call surfaces explicitly rather than as an empty diff.

func (*K8sSource) GetService

func (s *K8sSource) GetService(ctx context.Context, name string) (*ServiceDetails, error)

GetService returns details built from the named Pacto CRD's status in the cluster, or an error if no such resource exists.

func (*K8sSource) GetServiceVersion

func (s *K8sSource) GetServiceVersion(_ context.Context, _ Ref) (*ServiceDetails, error)

GetServiceVersion is unsupported for the k8s source: it observes only the single currently-deployed revision per service, so there is no version history to fetch. Per-version detail comes from the OCI/local sources.

func (*K8sSource) GetVersions

func (s *K8sSource) GetVersions(ctx context.Context, name string) ([]Version, error)

GetVersions returns the version history for name from PactoRevision CRDs in the cluster, sorted descending by semver.

func (*K8sSource) ListServices

func (s *K8sSource) ListServices(ctx context.Context) ([]Service, error)

ListServices returns one entry per Pacto CRD found in the cluster, built from each resource's status, sorted by name.

type LocalDiagnostics

type LocalDiagnostics struct {
	Dir            string `json:"dir"`
	PactoYamlFound bool   `json:"pactoYamlFound"`
	FoundIn        string `json:"foundIn,omitempty"`
	Error          string `json:"error,omitempty"`
}

LocalDiagnostics contains local source detection details.

type LocalSource

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

LocalSource implements DataSource by reading from the local filesystem. It scans a root directory for subdirectories containing pacto.yaml files.

func NewLocalSource

func NewLocalSource(root string) *LocalSource

NewLocalSource creates a data source backed by local filesystem directories. root is the directory to scan for service subdirectories.

func (*LocalSource) GetDiff

func (s *LocalSource) GetDiff(ctx context.Context, a, b Ref) (*DiffResult, error)

GetDiff compares the on-disk bundles for a and b found under the root directory, erroring if either service is not present locally.

func (*LocalSource) GetService

func (s *LocalSource) GetService(_ context.Context, name string) (*ServiceDetails, error)

GetService returns details for the named bundle found under the root directory, or an error if no bundle with that service name exists.

func (*LocalSource) GetServiceVersion

func (s *LocalSource) GetServiceVersion(_ context.Context, ref Ref) (*ServiceDetails, error)

GetServiceVersion returns details for the local bundle only when its on-disk version matches ref.Version; otherwise it returns an error.

func (*LocalSource) GetVersions

func (s *LocalSource) GetVersions(_ context.Context, name string) ([]Version, error)

GetVersions returns the single on-disk version of name, since the local source only knows the bundle currently present in the directory.

func (*LocalSource) ListServices

func (s *LocalSource) ListServices(_ context.Context) ([]Service, error)

ListServices returns one entry per service discovered by scanning the root directory for pacto.yaml bundles (first match per name wins), sorted by name.

type LockDepInfo

type LockDepInfo struct {
	Name        string `json:"name"`
	Source      string `json:"source,omitempty"`
	Ref         string `json:"ref,omitempty"`
	Path        string `json:"path,omitempty"`
	Constraint  string `json:"constraint,omitempty"`
	Version     string `json:"version,omitempty"`
	Digest      string `json:"digest,omitempty"`
	ContentHash string `json:"contentHash,omitempty"`
}

LockDepInfo is one resolved dependency entry from pacto.lock.

type LockInfo

type LockInfo struct {
	Present      bool          `json:"present"`
	RootDigest   string        `json:"rootDigest,omitempty"`
	Dependencies []LockDepInfo `json:"dependencies,omitempty"`
	References   []LockRefInfo `json:"references,omitempty"`
}

LockInfo surfaces pacto.lock content for the service detail view. It is set only by sources that can read the committed lockfile from disk (local).

type LockRefInfo

type LockRefInfo struct {
	Kind        string `json:"kind"`
	Name        string `json:"name"`
	Source      string `json:"source,omitempty"`
	Ref         string `json:"ref,omitempty"`
	Path        string `json:"path,omitempty"`
	Version     string `json:"version,omitempty"`
	Digest      string `json:"digest,omitempty"`
	ContentHash string `json:"contentHash,omitempty"`
}

LockRefInfo is one resolved config/policy reference from pacto.lock. Config/policy references carry no compatibility constraint (unlike dependencies), so there is no Constraint field.

type OCIDiagnostics

type OCIDiagnostics struct {
	StoreConfigured bool     `json:"storeConfigured"`
	Repos           []string `json:"repos,omitempty"`
	Error           string   `json:"error,omitempty"`
}

OCIDiagnostics contains OCI registry source detection details.

type OCISource

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

OCISource implements DataSource by pulling bundles from an OCI registry. It discovers the full dependency tree progressively in the background, returning whatever has been discovered so far on each ListServices call.

func NewOCISource

func NewOCISource(store oci.BundleStore, repos []string) *OCISource

NewOCISource creates a data source backed by OCI registries. repos is a list of OCI repository references (e.g., "ghcr.io/org/service").

func (*OCISource) Close

func (s *OCISource) Close()

Close stops the background discovery loop and waits for it to exit. It is safe to call multiple times and safe to call when discovery never started (e.g. ListServices was never invoked). Wiring this into the server shutdown path ensures the detached discovery goroutine does not outlive the server.

func (*OCISource) Discovering

func (s *OCISource) Discovering() bool

Discovering reports whether background dependency discovery is still running.

func (*OCISource) GetDiff

func (s *OCISource) GetDiff(ctx context.Context, a, b Ref) (*DiffResult, error)

GetDiff compares two versions by pulling each from the OCI registry, erroring if either ref cannot be pulled.

func (*OCISource) GetService

func (s *OCISource) GetService(ctx context.Context, name string) (*ServiceDetails, error)

GetService returns details for name by pulling its latest-tagged bundle from the OCI registry, or an error if the service repo cannot be resolved.

func (*OCISource) GetServiceVersion

func (s *OCISource) GetServiceVersion(ctx context.Context, ref Ref) (*ServiceDetails, error)

GetServiceVersion returns details for a specific ref by pulling that exact version's bundle from the OCI registry.

func (*OCISource) GetVersions

func (s *OCISource) GetVersions(ctx context.Context, name string) ([]Version, error)

GetVersions returns the semver tags for name from the OCI registry (latest first), enriched with hash, createdAt, and classification from the internal disk cache when available.

func (*OCISource) ListServices

func (s *OCISource) ListServices(ctx context.Context) ([]Service, error)

ListServices returns the services discovered so far from the OCI registry, kicking off background discovery on first call and returning immediately (initially empty) while it proceeds; results are sorted by name.

func (*OCISource) RescanCache

func (s *OCISource) RescanCache()

RescanCache triggers a rescan of the internal CacheSource, picking up any newly materialized bundles on disk.

func (*OCISource) SetCache

func (s *OCISource) SetCache(cs *CacheSource)

SetCache wires an internal CacheSource so that GetVersions can enrich bare tag listings with hash, createdAt, and classification data from materialized bundles on disk. The cache is never exposed as a public source.

func (*OCISource) SetOnDiscover

func (s *OCISource) SetOnDiscover(fn func())

SetOnDiscover sets a callback invoked each time a new service is discovered in the background. Typically used to invalidate caches so the new data surfaces immediately on the next API call.

func (*OCISource) SetRepoProvider

func (s *OCISource) SetRepoProvider(fn func(ctx context.Context) []string)

SetRepoProvider sets a callback invoked during each background discovery cycle to obtain additional OCI repos. This allows k8s-discovered repos to feed into OCI scanning even after the initial startup enrichment.

func (*OCISource) UnresolvedReason

func (s *OCISource) UnresolvedReason(depRef string) string

UnresolvedReason returns why a dependency ref could not be resolved during OCI background discovery. Returns "" if the ref is not an OCI ref, was successfully resolved, or discovery is still in progress for this repo.

type ObservedRuntime

type ObservedRuntime struct {
	WorkloadKind                  string   `json:"workloadKind,omitempty"`
	DeploymentStrategy            string   `json:"deploymentStrategy,omitempty"`
	PodManagementPolicy           string   `json:"podManagementPolicy,omitempty"`
	TerminationGracePeriodSeconds *int     `json:"terminationGracePeriodSeconds,omitempty"`
	ContainerImages               []string `json:"containerImages,omitempty"`
	HasPVC                        *bool    `json:"hasPVC,omitempty"`
	HasEmptyDir                   *bool    `json:"hasEmptyDir,omitempty"`
	HealthProbeInitialDelay       *int     `json:"healthProbeInitialDelaySeconds,omitempty"`
}

ObservedRuntime holds runtime state observed by the operator from the cluster.

type PolicyInfo

type PolicyInfo struct {
	Name        string        `json:"name"`
	HasSchema   bool          `json:"hasSchema"`
	Schema      string        `json:"schema,omitempty"`
	Ref         string        `json:"ref,omitempty"`
	Title       string        `json:"title,omitempty"`
	Description string        `json:"description,omitempty"`
	Content     string        `json:"content,omitempty"`
	Values      []ConfigValue `json:"values,omitempty"`
	// ValuesAreCurrent is set when a remote ref's values were resolved from the
	// referenced service's CURRENT version (unpinned ref, or pinned version
	// unavailable) while displaying a historical version. The UI labels such
	// values "(current)" to flag the temporal mismatch.
	ValuesAreCurrent bool `json:"valuesAreCurrent,omitempty"`
	// Lock pins, populated from pacto.lock references (kind=policy) when present.
	LockedDigest  string `json:"lockedDigest,omitempty"`
	LockedVersion string `json:"lockedVersion,omitempty"`
}

PolicyInfo describes an attached policy (JSON Schema constraint).

type PortsInfo

type PortsInfo struct {
	Expected   []int `json:"expected,omitempty"`
	Observed   []int `json:"observed,omitempty"`
	Missing    []int `json:"missing,omitempty"`
	Unexpected []int `json:"unexpected,omitempty"`
}

PortsInfo holds port comparison results.

type ReadinessCheckInfo

type ReadinessCheckInfo struct {
	ID           string `json:"id"`
	Type         string `json:"type"`
	Category     string `json:"category,omitempty"`
	Status       string `json:"status"` // done | partial | not-done | deferred
	Evidence     string `json:"evidence,omitempty"`
	Description  string `json:"description,omitempty"`
	Weight       int    `json:"weight"`
	EarnedWeight int    `json:"earnedWeight"`
	Excluded     bool   `json:"excluded"`
	// DocPath is set when Evidence resolves to an in-bundle document (an entry in
	// ServiceDetails.Docs), so the UI can render it inline. Empty for external evidence.
	DocPath string `json:"docPath,omitempty"`
}

ReadinessCheckInfo is a single derived readiness check for the dashboard.

type ReadinessInfo

type ReadinessInfo struct {
	Score         int     `json:"score"`
	MinScore      int     `json:"minScore"`
	TotalWeight   int     `json:"totalWeight"`
	EarnedWeight  int     `json:"earnedWeight"`
	PartialCredit float64 `json:"partialCredit"`
	Passing       bool    `json:"passing"`
	Expires       string  `json:"expires"`
	Expired       bool    `json:"expired"`
	DaysRemaining *int    `json:"daysRemaining,omitempty"`
	// Status counts use NO omitempty — 0 is a valid value.
	DoneCount     int                     `json:"doneCount"`
	PartialCount  int                     `json:"partialCount"`
	NotDoneCount  int                     `json:"notDoneCount"`
	DeferredCount int                     `json:"deferredCount"`
	Revisions     []ReadinessRevisionInfo `json:"revisions,omitempty"`
	Checks        []ReadinessCheckInfo    `json:"checks"`
}

ReadinessInfo is the derived readiness assessment surfaced in the dashboard.

type ReadinessRevisionInfo

type ReadinessRevisionInfo struct {
	Date        string `json:"date"`
	Version     string `json:"version"`
	Author      string `json:"author"`
	Description string `json:"description"`
}

ReadinessRevisionInfo is a single readiness revision-history entry.

type Ref

type Ref struct {
	Name    string `json:"name"`
	Version string `json:"version"`
	// Source is optional; defaults to the active data source.
	Source string `json:"source,omitempty"`
}

Ref identifies a specific version of a service for diffing.

type ResolvedSource

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

ResolvedSource implements DataSource by combining a contract source (local or OCI/cache) with an optional runtime source (k8s).

Resolution model:

  • Contract: exactly ONE authoritative snapshot per service. local wins over OCI. Cache is internal to OCI (not a separate source).
  • Runtime: k8s enriches with contract status, conditions, endpoints, resources, ports, scaling, insights, checks. Never overrides contract fields.
  • History: merged across all sources, labeled by origin.
  • Diff: only works with real contract bundles (local or OCI/cache).
  • Graph: built from the authoritative contract snapshot only.

func BuildResolvedSource

func BuildResolvedSource(sources map[string]DataSource) *ResolvedSource

BuildResolvedSource creates a ResolvedSource from a map of cached data sources. It automatically separates contract sources (local, oci) from runtime (k8s).

func NewResolvedSource

func NewResolvedSource(contractSources []namedContractSource, runtimeSource DataSource, allSources map[string]DataSource) *ResolvedSource

NewResolvedSource creates a data source with the new resolution model. contractSources: ordered by priority (local first, then oci). runtimeSource: optional k8s source for runtime enrichment. allSources: map of all sources for version history and diff fallback.

func (*ResolvedSource) AddContractSource

func (r *ResolvedSource) AddContractSource(name string, ds DataSource)

AddContractSource registers a new contract data source that participates in service detail resolution and version/diff lookups. Thread-safe via copy-on-write: concurrent readers see a consistent snapshot.

func (*ResolvedSource) AddSource

func (r *ResolvedSource) AddSource(name string, ds DataSource)

AddSource registers a data source for version/diff lookups only (not contract resolution). Thread-safe via copy-on-write.

func (*ResolvedSource) GetAggregated

func (r *ResolvedSource) GetAggregated(ctx context.Context, name string) (*AggregatedService, error)

GetAggregated returns the per-source breakdown for the debug/sources endpoint.

func (*ResolvedSource) GetDiff

func (r *ResolvedSource) GetDiff(ctx context.Context, from, to Ref) (*DiffResult, error)

GetDiff delegates to the contract bundle sources (the from.Source hint if given, else oci/local/cache in order); k8s is excluded as it has no history.

func (*ResolvedSource) GetService

func (r *ResolvedSource) GetService(ctx context.Context, name string) (*ServiceDetails, error)

GetService resolves the single authoritative contract snapshot (highest-priority contract source) and enriches it with k8s runtime data, erroring if name is found in no source.

func (*ResolvedSource) GetServiceVersion

func (r *ResolvedSource) GetServiceVersion(ctx context.Context, ref Ref) (*ServiceDetails, error)

GetServiceVersion delegates to the contract bundle sources (the ref.Source hint if given, else oci/local/cache in order) for the requested version.

func (*ResolvedSource) GetSource

func (r *ResolvedSource) GetSource(name string) DataSource

GetSource returns the DataSource registered under the given name, or nil.

func (*ResolvedSource) GetVersions

func (r *ResolvedSource) GetVersions(ctx context.Context, name string) ([]Version, error)

GetVersions merges version history for name across all sources (k8s, oci, local, cache), enriching duplicates by version, sorted descending by semver.

func (*ResolvedSource) HasSource

func (r *ResolvedSource) HasSource(name string) bool

HasSource reports whether a source with the given name is registered.

func (*ResolvedSource) ListServices

func (r *ResolvedSource) ListServices(ctx context.Context) ([]Service, error)

ListServices queries every registered source concurrently and returns one merged entry per service name (k8s runtime over contract sources), sorted by name.

func (*ResolvedSource) SetRuntimeSource

func (r *ResolvedSource) SetRuntimeSource(ds DataSource)

SetRuntimeSource replaces the runtime (k8s) source. This is used when the kubeconfig context changes at runtime and the k8s client must be recreated. Thread-safe via copy-on-write.

func (*ResolvedSource) SourceTypes

func (r *ResolvedSource) SourceTypes() []string

SourceTypes returns the list of active source types.

type ResourcesInfo

type ResourcesInfo struct {
	ServiceExists  *bool `json:"serviceExists,omitempty"`
	WorkloadExists *bool `json:"workloadExists,omitempty"`
}

ResourcesInfo holds Kubernetes resource existence checks.

type RuntimeDiffRow

type RuntimeDiffRow struct {
	Field         string `json:"field"`
	ContractPath  string `json:"contractPath,omitempty"`
	DeclaredValue string `json:"declaredValue"`
	ObservedValue string `json:"observedValue"`
	Status        string `json:"status"` // match, mismatch, skipped, not_applicable
}

RuntimeDiffRow represents a single contract-vs-runtime comparison.

func ComputeRuntimeDiff

func ComputeRuntimeDiff(workload string, state *StateInfo, observed *ObservedRuntime) []RuntimeDiffRow

ComputeRuntimeDiff builds the semantic contract-vs-runtime comparison rows.

type SectionInfo

type SectionInfo struct {
	State        string `json:"state"`                  // one of the Section* state consts
	Reason       string `json:"reason,omitempty"`       // human note for non-present states
	Source       string `json:"source,omitempty"`       // "k8s" | "oci" | "local" | "cache"
	OverriddenBy string `json:"overriddenBy,omitempty"` // source that overrode a contract value (e.g. "k8s")
}

SectionInfo records the availability + provenance of one dashboard section so the UI can explain absence (not-applicable vs unavailable vs empty) and label where present data came from.

type Server

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

Server serves the dashboard web UI and REST API.

func NewResolvedServer

func NewResolvedServer(resolved *ResolvedSource, ui fs.FS, sourceInfo []SourceInfo, diagnostics *SourceDiagnostics) *Server

NewResolvedServer creates a dashboard server with the contract+runtime resolution model.

func NewServer

func NewServer(source DataSource, ui fs.FS) *Server

NewServer creates a dashboard server backed by the given data source. ui is the embedded filesystem containing the web UI assets.

func (*Server) RefreshCacheSources

func (s *Server) RefreshCacheSources()

RefreshCacheSources rescans the disk cache and invalidates the in-memory data source cache so newly cached bundles become visible immediately. If no CacheSource exists yet (e.g. --no-cache was used) but a cacheDir is known, it creates one on-the-fly and wires it into the OCI source's internal cache (never as a separate public source).

func (*Server) RegisterOperations

func (s *Server) RegisterOperations(api huma.API)

RegisterOperations registers all dashboard API operations on the given Huma API. Exported so that OpenAPI specs can be generated without starting a server.

func (*Server) Serve

func (s *Server) Serve(ctx context.Context, port int, host ...string) error

Serve starts the HTTP server on the given host and port and blocks until ctx is cancelled. An empty host defaults to 127.0.0.1.

func (*Server) ServeOnListener

func (s *Server) ServeOnListener(ctx context.Context, ln net.Listener) error

ServeOnListener starts the HTTP server on an existing listener.

func (*Server) SetCORSOrigin

func (s *Server) SetCORSOrigin(origin string)

SetCORSOrigin allows an explicit cross-origin client to call the API. When empty (the default) the API is same-origin only and cross-origin mutating requests are rejected. Must be called before Serve.

func (*Server) SetCacheDir

func (s *Server) SetCacheDir(dir string)

SetCacheDir stores the OCI cache directory path so the server can create a CacheSource on-the-fly after fetch-all-versions, even when --no-cache was used and no CacheSource existed at startup.

func (*Server) SetCacheSource

func (s *Server) SetCacheSource(cs *CacheSource, memCache Cache)

SetCacheSource registers the CacheSource so the server can trigger a rescan after new bundles are cached (via resolve or fetch-all-versions).

func (*Server) SetK8sRedetect

func (s *Server) SetK8sRedetect(fn func(ctx context.Context) (DataSource, error))

SetK8sRedetect registers a callback that recreates the k8s client from fresh kubeconfig and returns a new cached DataSource. Called periodically to detect kubectl context switches without requiring a dashboard restart.

func (*Server) SetLazyEnrich

func (s *Server) SetLazyEnrich(fn func(ctx context.Context) bool)

SetLazyEnrich registers a callback that attempts OCI enrichment from K8s. The callback is invoked on-demand (from API handlers) if OCI was not available at startup. It returns true if enrichment succeeded.

func (*Server) SetListenAddr

func (s *Server) SetListenAddr(host string, port int)

SetListenAddr sets the server URL exposed in the OpenAPI spec.

func (*Server) SetLogger

func (s *Server) SetLogger(lg *slog.Logger)

SetLogger sets the logger injected into every request context, so handlers and sources that log via logging.LoggerFromContext use the command-configured logger. A nil logger falls back to slog.Default(). Must be called before Serve.

func (*Server) SetOCISource

func (s *Server) SetOCISource(src *OCISource)

SetOCISource registers the OCISource so the server can report discovery state.

func (*Server) SetResolver

func (s *Server) SetResolver(r *oci.Resolver)

SetResolver enables lazy on-demand resolution of remote OCI dependencies.

func (*Server) SetVersion

func (s *Server) SetVersion(v string)

SetVersion sets the Pacto version exposed by the health endpoint.

func (*Server) UpdateSourceInfo

func (s *Server) UpdateSourceInfo(info []SourceInfo)

UpdateSourceInfo replaces the source metadata shown by /api/sources. Deduplicates by type (keeps last occurrence).

func (*Server) WaitForVersionEnrich

func (s *Server) WaitForVersionEnrich()

WaitForVersionEnrich blocks until any in-flight background version enrichment completes. Used by tests to synchronize.

type Service

type Service struct {
	Name           string         `json:"name"`
	Version        string         `json:"version"`
	Owner          contract.Owner `json:"owner,omitempty"`
	ContractStatus ContractStatus `json:"contractStatus"`
	Source         string         `json:"source"`            // primary source: k8s, oci, local
	Sources        []string       `json:"sources,omitempty"` // all sources this service appears in
}

Service is a summary entry for the service list view.

func ServiceFromContract

func ServiceFromContract(c *contract.Contract, source string) Service

ServiceFromContract builds a Service summary from a parsed contract.

type ServiceDetails

type ServiceDetails struct {
	Service

	Namespace string            `json:"namespace,omitempty"`
	Metadata  map[string]string `json:"metadata,omitempty"`

	// Contract references from operator.
	ResolvedRef     string `json:"resolvedRef,omitempty"`
	CurrentRevision string `json:"currentRevision,omitempty"`

	// Version tracking: derived from resolvedRef and version history.
	VersionPolicy   string `json:"versionPolicy,omitempty"`   // "tracking", "pinned-tag", "pinned-digest"
	LatestAvailable string `json:"latestAvailable,omitempty"` // highest semver from version history
	UpdateAvailable bool   `json:"updateAvailable,omitempty"` // true when latestAvailable > version

	Interfaces     []InterfaceInfo     `json:"interfaces,omitempty"`
	Configurations []ConfigurationInfo `json:"configurations,omitempty"`
	Dependencies   []DependencyInfo    `json:"dependencies,omitempty"`
	Workload       string              `json:"workload,omitempty"`
	State          *StateInfo          `json:"state,omitempty"`
	Capabilities   []CapabilityInfo    `json:"capabilities,omitempty"`
	Policies       []PolicyInfo        `json:"policies,omitempty"`

	// Tools are agent-invocable capabilities derived from openapi interfaces'
	// operations. Populated by bundle-backed sources (local/OCI/cache);
	// empty for k8s-only services (no bundle FS to parse).
	Tools []CapabilityTool `json:"tools,omitempty"`

	// Skills are optional domain-knowledge documents (skills/*.md) shipped in the
	// bundle. Populated by bundle-backed sources; empty for k8s-only services.
	Skills []SkillInfo `json:"skills,omitempty"`

	Validation *ValidationInfo `json:"validation,omitempty"`

	// Lock surfaces the committed pacto.lock pins. Nil when no lockfile is present
	// (or for sources that cannot read it from disk, e.g. OCI/cache/k8s).
	Lock *LockInfo `json:"lock,omitempty"`

	// Compliance is the computed compliance assessment.
	Compliance *ComplianceInfo `json:"compliance,omitempty"`

	// EvaluationCoverage reports how many required assertions were evaluated.
	// Metadata only, never changes compliance status.
	EvaluationCoverage *EvaluationCoverage `json:"evaluationCoverage,omitempty"`

	// Readiness is the derived operational readiness assessment. It is a separate
	// dimension from contract compliance and does not affect compliance status.
	Readiness *ReadinessInfo `json:"readiness,omitempty"`

	// Docs are the in-bundle Markdown documents (docs/**/*.md). Populated by
	// bundle-backed sources (local/OCI/cache); empty for k8s-only services.
	Docs []DocInfo `json:"docs,omitempty"`

	// SBOM is the parsed software bill of materials from the bundle's sbom/
	// directory (SPDX or CycloneDX). Nil when the bundle has no SBOM.
	SBOM *sbom.Document `json:"sbom,omitempty"`

	// ObservedRuntime holds runtime state observed by the operator.
	ObservedRuntime *ObservedRuntime `json:"observedRuntime,omitempty"`

	// RuntimeDiff is the semantic contract-vs-runtime comparison.
	RuntimeDiff []RuntimeDiffRow `json:"runtimeDiff,omitempty"`

	// Endpoints surfaced from runtime (k8s).
	Endpoints []EndpointStatus `json:"endpoints,omitempty"`

	// Conditions from operator CRD status.
	Conditions []Condition `json:"conditions,omitempty"`

	// Insights are computed diagnostic messages (critical, warning, info).
	Insights []Insight `json:"insights,omitempty"`

	// ChecksSummary from operator (passed/total checks).
	ChecksSummary *ChecksSummary `json:"checksSummary,omitempty"`

	// Kubernetes-specific fields, populated only by k8s source.
	Resources *ResourcesInfo `json:"resources,omitempty"`
	Ports     *PortsInfo     `json:"ports,omitempty"`

	LastUpdated      *time.Time `json:"lastUpdated,omitempty"`
	LastReconciledAt string     `json:"lastReconciledAt,omitempty"`

	// RuntimeEvaluated is true only when a Kubernetes runtime overlay was applied
	// (the operator actually observed this service). When false, the view is
	// "definition only" — runtime status/sections cannot be asserted.
	RuntimeEvaluated bool `json:"runtimeEvaluated,omitempty"`

	// SectionMeta describes, per section id, why a section is shown or absent and
	// which source supplied it — so the UI never silently hides data. Keys are the
	// Section* ids. Populated by the resolver after the merge, or by the server's
	// getService handler as a fallback on the non-resolved single-source path.
	SectionMeta map[string]SectionInfo `json:"sectionMeta,omitempty"`
}

ServiceDetails contains all information for the service detail view.

func ServiceDetailsFromBundle

func ServiceDetailsFromBundle(bundle *contract.Bundle, source string) *ServiceDetails

ServiceDetailsFromBundle builds full ServiceDetails from a contract bundle.

func (*ServiceDetails) GenerateInsights

func (d *ServiceDetails) GenerateInsights()

GenerateInsights derives diagnostic insights from the service details when no operator-provided insights exist. This is the single source of truth for insight generation — the UI consumes these directly.

type ServiceListEntry

type ServiceListEntry struct {
	Service
	Namespace        string           `json:"namespace,omitempty"`
	BlastRadius      int              `json:"blastRadius,omitempty"`
	DependencyCount  int              `json:"dependencyCount,omitempty"`
	ChecksPassed     int              `json:"checksPassed"`
	ChecksTotal      int              `json:"checksTotal"`
	ChecksFailed     int              `json:"checksFailed"`
	ComplianceStatus ComplianceStatus `json:"complianceStatus"`
	ComplianceScore  *int             `json:"complianceScore"`
	ComplianceErrors int              `json:"complianceErrors"`
	ComplianceWarns  int              `json:"complianceWarnings"`
	TopInsight       string           `json:"topInsight,omitempty"`
	UpdateAvailable  bool             `json:"updateAvailable,omitempty"`
	// EvaluationCoverage feeds the list's compact coverage badge (E of R required
	// assertions evaluated). Metadata only, never changes status. Nil when the
	// service was not runtime-evaluated.
	EvaluationCoverage *EvaluationCoverage `json:"evaluationCoverage,omitempty"`
	// Readiness is the derived operational readiness assessment, carried on the
	// list entry so the aggregated readiness overview can summarize, sort, and
	// filter every service from a single /api/services call (mirroring how the
	// owners view aggregates client-side). Nil when the service declares no
	// readiness block. It is a separate dimension from contract compliance.
	Readiness *ReadinessInfo `json:"readiness,omitempty"`
}

ServiceListEntry is an enriched Service for the list view, including blast radius, dependency count, checks summary, compliance, and top insight.

type ServiceNameInput

type ServiceNameInput struct {
	Name string `path:"name" maxLength:"255" example:"order-service" doc:"Service name"`
}

ServiceNameInput is the path parameter for service-scoped endpoints.

type ServiceSourceData

type ServiceSourceData struct {
	SourceType string          `json:"sourceType"` // "k8s", "oci", "local"
	Service    *ServiceDetails `json:"service"`
}

ServiceSourceData holds service details from a single source.

type SkillInfo

type SkillInfo struct {
	Name    string `json:"name"`
	Content string `json:"content,omitempty"`
}

SkillInfo is a single bundled domain-knowledge document (skills/*.md).

type SourceDiagnostics

type SourceDiagnostics struct {
	K8s   K8sDiagnostics   `json:"k8s"`
	OCI   OCIDiagnostics   `json:"oci"`
	Cache CacheDiagnostics `json:"cache"`
	Local LocalDiagnostics `json:"local"`
}

SourceDiagnostics provides detailed diagnostic information about source detection.

type SourceInfo

type SourceInfo struct {
	Type    string `json:"type"` // "k8s", "oci", "local"
	Enabled bool   `json:"enabled"`
	Reason  string `json:"reason,omitempty"` // why enabled/disabled
}

SourceInfo describes a detected data source and its availability.

type StateInfo

type StateInfo struct {
	Type                  string `json:"type"`
	PersistenceScope      string `json:"persistenceScope,omitempty"`
	PersistenceDurability string `json:"persistenceDurability,omitempty"`
	DataCriticality       string `json:"dataCriticality,omitempty"`
}

StateInfo describes the state semantics of the service.

type ValidationCatalogEntry

type ValidationCatalogEntry struct {
	Category string
	Label    string
	Severity string // "error" or "warning"
}

ValidationCatalogEntry enriches a condition type with category, label, and default severity.

func LookupValidation

func LookupValidation(conditionType string) ValidationCatalogEntry

LookupValidation returns the catalog entry for a condition type. Unknown types get category "other", the type name as label, and "error" severity.

type ValidationInfo

type ValidationInfo struct {
	Valid    bool              `json:"valid"`
	Errors   []ValidationIssue `json:"errors,omitempty"`
	Warnings []ValidationIssue `json:"warnings,omitempty"`
}

ValidationInfo holds validation results.

type ValidationIssue

type ValidationIssue struct {
	Code    string `json:"code"`
	Path    string `json:"path"`
	Message string `json:"message"`
}

ValidationIssue represents a single validation error or warning.

type Version

type Version struct {
	Version        string     `json:"version"`
	Ref            string     `json:"ref,omitempty"`
	ContractHash   string     `json:"contractHash,omitempty"`
	CreatedAt      *time.Time `json:"createdAt,omitempty"`
	Source         string     `json:"source,omitempty"`         // origin: "k8s", "oci", "local"
	Classification string     `json:"classification,omitempty"` // diff vs previous: "NON_BREAKING", "POTENTIAL_BREAKING", "BREAKING"
	IsCurrent      bool       `json:"isCurrent,omitempty"`      // true for the version currently deployed/active
}

Version represents a historical version of a service.

Jump to

Keyboard shortcuts

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