Help us shape the future of Go! Take the 2026 Go Developer Survey

state

package
v0.1.0 Latest Latest
Warning

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

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

Documentation

Overview

Package state 是 fleetly 控制面状态层(SQLite 权威态 + 底座观测缓存 + 写前直读端口)。

分层判据与权威归属(state-model §2.1,本包实现的真源):

  • 权威态:只存无法从底座重算的知识——期望态(apps/revisions/env_vars/ domains/placements)、历史(deployments/events/audit_log)、凭证 (tokens)、备份台账(state_backups)、孤儿登记(orphans)。
  • 派生缓存:nodes 表 = Docker/Swarm 观测快照,每行带 observed_at/stale, 可整表重建,禁止用于决策(state-model §2.2)。平台不承诺任何底座侧 存活时间戳(Swarm 不暴露该概念),平台观测时间字段为 last_seen_at。
  • 实时直读:写操作先直读底座并以对象版本作乐观令牌,冲突返回 E_STATE_VERSION_CONFLICT(resolve.go 的 VersionResolver)。

审计 fail-closed(state-model §2.9):破坏性/管理操作与业务写同事务, 审计写失败即操作失败(audit.go,事务内 WriteAudit)。事件 seq 单调 (events.go,AUTOINCREMENT 永不复用),SSE 游标早于保留窗返回 E_EVENT_CURSOR_EXPIRED(410)并附 oldest_seq。删除走 tombstone-first (apps.go:deleting → deleted 状态位,恢复不复活)。

节点身份(state-model §2.3):领域身份 = 平台节点 ID(n_<ULID>),写入 Swarm node label fleetly.node-id;Swarm node ID 仅存适配器映射 runtime_node_refs(platform_id, swarm_node_id)。

底座访问经 DockerClient 小端口(docker.go)抽象,moby/client 实现见 internal/substrate 适配器——为架构 §2.8 端口纪律打底,核心不出现 第三方类型。

本包不依赖任何框架类型(D20:框架只做装配与生命周期);lynx.Service / lynx.Checker 的装配壳在 cmd/fleetlyd(CheckHealth 方法为结构性实现)。

Index

Constants

View Source
const (
	// AppStateRunning 以上皆否。
	AppStateRunning = "running"
	// AppStateDegraded 运行中但有不合格判定(观察窗失败 verdict=unstable /
	// 窗后不稳定 / W_DEPLOY_INSTABILITY)。
	AppStateDegraded = "degraded"
	// AppStateBlocked 平台侧无合法动作可执行(placement blocked/unresolved)。
	AppStateBlocked = "blocked"
	// AppStateDown 无有效版本或首发失败 scale=0(没有任何期望实例)。
	AppStateDown = "down"
)

AppDerivedState 词表(state-model §2.10)。

View Source
const (
	BackupKindDaily      = "daily"
	BackupKindPreUpgrade = "pre_upgrade"
	BackupKindPostDeploy = "post_deploy"
	BackupKindManual     = "manual"
)

备份 kind 词表(00008 CHECK 的包内镜像;写入入口校验用)。

View Source
const (
	BackupVerifyPending  = "pending"
	BackupVerifyVerified = "verified"
	BackupVerifyFailed   = "failed"
)

verify_status 词表。

View Source
const (
	// RecoveryReplay 已按最后有效 revision 归位重放(未切流失败/cancel;
	// 值取 replay——restore 专指 DR 灾难恢复,见词汇表 restore 词条)。
	RecoveryReplay = "replay"
	// RecoveryBlocked 恢复被阻塞(引擎不可达等;退避重试可续跑)。
	RecoveryBlocked = "blocked"
)

deployment recovery 词表(recovery 列;同记录恢复记录,D-REL-7)。

View Source
const (
	// DeployFlagPostWindowAlerted:观察窗后不稳定已告警(L4 一次)。
	DeployFlagPostWindowAlerted int64 = 1 << 0
	// DeployFlagInstabilityWarning:观察窗警告通过(W_DEPLOY_INSTABILITY)。
	DeployFlagInstabilityWarning int64 = 1 << 1
)

部署级标志位(deployments.flags,只增位不回收)。

View Source
const (
	EventTypeNode    = "node"
	EventTypeService = "service"
	EventTypeTask    = "task"
)

观测信号相关的事件类别(Docker events 的 Type 取值子集;变更 1s 内 触发 resync,state-model §2.2)。

View Source
const (
	DefaultEventRetentionDays = 30
	DefaultAuditRetentionDays = 365
)

DefaultEventRetentionDays / DefaultAuditRetentionDays 是保留期默认值 (架构 §2.3:事件 30 天、审计 1 年;config 可调)。

View Source
const (
	// DefaultBuildRetentionDays 是 builds 终态行保留天数(台账窗口)。
	DefaultBuildRetentionDays = 90
	// DefaultArtifactsRetentionDays 是 build artifacts 目录保留天数。
	DefaultArtifactsRetentionDays = 30
	// DefaultDeploymentDirRetentionDays 是部署 compose 持久化目录在部署
	// 终态后的保留天数(终态前行恒不清理)。
	DefaultDeploymentDirRetentionDays = 30
)

S18-A7/A10 新增保留窗默认值。

View Source
const (
	// LabelNamespace 是平台 label 保留命名空间前缀。
	LabelNamespace = "fleetly."

	// LabelManaged 标记平台受管对象(服务 label,"true"):归属判定、
	// 孤儿检测、删除保护的依据。
	LabelManaged = "fleetly.managed"
	// LabelApp 标记归属应用(服务/容器 label,值为应用名)。
	LabelApp = "fleetly.app"
	// LabelProcess 标记 compose 服务名(应用内进程名)。
	LabelProcess = "fleetly.process"
	// LabelDeployment 标记发布归属(值 = deployment ID)。
	LabelDeployment = "fleetly.deployment"
	// LabelDesiredHash 是服务级期望态哈希(对账变更判据的落点 label,
	// state-model §2.5 desired-hash 纪律;service-label 变更不触发任务
	// 重建——归位零成本的配套,Spike B2)。
	LabelDesiredHash = "fleetly.desired-hash"
	// LabelCron 标记定时任务 schedule(v0.2 契约,常量先行,state-model §2.4)。
	LabelCron = "fleetly.cron"

	// LabelNodeID 是节点身份锚(node label,值 = 平台节点 ID n_<ULID>,
	// state-model §2.3)。
	LabelNodeID = "fleetly.node-id"

	// LabelDomains 是平台约定路由域名列表(compose 服务 label,逗号分隔)。
	LabelDomains = "fleetly.domains"
	// LabelPlacementNode 是放置意图(compose 服务 label,v0.2 多节点消费,
	// 常量先行)。
	LabelPlacementNode = "fleetly.placement.node"
)

fleetly.* label 最小契约(state-model §2.4):保留命名空间 fleetly.* 为平台独占(用户占用 → E_LABEL_RESERVED 422,映射随 API 面落地);写者 唯一 = 适配器 Marker 端口(本阶段仅节点身份锚经 DockerClient.UpdateNodeLabel 写入,业务对象 label 下发随 T2.14);密钥/payload 永不入 label;平台保留 未知 fleetly.* 键不改写。

View Source
const (
	// RevisionStatusActive 在保留窗内(回滚选项集)。
	RevisionStatusActive = "active"
	// RevisionStatusSuperseded 被更新快照挤出保留窗(存档不删)。
	RevisionStatusSuperseded = "superseded"
)

保留窗状态位词表(revisions.status,00005 加法列;无 CHECK,词表在此 冻结)。v0.1 只有两个值;候选态(candidate)不进 v0.1——快照仅在成功 终态固化(verified=1 与 active 同拍写入)。

View Source
const DefaultGitBranch = "main"

DefaultGitBranch 是 app 配置分支的缺省值(push 与 webhook 共用)。

View Source
const JanitorCleanupInterval = time.Hour

JanitorCleanupInterval 是清理扫描周期。

View Source
const ManagedLabelValue = "true"

ManagedLabelValue 是 LabelManaged 的约定取值。

View Source
const (
	// MetaKeyPlatformNodeID 是本机平台节点 ID 的 meta 键(值 = n_<ULID>,
	// state-model §2.3:首次启动生成、此后持久复用)。
	MetaKeyPlatformNodeID = "platform_node_id"
)

meta 表:平台自身身份与小规模 settings(state-model §2.1「平台身份与 凭证」行的 settings 载体;v0.1 冻结清单未单列业务表,键值结构随阶段 只增键不改表)。

View Source
const NodeIDPrefix = "n_"

NodeIDPrefix 是平台节点 ID 前缀。

View Source
const (
	// ObservationInterval 是全量 resync 周期(state-model §2.2:统一 30s)。
	ObservationInterval = 30 * time.Second
)
View Source
const (
	// PhaseBlockedWaiting 发布中绑定节点 DOWN:看门狗暂停计时、可 cancel
	// (release-semantics §2.3,场景 15)。
	PhaseBlockedWaiting = "blocked_waiting"
)

deployment 子状态(phase 列词表;空 = 无子状态)。

View Source
const RevisionKeepVersions = 5

RevisionKeepVersions 是保留窗宽度(release-semantics §2.4 / architecture §2.5 默认参数表:版本保留 5)。

View Source
const (
	// VerdictUnstable 已切流观察窗失败(app=degraded 的来源之一)。
	VerdictUnstable = "unstable"
)

deployment verdict 词表(verdict 列;unstable 仅为 deployment 判定)。

Variables

View Source
var (
	// ErrAppExists 表示同名应用已在册(任何生命周期态名字均占用)。
	ErrAppExists = errors.New("app name already registered")
	// ErrAppTombstoned 表示目标应用处于删除状态位(deleting/deleted):
	// 不可复活、不可在其上继续业务写。
	ErrAppTombstoned = errors.New("app is tombstoned")
	// ErrAppNotFound 表示应用不存在。
	ErrAppNotFound = errors.New("app not found")
	// ErrInvalidLifecycleTransition 表示生命周期状态位迁移非法
	// (状态机:active → deleting → deleted,不可跳越、不可回退)。
	ErrInvalidLifecycleTransition = errors.New("invalid app lifecycle transition")
)

应用生命周期哨兵错误。

View Source
var (
	// ErrBuildNotFound 表示构建记录不存在。
	ErrBuildNotFound = errors.New("build not found")
	// ErrBuildStateTransition 表示构建状态迁移非法(终态不可逆、claim
	// 竞争失败等——调用方应重读状态后裁决)。
	ErrBuildStateTransition = errors.New("invalid build state transition")
)

构建记录哨兵错误。

View Source
var (
	// ErrDeploymentNotFound 表示部署记录不存在。
	ErrDeploymentNotFound = errors.New("deployment not found")
	// ErrDeploymentStateTransition 表示部署状态迁移非法(终态不可逆、
	// 竞争落败等——调用方重读状态后裁决)。
	ErrDeploymentStateTransition = errors.New("invalid deployment state transition")
	// ErrDuplicateGitDeployment 表示同一 (app, sha) 已有 enqueued/active/
	// succeeded 部署、本次入队被判重拒绝(M3-4:webhook sha 幂等去重的
	// 事务内复查哨兵——check-then-insert 竞态在入队事务原语内闭合,
	// 并发重投只建一行)。消费方把它映射为 duplicate 回执(200),非错误
	// 面披露。
	ErrDuplicateGitDeployment = errors.New("duplicate git deployment for sha")
)

DeploymentNotFound 哨兵与状态迁移哨兵。

View Source
var (
	// ErrObjectNotFound 表示直读的底座对象不存在(可能已被并发删除)。
	ErrObjectNotFound = errors.New("substrate object not found")
	// ErrVersionConflict 表示乐观令牌与底座当前版本不符(并发修改)。
	ErrVersionConflict = errors.New("substrate object version conflict")
	// ErrNotSwarmManager 表示引擎未启用 Swarm(或本机非 manager),
	// 节点身份锚定与节点观测不可用。
	ErrNotSwarmManager = errors.New("docker engine is not an active swarm manager")
)

底座端口哨兵错误:适配器将第三方错误归类为以下哨兵(errors.Is 判定), 核心据此映射契约错误码,适配器自身不出现契约码。

