stackspecmigration

package
v0.42.0 Latest Latest
Warning

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

Go to latest
Published: Sep 24, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package stackspecmigration contains the bounded compatibility seam for the one-minor StackSpec v1 -> v2 migration described by ADR-0029.

The package deliberately stops at architecture normalization. It does not compile a ResolvedPlan and it does not claim that a normalized architecture is a complete, CUE-valid StackSpec v2. The future compiler must combine this result with explicit topology, capability, provider, access, and inventory inputs before any generator or runtime can consume it.

Index

Constants

View Source
const (
	APIVersionV1                  = "stackkit/v1"
	APIVersionV2Alpha1            = "stackkit/v2alpha1"
	APIVersionV2Alpha2            = "stackkit/v2alpha2"
	APIVersionMigrationProjection = "stackkit.migration/v1"
	KindStackSpec                 = "StackSpec"
	KindMigrationProjection       = "StackSpecMigrationProjection"
)

Variables

This section is empty.

Functions

func MigrateDocument

func MigrateDocument(document Document, options Options) (NormalizedArchitecture, Report, error)

MigrateDocument is the safe entry for file/API migration. In contrast to MigrateV1 it has access to the lossless reader metadata and therefore blocks unknown legacy fields before a caller could write a lossy projection.

func MigrateV1

func MigrateV1(spec *models.StackSpec, options Options) (NormalizedArchitecture, Report, error)

MigrateV1 normalizes only architecture dimensions that are deterministic. It never mutates spec. Context validates/maps locality and Pi hardware; it never changes the selected KitProfile.

Types

type Blocker

type Blocker struct {
	Code                 string       `json:"code" yaml:"code"`
	Field                string       `json:"field" yaml:"field"`
	Message              string       `json:"message" yaml:"message"`
	RequiredInputs       []string     `json:"requiredInputs" yaml:"requiredInputs"`
	SuggestedKitProfiles []KitProfile `json:"suggestedKitProfiles,omitempty" yaml:"suggestedKitProfiles,omitempty"`
}

Blocker describes missing or contradictory intent that ADR-0029 forbids the migration from guessing.

type Decision

type Decision struct {
	Code   string `json:"code" yaml:"code"`
	Field  string `json:"field" yaml:"field"`
	From   string `json:"from,omitempty" yaml:"from,omitempty"`
	To     string `json:"to" yaml:"to"`
	Reason string `json:"reason" yaml:"reason"`
}

Decision makes every deterministic normalization or explicit operator choice auditable.

type Document

type Document struct {
	Version         SourceVersion
	Raw             []byte
	Legacy          *models.StackSpec
	UnknownV1Fields []string
	V2              *V2Identity
}

Document preserves the original bytes so dual-read cannot silently discard fields. Legacy is populated only for v1. V2 contains only dispatch identity; the complete document must still be validated by the CUE v2 contract.

func Read

func Read(data []byte) (Document, error)

Read classifies a StackSpec without normalizing v1 or partially validating v2 as though it were complete. Unknown versions and mixed v1/v2 identity fields fail closed.

type KitProfile

type KitProfile string

KitProfile is the canonical v2 product identity. Context never selects it.

const (
	KitProfileBasement KitProfile = "basement-kit"
	KitProfileCloud    KitProfile = "cloud-kit"
	KitProfileModern   KitProfile = "modern-homelab"

	// LegacyHAKitSlug is recognized only by the bounded v1 migration seam. It
	// is never a canonical KitProfile or an active product/discovery value.
	LegacyHAKitSlug = "ha-kit"
)

type ManualAction

type ManualAction struct {
	Code     string   `json:"code" yaml:"code"`
	Fields   []string `json:"fields" yaml:"fields"`
	Message  string   `json:"message" yaml:"message"`
	Required bool     `json:"required" yaml:"required"`
}

ManualAction records information that cannot be transferred into a complete StackSpecV2 without an operator or a later shadow-resolution stage. It must never be silently dropped by a write-mode migration command.

type MigrationError

type MigrationError struct {
	Blockers []Blocker
}

MigrationError is returned with the same blockers contained in Report. errors.As can be used to present machine-actionable guidance.

func (*MigrationError) Error

func (e *MigrationError) Error() string

type MigrationStatus

type MigrationStatus string

MigrationStatus communicates whether the normalization is usable by the next migration stage or requires additional operator intent.

