// Package automation owns MeshX automation run ledger persistence.
package automation

import "time"

const (
	AutomationRunStatusQueued    = "queued"
	AutomationRunStatusRunning   = "running"
	AutomationRunStatusWaiting   = "waiting"
	AutomationRunStatusBlocked   = "blocked"
	AutomationRunStatusFailed    = "failed"
	AutomationRunStatusSucceeded = "succeeded"
	AutomationRunStatusCanceled  = "canceled"
)

const (
	AutomationJobRunStatusPending   = "pending"
	AutomationJobRunStatusReady     = "ready"
	AutomationJobRunStatusQueued    = "queued"
	AutomationJobRunStatusLeased    = "leased"
	AutomationJobRunStatusRunning   = "running"
	AutomationJobRunStatusWaiting   = "waiting"
	AutomationJobRunStatusBlocked   = "blocked"
	AutomationJobRunStatusFailed    = "failed"
	AutomationJobRunStatusSucceeded = "succeeded"
	AutomationJobRunStatusSkipped   = "skipped"
	AutomationJobRunStatusCanceled  = "canceled"
)

const (
	AutomationJobStatusReady    = "ready"
	AutomationJobStatusLeased   = "leased"
	AutomationJobStatusDone     = "done"
	AutomationJobStatusFailed   = "failed"
	AutomationJobStatusCanceled = "canceled"
)

const (
	AutomationWaitStatusActive   = "active"
	AutomationWaitStatusResolved = "resolved"
	AutomationWaitStatusCanceled = "canceled"
)

const (
	AutomationWaitKindAgentTask = "agent_task"
	AutomationWaitKindWaitEvent = "wait_event"
)

const (
	AutomationRunnerStatusActive  = "active"
	AutomationRunnerStatusRevoked = "revoked"
)

const (
	AutomationRunnerTokenKindRegistration  = "registration"
	AutomationRunnerTokenKindSession       = "session"
	AutomationRunnerTokenKindActionsAccess = "actions_access"
)

const (
	AutomationRunnerSessionStatusActive  = "active"
	AutomationRunnerSessionStatusRevoked = "revoked"
)

const (
	AutomationRepoStatusStatePending = "pending"
	AutomationRepoStatusStateSuccess = "success"
	AutomationRepoStatusStateFailure = "failure"
	AutomationRepoStatusStateError   = "error"
)

const (
	AutomationRepoStatusOutboxStatusPending   = "pending"
	AutomationRepoStatusOutboxStatusDelivered = "delivered"
	AutomationRepoStatusOutboxStatusFailed    = "failed"
)

// AutomationContentPublication is the automation-owned projection that makes
// one ContentVersion ready for idempotent outbox consumption.
type AutomationContentPublication struct {
	WorkspaceID      string    `gorm:"primaryKey;size:64"`
	ContentID        string    `gorm:"primaryKey;size:64"`
	ContentVersionID string    `gorm:"primaryKey;size:64"`
	RepositoryOwner  string    `gorm:"size:128;not null"`
	RepositoryName   string    `gorm:"size:128;not null"`
	Ref              string    `gorm:"size:255;not null;default:''"`
	ChangedPathsJSON string    `gorm:"type:text;not null"`
	ActorID          string    `gorm:"size:64;not null"`
	CreatedAt        time.Time `gorm:"not null"`
}

func (AutomationContentPublication) TableName() string {
	return "automation_content_publications"
}

// AutomationContentRepository is the bounded current projection used by the
// Automation repository picker. Historical versions never participate in the
// list query.
type AutomationContentRepository struct {
	WorkspaceID      string    `gorm:"primaryKey;size:64"`
	RepositoryOwner  string    `gorm:"primaryKey;size:128"`
	RepositoryName   string    `gorm:"primaryKey;size:128"`
	ContentID        string    `gorm:"size:64;not null"`
	ContentVersionID string    `gorm:"size:64;not null"`
	Ref              string    `gorm:"size:255;not null;default:''"`
	UpdatedAt        time.Time `gorm:"not null"`
}

func (AutomationContentRepository) TableName() string {
	return "automation_content_repositories"
}

// AutomationContentDefinition records one bounded definition path in an exact
// immutable publication. It never carries a repository ref or payload key.
type AutomationContentDefinition struct {
	WorkspaceID      string    `gorm:"primaryKey;size:64"`
	ContentID        string    `gorm:"primaryKey;size:64"`
	ContentVersionID string    `gorm:"primaryKey;size:64"`
	DefinitionPath   string    `gorm:"primaryKey;size:512"`
	Digest           string    `gorm:"size:64;not null"`
	SizeBytes        int64     `gorm:"not null"`
	CreatedAt        time.Time `gorm:"not null"`
}