View Source
var (
	// ErrGitKeyNotFound 表示目标 git key 不存在。
	ErrGitKeyNotFound = errors.New("git key not found")
	// ErrGitKeyExists 表示同指纹公钥已在册。
	ErrGitKeyExists = errors.New("git key already registered")
)

git key 哨兵错误。

View Source
var (
	// ErrTokenNotFound 表示目标 token 不存在。
	ErrTokenNotFound = errors.New("token not found")
	// ErrTokenRevoked 表示 token 已吊销(认证拒绝路径)。
	ErrTokenRevoked = errors.New("token revoked")
	// ErrTokenInvalid 表示凭据不匹配(哈希查无此行或常量时间比对失败)。
	ErrTokenInvalid = errors.New("token invalid")
	// ErrTokenLastAdmin 表示最后管理员守卫拒绝(M4-6):本次吊销会使
	// 平台不存在任何未吊销 admin token——依次吊销全部 admin 后平台锁死
	// (重启不补种 bootstrap:HasAnyToken 已见 token 行,一次性语义),
	// 在吊销事务内拒绝。调用方映射为 409 业务冲突信封。
	ErrTokenLastAdmin = errors.New("last admin token")
)

token 相关哨兵错误。

View Source
var ErrAppDerivedStateConflict = errors.New("app derived state conflict")

ErrAppDerivedStateConflict 表示派生状态 CAS 落败(并发翻转已发生)。

View Source
var ErrDomainNotFound = errors.New("domain not found")

ErrDomainNotFound 表示域名台账行不存在。

View Source
var ErrEnvNotFound = errors.New("env var not found")

ErrEnvNotFound 表示目标 env 键不存在。

View Source
var ErrIllegalTransition = fmt.Errorf("%w: illegal per transition table", ErrDeploymentStateTransition)

ErrIllegalTransition 表示按转移表判定的非法状态迁移(from→to 无边—— 确定性编码错误)。它是 ErrDeploymentStateTransition 的特化(包装链): 既有调用方按「迁移非法家族」处理(errors.Is 双哨兵均真——引擎对竞争 落败的幂等收敛语义不变);需要区分「表外组合」与「CAS 竞争落败」的 调用方(测试、诊断)精确匹配本哨兵——前者应修调用方,后者应重读状态 后裁决。

View Source
var ErrPlacementNotFound = errors.New("placement not found")

ErrPlacementNotFound 表示目标应用无绑定记录(有卷应用不存在「无绑定」 的合法运行态——出现即调用方该走自动选点,本哨兵不外溢为 API 错误)。

View Source
var ErrRefNotFound = fmt.Errorf("runtime node ref not found")

GetRuntimeNodeRef 按 platform_id 取映射;不存在返回 ("", ErrAppNotFound) 语义即未锚定——用独立哨兵 ErrRefNotFound 表达。

View Source
var ErrRevisionNotFound = errors.New("revision not found")

ErrRevisionNotFound 表示版本快照不存在(含 superseded 后不可经选项面 解析的形态——调用方按 E_ROLLBACK_NO_TARGET 映射)。

View Source
var ErrVolumeNotFound = errors.New("volume not found")

ErrVolumeNotFound 表示注册表中无该卷。

Functions

func CanTransitionDeployment

func CanTransitionDeployment(from, to DeploymentStatus) bool

CanTransitionDeployment 报告 from → to 是否合法转移(未知状态、终态出边、 表外组合一律非法)。

func DeploymentsRoot

func DeploymentsRoot(dbPath string) string

DeploymentsRoot 返回部署 compose 持久化根目录(S18-A7:<数据根>/ deployments;数据根 = 状态库同目录——与 cmd 装配的 BackupRoot/GitRoot 同款派生,入队点(api/gitserver)与 janitor 清理共用同一布局)。

func DiffSummary

func DiffSummary(kvs ...any) string

