feat(workspace): domain types + pathing/validation

This commit is contained in:
2026-05-01 22:02:11 +08:00
parent b44d6c298c
commit e5800ef5dc
3 changed files with 320 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
// Package workspace 承载 Workspace / Worktree / GitOps 三个 service 的领域类型与
// 接口契约。沿 PM 模块(internal/project)的"单包多 service"风格:聚合在 schema
// 上紧耦合,分包反而要互相 import。
package workspace
import (
"context"
"time"
"github.com/google/uuid"
"github.com/yan1h/agent-coding-workflow/internal/infra/git"
)
// SyncStatus 与 DB CHECK 约束完全一致。
type SyncStatus string
// SyncStatus 枚举值,与 migrations/0003 的 CHECK 约束完全一致。
const (
SyncStatusCloning SyncStatus = "cloning"
SyncStatusIdle SyncStatus = "idle"
SyncStatusSyncing SyncStatus = "syncing"
SyncStatusError SyncStatus = "error"
)
// IsValid 报告 s 是否在枚举集合内。
func (s SyncStatus) IsValid() bool {
switch s {
case SyncStatusCloning, SyncStatusIdle, SyncStatusSyncing, SyncStatusError:
return true
}
return false
}
// WorktreeStatus 与 DB CHECK 约束完全一致。
type WorktreeStatus string
// WorktreeStatus 枚举值,与 migrations/0003 的 CHECK 约束完全一致。
const (
WorktreeStatusIdle WorktreeStatus = "idle"
WorktreeStatusActive WorktreeStatus = "active"
WorktreeStatusPruning WorktreeStatus = "pruning"
)
// CredentialKind 与 DB CHECK 约束完全一致;与 git.CredentialKind 同值,但分开
// 定义避免业务包对 infra/git 类型的强依赖。
type CredentialKind string
// CredentialKind 枚举值,与 migrations/0003 的 CHECK 约束完全一致。
const (
CredKindPAT CredentialKind = "pat"
CredKindSSHKey CredentialKind = "ssh_key"
CredKindNone CredentialKind = "none"
)
// IsValid 报告 k 是否在枚举集合内。
func (k CredentialKind) IsValid() bool {
return k == CredKindPAT || k == CredKindSSHKey || k == CredKindNone
}
// Workspace 是顶层聚合根。
type Workspace struct {
ID uuid.UUID
ProjectID uuid.UUID
Slug string
Name string
Description string
GitRemoteURL string
DefaultBranch string
MainPath string
SyncStatus SyncStatus
LastSyncedAt *time.Time
LastSyncError string
CreatedAt time.Time
UpdatedAt time.Time
}
// Worktree 表示一个支线 worktree(不含 main_path)。
type Worktree struct {
ID uuid.UUID
WorkspaceID uuid.UUID
Branch string
Path string
Status WorktreeStatus
ActiveHolder string // "user:<uid>" / "session:<sid>" / 空
AcquiredAt *time.Time
LastUsedAt time.Time
CreatedAt time.Time
}
// Credential 是 git_credentials 表的领域投影。Secret 仅在创建/更新时有值,
// 读取路径上 Service 永远不返回明文 secret。Fingerprint 是给前端展示的脱敏串。
type Credential struct {
ID uuid.UUID
WorkspaceID uuid.UUID
Kind CredentialKind
Username string
Secret []byte // 写路径填明文;读路径恒为 nil
Fingerprint string
CreatedAt time.Time
UpdatedAt time.Time
}
// Caller 表示发起请求的用户上下文。Service 据此判定鉴权与 holder 字符串。
type Caller struct {
UserID uuid.UUID
IsAdmin bool
}
// Holder 把 Caller 折成 acquire_holder 字符串。Plan #4 的 ACP supervisor 会用
// "session:<sid>" 形式调相同接口。
func (c Caller) Holder() string {
return "user:" + c.UserID.String()
}
// ===== Service 接口 =====
// WorkspaceService 暴露 Workspace 聚合根的应用服务方法。
//
//nolint:revive // 名字带聚合前缀比 "Service" 更准确:包内有 3 个并列服务接口
type WorkspaceService interface {
Create(ctx context.Context, c Caller, projectSlug string, in CreateWorkspaceInput) (*Workspace, error)
Get(ctx context.Context, c Caller, wsID uuid.UUID) (*Workspace, error)
List(ctx context.Context, c Caller, projectSlug string) ([]*Workspace, error)
Update(ctx context.Context, c Caller, wsID uuid.UUID, in UpdateWorkspaceInput) (*Workspace, error)
Delete(ctx context.Context, c Caller, wsID uuid.UUID) error
Sync(ctx context.Context, c Caller, wsID uuid.UUID) (*Workspace, error)
UpsertCredential(ctx context.Context, c Caller, wsID uuid.UUID, in UpsertCredentialInput) (*Credential, error)
GetCredentialMeta(ctx context.Context, c Caller, wsID uuid.UUID) (*Credential, error)
}
// WorktreeService 暴露支线 worktree 的应用服务方法。
type WorktreeService interface {
Create(ctx context.Context, c Caller, wsID uuid.UUID, in CreateWorktreeInput) (*Worktree, error)
List(ctx context.Context, c Caller, wsID uuid.UUID) ([]*Worktree, error)
Delete(ctx context.Context, c Caller, wtID uuid.UUID) error
Acquire(ctx context.Context, c Caller, wtID uuid.UUID) (*Worktree, error)
Release(ctx context.Context, c Caller, wtID uuid.UUID) (*Worktree, error)
}
// GitOpsService 暴露 status/commit/push 操作。target 既可以是 Workspace(main_path)
// 也可以是 Worktree。
type GitOpsService interface {
StatusOnMain(ctx context.Context, c Caller, wsID uuid.UUID) ([]git.FileStatus, error)
CommitOnMain(ctx context.Context, c Caller, wsID uuid.UUID, in CommitInput) (string, error)
PushOnMain(ctx context.Context, c Caller, wsID uuid.UUID) error
StatusOnWorktree(ctx context.Context, c Caller, wtID uuid.UUID) ([]git.FileStatus, error)
CommitOnWorktree(ctx context.Context, c Caller, wtID uuid.UUID, in CommitInput) (string, error)
PushOnWorktree(ctx context.Context, c Caller, wtID uuid.UUID) error
}
// ===== Input DTO =====
// CreateWorkspaceInput 携带创建 Workspace 与其凭据的字段。
type CreateWorkspaceInput struct {
Slug string
Name string
Description string
GitRemoteURL string
DefaultBranch string
Credential UpsertCredentialInput
}
// UpdateWorkspaceInput 是 patch 输入:nil = 保持原值。
type UpdateWorkspaceInput struct {
Name *string
Description *string
DefaultBranch *string
}
// UpsertCredentialInput 创建或替换 git 凭据。Secret 是明文(PAT token / SSH 私钥 PEM)。
type UpsertCredentialInput struct {
Kind CredentialKind
Username string // PAT 时填
Secret []byte // PAT/SSH 时填;None 时为空
}
// CreateWorktreeInput 创建支线 worktree。BaseBranch 留空时用 workspace.DefaultBranch。
type CreateWorktreeInput struct {
Branch string
BaseBranch string
}
// CommitInput 提交描述。AddAll 留 false 等价于"已经手动 git add",默认 service
// 调用方传 true(与 4.4 端点 default 对齐)。
type CommitInput struct {
Message string
Push bool
AddAll bool
}