func (AutomationContentDefinition) TableName() string {
	return "automation_content_definitions"
}

// AutomationRun records one execution of an immutable automation definition.
type AutomationRun struct {
	ID                   string  `gorm:"primaryKey;size:64;index:idx_automation_runs_status_updated,priority:3"`
	WorkspaceID          string  `gorm:"size:64;not null;index:idx_automation_runs_workspace_updated,priority:1;index:idx_automation_runs_workspace_status_updated,priority:1;uniqueIndex:uk_automation_runs_workspace_idem,priority:1"`
	IdempotencyKey       *string `gorm:"size:255;uniqueIndex:uk_automation_runs_workspace_idem,priority:2"`
	SourceKind           string  `gorm:"size:64;not null;default:'agent_git_service_repo'"`
	ContentID            string  `gorm:"size:64;not null;default:'';index"`
	ContentVersionID     string  `gorm:"size:64;not null;default:'';index"`
	RepositoryOwner      string  `gorm:"size:64;not null;default:''"`
	RepositoryName       string  `gorm:"size:128;not null;default:''"`
	RepositoryFullName   string  `gorm:"size:255;not null;default:''"`
	DefinitionPath       string  `gorm:"size:512;not null;default:''"`
	GitRef               string  `gorm:"size:255;not null;default:''"`
	CommitSHA            string  `gorm:"size:128;not null;default:''"`
	DefinitionID         string  `gorm:"size:255;not null;default:''"`
	Name                 string  `gorm:"size:255;not null"`
	RunName              string  `gorm:"size:255;not null;default:''"`
	Status               string  `gorm:"size:64;not null;default:'queued';index:idx_automation_runs_workspace_status_updated,priority:2;index:idx_automation_runs_status_updated,priority:1"`
	InputJSON            string  `gorm:"type:text;not null"`
	OutputJSON           string  `gorm:"type:text;not null"`
	ErrorJSON            string  `gorm:"type:text;not null"`
	TriggerKind          string  `gorm:"size:64;not null;default:''"`
	TriggerRef           string  `gorm:"size:512;not null;default:''"`
	TargetKind           string  `gorm:"size:64;not null;default:''"`
	TargetRef            string  `gorm:"size:512;not null;default:''"`
	OwnerPrincipalID     string  `gorm:"size:64;not null;default:''"`
	CreatedByPrincipalID string  `gorm:"size:64;not null;default:''"`
	CurrentJobID         string  `gorm:"size:64;not null;default:''"`
	Summary              string  `gorm:"type:text;not null"`
	Metadata             string  `gorm:"type:text;not null"`
	StartedAt            *time.Time
	CompletedAt          *time.Time
	CreatedAt            time.Time `gorm:"not null"`
	UpdatedAt            time.Time `gorm:"not null;index:idx_automation_runs_workspace_updated,priority:2;index:idx_automation_runs_workspace_status_updated,priority:3;index:idx_automation_runs_status_updated,priority:2"`
}

func (AutomationRun) TableName() string { return "automation_runs" }

// AutomationRepoStatusOutbox records the desired AGS commit status for a commit context.
type AutomationRepoStatusOutbox struct {
	ID              string    `gorm:"primaryKey;size:64;index:idx_automation_repo_status_outbox_status_next,priority:3"`
	WorkspaceID     string    `gorm:"size:64;not null;uniqueIndex:uk_automation_repo_status_outbox_commit_context,priority:1"`
	RunID           string    `gorm:"size:64;not null"`
	RunCreatedAt    time.Time `gorm:"not null"`
	RepositoryOwner string    `gorm:"size:128;not null;default:'';uniqueIndex:uk_automation_repo_status_outbox_commit_context,priority:2"`
	RepositoryName  string    `gorm:"size:128;not null;default:'';uniqueIndex:uk_automation_repo_status_outbox_commit_context,priority:3"`
	CommitSHA       string    `gorm:"size:128;not null;default:'';uniqueIndex:uk_automation_repo_status_outbox_commit_context,priority:4"`
	Context         string    `gorm:"size:255;not null;uniqueIndex:uk_automation_repo_status_outbox_commit_context,priority:5"`
	State           string    `gorm:"size:16;not null;default:'pending'"`
	Description     string    `gorm:"size:255;not null;default:''"`
	Sequence        int64     `gorm:"not null;default:1"`
	Status          string    `gorm:"size:32;not null;default:'pending';index:idx_automation_repo_status_outbox_status_next,priority:1"`
	Attempts        int       `gorm:"not null;default:0"`
	MaxAttempts     int       `gorm:"not null;default:10"`
	NextAttemptAt   time.Time `gorm:"not null;index:idx_automation_repo_status_outbox_status_next,priority:2"`
	LeaseOwner      string    `gorm:"size:128;not null;default:''"`
	LeaseExpiresAt  *time.Time
	LastError       string `gorm:"type:text;not null"`
	DeliveredAt     *time.Time
	CreatedAt       time.Time `gorm:"not null"`
	UpdatedAt       time.Time `gorm:"not null"`
}