DiffSummary 构造审计 diff 摘要 JSON 字符串(B4:审计摘要的唯一构造器 ——内部 json.Marshal,键值含 `"`、`\`、控制字符时按 JSON 规则转义, 消灭手拼 JSON 的注入与破包面)。kvs 为 key,value 成对变参(key 取 string;value 支持 string/数值/布尔等可 marshal 类型);奇数个尾参 丢弃末项(防御式——调用方均为固定键值对)。marshal 失败(理论不可达) 回落 "{}"。map 序列化键序确定(字典序)。

func HashToken

func HashToken(plaintext string) string

HashToken 计算明文 token 的存储哈希(sha256 hex,64 字符)——落库与认证 双方共用此形态,防止出现两种哈希口径。

func IsReservedLabel

func IsReservedLabel(key string) bool

IsReservedLabel 报告 key 是否落在平台保留命名空间(fleetly.*): 用户声明该命名空间内的 label 时上游应拒绝(E_LABEL_RESERVED)。

func PersistDeploymentCompose

func PersistDeploymentCompose(root, deploymentID string, compose []byte) (string, error)

PersistDeploymentCompose 把部署 compose 字节持久化到 <root>/<deploymentID>/compose.yaml(S18-A7 入队点共享写入通道:先写 文件后建行——部署行不指向缺失文件;0600 权限;OS 临时目录自此仅作解析 中转,tmpfiles 清理不再影响引擎 preparing 重载与成功固化重载)。

func RelevantForObservation

func RelevantForObservation(ev SubstrateEvent) bool

RelevantForObservation 报告事件是否应触发观测缓存失效。

func SchemaVersions

func SchemaVersions(ctx context.Context, path string) (dbVersion, maxVersion int64, err error)

SchemaVersions 只读返回(DB 当前 schema 版本,本二进制内嵌迁移的最大 版本)。不开 Store、不应用迁移、不触发 ensureMigrated 的高版本守卫—— 升级/回退编排(fleetlyd schema-version 子命令,F5/S20)需要在旧二进制 「拒绝打开新 schema 库」之前比对两侧版本,给操作员可行动指引或自动 恢复,而不是 start 失败后留下 DEGRADED 现场让人猜。

版本读取口径 = goose 版本表的 MAX(version_id)(本平台迁移只加法、不写 down 行,MAX 即已应用最高版本)。库文件不存在 / 版本表不存在(从未被 fleetlyd 打开过)→ dbVersion 0(空库语义,goose 首启建表落 0)。

func ValidateEnvKey

func ValidateEnvKey(key string) error

ValidateEnvKey 校验平台 env 键:非空、无空白、无 = / NUL(注入安全下限, 字符集从宽——compose/Docker 允许点与连字符;窄白名单属过度设计)。

Types

type App

type App struct {
	ID         string
	Name       string
	Lifecycle  AppLifecycle
	CreatedAt  time.Time
	UpdatedAt  time.Time
	DeletingAt time.Time // 零值 = 未进入删除
	DeletedAt  time.Time // 零值 = 未完成删除
}

App 是应用权威态行(v0.1 最小面:期望态根 + tombstone 状态位)。

type AppGitConfig

type AppGitConfig struct {
	Branch string
	// SecretSet 报告 webhook 签名密钥已配置。
	SecretSet bool
	// WebhookSecret 是密文形态(SecretSet=false 时为空)。
	WebhookSecret string
	SourceURL     string
	AuthKind      SourceAuthKind
	// AuthSecret 是密文形态(” = 无认证材料)。
	AuthSecret string
}

AppGitConfig 是 app git 触发配置投影(webhook_secret 携带密文形态, daemon 侧解密消费;api 读面只用 SecretSet)。

type AppLifecycle

type AppLifecycle string

AppLifecycle 是应用生命周期状态位。

const (
	// LifecycleActive 正常在册。
	LifecycleActive AppLifecycle = "active"
	// LifecycleDeleting 删除进行中(deleting,等待清理与保留期)。
	LifecycleDeleting AppLifecycle = "deleting"
	// LifecycleDeleted 已删除(tombstone,保留期内名字仍占用)。
	LifecycleDeleted AppLifecycle = "deleted"
)

type AppSourceWrite

type AppSourceWrite struct {
	// URL 为空 = 清除拉源配置(auth 字段一并清空)。
	URL        string
	Branch     string
	AuthKind   SourceAuthKind
	AuthSecret string // envelope 密文
	// ActorTokenID 审计调用方 token。
	ActorTokenID string
}

AppSourceWrite 是一次拉源配置写入(ciphertext 密文形态入参)。

type AuditEntry

type AuditEntry struct {
	// ID 记录 ID(ULID;留空自动生成)。
	ID string
	// At 发生时间(零值取写入时刻)。
	At time.Time
	// Actor 操作主体:human / ai_agent / system(架构 §1.1 术语约定)。
	Actor string
	// ActorTokenID 关联 token(可空)。
	ActorTokenID string
	// Action 稳定动作串(如 app.delete、node.identity_created)。
	Action string
	// Target 操作对象(如 app:<id>、node:<platform_id>)。
	Target string
	// Result 取 ok / error。
	Result string
	// ErrorCode 失败时的注册表错误码(可空)。
	ErrorCode string
	// RequestID 关联请求(可空)。
	RequestID string
	// DiffSummary diff 摘要(脱敏后的 JSON/文本,可空)。
	DiffSummary string
}

AuditEntry 是一条审计记录。ID 可留空(自动生成 ULID);Actor/Action/ Result 为数据库级非空约束(audit_log 表 CHECK),写不出合法行即整事务 回滚——这是 fail-closed 的硬保证,包内不做宽松兜底。

type AuditRecord

type AuditRecord struct {
	ID     string
	At     time.Time
	Actor  string
	Action string
	Target string
	Result string
	// ErrorCode 是失败路径的注册表错误码(” = 成功行)。
	ErrorCode string
	// DiffSummary 是审计差异摘要(” = 无)。
	DiffSummary string
}

AuditRecord 是审计只读投影(验证/后台展示用)。T2.15 起随读通道披露 ErrorCode/DiffSummary(路由发布失败审计的断言面;加法扩展)。

type BackupWrite

type BackupWrite struct {
	// ID 留空自动生成 ULID(调用方需要目录名与台账 ID 一致时自行生成后
	// 传入——Manager 先建目录后落账,传显式 ID)。
	ID string
	// At 落账时刻(零值取写入时刻)。
	At time.Time
	// Kind 必须是注册词表之一(unknown kind 直接报错——台账不接受不可归类
	// 的行)。
	Kind string
	// Path / SHA256 / SizeBytes 是快照产物事实。
	Path   string
	SHA256 string
	Size   int64
	// Verify 必须是 verified / failed(pending 不可落账——落账即判定)。
	Verify string
	// Error 校验失败原因(failed 行必填)。
	Error string
	// AuditActor 审计 actor(默认 "system"——手动触发的行由 RPC 层传 token
	// actor 形态,但备份本体恒为 daemon 执行,默认值覆盖全部自动路径)。
	AuditActor string
}

BackupWrite 是一次备份的落账载荷(RecordStateBackup 消费)。

type BuildRecord

type BuildRecord struct {
	ID       string
	AppID    string
	Service  string
	Driver   Driver
	Status   BuildStatus
	ImageRef string
	// ImageDigest 是不可变镜像 ID(`sha256:<hex>`);成功终态必非空(D9)。
	ImageDigest string
	// Request 是构建输入 JSON(构建队列的跨进程执行输入)。
	Request string
	// PlanPath / LogPath 是产物归档路径(railpack plan JSON / 构建日志)。
	PlanPath string
	LogPath  string
	// ErrorCode 是失败终态的注册表错误码。
	ErrorCode string
	CreatedAt time.Time
	// StartedAt / FinishedAt:零值 = 未开始 / 未到终态。
	StartedAt  time.Time
	FinishedAt time.Time
}

BuildRecord 是一次构建的权威记录行。

type BuildStatus

type BuildStatus string

BuildStatus 是构建状态机的状态位。

const (
	// BuildQueued 已入队待执行。
	BuildQueued BuildStatus = "queued"
	// BuildBuilding 执行中。
	BuildBuilding BuildStatus = "building"
	// BuildSucceeded 成功终态(image_digest 必非空)。
	BuildSucceeded BuildStatus = "succeeded"
	// BuildFailed 失败终态(error_code 必非空)。
	BuildFailed BuildStatus = "failed"
)

func (BuildStatus) Valid

func (s BuildStatus) Valid() bool

Valid 报告状态是否为已定义状态位。

type CachedNode

type CachedNode struct {
	SwarmNodeID      string
	Hostname         string
	State            string
	Availability     string
	IsManager        bool
	SubstrateVersion uint64
	Labels           map[string]string
	// LastSeenAt 平台最近一次成功观测到该节点的时刻(观测语义,非底座
	// 提供的时间戳)。
	LastSeenAt time.Time
	// ObservedAt 本行快照写入时刻(读契约字段)。
	ObservedAt time.Time
	// Stale 底座最近一次不可达时被整表置位;为真时本行内容可能是旧值,
	// 禁止当事实消费(读契约字段)。
	Stale bool
}

CachedNode 是 nodes 表行(观测缓存读投影)。

type DeployRecord

type DeployRecord struct {
	ID string
	// AppID / AppName:app 外键与 compose 名(冗余快照便于跨进程渲染)。
	AppID   string
	AppName string
	// Kind ∈ deploy|rollback(00001 CHECK):仅已切流回滚建新记录(D-REL-7)。
	Kind string
	// Status 是状态机主状态;Phase 是子状态(blocked_waiting 或空)。
	Status DeploymentStatus
	Phase  string
	// RevisionID 是成功后固化的版本行(成功时回填;可空)。
	RevisionID string
	// RecoveryOf 是 rollback 记录指向的原 deployment(可空)。
	RecoveryOf string
	// SubstrateHalted:首发失败 scale=0 保留现场(场景 14)。
	SubstrateHalted bool
	// FirstHealthyAt 是切流判据(零值 = 未切流,D-REL-4)。
	FirstHealthyAt time.Time
	// Recovery / Verdict:同记录恢复记录与终态判定(可空)。
	Recovery string
	Verdict  string
	// ErrorCode 是失败终态的注册表错误码(可空)。
	ErrorCode string
	// 停机账(stop-first 如实累计)。
	DowntimeMS        int64
	DowntimeStartedAt time.Time
	DowntimeEndedAt   time.Time
	// 看门狗/观察窗时间标记(零值 = 未进入对应阶段)。
	ReleaseStartedAt   time.Time
	WatchdogDeadlineAt time.Time
	ObserveStartedAt   time.Time
	// PhaseStartedAt 是准备/构建预算基线(00009 加法列):queued → preparing
	// 转换(引擎拾取)时刻——排队等待不计入预算(H11);零值(存量行未写)
	// 时消费方回落 CreatedAt。releasing 由 ReleaseStartedAt 起算,两者互不
	// 干扰。
	PhaseStartedAt time.Time
	// 期望态快照(spec_hash/env_snapshot_hash 明文哈希;desired_spec 为
	// box envelope 密文,本层不解释)。
	SpecHash        string
	EnvSnapshotHash string
	DesiredHash     string
	DesiredSpec     string
	ComposePath     string
	// CancelRequested:CLI 置位、引擎消费(曾健康拒绝并清位)。
	CancelRequested bool
	// Flags 是部署级告警/标志位(bitmask;PostWindowAlerted /
	// InstabilityWarning——L4 只告警一次与观察窗警告通过)。
	Flags int64
	// git 触发来源(T2.19 迁移 00007;空串 = API/CLI 直传 compose)。
	SourceGitSHA string
	SourceGitRef string
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

DeployRecord 是一次部署的状态机行。

type DeploymentPatch

type DeploymentPatch struct {
	Status             *DeploymentStatus
	PrevStatus         *DeploymentStatus // 非 nil 时作 from 谓词(CAS 推进)
	Phase              *string
	RevisionID         *string
	SubstrateHalted    *bool
	FirstHealthyAt     *time.Time
	Recovery           *string
	Verdict            *string
	ErrorCode          *string
	DowntimeMS         *int64
	DowntimeStartedAt  *time.Time
	DowntimeEndedAt    *time.Time
	ReleaseStartedAt   *time.Time
	WatchdogDeadlineAt *time.Time
	ObserveStartedAt   *time.Time
	PhaseStartedAt     *time.Time
	SpecHash           *string
	EnvSnapshotHash    *string
	DesiredHash        *string
	DesiredSpec        *string
	ComposePath        *string
	CancelRequested    *bool
	Flags              *int64
	SourceGitSHA       *string
	SourceGitRef       *string
}

DeploymentPatch 是一次行更新承载的可选字段(零值 = 不写;时间字段用 指针区分「不写」与「清空」——NULL 语义字段才允许置回 NULL)。

type DeploymentStatus

type DeploymentStatus string

DeploymentStatus 是发布状态机主状态(release-semantics §2.3)。

const (
	// DeployQueued 已入队(同 app 互斥:等待在途部署终态)。
	DeployQueued DeploymentStatus = "queued"
	// DeployPreparing 准备中(compose 重载/放置解析/env 合并/镜像 preflight)。
	DeployPreparing DeploymentStatus = "preparing"
	// DeployBuilding 构建核对(build 层已完成则直通)。
	DeployBuilding DeploymentStatus = "building"
	// DeployReleasing 发布中(Swarm service 对账 + 健康门;含
	// blocked_waiting 子状态 = phase 列)。
	DeployReleasing DeploymentStatus = "releasing"
	// DeployObserving 观察窗(默认 60s,只告警)。
	DeployObserving DeploymentStatus = "observing"
	// DeploySucceeded 成功终态(观察窗通过;active revision 已前移)。
	DeploySucceeded DeploymentStatus = "succeeded"
	// DeployFailed 失败终态(error_code 必非空;归位/分流结果在同记录)。
	DeployFailed DeploymentStatus = "failed"
	// DeployCancelled 取消终态(先归位再落 cancelled)。
	DeployCancelled DeploymentStatus = "cancelled"
)

func AllDeploymentStatuses

func AllDeploymentStatuses() []DeploymentStatus

AllDeploymentStatuses 返回主状态全词表(穷举测试遍历用)。

func LegalDeploymentTransitions

func LegalDeploymentTransitions(from DeploymentStatus) []DeploymentStatus

LegalDeploymentTransitions 返回 from 的合法目标集合(穷举测试断言用; from 为终态或未知状态返回空)。

func (DeploymentStatus) Terminal

func (s DeploymentStatus) Terminal() bool

Terminal 报告是否终态(succeeded/failed/cancelled)。

func (DeploymentStatus) Valid

func (s DeploymentStatus) Valid() bool

Valid 报告状态是否为已定义状态位。

type DockerClient

type DockerClient interface {
	// Ping 探测底座可达性(观测缓存刷新的先决条件)。
	Ping(ctx context.Context) error

	// ListNodeObservations 返回全量节点观测快照(观测缓存 30s 全量 resync
	// 的数据源,state-model §2.2)。底座不可达时返回错误,绝不返回部分
	// 快照冒充全量。
	ListNodeObservations(ctx context.Context) ([]SubstrateNode, error)

	// SelfNodeID 返回本机 Swarm node ID;引擎未启用 Swarm 时返回
	// ErrNotSwarmManager。
	SelfNodeID(ctx context.Context) (string, error)

	// UpdateNodeLabel 以乐观令牌更新节点 label(v0.1 唯一的 label 写入
	// 接口,承载 node-id 身份锚;§2.4 最小 label 集,业务对象 label 下发
	// 随 T2.14)。expected 与底座当前版本不符时返回 ErrVersionConflict;
	// label 已是目标值时为幂等 no-op 并返回 nil。
	UpdateNodeLabel(ctx context.Context, swarmNodeID, key, value string, expected ObjectVersion) error

	// ResolveObjectVersion 直读底座对象版本(写前直读;对象缺失返回
	// ErrObjectNotFound)。
	ResolveObjectVersion(ctx context.Context, kind ObjectKind, id string) (ObjectVersion, error)

	// SubscribeEvents 订阅底座事件流(node/service/task 变更作观测缓存的
	// 失效信号,state-model §2.2;只作缓存失效信号,不作产品事件来源)。
	// 返回的 channel 在 ctx 取消或流结束时关闭。
	SubscribeEvents(ctx context.Context) (<-chan SubstrateEvent, error)

	// Close 释放底层连接资源。
	Close() error
}

DockerClient 是底座(Docker/Swarm)访问的小端口(架构 §2.8 Runtime 端口 的观测与身份子集,v0.1 切面)。核心(本包)只认识本文件定义的核心类型, 第三方类型只存在于适配器内部(internal/substrate,moby/client 实现)。

纪律:

  • 方法返回的核心类型字段命名用平台语义,不透传底座结构;
  • 底座对象版本(ObjectVersion)是写前直读的乐观令牌(state-model §2.2 读契约),适配器必须逐字取自底座对象版本,不得自造。

type Domain

type Domain struct {
	ID      string
	AppID   string
	Service string
	Domain  string
	// Port 是路由目标端口(compose expose 首端口;” = 未同步)。
	Port string
	// CertSHA256 是证书 PEM(链 + 叶)内容 sha256 hex;” = 尚无证书。
	CertSHA256 string
	// CertNotAfter 是叶证书 NotAfter;零值 = 尚无证书。
	CertNotAfter time.Time
	// CertUpdatedAt 是证书登记最近一次写入;零值 = 从未。
	CertUpdatedAt time.Time
	// CreatedAt 是域名首 declarations 时间。
	CreatedAt time.Time
}

Domain 是一条域名台账行。

type DomainServiceRoutes

type DomainServiceRoutes struct {
	Service string
	// Port 是路由目标端口(compose expose 首端口)。
	Port    string
	Domains []string
}

DomainServiceRoutes 是一次 per-service 域名声明(发布同步的输入单元)。

type Driver

type Driver string

Driver 是构建驱动(与 compose 服务 build/image 两模式对应)。

const (
	// DriverRailpack 无 build.dockerfile → Railpack 自动检出(钉版 v0.39.0,
	// internal/build)。
	DriverRailpack Driver = "railpack"
	// DriverDockerfile 有 build.dockerfile → Dockerfile 前端(一等路径)。
	DriverDockerfile Driver = "dockerfile"
	// DriverPassthrough 仅 image 模式直通(无构建;v0.1 不建行,枚举位预留)。
	DriverPassthrough Driver = "passthrough"
)

func (Driver) Valid

func (d Driver) Valid() bool

Valid 报告驱动是否为已定义值。

type EnvVar

type EnvVar struct {
	ID        string
	AppID     string
	Key       string
	Value     string
	Source    string // platform | system(模板连接串留位,只读)
	Status    EnvVarStatus
	CreatedAt time.Time
	UpdatedAt time.Time
}

EnvVar 是平台层环境变量行(value 为调用方传入的存储形态——本层不解释 密文/明文,加密边界在 internal/secrets 与其调用方)。

type EnvVarStatus

type EnvVarStatus string

EnvVarStatus 是 env_vars 生效状态位。

const (
	// EnvStatusPending 已创建/更新但未部署消费(当前运行 env 不含它)。
	EnvStatusPending EnvVarStatus = "pending"
	// EnvStatusEffective 已随部署生效(合并链可消费)。
	EnvStatusEffective EnvVarStatus = "effective"
)

type Event

type Event struct {
	Seq     int64
	At      time.Time
	Name    string
	Subject string
	// Payload 是脱敏后的 JSON 文本(默认 "{}")。
	Payload string
}

Event 是一条平台事件。Seq 由库分配(单调、删除后永不复用);Name 必须 是 eventcode 注册表内事件名(构造期纪律与 errcode 一致:非法名 panic)。

type EventRecord

type EventRecord = Event

EventRecord 是事件只读投影。

type GitKey

type GitKey struct {
	ID string
	// Fingerprint 是公钥 SHA256 指纹("SHA256:<base64>")。
	Fingerprint string
	// PublicKey 是 authorized_keys 单行原文(公开材料,可回读)。
	PublicKey string
	// KeyType 是公钥类型词(ssh-ed25519 / ssh-rsa / ecdsa-sha2-nistp256…)。
	KeyType string
	// Note 是人读备注。
	Note      string
	CreatedAt time.Time
}

GitKey 是一条平台管理的 git 公钥行(只读投影;平台从不接触私钥)。

type GitKeyWrite

type GitKeyWrite struct {
	// ID 留空自动生成 ULID。
	ID string
	// Fingerprint 必须非空(SHA256 指纹,调用方以 golang.org/x/crypto/ssh
	// 的 FingerprintSHA256 计算后传入)。
	Fingerprint string
	// PublicKey 是 authorized_keys 单行原文。
	PublicKey string
	// KeyType 是公钥类型词。
	KeyType string
	// Note 是人读备注。
	Note string
	// ActorTokenID 是发起写入的调用方 token(审计 actor_token_id)。
	ActorTokenID string
}

GitKeyWrite 是一次 git key 写入。

type Janitor

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

Janitor 周期清理过期事件与审计记录(S18-A7/A10:外加部署目录/构建 台账/产物目录保留窗与非终态超龄扫描)。

func NewJanitor

func NewJanitor(store *Store, cfg JanitorConfig, log *slog.Logger) *Janitor

NewJanitor 构造保留期清理守护。cfg 天数取非正值时回落默认(保留期是 契约默认,不允许被误配成 0 而静默关闭)。

func (*Janitor) AuditRetention

func (j *Janitor) AuditRetention() time.Duration

func (*Janitor) EventRetention

func (j *Janitor) EventRetention() time.Duration

EventRetention / AuditRetention 返回生效保留期(诊断用)。

func (*Janitor) PruneOnce

func (j *Janitor) PruneOnce(ctx context.Context, now time.Time) (events int64, audits int64, err error)

PruneOnce 执行一轮清理(now 为基准时刻),返回 (事件条数, 审计条数)。 独立导出供测试直接驱动。S18-A7/A10:一轮内顺次执行全部 duties—— 事件/审计分批删除 → builds 终态行 → 产物目录 → 部署 compose 目录 → 非终态超龄扫描;各 duty 失败独立记日志不中断后续(单 duty 失败不该 瘫痪整轮保留期治理),事件/审计错误仍向上返回(既有契约)。

func (*Janitor) Start

func (j *Janitor) Start(ctx context.Context) error

Start 非阻塞启动清理循环(启动先清一拍,此后每小时一拍)。

func (*Janitor) Stop

func (j *Janitor) Stop(_ context.Context) error

Stop 停止清理循环并等待退出。

type JanitorConfig

type JanitorConfig struct {
	// EventRetentionDays / AuditRetentionDays 是事件/审计保留天数。
	EventRetentionDays int
	AuditRetentionDays int
	// BuildRetentionDays 是 builds 终态行保留天数(缺省 90)。
	BuildRetentionDays int
	// ArtifactsDir 是 build 产物归档根目录(build.artifacts_dir;空 = 跳过
	// 目录清理——进程内测试夹具形态)。
	ArtifactsDir string
	// ArtifactsRetentionDays 是产物目录保留天数(缺省 30)。
	ArtifactsRetentionDays int
	// DeploymentsRoot 是部署 compose 持久化根(<数据根>/deployments;
	// 空 = 跳过目录清理)。
	DeploymentsRoot string
	// DeploymentDirRetentionDays 是部署目录在终态后的保留天数(缺省 30)。
	DeploymentDirRetentionDays int
	// StaleDeploymentBudget 是部署非终态超龄判定预算(2×(DeployTimeout+
	// ObserveWindow),装配自 engine 配置;≤0 跳过部署扫描)。
	StaleDeploymentBudget time.Duration
	// StaleBuildBudget 是构建非终态超龄判定预算(2×构建超时,装配自
	// build 配置;≤0 跳过构建扫描)。
	StaleBuildBudget time.Duration
}

JanitorConfig 是 janitor 的保留窗与预算参数集(S18-A7/A10 装配扩展: 构造参数从两个散装天数收口为结构体——新增 duties 的参数不再逐个膨胀 构造签名)。零值字段回落默认;目录/根为空时对应 duty 整体跳过。

type NodeIdentity

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

NodeIdentity 管理本机平台节点身份的生成、持久化与底座锚定。

func NewNodeIdentity

func NewNodeIdentity(store *Store, d DockerClient, log *slog.Logger) *NodeIdentity

NewNodeIdentity 构造节点身份管理器。

func (*NodeIdentity) Anchor

func (n *NodeIdentity) Anchor(ctx context.Context) error

Anchor 执行一次完整锚定:自省本机 Swarm node ID → 幂等写身份 label (写前直读取令牌 + 冲突重试)→ 登记 runtime_node_refs 映射(变更时 写系统审计)。引擎未启用 Swarm 返回 ErrNotSwarmManager(调用方退避 重试,例如安装流程 swarm init 完成前)。

func (*NodeIdentity) Anchored

func (n *NodeIdentity) Anchored() bool

Anchored 报告身份是否已锚定到 Swarm 节点 label 并登记映射。

func (*NodeIdentity) CheckHealth

func (n *NodeIdentity) CheckHealth() error

CheckHealth 报告身份就绪态:平台 ID 已生成即视为身份层健康(底座锚定 的健康语义由 observer 的底座检查承载,不在此重复——避免 swarm 未启用 的单机上身份检查拖垮 readiness)。

func (*NodeIdentity) EnsurePlatformID

func (n *NodeIdentity) EnsurePlatformID(ctx context.Context) (string, error)

EnsurePlatformID 确保 meta 中存在本机平台节点 ID:缺失则生成 n_<ULID> 并与系统审计同事务落库(系统自动动作必入审计,state-model §2.9)。 幂等;返回平台节点 ID。

func (*NodeIdentity) PlatformID

func (n *NodeIdentity) PlatformID() string

PlatformID 返回已确保的平台节点 ID(EnsurePlatformID 成功前为空串)。

func (*NodeIdentity) Start

func (n *NodeIdentity) Start(ctx context.Context) error

Start 启动锚定守护:EnsurePlatformID 已在装配期完成(Init 阶段 fail-fast),此处循环执行 Anchor 直到成功或 ctx 取消;失败按指数退避 重试(底座未就绪/重启窗口不崩溃、不放弃)。非阻塞。 done 通道在 Start 内重开(lynx 生命周期保证 Start 先于 Stop 顺序执行, 无并发写)。

func (*NodeIdentity) Stop

func (n *NodeIdentity) Stop(_ context.Context) error

Stop 通知守护退出并等待其结束。

type ObjectKind

type ObjectKind string

ObjectKind 是写前直读的底座对象类别。

const (
	// ObjectKindNode 是 Swarm 节点(id = swarm node ID)。
	ObjectKindNode ObjectKind = "node"
	// ObjectKindService 是 Swarm 服务(id = swarm 服务名;平台名到底座名
	// 的映射随 T2.14 适配器落地,本阶段令牌纪律先立)。
	ObjectKindService ObjectKind = "service"
)

func (ObjectKind) Valid

func (k ObjectKind) Valid() bool

Valid 报告 kind 是否为已定义类别。

type ObjectVersion

type ObjectVersion struct {
	Index uint64
}

ObjectVersion 是底座对象版本(乐观令牌)。Index 取自底座对象自身的 单调版本号,语义逐字镜像底座。

type Observer

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

Observer 维护 nodes 观测缓存。CheckHealth 结构性实现 lynx.Checker: 最近一次全量同步成功即健康。

func NewObserver

func NewObserver(store *Store, d DockerClient, log *slog.Logger) *Observer

NewObserver 构造观测缓存刷新器。

func (*Observer) CheckHealth

func (o *Observer) CheckHealth() error

CheckHealth 实现 lynx.Checker:最近一次全量观测同步成功(含启动后的 首次同步)才健康;底座不可达 → 不健康(readiness 如实反映底座健康)。

func (*Observer) Invalidate

func (o *Observer) Invalidate()

Invalidate 请求立即刷新(事件驱动失效信号入口;非阻塞,合并连发)。

func (*Observer) Start

func (o *Observer) Start(ctx context.Context) error

Start 非阻塞启动刷新循环(同步首拍 + 周期拍 + 事件拍 + 事件流订阅)。

func (*Observer) Stop

func (o *Observer) Stop(_ context.Context) error

Stop 停止刷新循环并等待 goroutine 退出。

type Placement

type Placement struct {
	AppID          string
	PlatformNodeID string
	State          PlacementState
	Source         PlacementSource
	// LabelRef 是用户 label 书写原值(显示名或 n_<ULID>;空 = 未声明)。
	LabelRef string
	// Reason 是进入当前状态的派生原因(如 node_down / node_gone;可空)。
	Reason string
	// Etag 是绑定行乐观令牌(每次写重新生成)。
	Etag string
	// PinnedAt 首次钉住时刻(零值 = 未钉)。
	PinnedAt  time.Time
	CreatedAt time.Time
	UpdatedAt time.Time
}

Placement 是 placements 行(绑定记录投影)。

type PlacementSource

type PlacementSource string

PlacementSource 是绑定来源词表。

const (
	// PlacementSourcePlatform 平台自动选点(含首次自动绑定本机)。
	PlacementSourcePlatform PlacementSource = "platform"
	// PlacementSourceLabel 用户 label 显式钉住(解析成功后落账)。
	PlacementSourceLabel PlacementSource = "label"
)

type PlacementState

type PlacementState string

PlacementState 是绑定状态位(00001 词表)。

const (
	// PlacementBound 已绑定(设计文档的 ok 态)。
	PlacementBound PlacementState = "bound"
	// PlacementBlocked 绑定节点不可用/已移除,应用 blocked。
	PlacementBlocked PlacementState = "blocked"
	// PlacementUnresolved DR 后绑定无法判定,要求显式放置(不猜测)。
	PlacementUnresolved PlacementState = "unresolved"
)

type PlacementWrite

type PlacementWrite struct {
	AppID          string
	PlatformNodeID string
	State          PlacementState
	Source         PlacementSource
	LabelRef       string
	Reason         string
	ExpectedEtag   string
	// Pinned 首次钉住时置位(pinned_at 取写入时刻;已有值保持不动)。
	Pinned bool
}

PlacementWrite 是一次绑定写入:ExpectedEtag 非空时为 CAS(compare-and- swap,令牌不符 → ErrVersionConflict);空 = 无条件 upsert(首次绑定)。

type Revision

type Revision struct {
	ID                string
	AppID             string
	Seq               int64
	ComposeNormalized string
	Overlay           string
	DesiredHash       string
	Verified          bool
	// Status 是保留窗状态位(active = 可回滚选项;superseded = 被保留窗
	// 淘汰,仅存档——列表即选项,列不出来的不可回滚)。
	Status    string
	CreatedAt time.Time
}

Revision 是一次版本快照行。

type RevisionWrite

type RevisionWrite struct {
	// ID 留空自动生成 ULID。
	ID                string
	AppID             string
	ComposeNormalized string
	Overlay           string
	DesiredHash       string
}

RevisionWrite 是一次版本快照写入。

type RuntimeNodeRef

type RuntimeNodeRef struct {
	PlatformID  string
	SwarmNodeID string
	CreatedAt   time.Time
	UpdatedAt   time.Time
	AnchoredAt  time.Time
}

RuntimeNodeRef 是适配器映射行。

type SourceAuthKind

type SourceAuthKind string

SourceAuthKind 是 webhook 拉源认证形态词表。

const (
	// SourceAuthNone 匿名拉取(file:// / 公开 https 仓库)。
	SourceAuthNone SourceAuthKind = "none"
	// SourceAuthToken HTTPS + token(http.extraHeader 形态注入)。
	SourceAuthToken SourceAuthKind = "https_token"
	// SourceAuthSSHKey SSH 私钥(GIT_SSH_COMMAND 临时密钥文件注入)。
	SourceAuthSSHKey SourceAuthKind = "ssh_key"
)

func (SourceAuthKind) Valid

func (k SourceAuthKind) Valid() bool

Valid 报告认证形态是否为已定义词。

type StateBackup

type StateBackup struct {
	// ID 记录 ID(ULID;与备份目录名一致——<backup.dir>/<ID>/fleetly.db)。
	ID string
	// Kind 触发类别:daily / pre_upgrade / post_deploy / manual(历史行可为
	// hot/cold——00008 之前的占位枚举)。
	Kind string
	// Path 是快照文件路径(manifest.json 与其同目录)。
	Path string
	// SHA256 是快照文件的 sha256(hex;回读校验对象)。
	SHA256 string
	// SizeBytes 是快照文件字节数。
	SizeBytes int64
	// VerifyStatus 是回读校验结论:verified / failed(pending = 落账时未校验,
	// 现行写入路径不会产生——校验先于落账,唯一诚实态是已判定)。
	VerifyStatus string
	// Error 是校验失败原因原文(verified 行为空)。
	Error string
	// CreatedAt 是台账落账时刻(UTC)。
	CreatedAt time.Time
}

StateBackup 是 state_backups 台账行的只读投影。

type Store

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

Store 是控制面状态层门面:SQLite 权威态存储 + 底座观测缓存写入 + 写前直读端口消费。零框架依赖——lynx.Service/Checker 装配壳在 cmd/fleetlyd(CheckHealth 为结构性实现,进 healthz readiness)。

func Open

func Open(ctx context.Context, path string) (*Store, error)

Open 打开(必要时创建)状态库并应用全部迁移:启动即建库迁移、失败 fail-fast 拒绝启动。path 为数据库文件路径(默认 ./fleetly.db,由 config state.db_path 提供)。

func (*Store) AppHasNonTerminalDeployment

func (s *Store) AppHasNonTerminalDeployment(ctx context.Context, appID string) (bool, error)

AppHasNonTerminalDeployment 报告应用是否存在在途部署(同 app 互斥)。

func (*Store) AuthenticateToken

func (s *Store) AuthenticateToken(ctx context.Context, plaintext string) (Token, error)

AuthenticateToken 按明文认证:哈希查行 → 常量时间二次比对(belt-and- suspenders:行查找按哈希等值走索引,不泄漏明文时序;二次比对保证比对 通道本身常量时间)→ 吊销检查。成功返回在册 token。**不盖 last_used_at** (S18-A2:每请求同步写是 SQLite 写放大——盖写职责上移到调用方 internal/api 的认证路径,经进程内节流后调 TouchTokenUsed),本层保持 纯认证语义。

func (*Store) BindPlacement

func (s *Store) BindPlacement(ctx context.Context, w PlacementWrite) (Placement, error)

BindPlacement 写入绑定(无条件 upsert,etag 重新生成)。CAS 语义见 PlacementWrite.ExpectedEtag;pinned_at 只在首次置位、此后保持(数据诞生 点叙事),显式换点不洗掉历史钉住时刻。

func (*Store) CheckHealth

func (s *Store) CheckHealth() error

CheckHealth 实现 lynx.Checker(结构性满足,本包不 import 框架): 数据库可达即健康。检查自带 2s 上限(readiness 探测挂死防护由框架 另有 3s 兜底,此处自查优先快速失败)。

func (*Store) ClaimBuild

func (s *Store) ClaimBuild(ctx context.Context, id string) error

ClaimBuild 原子认领:queued → building(started_at 盖章),审计 build.start 同事务。ErrBuildStateTransition 表示已被认领/终态(多 worker/ 重复扫描竞争的安全路径——行级谓词保证恰好一个 claimer 胜出)。

func (*Store) Close

func (s *Store) Close() error

Close 关闭连接池。

func (*Store) CountGitDeploymentsForSHA

func (s *Store) CountGitDeploymentsForSHA(ctx context.Context, appID, sha string) (int64, error)

CountGitDeploymentsForSHA 统计应用在给定 git commit 上处于 enqueued/ active/succeeded 的部署数(T2.19 webhook 幂等去重判据:> 0 = 该 sha 已有 进行中或成功的部署,重投不建新记录;failed/cancelled 不计入——失败后重投 应允许重试)。source_git_sha 为空串的部署(API/CLI 直传)不参与匹配。

func (*Store) CreateApp

func (s *Store) CreateApp(ctx context.Context, appID, name string) (App, error)

CreateApp 创建应用行(active)。同名(任意生命周期态)返回 ErrAppExists——deleted 名字在保留期内不释放,不复活、也不顶替。 appID 留空自动生成 ULID。

func (*Store) CreateBuild

func (s *Store) CreateBuild(ctx context.Context, rec BuildRecord) (BuildRecord, error)

CreateBuild 创建 queued 构建记录(构建入队;id 留空自动生成 ULID)。 审计 build.create 与建行同事务(fail-closed),归因固定 system(内部 队列/复位路径)。调用方触发(API TriggerBuild)的归因见 CreateBuildAs。

func (*Store) CreateBuildAs

func (s *Store) CreateBuildAs(ctx context.Context, rec BuildRecord, audit *AuditEntry) (BuildRecord, error)

CreateBuildAs 是 CreateBuild 的审计归因扩展(M4-8):audit 非 nil 时 build.create 审计行由调用方注入——TriggerBuild 的入队审计带调用方 token(H14 敏感写面:base_dir 可指宿主任意目录,行为人必须可追溯); nil 时回落 CreateBuild 既有 system 归因(与旧行为逐字一致)。建行与 审计仍同事务 fail-closed。

func (*Store) CreateDeployment

func (s *Store) CreateDeployment(ctx context.Context, rec DeployRecord) (DeployRecord, error)

CreateDeployment 创建 queued 部署行(发布入队;独立事务薄壳,兼容既有 调用方与测试夹具)。kind 取 deploy|rollback。部署入队需要事件/审计 fail-closed 同事务(state-model §2.9,H13)的调用方必须改用 Store.InTx + Tx.CreateDeployment 组合——本壳内的事件/审计无从共享事务。

func (*Store) CreateGitKey

func (s *Store) CreateGitKey(ctx context.Context, w GitKeyWrite) (GitKey, error)

CreateGitKey 落一条 git key 行并与审计(gitkey.add)同事务 fail-closed。 同指纹重复注册返回 ErrGitKeyExists。

func (*Store) CreateToken

func (s *Store) CreateToken(ctx context.Context, w TokenWrite) (Token, error)

CreateToken 在事务内落一条 token 行(哈希形态入参)并与审计同事务 fail-closed。

func (*Store) DeleteAppDomains

func (s *Store) DeleteAppDomains(ctx context.Context, appID string) error

DeleteAppDomains 删除应用的全部域名台账行(应用移除/路由撤销时调用; 幂等)。

func (*Store) DeleteAppEnv

func (s *Store) DeleteAppEnv(ctx context.Context, appID, key string) error

DeleteAppEnv 删除单条 env(幂等:键不存在返回 ErrEnvNotFound)。审计同 事务 fail-closed,摘要只含键名。

func (*Store) DeleteStateBackup

func (s *Store) DeleteStateBackup(ctx context.Context, id string) (string, error)

DeleteStateBackup 删除一行台账(保留期清理用;与 backup.pruned 审计同 事务——删账必留痕)。返回删除行的 path(调用方负责目录清除)。

func (*Store) EnterPhase

func (s *Store) EnterPhase(ctx context.Context, id string, from, to DeploymentStatus, extra DeploymentPatch, events ...Event) error

EnterPhase 是部署状态转换的单一写点(v0.2 T0-V2.2,设计出处:评审报告 类 A 补齐①/整改方案 §9 挂账项「EnterPhase 全量单写点」)。同一事务内 完成四件事:

  1. 转移合法性校验:CanTransitionDeployment(from, to),表外组合拒写并 返回 ErrIllegalTransition(语义与 S16-C5 逐字一致);
  2. status/phase/error 等伴随字段写入:extra 补丁承载(ReleaseStartedAt/ WatchdogDeadlineAt/ErrorCode/Verdict/RevisionID/Recovery…),与 CAS 一并原子生效(复用 updateDeployment 内核——终态不可逆守卫与 RowsAffected 竞争裁决语义不变);extra 不得携带 Status/PrevStatus (转换边由 from/to 参数权威给出,双源即编码错误);
  3. 计时相位锚点:queued → preparing(引擎拾取边)必须携带 extra.PhaseStartedAt = 拾取时刻(S9/H11:预算自拾取起算、排队等待 不计入;时间戳由调用方时钟提供——引擎单测的假时钟下写点自取墙钟 会错位预算基准)。缺锚即拒:锚点漏写/误用因单写点不可发生。其余 边不刷新锚点——准备+构建共用拾取基线(preparing→building 刷新即 私自续预算)、releasing 由 watchdog_deadline_at 起算,两者互不干扰;
  4. 既有事件追加:events 逐条经 Tx.AppendEvent(eventcode 注册表校验) 写入同一事务(Outbox,state-model §2.9)——转换落库与事件披露原子; 只允许既有事件码(不新增);CAS 落败(RowsAffected=0)时事务回滚、 不产生任何事件。

Store 形态 = 独立事务薄壳(独立转换调用方);需要把转换与 revision 固化、 审计等业务写组合在同一事务的调用方(成功终态、回滚失败终态——S18-A6) 使用 Tx 形态嵌入既有 InTx。

func (*Store) EventsSince

func (s *Store) EventsSince(ctx context.Context, since int64, limit int) ([]Event, error)

EventsSince 返回 seq > since 的事件(升序,至多 limit 条)。游标早于 保留窗((since, oldest_seq) 区间的事件已被清理)时返回 *apperr.Error{code: E_EVENT_CURSOR_EXPIRED}(HTTP 410),context 携带 oldest_seq——显式断档,调用方(SSE/列表)应从 oldest_seq 重新拉全量。

func (*Store) FailStrandedBuild

func (s *Store) FailStrandedBuild(ctx context.Context, id, errorCode, reason string) error

FailStrandedBuild 把单条 building 行收敛为 failed 终态(队列侧兜底:执行 器返回后行仍停留 building——超时取消后未收敛、异常退出等路径)。CAS building→failed + finished_at 盖章 + error_code,审计 build.finish (result=error)同事务;reason 进审计 diff(builds 表只存注册表 error_code,兜底上下文——超时预算/中断原因——的可观测落点在审计)。

func (*Store) FindBuildsByDigest

func (s *Store) FindBuildsByDigest(ctx context.Context, digest string) ([]BuildRecord, error)

FindBuildsByDigest 按不可变镜像 ID 反查登记(digest→ref 映射读通道, T2.9 镜像身份;返回含该 digest 的全部成功构建行)。

func (*Store) FinishBuildFailed

func (s *Store) FinishBuildFailed(ctx context.Context, id, errorCode string) error

FinishBuildFailed 推进 building → failed 并落注册表错误码;审计 build.finish(result=error)同事务。

func (*Store) FinishBuildSucceeded

func (s *Store) FinishBuildSucceeded(ctx context.Context, id, imageRef, imageDigest, planPath, logPath string) error

FinishBuildSucceeded 推进 building → succeeded 并落镜像身份(ref + 不可变 digest,D9)。终态谓词防重复收敛;审计 build.finish 同事务。

func (*Store) GetAppByID

func (s *Store) GetAppByID(ctx context.Context, id string) (App, error)

GetAppByID 按平台 ID 取应用行;不存在返回 ErrAppNotFound(入口路由 合成时的 app 名反查消费)。

func (*Store) GetAppByName

func (s *Store) GetAppByName(ctx context.Context, name string) (App, error)

GetAppByName 按名取应用行;不存在返回 ErrAppNotFound。

func (*Store) GetAppDerivedState

func (s *Store) GetAppDerivedState(ctx context.Context, appID string) (string, error)

GetAppDerivedState 读派生状态缓存(空串 = 尚未推导,读面按派生规则即时 计算的语义归调用方)。

func (*Store) GetAppDriftConverge

func (s *Store) GetAppDriftConverge(ctx context.Context, appID string) (bool, error)

GetAppDriftConverge 读取漂移自动收敛 opt-in 位(apps.drift_converge, 00005 加法列)。默认关(D11:检测默认开、自动收敛默认关)——列不存在 语义即关,false 是唯一安全缺省。回滚失败时引擎强制清 0(D-REL-10), 人工经 CLI 重新置位(带审计)。

func (*Store) GetAppEnv

func (s *Store) GetAppEnv(ctx context.Context, appID, key string) (EnvVar, error)

GetAppEnv 取单条 env(任意状态位);不存在返回 ErrEnvNotFound。

func (*Store) GetAppGitConfig

func (s *Store) GetAppGitConfig(ctx context.Context, appID string) (AppGitConfig, error)

GetAppGitConfig 读 app git 触发配置(appID 必须存在——不存在返回 ErrAppNotFound)。

func (*Store) GetAppRevision

func (s *Store) GetAppRevision(ctx context.Context, appID, revisionID string) (Revision, error)

GetAppRevision 解析该 app 的一个可回滚目标(active + app 归属双谓词); 不存在 / 已被保留窗淘汰 / 归属不符 → ErrRevisionNotFound(列表即选项: 列不出来的不可回滚)。

func (*Store) GetAppVolume

func (s *Store) GetAppVolume(ctx context.Context, appID, key string) (Volume, error)

GetAppVolume 取单卷;不存在返回 ErrVolumeNotFound。

func (*Store) GetBuild

func (s *Store) GetBuild(ctx context.Context, id string) (BuildRecord, error)

GetBuild 按ID取构建记录;不存在返回 ErrBuildNotFound。

func (*Store) GetDeployment

func (s *Store) GetDeployment(ctx context.Context, id string) (DeployRecord, error)

GetDeployment 按ID取部署行;不存在返回 ErrDeploymentNotFound。

func (*Store) GetGitKeyByFingerprint

func (s *Store) GetGitKeyByFingerprint(ctx context.Context, fingerprint string) (GitKey, error)

GetGitKeyByFingerprint 按指纹取 key 行(SSH publickey 回调的认证查点); 不存在返回 ErrGitKeyNotFound。

func (*Store) GetMeta

func (s *Store) GetMeta(ctx context.Context, key string) (string, error)

GetMeta 读取 meta 键值;键不存在返回 ("", nil)(调用方以空串判定缺失)。

func (*Store) GetPlacement

func (s *Store) GetPlacement(ctx context.Context, appID string) (Placement, error)

GetPlacement 取绑定记录;无记录返回 ErrPlacementNotFound。

func (*Store) GetRevision

func (s *Store) GetRevision(ctx context.Context, id string) (Revision, error)

GetRevision 按 ID 取版本快照(不限保留窗状态——存档行仍可读);不存在 返回 ErrRevisionNotFound。回滚目标解析须走 GetAppRevision(active 谓词)。

func (*Store) GetRuntimeNodeRef

func (s *Store) GetRuntimeNodeRef(ctx context.Context, platformID string) (RuntimeNodeRef, error)

GetRuntimeNodeRef 返回映射行(未锚定返回 ErrRefNotFound)。

func (*Store) HasAnyToken

func (s *Store) HasAnyToken(ctx context.Context) (bool, error)

HasAnyToken 报告是否已存在任意 token 行(含已吊销)——bootstrap 判定 「首启无任何 token」的谓词(吊销过的也算存在过:bootstrap 一次性语义)。

func (*Store) InTx

func (s *Store) InTx(ctx context.Context, fn func(tx *Tx) error) (err error)

InTx 在单个写事务内执行 fn:事务以 BEGIN IMMEDIATE 开启(见 dsn), fn 返回错误或 panic 均回滚(panic 回滚后原样重抛,不吞栈)——审计/ 事件与业务写共享同一事务即由此组合(fail-closed)。

func (*Store) LatestDeploymentsByApp

func (s *Store) LatestDeploymentsByApp(ctx context.Context, appIDs []string, perApp int) (map[string][]DeployRecord, error)

LatestDeploymentsByApp 批量返回一组应用各自的最近部署窗口(每 app 至多 perApp 条,created_at 倒序——与逐 app 调 ListAppDeployments 同序同窗)。 S18-A4:ListApps 派生状态的 N+1 收口——N 个 app 的派生输入从 N 次 per-app 查询并为一次 IN 查询(窗口截断经 ROW_NUMBER,不拉全量行)。 空 appIDs 直接返回空 map(不发 SQL);map 中不出现的键 = 该 app 无 部署记录。

func (*Store) LatestStateBackup

func (s *Store) LatestStateBackup(ctx context.Context) (*StateBackup, error)

LatestStateBackup 返回最近一条台账(无备份记录 → nil, nil——调用方据此 表达「从未成功备份」的不健康态,不谎报)。

func (*Store) ListActiveApps

func (s *Store) ListActiveApps(ctx context.Context) ([]App, error)

ListActiveApps 返回全部 active 应用(created_at 升序;引擎运行期巡检的 候选集,v0.1 单机规模)。

func (*Store) ListAllDomains

func (s *Store) ListAllDomains(ctx context.Context) ([]Domain, error)

ListAllDomains 返回全部域名台账行(app_id, domain 字典序;全量配置 合成的事实源)。

func (*Store) ListAppBuilds

func (s *Store) ListAppBuilds(ctx context.Context, appID string, limit int) ([]BuildRecord, error)

ListAppBuilds 按应用返回构建记录(created_at 倒序,至多 limit 条; limit ≤ 0 取默认 50)。

func (*Store) ListAppDeployments

func (s *Store) ListAppDeployments(ctx context.Context, appID string, limit int) ([]DeployRecord, error)

ListAppDeployments 按应用返回部署记录(created_at 倒序,至多 limit 条)。

func (*Store) ListAppDomains

func (s *Store) ListAppDomains(ctx context.Context, appID string) ([]Domain, error)

ListAppDomains 返回应用的域名台账行(domain 字典序)。

func (*Store) ListAppEnv

func (s *Store) ListAppEnv(ctx context.Context, appID string) ([]EnvVar, error)

ListAppEnv 返回该 app 全部 env 行(含 pending,按 key 字典序)。消费面 三处:发布引擎合并链(pending 参与合并——部署即消费点,S16-C4)、CLI/ API 展示(键名/来源/状态位投影)、日志脱敏值集(pending 值同样不得进 日志)。

func (*Store) ListAppVolumes

func (s *Store) ListAppVolumes(ctx context.Context, appID string) ([]Volume, error)

ListAppVolumes 返回该 app 全部卷(按 key 字典序)。

func (*Store) ListAppsByLifecycle

func (s *Store) ListAppsByLifecycle(ctx context.Context, lifecycle AppLifecycle) ([]App, error)

ListAppsByLifecycle 返回指定生命周期状态位的全部应用(created_at 升序; H10/MG-3:引擎 deleting 回收 duty 的候选集查询——tombstone 第二拍的 执行者据此发现待收敛应用)。lifecycle 必须是 AppLifecycle 词表值, 调用方(引擎 duty)直接传常量,本函数不做词表校验(空集 = 无待收敛)。

func (*Store) ListCachedNodes

func (s *Store) ListCachedNodes(ctx context.Context) ([]CachedNode, error)

ListCachedNodes 返回全部观测缓存行(按 swarm_node_id 字典序)。 展示/诊断专用:决策路径禁用(见包注释与 state-model §2.2)。

func (*Store) ListGitKeys

func (s *Store) ListGitKeys(ctx context.Context) ([]GitKey, error)

ListGitKeys 返回全部在册 git key(created_at 升序)。

func (*Store) ListNonTerminalBuilds

func (s *Store) ListNonTerminalBuilds(ctx context.Context) ([]BuildRecord, error)

ListNonTerminalBuilds 返回全部非终态构建行(S18-A10:janitor 非终态超龄 扫描的输入——正常态由队列 worker 认领/收敛,超龄停留即状态机漏洞的显性 化告警;只读不自愈)。queued 行基线 created_at,building 行基线 started_at。

func (*Store) ListNonTerminalDeployments

func (s *Store) ListNonTerminalDeployments(ctx context.Context) ([]DeployRecord, error)

ListNonTerminalDeployments 返回全部非终态部署(重启恢复扫描)。

func (*Store) ListRevisions

func (s *Store) ListRevisions(ctx context.Context, appID string) ([]Revision, error)

ListRevisions 返回该 app 保留窗内的版本快照(active,seq 降序 = 最新 在前,release-semantics §2.4「列表即选项」——返回集即可回滚目标全集)。

func (*Store) ListStateBackups

func (s *Store) ListStateBackups(ctx context.Context, n int) ([]StateBackup, error)

ListStateBackups 按 created_at 倒序返回最近 n 条台账(n<=0 = 全部—— 台账量级 = 保留份数 + 失败行,天花板低)。

func (*Store) ListTokens

func (s *Store) ListTokens(ctx context.Context) ([]Token, error)

ListTokens 返回全部在册(未吊销)token(created_at 升序)。

func (*Store) MarkAllNodesStale

func (s *Store) MarkAllNodesStale(ctx context.Context) error

MarkAllNodesStale 将全部缓存行置 stale=1(底座不可达的降级读契约: 内容可能是旧值),observed_at/last_seen_at 不动(仍指最后一次真实 观测)。无行时为 no-op。

func (*Store) MarkAppDeleted

func (s *Store) MarkAppDeleted(ctx context.Context, appID string) error

MarkAppDeleted 推进 deleting → deleted(tombstone 第二拍)。仅允许从 deleting 出发——active 直达 deleted 被拒绝(状态机纪律,防跳过清理)。

func (*Store) MarkAppDeleting

func (s *Store) MarkAppDeleting(ctx context.Context, appID string) error

MarkAppDeleting 推进 active → deleting(tombstone 第一拍)。仅允许从 active 出发;deleting/deleted 重复进入返回 ErrInvalidLifecycleTransition。

func (*Store) MarkAppEnvEffective

func (s *Store) MarkAppEnvEffective(ctx context.Context, appID string) (int, error)

MarkAppEnvEffective 把该 app 全部 pending 行提升为 effective(部署成功 终态后的消费点,observing.go succeedDeployment 在 env 注入并成功后调用; kind=rollback 不提升——重放的 env 随快照,pending 未被本次部署消费), 返回提升行数。幂等。

func (*Store) MarkAppVolumesOrphaned

func (s *Store) MarkAppVolumesOrphaned(ctx context.Context, appID string) (int, error)

MarkAppVolumesOrphaned 把该 app 全部 active 卷置 orphaned(应用删除默认 保留卷语义;调用方在 tombstone 流程触发)。返回置孤儿卷数。幂等。

func (*Store) NextQueuedBuilds

func (s *Store) NextQueuedBuilds(ctx context.Context, limit int) ([]BuildRecord, error)

NextQueuedBuilds 返回最早入队的至多 limit 条 queued 记录(FIFO 排队语义, 队列 worker 的候选扫描;claim 由 ClaimBuild 原子完成)。

func (*Store) NextQueuedDeployments

func (s *Store) NextQueuedDeployments(ctx context.Context, limit int) ([]DeployRecord, error)

NextQueuedDeployments 返回最早入队的至多 limit 条 queued 记录(FIFO)。

func (*Store) OldestSeq

func (s *Store) OldestSeq(ctx context.Context) (int64, bool, error)

OldestSeq 返回保留窗内最旧事件的 seq;事件表为空时返回 (0, false)。

func (*Store) Path

func (s *Store) Path() string

Path 返回数据库文件路径。

func (*Store) Ping

func (s *Store) Ping(ctx context.Context) error

Ping 探测数据库可用性。

func (*Store) PlacementByApp

func (s *Store) PlacementByApp(ctx context.Context, appIDs []string) (map[string]Placement, error)

PlacementByApp 批量取一组应用的绑定记录。S18-A4:ListApps 派生状态的 N+1 收口——N 个 app 的绑定从 N 次 GetPlacement 并为一次 IN 查询。 空 appIDs 直接返回空 map(不发 SQL);map 中不出现的键 = 该 app 无 绑定记录(ErrPlacementNotFound 的批量等价形态——无绑定是合法运行态, 不以错误表达)。

func (*Store) PruneExpiredAudits

func (s *Store) PruneExpiredAudits(ctx context.Context, cutoff time.Time) (int64, error)

PruneExpiredAudits 删除早于 cutoff 的审计记录,返回清理条数 (审计保留期默认 1 年,state-model §2.9)。分批形态同 PruneExpiredEvents。

func (*Store) PruneExpiredEvents

func (s *Store) PruneExpiredEvents(ctx context.Context, cutoff time.Time) (int64, error)

PruneExpiredEvents 删除早于 cutoff 的事件,返回清理条数(保留期清理 job 的执行体;job 编排在 janitor.go)。S18-A10:分批循环删除(子查询 限定每批 500 行——modernc SQLite 不支持 DELETE...LIMIT 语法,子查询形态 承载批量语义)。

func (*Store) PruneTerminalBuildsOlderThan

func (s *Store) PruneTerminalBuildsOlderThan(ctx context.Context, cutoff time.Time) (int64, error)

PruneTerminalBuildsOlderThan 分批删除终态早于 cutoff 的构建行(S18-A10: builds 台账 90 天保留窗;finished_at 是终态时刻,零值行不删——防御存量 脏数据)。分批形态与事件/审计清理一致(见 PruneExpiredEvents)。

func (*Store) RecentAudits

func (s *Store) RecentAudits(ctx context.Context, n int) ([]AuditRecord, error)

RecentAudits 按 at 倒序返回最近 n 条审计记录。

func (*Store) RecordStateBackup

func (s *Store) RecordStateBackup(ctx context.Context, w BackupWrite) (StateBackup, error)

RecordStateBackup 落一行备份台账(与审计同事务,fail-closed:审计写不出 合法行则台账行一并回滚——备份账与审计账互为证据)。kind/verify 词表 校验在此收口,非法值整单拒绝。

func (*Store) RegisterAppVolume

func (s *Store) RegisterAppVolume(ctx context.Context, w VolumeWrite) (Volume, bool, error)

RegisterAppVolume 登记卷(重新声明转 active——孤儿卷被应用重新声明即 复活;数据不随声明删除,name/node 等事实字段以最新声明为准)。created_at 首次落账后保持(防代际静默复用的叙事锚)。返回 isNew:首次登记为 true (调用方据此发 volume.created 事件——数据诞生点)。

func (*Store) RemoveGitKey

func (s *Store) RemoveGitKey(ctx context.Context, id, actorTokenID string) error

RemoveGitKey 物理删除一条 git key(历史在审计可查)并与审计(gitkey. remove)同事务 fail-closed;不存在返回 ErrGitKeyNotFound。

func (*Store) ReplaceAppDomains

func (s *Store) ReplaceAppDomains(ctx context.Context, appID string, declared []DomainServiceRoutes) error

ReplaceAppDomains 把应用的域名台账对账到声明集(发布同步语义, architecture §2.4 域名行):声明集内逐域名 upsert(归属 service/端口变更 即改写),台账中声明集之外的本应用行删除。幂等;单一写事务(fail-closed)。

func (*Store) ResetInterruptedBuilds

func (s *Store) ResetInterruptedBuilds(ctx context.Context, errorCode, reason string) (int, error)

ResetInterruptedBuilds 复位全部 building 行为 failed 终态并返回实际复位 行数(daemon 启动恢复:崩溃/关停时在途构建无人收敛——NextQueuedBuilds 只扫 queued,遗留 building 行永不重跑,等它的部署在引擎侧空转到发布 超时)。逐行经 FailStrandedBuild 的 CAS building→failed(行级谓词,与 ClaimBuild 同款竞争语义:复位时行已被并发收敛/已终态则跳过不误伤), finished_at 盖章、审计 build.finish 逐行同事务;reason 进审计 diff。 queued 行不动(本方法只扫 building;重启后队列自然重扫认领)。

func (*Store) RevokeToken

func (s *Store) RevokeToken(ctx context.Context, id, actorTokenID string) error

RevokeToken 吊销 token(幂等:已吊销返回成功;不存在返回 ErrTokenNotFound)。与审计同事务 fail-closed。

func (*Store) RevokeTokenGuardLastAdmin

func (s *Store) RevokeTokenGuardLastAdmin(ctx context.Context, id, actorTokenID string, isAdmin func(scopes string) bool) error

RevokeTokenGuardLastAdmin 是带最后管理员守卫的吊销(M4-6):吊销生效后 仍须存在 ≥1 枚未吊销 admin token,否则整笔回滚返回 ErrTokenLastAdmin (幂等面与 RevokeToken 一致:目标已吊销 = 幂等成功,不触发守卫——没有 新的吊销发生;不存在仍 ErrTokenNotFound)。守卫判定与吊销在同一事务内 (先 UPDATE 再复查剩余在册行,不满足即返回错误回滚),消除「检查与吊销 分离」的竞态窗。isAdmin 由调用方注入(scope 蕴含判定 admin ⊃ deploy ⊃ read 属 api 层语义,本层不解释 scopes 词表——本层只提供原子性)。

func (*Store) SchemaVersion

func (s *Store) SchemaVersion(ctx context.Context) (int64, error)

SchemaVersion 返回已应用迁移版本(goose 版本表最大 version_id;manifest 的 schema_version 字段来源)。空库不该发生(Open 即迁移),查询失败照 实上抛。

func (*Store) SetAppEnv

func (s *Store) SetAppEnv(ctx context.Context, appID, key, value, source string) (EnvVar, error)

SetAppEnv 创建或更新平台 env(同 app 同 key 唯一):写值并把 status 重置 为 pending(既有 effective 行被覆盖同样回到 pending——生效语义 = 下次部署 消费)。审计同事务 fail-closed,diff 摘要只含键名与状态,不含值。 source 取 platform / system;留空回落 platform。

func (*Store) SetAppSource

func (s *Store) SetAppSource(ctx context.Context, appID string, w AppSourceWrite) error

SetAppSource 写入拉源配置(branch 同步承载 push 触发分支语义)。与审计 (app.source_set)同事务 fail-closed。

func (*Store) SetAppWebhookSecret

func (s *Store) SetAppWebhookSecret(ctx context.Context, appID, ciphertext, actorTokenID string) error

SetAppWebhookSecret 设置/清除 webhook 签名密钥(ciphertext 为 envelope 密文;空串 = 清除,端点回到未启用语义)。与审计(app.webhook_secret_set) 同事务 fail-closed;动作可能是清除——diff 如实记录 set/clear。

func (*Store) SetBuildLogPath

func (s *Store) SetBuildLogPath(ctx context.Context, id, logPath string) error

SetBuildLogPath 回填 building 行的 log_path(M2-5:构建产物目录就位即写 ——log_path 原先唯一写点在 FinishBuildSucceeded,失败终态行恒空,失败 取证(日志尾部 + log_path context)落空)。行级谓词限定 building:终态 行不动(成功终态的 log_path 由 FinishBuildSucceeded 权威写入);0 行更新 (行已终态/不存在)静默成功——回填是 best-effort 观测面而非状态机事件, 无审计、不因竞态报错。

func (*Store) SetDomainCert

func (s *Store) SetDomainCert(ctx context.Context, appID, domain, certSHA256 string, notAfter time.Time) error

SetDomainCert 登记证书材料(sha256 + 叶到期时间;同事务刷新登记时间)。 未命中(域名已被同步删除)返回 ErrDomainNotFound——签发晚于域名撤销的 竞态安全路径。

func (*Store) SetMeta

func (s *Store) SetMeta(ctx context.Context, key, value string) error

SetMeta 写入(upsert)meta 键值。

func (*Store) SyncNodeObservations

func (s *Store) SyncNodeObservations(ctx context.Context, nodes []SubstrateNode, at time.Time) error

SyncNodeObservations 全量写入一拍观测快照:upsert 全部节点(observed_at = at、stale 清零、last_seen_at 取 max(旧值, at))并在同事务内修剪快照 中已消失的节点行(缓存可整表重建,消失即删;节点下线叙事属 events 表 历史,产品事件随后续票接入)。

func (*Store) TerminalDeploymentIDsOlderThan

func (s *Store) TerminalDeploymentIDsOlderThan(ctx context.Context, cutoff time.Time) (map[string]bool, error)

TerminalDeploymentIDsOlderThan 返回终态早于 cutoff 的部署 ID 集合 (S18-A7:janitor 按「终态后 30 天窗」清理 deployments/<id>/ compose 持久化目录的判据来源;updated_at 是终态写入时刻的最近似代理——终态 不可逆,终态行此后只有 flag 类就地更新)。单查询全量返回,janitor 周期 (小时级)消费。

func (*Store) TouchTokenUsed

func (s *Store) TouchTokenUsed(ctx context.Context, id string) error

TouchTokenUsed 刷新 last_used_at(尽力而为观测面;token 已消失时静默)。

func (*Store) UpdateDeployment

func (s *Store) UpdateDeployment(ctx context.Context, id string, p DeploymentPatch) error

UpdateDeployment 按补丁更新部署行。PrevStatus 非 nil 时为 CAS 迁移 (当前状态 ≠ PrevStatus → ErrDeploymentStateTransition,RowsAffected=0), 且**先经转移表校验** PrevStatus → Status 合法(S16-C5:表外组合是确定性 编码错误,拒写返回 ErrIllegalTransition——即使当前行恰好仍是 from 状态 也不落库);携带 Status 而 PrevStatus 为 nil 时拒绝(M3-2:状态写必须 带 from 谓词,引擎单写点纪律);两者皆 nil 时不带状态谓词(子状态/时间 锚/告警位等就地更新,仅受终态不可逆守卫)。updated_at 恒重盖。同一补丁 内 Status 与字段一并原子生效。

func (*Store) UpsertRuntimeNodeRef

func (s *Store) UpsertRuntimeNodeRef(ctx context.Context, platformID, swarmNodeID string, anchoredAt time.Time) (bool, error)

UpsertRuntimeNodeRef 维护平台节点 ID ↔ Swarm node ID 适配器映射 (state-model §2.3:映射本身可从节点 label 反建;身份 label 被删改后 对账器自动重放的依据)。返回是否发生了变更(供调用方决定是否审计)。 同一 swarm_node_id 换绑到新 platform_id 视为换机/重建,拒绝并返回 ErrVersionConflict 复用冲突语义(重绑走人工 rebind,平台不猜测)。

func (*Store) VacuumInto

func (s *Store) VacuumInto(ctx context.Context, target string) error

VacuumInto 产出数据库一致性快照到 target 路径(SQLite VACUUM INTO—— 单语句原子:读事务内整库落盘,WAL 下与读写并行安全;目标文件必须不 存在,由 SQLite 自身强制。目标经绑定参数下发——SQLite 的 INTO 子句 接受表达式实参,modernc 驱动实证支持,无字面量拼接面)。

type SubstrateEvent

type SubstrateEvent struct {
	Type   string
	Action string
	At     time.Time
}

SubstrateEvent 是一次底座事件(仅作观测缓存失效信号)。

type SubstrateNode

type SubstrateNode struct {
	// SwarmNodeID 是底座节点 ID(runtime_node_refs 映射的键)。
	SwarmNodeID string
	// Hostname 是底座节点主机名(显示名)。
	Hostname string
	// State 是底座节点状态(ready/down/disconnected/unknown 逐字镜像)。
	State string
	// Availability 是底座节点可用性(active/pause/drain 逐字镜像)。
	Availability string
	// IsManager 报告该节点是否承担 manager 角色。
	IsManager bool
	// Version 是底座节点对象版本(节点 label 写入的乐观令牌)。
	Version ObjectVersion
	// Labels 是节点全部 label(含 fleetly.node-id 身份锚)。
	Labels map[string]string
}

SubstrateNode 是一次节点观测快照(nodes 表行来源)。State/Availability 逐字镜像底座(平台不制造节点健康语义,state-model §2.3)。

type Token

type Token struct {
	ID string
	// TokenHash 是明文 token 的 sha256 hex(64 字符)。
	TokenHash string
	// Name 是人读备注(proto 面 note;建行时落)。
	Name string
	// Scopes 是逗号分隔 scope 词表(如 "read,deploy")。
	Scopes string
	// HashPrefix 是 TokenHash 前 12 hex(识别用,非凭据)。
	HashPrefix string
	CreatedAt  time.Time
	// LastUsedAt 零值 = 从未使用。
	LastUsedAt time.Time
	// RevokedAt 零值 = 在册。
	RevokedAt time.Time
}

Token 是一条 API token 行(只读投影;明文不存在于任何通道)。

type TokenWrite

type TokenWrite struct {
	// ID 留空自动生成 ULID。
	ID string
	// Hash 必须是 HashToken 产物形态(64 hex sha256);非法形态拒绝
	//(防御性,防旁路写入明文)。
	Hash string
	// Name 是人读备注(proto 面 note)。
	Name string
	// Scopes 是逗号分隔 scope 词表(调用方已归一,如 "read,deploy")。
	Scopes string
	// ActorTokenID 是发起写入的调用方 token(可空——bootstrap 种子无调用
	// 方 token);入审计 fail-closed。
	ActorTokenID string
	// Actor 是审计主体(human/ai_agent/system;空回落 human——系统代签发
	// 的 token 如 git push 钩子回调 token 传 system,T2.19)。
	Actor string
}

TokenWrite 是一次 token 写入。

type Tx

type Tx struct {
	*sql.Tx
}

Tx 是写事务句柄:业务写 + 审计 + 事件在同一事务内组合。

func (*Tx) AppendEvent

func (t *Tx) AppendEvent(ctx context.Context, e Event) (int64, error)

AppendEvent 在事务内追加事件并返回分配的 seq:AUTOINCREMENT 保证 seq 严格单调且被保留期清理删除后不复用(sqlite_sequence 记录历史最大值), SSE 游标语义因此可依赖「seq 不回退、不断号不透明化」——断档必须经 E_EVENT_CURSOR_EXPIRED 显式暴露。与业务写同事务 = Outbox 模式。

func (*Tx) BindPlacement

func (t *Tx) BindPlacement(ctx context.Context, w PlacementWrite) (Placement, error)

BindPlacement 是事务内绑定写(供与审计/事件同事务组合)。

func (*Tx) CountGitDeploymentsForSHA

func (t *Tx) CountGitDeploymentsForSHA(ctx context.Context, appID, sha string) (int64, error)

CountGitDeploymentsForSHA 是事务内的同口径复查(M3-4:webhook sha 幂等 去重的竞态闭合——COUNT 与 INSERT 必须同事务。Store 层各事务以 BEGIN IMMEDIATE 起手取写锁(见 store.go dsn),两路并发同 sha 入队在写锁上 串行化,后到事务的 COUNT 必然看到先行事务已提交的行 → 返回 ErrDuplicateGitDeployment 判据由调用方在建行前消费)。词法口径与 Store.CountGitDeploymentsForSHA 逐字一致。

func (*Tx) CreateApp

func (t *Tx) CreateApp(ctx context.Context, appID, name string) (App, error)

CreateApp 是事务内创建应用。

func (*Tx) CreateBuild

func (t *Tx) CreateBuild(ctx context.Context, rec BuildRecord) (BuildRecord, error)

CreateBuild 是事务内创建 queued 构建记录。

func (*Tx) CreateDeployment

func (t *Tx) CreateDeployment(ctx context.Context, rec DeployRecord) (DeployRecord, error)

CreateDeployment 在事务内创建 queued 部署行(发布入队原语,H13)。 fail-closed 语义:入队调用方应把本 INSERT 与 deployment 事件、审计写在 同一 InTx 回调内——回调内任一写失败(含事件/审计写失败)即整体回滚, 部署行不落库,杜绝「部署行已存在、引擎照常执行但事件与审计缺失」的 审计黑洞。kind 取 deploy|rollback(校验在此层);actor 语义在调用方 (CLI=human、引擎=system)。

func (*Tx) CreateRevision

func (t *Tx) CreateRevision(ctx context.Context, w RevisionWrite) (Revision, error)

CreateRevision 在事务内创建 verified=1 的版本快照(seq = app 内 max+1)。 与部署终态写、审计同事务组合(fail-closed)。

func (*Tx) EnterPhase

func (t *Tx) EnterPhase(ctx context.Context, id string, from, to DeploymentStatus, extra DeploymentPatch, events ...Event) error

EnterPhase 是事务内的转换写点原语(语义见 Store.EnterPhase)。

func (*Tx) GetAppDerivedState

func (t *Tx) GetAppDerivedState(ctx context.Context, appID string) (string, error)

GetAppDerivedState 是事务内读派生状态(事件翻转与 CAS 同事务的组合点)。

func (*Tx) GetAppDriftConverge

func (t *Tx) GetAppDriftConverge(ctx context.Context, appID string) (bool, error)

GetAppDriftConverge 是事务内读 opt-in 位(与清位写同事务的组合点)。

func (*Tx) GetAppEnv

func (t *Tx) GetAppEnv(ctx context.Context, appID, key string) (EnvVar, error)

GetAppEnv 是事务内取单条(供写后回读)。

func (*Tx) GetAppVolume

func (t *Tx) GetAppVolume(ctx context.Context, appID, key string) (Volume, error)

GetAppVolume 是事务内取单卷(写后回读)。

func (*Tx) GetPlacement

func (t *Tx) GetPlacement(ctx context.Context, appID string) (Placement, error)

GetPlacement 是事务内取绑定(供 CAS 前置读取)。

func (*Tx) MarkAppDeleted

func (t *Tx) MarkAppDeleted(ctx context.Context, appID string) error

MarkAppDeleted 是事务内 tombstone 第二拍(H10/MG-3:与终局事件/审计 同事务组合的形态——引擎 deleting 回收 duty 在受管服务全部移除后原子 落终态,进程在「迁移已落、事件未发」之间崩溃的披露缺口不存在)。

func (*Tx) MarkAppDeleting

func (t *Tx) MarkAppDeleting(ctx context.Context, appID string) error

MarkAppDeleting 是事务内 tombstone 第一拍(供与审计/事件同事务组合—— T2.17 API 删除走 fail-closed 审计)。

func (*Tx) RegisterAppVolume

func (t *Tx) RegisterAppVolume(ctx context.Context, w VolumeWrite) (Volume, error)

RegisterAppVolume 是事务内卷登记(供与事件等同事务组合)。

func (*Tx) ReplaceAppDomains

func (t *Tx) ReplaceAppDomains(ctx context.Context, appID string, declared []DomainServiceRoutes) error

ReplaceAppDomains 是事务内对账域名台账。

func (*Tx) ReusableRevisionByDesiredHash

func (t *Tx) ReusableRevisionByDesiredHash(ctx context.Context, appID, desiredHash string) (Revision, bool, error)

ReusableRevisionByDesiredHash 在事务内裁决成功固化的幂等复用(S18-A6): 按 (app_id, desired_hash) 查既有 active 快照,**且该行同时是该 app 最新 active 快照**时返回复用(seq 不递增、不重复插入);否则返回未命中走插入。

「最新 active」判据兼顾两侧契约:

  • 崩溃重放幂等:两事务间崩溃留下的残行必然是最新 active(同 app 互斥 ——残行所属部署未终态,同 app 无更晚成功部署),命中复用,重跑窗口 再固化不产生重复行;
  • 回滚/旧态重部署语义:目标 hash 的既有行不是最新(其后已有更新版本) 时不复用——按新 revision 固化,回退版本在「列表即选项」里前移到最新 位(release-semantics §2.4「回滚 = 一次成功部署」)。

superseded 行(保留窗外存档)恒不复用;空哈希(旧形态行)无可比性, 恒走插入。

func (*Tx) SetAppDerivedState

func (t *Tx) SetAppDerivedState(ctx context.Context, appID, expected, next string) error

SetAppDerivedStateIfCAS 派生状态翻转(CAS):当前值 ≠ expected 时返回 ErrAppDerivedStateConflict(并发翻转已发生,调用方重读重算、不重发事件)。 与事件写入同事务组合由调用方完成(传入同一 tx)。

func (*Tx) SetAppDriftConverge

func (t *Tx) SetAppDriftConverge(ctx context.Context, appID string, on bool) error

SetAppDriftConverge 置位/清除漂移收敛 opt-in(幂等写;审计由调用方与 本写同事务组合——fail-closed)。

func (*Tx) SetAppEnv

func (t *Tx) SetAppEnv(ctx context.Context, appID, key, value, source string) (EnvVar, error)

SetAppEnv 是事务内 env 写(供与事件等同事务组合)。

func (*Tx) SetMeta

func (t *Tx) SetMeta(ctx context.Context, key, value string) error

SetMeta 在事务内 upsert meta 键值(供与审计/业务写同事务组合)。

func (*Tx) UpdateDeployment

func (t *Tx) UpdateDeployment(ctx context.Context, id string, p DeploymentPatch) error

UpdateDeployment 是事务内的行更新原语(S18-A6:成功终态 CAS 与 revision 固化、事件、审计组合在同一 InTx——两事务间崩溃不再留下「revision 已 固化、部署仍 observing」的重放窗口)。语义与 Store 同名方法逐字一致。

func (*Tx) WriteAudit

func (t *Tx) WriteAudit(ctx context.Context, e AuditEntry) error

WriteAudit 在事务内追加审计记录:与同事务内的业务写原子生效或原子 回滚。表级 CHECK(actor/action 非空、result 枚举)使非法审计行直接 产生数据库错误,调用方不得吞掉——这是 fail-closed 的验证路径 (audit_test.go 用真实约束违例证明业务写随之回滚)。

type VersionResolver

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

VersionResolver 是写前直读端口。零状态,直读结果绝不落缓存。

func NewVersionResolver

func NewVersionResolver(d DockerClient) *VersionResolver

NewVersionResolver 构造直读端口。

func (*VersionResolver) CheckVersion

func (r *VersionResolver) CheckVersion(ctx context.Context, kind ObjectKind, id string, expected ObjectVersion) error

CheckVersion 校验调用方持有的令牌是否仍与底座当前版本一致:不一致 (或对象已消失)返回 E_STATE_VERSION_CONFLICT(409)。

func (*VersionResolver) ResolveVersion

func (r *VersionResolver) ResolveVersion(ctx context.Context, kind ObjectKind, id string) (ObjectVersion, error)

ResolveVersion 直读底座对象当前版本作乐观令牌。对象已不存在视为并发 冲突的特例(有人删了它):返回 E_STATE_VERSION_CONFLICT(409,context 标注 reason=object_not_found),不发明清单外错误码。底层传输错误原样 透传(不打契约码)。

type Volume

type Volume struct {
	ID             string
	AppID          string
	Key            string
	Name           string
	Kind           VolumeKind
	PlatformNodeID string
	MountPath      string
	HostPath       string
	Status         VolumeStatus
	CreatedAt      time.Time
	UpdatedAt      time.Time
}

Volume 是卷注册表行投影。Name 即设计表的 docker_name(命名约定值)。

type VolumeKind

type VolumeKind string

VolumeKind 是卷类别词表。

const (
	// VolumeKindNamed 命名卷(v0.1 受控子集唯一支持的挂载形态)。
	VolumeKindNamed VolumeKind = "named"
	// VolumeKindBind 宿主绑定挂载(v0.1 校验拒绝;词表先行对齐设计表)。
	VolumeKindBind VolumeKind = "bind"
)

type VolumeStatus

type VolumeStatus string

VolumeStatus 是卷注册表状态位。

const (
	// VolumeActive 在册(被应用声明或已钉节点)。
	VolumeActive VolumeStatus = "active"
	// VolumeOrphaned 应用已删除/解绑,卷保留可发现。
	VolumeOrphaned VolumeStatus = "orphaned"
	// VolumeDiscarded 显式丢弃(admin+confirm+审计)。
	VolumeDiscarded VolumeStatus = "discarded"
)

type VolumeWrite

type VolumeWrite struct {
	AppID          string
	Key            string
	Name           string
	Kind           VolumeKind
	PlatformNodeID string
	MountPath      string
	HostPath       string
}

VolumeWrite 是一次卷登记写入(按 app_id+key 唯一 upsert)。Name 必须 由调用方按命名约定生成(internal/naming.VolumeName)——本层不解释命名。

func (VolumeWrite) Validate

func (w VolumeWrite) Validate() error

Validate 校验 VolumeWrite 词表(kind 必须在册)。

Jump to

Keyboard shortcuts

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