const (
	MigrationStatusReady     MigrationStatus = "ready-for-shadow-resolution"
	MigrationStatusCompleted MigrationStatus = "completed-v2"
	MigrationStatusBlocked   MigrationStatus = "blocked"
)

type NodeDefaults

type NodeDefaults struct {
	SiteRef               string `json:"siteRef" yaml:"siteRef"`
	HardwareProfile       string `json:"hardwareProfile,omitempty" yaml:"hardwareProfile,omitempty"`
	ApplyToAllLegacyNodes bool   `json:"applyToAllLegacyNodes" yaml:"applyToAllLegacyNodes"`
}

NodeDefaults records how the deprecated stack-level context is projected to legacy nodes. HardwareProfile is populated only for context=pi; local/cloud never invent a hardware class.

type NormalizedArchitecture

type NormalizedArchitecture struct {
	APIVersion       string       `json:"apiVersion" yaml:"apiVersion"`
	Kind             string       `json:"kind" yaml:"kind"`
	KitProfile       KitProfile   `json:"kitProfile" yaml:"kitProfile"`
	PrimarySite      SiteTarget   `json:"primarySite" yaml:"primarySite"`
	AuthoritySiteRef string       `json:"authoritySiteRef" yaml:"authoritySiteRef"`
	NodeDefaults     NodeDefaults `json:"nodeDefaults" yaml:"nodeDefaults"`
}

NormalizedArchitecture is the architecture-only output of v1 normalization. It is intentionally not named StackSpecV2: topology and security contracts still have to be supplied and CUE-validated by the compiler.

type Options

type Options struct {
	TargetKitProfile KitProfile `json:"targetKitProfile,omitempty" yaml:"targetKitProfile,omitempty"`
}

Options contains explicit operator decisions. TargetKitProfile is never inferred from context. It is only needed when the legacy product identity is missing or when the operator explicitly accepts a supported reclassification.

type ReadError

type ReadError struct {
	Code    string
	Message string
}

ReadError is a typed fail-closed dual-read error.

func (*ReadError) Error

func (e *ReadError) Error() string

type Report

type Report struct {
	SourceVersion              string          `json:"sourceVersion" yaml:"sourceVersion"`
	TargetVersion              string          `json:"targetVersion" yaml:"targetVersion"`
	Status                     MigrationStatus `json:"status" yaml:"status"`
	RequiresExplicitAcceptance bool            `json:"requiresExplicitAcceptance" yaml:"requiresExplicitAcceptance"`
	Decisions                  []Decision      `json:"decisions" yaml:"decisions"`
	Warnings                   []Warning       `json:"warnings" yaml:"warnings"`
	ManualActions              []ManualAction  `json:"manualActions" yaml:"manualActions"`
	Blockers                   []Blocker       `json:"blockers" yaml:"blockers"`
}

Report is emitted for successful and blocked migrations. Callers must show it to the operator before explicit acceptance; it is not optional telemetry.

type SiteKind

type SiteKind string

SiteKind is the canonical v2 locality dimension.

const (
	SiteKindHome  SiteKind = "home"
	SiteKindCloud SiteKind = "cloud"
)

type SiteTarget

type SiteTarget struct {
	ID   string   `json:"id" yaml:"id"`
	Kind SiteKind `json:"kind" yaml:"kind"`
}

SiteTarget is the single-site target that can be derived from a non-Modern v1 spec without inventing a hybrid topology.

type SourceVersion

type SourceVersion string

SourceVersion identifies which side of the one-minor dual-read seam a document belongs to.

const (
	SourceVersionV1       SourceVersion = "v1"
	SourceVersionV2Alpha1 SourceVersion = "v2alpha1"
	SourceVersionV2Alpha2 SourceVersion = "v2alpha2"
)

func (SourceVersion) IsV2

func (v SourceVersion) IsV2() bool

IsV2 identifies the CUE-owned architecture family without collapsing the explicit v2alpha1 compatibility adapter into native v2alpha2 intent.

type V2Identity

type V2Identity struct {
	APIVersion string
	Kind       string
	KitProfile KitProfile
}

V2Identity is the minimum safe dispatch header for a canonical v2 document.

type Warning

type Warning struct {
	Code           string `json:"code" yaml:"code"`
	Field          string `json:"field" yaml:"field"`
	Message        string `json:"message" yaml:"message"`
	RequiredAction string `json:"requiredAction,omitempty" yaml:"requiredAction,omitempty"`
}

Warning describes a non-blocking compatibility concern.

Jump to

Keyboard shortcuts

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