func (AutomationRepoStatusOutbox) TableName() string { return "automation_repo_status_outbox" }

// AutomationRunSlot reserves one active-run capacity slot for a workspace.
type AutomationRunSlot struct {
	WorkspaceID string    `gorm:"primaryKey;size:64"`
	SlotIndex   int       `gorm:"primaryKey"`
	RunID       string    `gorm:"size:64;not null;uniqueIndex:uk_automation_run_slots_run"`
	CreatedAt   time.Time `gorm:"not null"`
	UpdatedAt   time.Time `gorm:"not null"`
}

func (AutomationRunSlot) TableName() string { return "automation_run_slots" }

// AutomationJobRun records durable state for one automation job in a run.
type AutomationJobRun struct {
	ID            string `gorm:"primaryKey;size:64;index:idx_automation_job_runs_status_updated,priority:3"`
	WorkspaceID   string `gorm:"size:64;not null;index:idx_automation_job_runs_run_created,priority:1"`
	RunID         string `gorm:"size:64;not null;index:idx_automation_job_runs_run_created,priority:2"`
	JobID         string `gorm:"size:64;not null"`
	JobType       string `gorm:"size:64;not null;default:''"`
	Status        string `gorm:"size:64;not null;index:idx_automation_job_runs_status_updated,priority:1"`
	Attempt       int    `gorm:"not null;default:0"`
	MaxAttempts   int    `gorm:"not null;default:1"`
	RunsOnJSON    string `gorm:"type:text;not null"`
	InputJSON     string `gorm:"type:text;not null"`
	OutputJSON    string `gorm:"type:mediumtext;not null"`
	ErrorJSON     string `gorm:"type:text;not null"`
	DependsOnJSON string `gorm:"type:text;not null"`
	LeaseOwner    string `gorm:"size:128;not null;default:''"`
	LeaseUntil    *time.Time
	ScheduledAt   time.Time `gorm:"not null"`
	StartedAt     *time.Time
	CompletedAt   *time.Time
	CreatedAt     time.Time `gorm:"not null;index:idx_automation_job_runs_run_created,priority:3"`
	UpdatedAt     time.Time `gorm:"not null;index:idx_automation_job_runs_status_updated,priority:2"`
}

func (AutomationJobRun) TableName() string { return "automation_job_runs" }

// AutomationEvent is the clean job-level automation event ledger for durable runtime.
type AutomationEvent struct {
	ID               string    `gorm:"primaryKey;size:64"`
	WorkspaceID      string    `gorm:"size:64;not null;index:idx_automation_events_run_created,priority:1"`
	RunID            string    `gorm:"size:64;not null;index:idx_automation_events_run_created,priority:2"`
	JobRunID         string    `gorm:"size:64;not null;default:''"`
	EventType        string    `gorm:"size:64;not null"`
	ActorPrincipalID string    `gorm:"size:64;not null;default:''"`
	ResourceType     string    `gorm:"size:64;not null;default:''"`
	ResourceID       string    `gorm:"size:512;not null;default:''"`
	Summary          string    `gorm:"type:text;not null"`
	MetadataJSON     string    `gorm:"type:text;not null"`
	CreatedAt        time.Time `gorm:"not null;index:idx_automation_events_run_created,priority:3"`
}

func (AutomationEvent) TableName() string { return "automation_events" }

// AutomationJob is a TiDB-backed queue row for a automation job.
type AutomationJob struct {
	ID             int64     `gorm:"primaryKey;autoIncrement;index:idx_automation_jobs_claim_lookup,priority:8;index:idx_automation_jobs_workspace_claim_lookup,priority:9;index:idx_automation_jobs_lease_recover,priority:3"`
	WorkspaceID    string    `gorm:"size:64;not null;index:idx_automation_jobs_run_status,priority:1;index:idx_automation_jobs_workspace_claim_lookup,priority:1;index:idx_automation_jobs_ready_workspace_lookup,priority:4"`
	RunID          string    `gorm:"size:64;not null;index:idx_automation_jobs_run_status,priority:2"`
	JobRunID       string    `gorm:"size:64;not null"`
	QueueName      string    `gorm:"size:64;not null;index:idx_automation_jobs_claim_lookup,priority:1;index:idx_automation_jobs_workspace_claim_lookup,priority:2;index:idx_automation_jobs_ready_workspace_lookup,priority:2"`
	Status         string    `gorm:"size:32;not null;default:'ready';index:idx_automation_jobs_claim_lookup,priority:3;index:idx_automation_jobs_workspace_claim_lookup,priority:4;index:idx_automation_jobs_lease_recover,priority:1;index:idx_automation_jobs_run_status,priority:3;index:idx_automation_jobs_ready_workspace_lookup,priority:1"`
	Priority       int       `gorm:"not null;default:100;index:idx_automation_jobs_claim_lookup,priority:7;index:idx_automation_jobs_workspace_claim_lookup,priority:8"`
	ScheduledAt    time.Time `gorm:"not null;index:idx_automation_jobs_claim_lookup,priority:6;index:idx_automation_jobs_workspace_claim_lookup,priority:7;index:idx_automation_jobs_ready_workspace_lookup,priority:3"`
	NotBefore      *time.Time
	LeaseOwner     string     `gorm:"size:128;not null;default:''"`
	LeaseUntil     *time.Time `gorm:"index:idx_automation_jobs_lease_recover,priority:2"`
	Attempt        int        `gorm:"not null;default:0"`
	MaxAttempts    int        `gorm:"not null;default:3"`
	IdempotencyKey string     `gorm:"size:255;not null;uniqueIndex:uk_automation_jobs_idem"`
	RunnerGroup    string     `gorm:"size:128;not null;default:''"`
	RunnerGroupKey string     `gorm:"size:128;not null;default:'';index:idx_automation_jobs_claim_lookup,priority:4;index:idx_automation_jobs_workspace_claim_lookup,priority:5"`
	LabelsJSON     string     `gorm:"type:text;not null"`
	LabelKey       string     `gorm:"size:512;not null;default:'';index:idx_automation_jobs_claim_lookup,priority:5"`
	LabelKeyHash   string     `gorm:"size:64;not null;default:'';index:idx_automation_jobs_workspace_claim_lookup,priority:6"`
	LabelCount     int        `gorm:"not null;default:0"`
	ShardBucket    int        `gorm:"not null;index:idx_automation_jobs_claim_lookup,priority:2;index:idx_automation_jobs_workspace_claim_lookup,priority:3"`
	CreatedAt      time.Time  `gorm:"not null"`
	UpdatedAt      time.Time  `gorm:"not null"`
}

func (AutomationJob) TableName() string { return "automation_jobs" }

// AutomationWait is a durable AgentTeam-native wait subscription. ActiveKey is set only
// while the wait is active so TiDB/MySQL and SQLite can enforce uniqueness
// without a partial unique index; resolved/canceled waits store NULL ActiveKey.
type AutomationWait struct {
	ID              string    `gorm:"primaryKey;size:64;index:idx_automation_waits_signal_status,priority:4"`
	WorkspaceID     string    `gorm:"size:64;not null;index:idx_automation_waits_run_status_created,priority:1"`
	RunID           string    `gorm:"size:64;not null;index:idx_automation_waits_run_status_created,priority:2"`
	JobRunID        string    `gorm:"size:64;not null"`
	WaitKind        string    `gorm:"size:64;not null"`
	Status          string    `gorm:"size:64;not null;index:idx_automation_waits_run_status_created,priority:3;index:idx_automation_waits_signal_status,priority:2"`
	ActiveKey       *string   `gorm:"size:512;uniqueIndex:uk_automation_waits_active"`
	SignalKey       string    `gorm:"size:64;not null;default:'';index:idx_automation_waits_signal_status,priority:1"`
	ResourceType    string    `gorm:"size:64;not null;default:''"`
	ResourceID      string    `gorm:"size:512;not null;default:''"`
	ResumeEventType string    `gorm:"size:128;not null;default:''"`
	InputJSON       string    `gorm:"type:text;not null"`
	ResultJSON      string    `gorm:"type:text;not null"`
	CreatedBy       string    `gorm:"size:64;not null;default:''"`
	ResolvedBy      string    `gorm:"size:64;not null;default:''"`
	CreatedAt       time.Time `gorm:"not null;index:idx_automation_waits_run_status_created,priority:4"`
	UpdatedAt       time.Time `gorm:"not null;index:idx_automation_waits_signal_status,priority:3"`
	ResolvedAt      *time.Time
	CanceledAt      *time.Time
}

func (AutomationWait) TableName() string { return "automation_waits" }

// AutomationRunner records one external automation runner registered to a workspace.
type AutomationRunner struct {
	WorkspaceID  string     `gorm:"primaryKey;size:64"`
	RunnerID     string     `gorm:"primaryKey;size:64"`
	Name         string     `gorm:"size:255;not null"`
	RunnerGroup  string     `gorm:"size:128;not null;default:''"`
	LabelsJSON   string     `gorm:"type:text;not null"`
	Status       string     `gorm:"size:32;not null;default:'active';index"`
	LastSeenAt   *time.Time `gorm:"index"`
	RevokedAt    *time.Time `gorm:"index"`
	RegisteredAt time.Time  `gorm:"not null"`
	CreatedAt    time.Time  `gorm:"not null"`
	UpdatedAt    time.Time  `gorm:"not null"`
}

func (AutomationRunner) TableName() string { return "automation_runners" }

// AutomationRunnerToken stores hashed runner registration/session tokens.
type AutomationRunnerToken struct {
	TokenHash        string     `gorm:"primaryKey;size:128"`
	WorkspaceID      string     `gorm:"size:64;not null;index:idx_automation_runner_tokens_runner_expiry,priority:1;index:idx_automation_runner_tokens_session_lookup,priority:1"`
	RunnerID         string     `gorm:"size:64;not null;index:idx_automation_runner_tokens_runner_expiry,priority:2;index:idx_automation_runner_tokens_session_lookup,priority:2"`
	TokenKind        string     `gorm:"size:32;not null;default:'registration';index:idx_automation_runner_tokens_session_lookup,priority:3"`
	TokenScope       string     `gorm:"size:32;not null;default:''"`
	SessionID        string     `gorm:"size:64;not null;default:'';index:idx_automation_runner_tokens_session_lookup,priority:4"`
	SessionTokenHash string     `gorm:"size:128;not null;default:''"`
	ExpiresAt        time.Time  `gorm:"not null;index:idx_automation_runner_tokens_runner_expiry,priority:3;index:idx_automation_runner_tokens_session_lookup,priority:6"`
	RevokedAt        *time.Time `gorm:"index;index:idx_automation_runner_tokens_session_lookup,priority:5"`
	UsedAt           *time.Time `gorm:"index"`
	CreatedAt        time.Time  `gorm:"not null"`
	UpdatedAt        time.Time  `gorm:"not null;index:idx_automation_runner_tokens_session_lookup,priority:7"`
}

func (AutomationRunnerToken) TableName() string { return "automation_runner_tokens" }

// AutomationRunnerSession records the active lease identity used by a runner.
type AutomationRunnerSession struct {
	WorkspaceID string     `gorm:"primaryKey;size:64;index:idx_automation_runner_sessions_runner_expiry,priority:1"`
	RunnerID    string     `gorm:"primaryKey;size:64;index:idx_automation_runner_sessions_runner_expiry,priority:2"`
	SessionID   string     `gorm:"primaryKey;size:64;index:idx_automation_runner_sessions_runner_expiry,priority:3"`
	LeaseOwner  string     `gorm:"size:128;not null;default:'';index"`
	RunnerGroup string     `gorm:"size:128;not null;default:''"`
	LabelsJSON  string     `gorm:"type:text;not null"`
	Status      string     `gorm:"size:32;not null;default:'active';index"`
	HeartbeatAt time.Time  `gorm:"not null"`
	ExpiresAt   time.Time  `gorm:"not null;index:idx_automation_runner_sessions_runner_expiry,priority:4"`
	RevokedAt   *time.Time `gorm:"index"`
	CreatedAt   time.Time  `gorm:"not null"`
	UpdatedAt   time.Time  `gorm:"not null"`
}

func (AutomationRunnerSession) TableName() string { return "automation_runner_sessions" }

// AutomationActionsRunnerCredential maps official actions/runner OAuth clients
// to MeshX runner identities.
type AutomationActionsRunnerCredential struct {
	ClientID         string     `gorm:"primaryKey;size:64"`
	WorkspaceID      string     `gorm:"size:64;not null;index:idx_automation_actions_runner_credentials_runner,priority:1"`
	RunnerID         string     `gorm:"size:64;not null;index:idx_automation_actions_runner_credentials_runner,priority:2"`
	OfficialRunnerID int64      `gorm:"not null;uniqueIndex:idx_automation_actions_runner_credentials_official_runner_id"`
	PublicKey        string     `gorm:"type:text;not null"`
	CreatedAt        time.Time  `gorm:"not null"`
	UpdatedAt        time.Time  `gorm:"not null"`
	RevokedAt        *time.Time `gorm:"index:idx_automation_actions_runner_credentials_revoked_at"`
}

func (AutomationActionsRunnerCredential) TableName() string {
	return "automation_actions_runner_credentials"
}

// AutomationLogChunk stores metadata for one externally stored automation log chunk.
type AutomationLogChunk struct {
	ID          string    `gorm:"primaryKey;size:64"`
	WorkspaceID string    `gorm:"size:64;not null;index"`
	RunID       string    `gorm:"size:64;not null;index"`
	JobRunID    string    `gorm:"size:64;not null;uniqueIndex:uk_automation_log_chunks_sequence,priority:1"`
	Stream      string    `gorm:"size:32;not null;uniqueIndex:uk_automation_log_chunks_sequence,priority:2"`
	Sequence    int64     `gorm:"not null;uniqueIndex:uk_automation_log_chunks_sequence,priority:3"`
	ObjectKey   string    `gorm:"size:512;not null"`
	SizeBytes   int64     `gorm:"not null;default:0"`
	SHA256      string    `gorm:"size:64;not null;default:''"`
	ContentType string    `gorm:"size:128;not null;default:''"`
	CreatedAt   time.Time `gorm:"not null"`
}

func (AutomationLogChunk) TableName() string { return "automation_log_chunks" }

// AutomationArtifact stores metadata for one externally stored automation artifact.
type AutomationArtifact struct {
	ID          string     `gorm:"primaryKey;size:64"`
	WorkspaceID string     `gorm:"size:64;not null;index"`
	RunID       string     `gorm:"size:64;not null;index:idx_automation_artifacts_run_job_name,priority:1"`
	JobRunID    string     `gorm:"size:64;not null;index:idx_automation_artifacts_run_job_name,priority:2"`
	Name        string     `gorm:"size:255;not null;index:idx_automation_artifacts_run_job_name,priority:3"`
	ObjectKey   string     `gorm:"size:512;not null;default:''"`
	ObjectURL   string     `gorm:"type:text;not null"`
	SizeBytes   int64      `gorm:"not null;default:0"`
	SHA256      string     `gorm:"size:64;not null;default:''"`
	ContentType string     `gorm:"size:128;not null;default:''"`
	ExpiresAt   *time.Time `gorm:"index"`
	CreatedAt   time.Time  `gorm:"not null"`
	UpdatedAt   time.Time  `gorm:"not null"`
}

func (AutomationArtifact) TableName() string { return "automation_artifacts" }

// AutomationSecret stores encrypted repo-scoped automation secret material.
type AutomationSecret struct {
	WorkspaceID     string    `gorm:"primaryKey;size:64"`
	RepositoryOwner string    `gorm:"primaryKey;size:128"`
	RepositoryName  string    `gorm:"primaryKey;size:128"`
	Name            string    `gorm:"primaryKey;size:128"`
	ValueCiphertext string    `gorm:"type:text;not null"`
	CreatedBy       string    `gorm:"size:64;not null;default:''"`
	UpdatedBy       string    `gorm:"size:64;not null;default:''"`
	CreatedAt       time.Time `gorm:"not null"`
	UpdatedAt       time.Time `gorm:"not null"`
}

func (AutomationSecret) TableName() string { return "automation_secrets" }

// AutomationPinnedRepo stores a user-pinned automation repository for quick sidebar access.
type AutomationPinnedRepo struct {
	WorkspaceID string    `gorm:"primaryKey;size:64"`
	PrincipalID string    `gorm:"primaryKey;size:64"`
	Owner       string    `gorm:"primaryKey;size:128"`
	Repo        string    `gorm:"primaryKey;size:128"`
	CreatedAt   time.Time `gorm:"not null"`
	UpdatedAt   time.Time `gorm:"not null;index"`
}

func (AutomationPinnedRepo) TableName() string { return "automation_pinned_repos" }
