Documentation
¶
Overview ¶
Package store is the embedded SQLite state layer: WAL mode, modernc.org/sqlite (pure Go, no cgo, keeps cross-compiling the control plane binary trivial), forward-only versioned migrations.
Index ¶
- Constants
- Variables
- func BackupTargetSecretsKey(targetID string) string
- func BitbucketAppSecretsKey() string
- func CloudflareDNSSecretsKey() string
- func CloudflareTunnelSecretsKey() string
- func DomainBasicAuthSecretsKey(domain string) string
- func DomainTLSCertSecretsKey(domain string) string
- func EmailSettingsSecretsKey() string
- func FormatAuditTime(t time.Time) string
- func GitHubAppSecretsKey() string
- func GitLabAppSecretsKey() string
- func GitSourceSecretsKey(serviceName string) string
- func IsSupportedEngine(id string) (bool, error)
- func NewAuditEntryID() (string, error)
- func NewDeployAttemptID() (string, error)
- func NewDeviceAuthRequestID() (string, error)
- func NewDeviceCode() (string, error)
- func NewPolicyAttachmentID() (string, error)
- func NewPolicyID() (string, error)
- func NewPreviewEnvironmentID() (string, error)
- func NewPreviewEphemeralDatabaseID() (string, error)
- func NewUserCode() (string, error)
- func NewWebhookDeliveryID() (string, error)
- func OAuthProviderSecretsKey(provider string) string
- func RegistryCredentialSecretsKey(id string) string
- func RegistrySettingsSecretsKey() string
- func ServiceVolumeDockerName(svc DesiredService, volumeName string) (string, bool)
- func UserTOTPSecretsKey(userID string) string
- type APIToken
- type App
- type AuditEntry
- type AuditEntryFilter
- type BackupHistory
- type BackupTarget
- type BackupVerification
- type BitbucketAppConnection
- type CertStorageKeyInfo
- type CertStorageValue
- type CloneRestore
- type CloudflareDNSSettings
- type CloudflareTunnelSettings
- type DB
- func (db *DB) AcquireCertStorageLock(ctx context.Context, name string, staleAfter time.Duration) (bool, error)
- func (db *DB) AttachPolicy(ctx context.Context, id, policyID, principalType, principalID string) error
- func (db *DB) ClaimInvite(ctx context.Context, id string) error
- func (db *DB) ClaimPasswordResetToken(ctx context.Context, id string) error
- func (db *DB) ConsumeUserRecoveryCode(ctx context.Context, userID, hash string) (bool, error)
- func (db *DB) CountUnusedUserRecoveryCodes(ctx context.Context, userID string) (int, error)
- func (db *DB) CountUsers(ctx context.Context) (int, error)
- func (db *DB) CreateUser(ctx context.Context, u User) error
- func (db *DB) DeleteApp(ctx context.Context, id string) error
- func (db *DB) DeleteAuditEntriesOlderThan(ctx context.Context, cutoff time.Time) (int64, error)
- func (db *DB) DeleteBackupTarget(ctx context.Context, id string) error
- func (db *DB) DeleteBitbucketAppConnection(ctx context.Context) error
- func (db *DB) DeleteCertStorageValue(ctx context.Context, key string) error
- func (db *DB) DeleteDesiredDatabase(ctx context.Context, name string) error
- func (db *DB) DeleteDesiredService(ctx context.Context, name string) error
- func (db *DB) DeleteDomainBasicAuth(ctx context.Context, domain string) error
- func (db *DB) DeleteDomainMaintenance(ctx context.Context, domain string) error
- func (db *DB) DeleteDomainTLSCert(ctx context.Context, domain string) error
- func (db *DB) DeleteDomainWAF(ctx context.Context, domain string) error
- func (db *DB) DeleteEnvironment(ctx context.Context, id string) error
- func (db *DB) DeleteFeatureFlag(ctx context.Context, id string) error
- func (db *DB) DeleteGitHubAppConnection(ctx context.Context) error
- func (db *DB) DeleteGitLabAppConnection(ctx context.Context) error
- func (db *DB) DeleteGitSource(ctx context.Context, serviceName string) error
- func (db *DB) DeleteNode(ctx context.Context, id string) error
- func (db *DB) DeleteOrganization(ctx context.Context, id string) error
- func (db *DB) DeletePolicy(ctx context.Context, id string) error
- func (db *DB) DeletePreviewEnvironment(ctx context.Context, id string) error
- func (db *DB) DeletePreviewEphemeralDatabase(ctx context.Context, id string) error
- func (db *DB) DeleteProject(ctx context.Context, id string) error
- func (db *DB) DeleteRegistryCredential(ctx context.Context, id string) error
- func (db *DB) DeleteScheduledTask(ctx context.Context, id string) error
- func (db *DB) DeleteServiceSecrets(ctx context.Context, serviceName string) error
- func (db *DB) DeleteUser(ctx context.Context, id string) error
- func (db *DB) DeleteUserRecoveryCodes(ctx context.Context, userID string) error
- func (db *DB) DetachPolicy(ctx context.Context, policyID, principalType, principalID string) error
- func (db *DB) DisableUserTOTP(ctx context.Context, id string) error
- func (db *DB) EnableUserTOTP(ctx context.Context, id string, confirmedAt time.Time) error
- func (db *DB) ExistsCertStorageValue(ctx context.Context, key string) (bool, error)
- func (db *DB) FailOrphanedDeployAttempts(ctx context.Context, finishedAt time.Time) (int, error)
- func (db *DB) FinishBackupHistory(ctx context.Context, id, status string, sizeBytes int64, ...) error
- func (db *DB) FinishBackupVerification(ctx context.Context, id, status string, ...) error
- func (db *DB) FinishCloneRestore(ctx context.Context, id, status, errMsg, finishedAt string) error
- func (db *DB) FinishDeployAttempt(ctx context.Context, id, status string, finishedAt time.Time, errMsg string) error
- func (db *DB) FinishRestoreHistory(ctx context.Context, id, status, errMsg, finishedAt string) error
- func (db *DB) FinishVolumeCloneRestore(ctx context.Context, id, status, errMsg, finishedAt string) error
- func (db *DB) GetAPITokenByHash(ctx context.Context, hash string) (*APIToken, error)
- func (db *DB) GetApp(ctx context.Context, id string) (App, error)
- func (db *DB) GetAppByName(ctx context.Context, name string) (App, error)
- func (db *DB) GetBackupHistory(ctx context.Context, id string) (BackupHistory, error)
- func (db *DB) GetBackupTarget(ctx context.Context, id string) (BackupTarget, error)
- func (db *DB) GetBitbucketAppConnection(ctx context.Context) (BitbucketAppConnection, error)
- func (db *DB) GetCertStorageValue(ctx context.Context, key string) (*CertStorageValue, error)
- func (db *DB) GetCloudflareDNSSettings(ctx context.Context) (CloudflareDNSSettings, error)
- func (db *DB) GetCloudflareTunnelSettings(ctx context.Context) (CloudflareTunnelSettings, error)
- func (db *DB) GetConditions(ctx context.Context, controllerName string) ([]reconcile.Condition, error)
- func (db *DB) GetConditionsForControllers(ctx context.Context, controllerNames []string) (map[string][]reconcile.Condition, error)
- func (db *DB) GetDeployAttempt(ctx context.Context, id string) (*DeployAttempt, error)
- func (db *DB) GetDesiredDatabase(ctx context.Context, name string) (*DesiredDatabase, error)
- func (db *DB) GetDesiredService(ctx context.Context, name string) (*DesiredService, error)
- func (db *DB) GetDeviceAuthRequestByDeviceCode(ctx context.Context, deviceCode string) (*DeviceAuthRequest, error)
- func (db *DB) GetDeviceAuthRequestByUserCode(ctx context.Context, userCode string) (*DeviceAuthRequest, error)
- func (db *DB) GetDomainBasicAuth(ctx context.Context, domain string) (DomainBasicAuth, bool, error)
- func (db *DB) GetDomainMaintenance(ctx context.Context, domain string) (bool, error)
- func (db *DB) GetDomainTLSCert(ctx context.Context, domain string) (DomainTLSCert, bool, error)
- func (db *DB) GetDomainWAF(ctx context.Context, domain string) (DomainWAF, bool, error)
- func (db *DB) GetEmailSettings(ctx context.Context) (EmailSettings, error)
- func (db *DB) GetEnvironment(ctx context.Context, id string) (Environment, error)
- func (db *DB) GetFeatureFlag(ctx context.Context, id string) (FeatureFlag, error)
- func (db *DB) GetFeatureFlagByKey(ctx context.Context, key string) (FeatureFlag, error)
- func (db *DB) GetGitHubAppConnection(ctx context.Context) (GitHubAppConnection, error)
- func (db *DB) GetGitLabAppConnection(ctx context.Context) (GitLabAppConnection, error)
- func (db *DB) GetGitSource(ctx context.Context, serviceName string) (*GitSource, error)
- func (db *DB) GetHookRuns(ctx context.Context, serviceName string) ([]HookRun, error)
- func (db *DB) GetIngressSettings(ctx context.Context) (IngressSettings, error)
- func (db *DB) GetInviteByHash(ctx context.Context, hash string) (*Invite, error)
- func (db *DB) GetInviteByID(ctx context.Context, id string) (*Invite, error)
- func (db *DB) GetLatestBackupVerification(ctx context.Context, backupHistoryID string) (BackupVerification, error)
- func (db *DB) GetMasterKeyRotatedAt(ctx context.Context) (rotatedAt time.Time, ok bool, err error)
- func (db *DB) GetNode(ctx context.Context, id string) (*Node, error)
- func (db *DB) GetNodeJoinTokenByHash(ctx context.Context, hash string) (*NodeJoinToken, error)
- func (db *DB) GetOAuthIdentity(ctx context.Context, provider, providerUserID string) (*OAuthIdentity, error)
- func (db *DB) GetOAuthProviderSettings(ctx context.Context, provider string) (OAuthProviderSettings, error)
- func (db *DB) GetOnboardingCompleted(ctx context.Context) (bool, error)
- func (db *DB) GetOrganization(ctx context.Context, id string) (Organization, error)
- func (db *DB) GetPasswordResetTokenByHash(ctx context.Context, hash string) (*PasswordResetToken, error)
- func (db *DB) GetPolicy(ctx context.Context, id string) (*Policy, error)
- func (db *DB) GetPreviewEnvironmentByAppAndPR(ctx context.Context, appName string, prNumber int) (*PreviewEnvironment, error)
- func (db *DB) GetPreviewEphemeralDatabaseByPreviewAndKey(ctx context.Context, previewEnvironmentID, sourceKey string) (*PreviewEphemeralDatabase, error)
- func (db *DB) GetProject(ctx context.Context, id string) (Project, error)
- func (db *DB) GetRegistryCredential(ctx context.Context, id string) (RegistryCredential, error)
- func (db *DB) GetRegistryCredentialByName(ctx context.Context, name string) (RegistryCredential, error)
- func (db *DB) GetRegistrySettings(ctx context.Context) (RegistrySettings, error)
- func (db *DB) GetScheduledTask(ctx context.Context, id string) (ScheduledTask, error)
- func (db *DB) GetSecretKeyLocked(ctx context.Context, serviceName, envKey string) (exists, locked bool, err error)
- func (db *DB) GetSecretValue(ctx context.Context, serviceName, envKey string) ([]byte, error)
- func (db *DB) GetServiceDEK(ctx context.Context, serviceName string) ([]byte, error)
- func (db *DB) GetServiceVolumeBackupSchedule(ctx context.Context, serviceName, volumeName string) (ServiceVolumeBackupConfig, error)
- func (db *DB) GetUserByEmail(ctx context.Context, email string) (*User, error)
- func (db *DB) GetUserByID(ctx context.Context, id string) (*User, error)
- func (db *DB) GetWebhookDelivery(ctx context.Context, id string) (*WebhookDelivery, error)
- func (db *DB) HasSecretValue(ctx context.Context, serviceName, envKey string) (bool, error)
- func (db *DB) ListAPITokens(ctx context.Context) ([]APIToken, error)
- func (db *DB) ListApps(ctx context.Context) ([]App, error)
- func (db *DB) ListAttachmentsForPolicy(ctx context.Context, policyID string) ([]PolicyAttachment, error)
- func (db *DB) ListAuditEntries(ctx context.Context, limit int, before *time.Time, filter AuditEntryFilter) ([]AuditEntry, error)
- func (db *DB) ListBackupHistory(ctx context.Context, databaseName string, limit int, before *time.Time) ([]BackupHistory, error)
- func (db *DB) ListBackupTargets(ctx context.Context) ([]BackupTarget, error)
- func (db *DB) ListBackupVerifications(ctx context.Context, backupHistoryID string, limit int) ([]BackupVerification, error)
- func (db *DB) ListCertStorageKeys(ctx context.Context, prefix string, recursive bool) ([]string, error)
- func (db *DB) ListCloneRestores(ctx context.Context, sourceDatabaseName string) ([]CloneRestore, error)
- func (db *DB) ListDeployAttempts(ctx context.Context, serviceName string) ([]DeployAttempt, error)
- func (db *DB) ListDesiredDatabases(ctx context.Context) ([]DesiredDatabase, error)
- func (db *DB) ListDesiredDatabasesByNode(ctx context.Context, nodeID string) ([]DesiredDatabase, error)
- func (db *DB) ListDesiredDatabasesByProject(ctx context.Context, projectID string) ([]DesiredDatabase, error)
- func (db *DB) ListDesiredServices(ctx context.Context) ([]DesiredService, error)
- func (db *DB) ListDesiredServicesByNode(ctx context.Context, nodeID string) ([]DesiredService, error)
- func (db *DB) ListDesiredServicesByProject(ctx context.Context, projectID string) ([]DesiredService, error)
- func (db *DB) ListDomainBasicAuth(ctx context.Context) ([]DomainBasicAuth, error)
- func (db *DB) ListDomainMaintenance(ctx context.Context) ([]string, error)
- func (db *DB) ListDomainTLSCerts(ctx context.Context) ([]DomainTLSCert, error)
- func (db *DB) ListDomainWAF(ctx context.Context) ([]DomainWAF, error)
- func (db *DB) ListEnabledScheduledTasks(ctx context.Context) ([]ScheduledTask, error)
- func (db *DB) ListEnvironmentEnvVars(ctx context.Context, environmentID string) (map[string]string, error)
- func (db *DB) ListEnvironmentsByProject(ctx context.Context, projectID string) ([]Environment, error)
- func (db *DB) ListFeatureFlagsForService(ctx context.Context, serviceName string) ([]FeatureFlag, error)
- func (db *DB) ListNodes(ctx context.Context) ([]Node, error)
- func (db *DB) ListOAuthIdentitiesForUser(ctx context.Context, userID string) ([]OAuthIdentity, error)
- func (db *DB) ListOAuthProviderSettings(ctx context.Context) ([]OAuthProviderSettings, error)
- func (db *DB) ListOrganizationEnvVars(ctx context.Context, orgID string) (map[string]string, error)
- func (db *DB) ListOrganizationEnvVarsForProject(ctx context.Context, projectID string) (map[string]string, error)
- func (db *DB) ListOrganizations(ctx context.Context) ([]Organization, error)
- func (db *DB) ListPendingDeviceAuthRequests(ctx context.Context, now time.Time) ([]DeviceAuthRequest, error)
- func (db *DB) ListPendingInvites(ctx context.Context) ([]Invite, error)
- func (db *DB) ListPolicies(ctx context.Context) ([]Policy, error)
- func (db *DB) ListPoliciesForPrincipal(ctx context.Context, principalType, principalID string) ([]Policy, error)
- func (db *DB) ListPreviewEnvironmentsByApp(ctx context.Context, appName string) ([]PreviewEnvironment, error)
- func (db *DB) ListPreviewEphemeralDatabasesByPreview(ctx context.Context, previewEnvironmentID string) ([]PreviewEphemeralDatabase, error)
- func (db *DB) ListProjectEnvVars(ctx context.Context, projectID string) (map[string]string, error)
- func (db *DB) ListProjects(ctx context.Context) ([]Project, error)
- func (db *DB) ListRegistryCredentials(ctx context.Context) ([]RegistryCredential, error)
- func (db *DB) ListRestoreHistory(ctx context.Context, databaseName string) ([]RestoreHistory, error)
- func (db *DB) ListScheduledDatabases(ctx context.Context) ([]DesiredDatabase, error)
- func (db *DB) ListScheduledServiceVolumes(ctx context.Context) ([]ServiceVolumeBackupConfig, error)
- func (db *DB) ListScheduledTasksForService(ctx context.Context, serviceName string) ([]ScheduledTask, error)
- func (db *DB) ListSecretKeys(ctx context.Context, serviceName string) ([]SecretKeyInfo, error)
- func (db *DB) ListServiceDomains(ctx context.Context) ([]ServiceDomain, error)
- func (db *DB) ListServiceVolumeBackupHistory(ctx context.Context, serviceName, volumeName string, limit int, ...) ([]BackupHistory, error)
- func (db *DB) ListServiceVolumeRestoreHistory(ctx context.Context, serviceName, volumeName string) ([]RestoreHistory, error)
- func (db *DB) ListServicesByApp(ctx context.Context, appID string) ([]DesiredService, error)
- func (db *DB) ListStalePreviewEnvironments(ctx context.Context, cutoff time.Time) ([]PreviewEnvironment, error)
- func (db *DB) ListStaticSites(ctx context.Context) ([]StaticSite, error)
- func (db *DB) ListUsers(ctx context.Context) ([]User, error)
- func (db *DB) ListVolumeCloneRestores(ctx context.Context, sourceServiceName, sourceVolumeName string) ([]VolumeCloneRestore, error)
- func (db *DB) ListWebhookDeliveries(ctx context.Context, serviceName string, limit int, before *time.Time) ([]WebhookDelivery, error)
- func (db *DB) MarkNodeJoinTokenUsed(ctx context.Context, id string) error
- func (db *DB) MarkOnboardingCompleted(ctx context.Context) error
- func (db *DB) PruneBackupHistory(ctx context.Context, databaseName string, keep int, olderThan time.Time) ([]PrunedBackup, error)
- func (db *DB) PruneServiceVolumeBackupHistory(ctx context.Context, serviceName, volumeName string, keep int, ...) ([]PrunedBackup, error)
- func (db *DB) RecordScheduledTaskRun(ctx context.Context, id string, ranAt time.Time, status, output string) error
- func (db *DB) RedeemDeviceAuthRequest(ctx context.Context, deviceCode, tokenID string, redeemedAt time.Time) error
- func (db *DB) ReleaseCertStorageLock(ctx context.Context, name string) error
- func (db *DB) ReplaceUserRecoveryCodes(ctx context.Context, userID string, hashes []string) error
- func (db *DB) ResolveServiceVolumeDockerName(ctx context.Context, serviceName, volumeName string) (string, error)
- func (db *DB) RestartService(ctx context.Context, name string) error
- func (db *DB) RevokeAPIToken(ctx context.Context, id string) error
- func (db *DB) RevokeInvite(ctx context.Context, id string) error
- func (db *DB) RotateServiceDEKs(ctx context.Context, ...) error
- func (db *DB) SaveAPIToken(ctx context.Context, t APIToken) error
- func (db *DB) SaveApp(ctx context.Context, a App) error
- func (db *DB) SaveAuditEntry(ctx context.Context, e AuditEntry) error
- func (db *DB) SaveBackupTarget(ctx context.Context, t BackupTarget) error
- func (db *DB) SaveBitbucketAppConnection(ctx context.Context, c BitbucketAppConnection) error
- func (db *DB) SaveCertStorageValue(ctx context.Context, key string, value []byte) error
- func (db *DB) SaveDeployAttempt(ctx context.Context, a DeployAttempt) error
- func (db *DB) SaveDesiredDatabase(ctx context.Context, d DesiredDatabase) error
- func (db *DB) SaveDesiredService(ctx context.Context, svc DesiredService) error
- func (db *DB) SaveDeviceAuthRequest(ctx context.Context, r DeviceAuthRequest) error
- func (db *DB) SaveEnvironment(ctx context.Context, e Environment) error
- func (db *DB) SaveFeatureFlag(ctx context.Context, f FeatureFlag) error
- func (db *DB) SaveGitHubAppConnection(ctx context.Context, c GitHubAppConnection) error
- func (db *DB) SaveGitLabAppConnection(ctx context.Context, c GitLabAppConnection) error
- func (db *DB) SaveGitSource(ctx context.Context, g GitSource) error
- func (db *DB) SaveInvite(ctx context.Context, inv Invite) error
- func (db *DB) SaveNode(ctx context.Context, n Node) error
- func (db *DB) SaveNodeJoinToken(ctx context.Context, t NodeJoinToken) error
- func (db *DB) SaveOAuthIdentity(ctx context.Context, i OAuthIdentity) error
- func (db *DB) SaveOrganization(ctx context.Context, o Organization) error
- func (db *DB) SavePasswordResetToken(ctx context.Context, t PasswordResetToken) error
- func (db *DB) SavePolicy(ctx context.Context, p Policy) error
- func (db *DB) SavePreviewEnvironment(ctx context.Context, p PreviewEnvironment) error
- func (db *DB) SavePreviewEphemeralDatabase(ctx context.Context, p PreviewEphemeralDatabase) error
- func (db *DB) SaveProject(ctx context.Context, p Project) error
- func (db *DB) SaveRegistryCredential(ctx context.Context, c RegistryCredential) error
- func (db *DB) SaveScheduledTask(ctx context.Context, t ScheduledTask) error
- func (db *DB) SaveSecretValue(ctx context.Context, serviceName, envKey string, ciphertext []byte) error
- func (db *DB) SaveServiceDEK(ctx context.Context, serviceName string, wrappedDEK []byte) error
- func (db *DB) SaveStaticSite(ctx context.Context, site StaticSite) error
- func (db *DB) SaveWebhookDelivery(ctx context.Context, d WebhookDelivery) error
- func (db *DB) SetDatabaseBackupSchedule(ctx context.Context, name, targetID, schedule string, retain, retainDays int) error
- func (db *DB) SetDatabasePublicAccess(ctx context.Context, name string, enabled bool, requestedPort int) (int, error)
- func (db *DB) SetDeviceAuthRequestStatus(ctx context.Context, userCode, status, approvedByUserID string) (int64, error)
- func (db *DB) SetDomainBasicAuth(ctx context.Context, domain, username string) error
- func (db *DB) SetDomainMaintenance(ctx context.Context, domain string) error
- func (db *DB) SetDomainTLSCert(ctx context.Context, domain string, uploadedAt, expiresAt time.Time) error
- func (db *DB) SetDomainWAF(ctx context.Context, domain string, wafEnabled bool, mode string, ...) error
- func (db *DB) SetEnvironmentEnvVars(ctx context.Context, environmentID string, vars map[string]string) error
- func (db *DB) SetEnvironmentProtected(ctx context.Context, id string, protected bool) error
- func (db *DB) SetGitSourcePostPRComments(ctx context.Context, serviceName string, enabled bool) error
- func (db *DB) SetGitSourcePreviewEnabled(ctx context.Context, serviceName string, enabled bool) error
- func (db *DB) SetNodeSchedulable(ctx context.Context, id string, schedulable bool) error
- func (db *DB) SetOrganizationEnvVars(ctx context.Context, orgID string, vars map[string]string) error
- func (db *DB) SetProjectEnvVars(ctx context.Context, projectID string, vars map[string]string) error
- func (db *DB) SetProjectOrganization(ctx context.Context, projectID, orgID string) error
- func (db *DB) SetSecretLocked(ctx context.Context, serviceName, envKey string, locked bool) error
- func (db *DB) SetServiceEnvironment(ctx context.Context, serviceName, envID string) error
- func (db *DB) SetServiceVolumeBackupSchedule(ctx context.Context, serviceName, volumeName, targetID, schedule string, ...) error
- func (db *DB) StartBackupHistory(ctx context.Context, h BackupHistory) error
- func (db *DB) StartBackupVerification(ctx context.Context, v BackupVerification) error
- func (db *DB) StartCloneRestore(ctx context.Context, h CloneRestore) error
- func (db *DB) StartRestoreHistory(ctx context.Context, h RestoreHistory) error
- func (db *DB) StartVolumeCloneRestore(ctx context.Context, h VolumeCloneRestore) error
- func (db *DB) StatCertStorageValue(ctx context.Context, key string) (*CertStorageKeyInfo, error)
- func (db *DB) TouchAPITokenLastUsed(ctx context.Context, id string) error
- func (db *DB) TouchCertStorageLock(ctx context.Context, name string) error
- func (db *DB) TouchNodeLastSeen(ctx context.Context, id string) error
- func (db *DB) UpdateBackupTarget(ctx context.Context, id, name, provider, endpoint, region, bucket string) error
- func (db *DB) UpdateCloudflareDNSSettings(ctx context.Context, s CloudflareDNSSettings) error
- func (db *DB) UpdateCloudflareTunnelSettings(ctx context.Context, s CloudflareTunnelSettings) error
- func (db *DB) UpdateDatabaseNode(ctx context.Context, name, nodeID string) error
- func (db *DB) UpdateDatabaseProject(ctx context.Context, name, projectID string) error
- func (db *DB) UpdateDatabaseSuspended(ctx context.Context, name string, suspended bool) error
- func (db *DB) UpdateEmailSettings(ctx context.Context, s EmailSettings) error
- func (db *DB) UpdateFeatureFlag(ctx context.Context, id, name, description string, enabled bool, ...) error
- func (db *DB) UpdateGitHubAppInstallation(ctx context.Context, installationID int64, accountLogin string) error
- func (db *DB) UpdateIngressSettings(ctx context.Context, s IngressSettings) error
- func (db *DB) UpdateNodeMesh(ctx context.Context, id, publicKey, address string) error
- func (db *DB) UpdateNodeStatus(ctx context.Context, id string, status NodeStatus) error
- func (db *DB) UpdateNodeWorkloads(ctx context.Context, id string, acceptsApp, acceptsBuild bool) error
- func (db *DB) UpdateOAuthProviderSettings(ctx context.Context, s OAuthProviderSettings) error
- func (db *DB) UpdatePolicy(ctx context.Context, id, name, description, document string) error
- func (db *DB) UpdatePreviewEnvironment(ctx context.Context, p PreviewEnvironment) error
- func (db *DB) UpdatePreviewEphemeralDatabaseStatus(ctx context.Context, id, status, statusReason, updatedAt string) error
- func (db *DB) UpdateRegistryCredential(ctx context.Context, id, name, registryHost, username string, ...) error
- func (db *DB) UpdateRegistrySettings(ctx context.Context, s RegistrySettings) error
- func (db *DB) UpdateScheduledTask(ctx context.Context, id string, command []string, schedule string, ...) error
- func (db *DB) UpdateServiceApp(ctx context.Context, name, appID string) error
- func (db *DB) UpdateServiceDatabaseAttachment(ctx context.Context, name string, att *DatabaseAttachment) error
- func (db *DB) UpdateServiceLogDrain(ctx context.Context, name string, drain *LogDrain) error
- func (db *DB) UpdateServiceNode(ctx context.Context, name, nodeID string) error
- func (db *DB) UpdateServiceProject(ctx context.Context, name, projectID string) error
- func (db *DB) UpdateServiceStorageTarget(ctx context.Context, name, storageTargetID string) error
- func (db *DB) UpdateServiceSuspended(ctx context.Context, name string, suspended bool) error
- func (db *DB) UpdateUserAbilities(ctx context.Context, id string, abilities []string) error
- func (db *DB) UpdateUserLastLogin(ctx context.Context, id string, when time.Time) error
- func (db *DB) UpdateUserPasswordHash(ctx context.Context, id string, hash *string) error
- func (db *DB) UpsertConditions(ctx context.Context, controllerName string, conditions []reconcile.Condition) error
- func (db *DB) UpsertHookRun(ctx context.Context, run HookRun) error
- type DatabaseAttachment
- type DatabaseEngineInfo
- type DatabaseEnvRef
- type DeployAttempt
- type DeployAttemptEnvKey
- type DeployAttemptEnvKind
- type DeployAttemptSnapshot
- type DesiredDatabase
- type DesiredService
- type DeviceAuthRequest
- type DomainBasicAuth
- type DomainTLSCert
- type DomainWAF
- type EmailSettings
- type Environment
- type ErrDomainTaken
- type FeatureFlag
- type GitHubAppConnection
- type GitLabAppConnection
- type GitSource
- type GitSourceBuild
- type HookRun
- type IngressSettings
- type Invite
- type LogDrain
- type LogDrainType
- type Node
- type NodeJoinToken
- type NodeStatus
- type OAuthIdentity
- type OAuthProviderSettings
- type Organization
- type PasswordResetToken
- type Policy
- type PolicyAttachment
- type PreviewEnvironment
- type PreviewEphemeralDatabase
- type Project
- type PrunedBackup
- type RegistryCredential
- type RegistrySettings
- type RestoreHistory
- type ScheduledTask
- type SecretKeyInfo
- type ServiceBindMount
- type ServiceDomain
- type ServiceHealth
- type ServiceHooks
- type ServiceProbe
- type ServiceResources
- type ServiceVolume
- type ServiceVolumeBackupConfig
- type StaticSite
- type User
- type VolumeCloneRestore
- type WebhookDelivery
Constants ¶
const ( BackupStatusRunning = "running" BackupStatusSucceeded = "succeeded" BackupStatusFailed = "failed" )
Backup attempt statuses migrations/0018_backup_targets.sql's CHECK constraint accepts. "running" is written first (StartBackupHistory) so a backup that crashes the control plane mid-upload leaves a real, visible "running" row behind rather than no record at all; nothing currently sweeps a stuck "running" row back to "failed", a known, honest gap for the eventual scheduler to close alongside its own retry logic, not invented speculatively here.
const ( BackupResourceKindDatabase = "database" BackupResourceKindVolume = "volume" )
Backup resource kinds migrations/0075_service_volume_backups.sql's own CHECK constraint accepts: which of the two things a backup_history row describes. BackupResourceKindDatabase is the zero value's effective meaning for every row written before this constant existed.
const ( BackupProviderAWS = "aws" BackupProviderR2 = "r2" BackupProviderCustom = "custom" )
Backup target providers migrations/0018_backup_targets.sql's CHECK constraint accepts. "aws" leaves Endpoint empty (the AWS SDK's default per-region resolver already knows the right host); "r2" and "custom" both require an explicit Endpoint, the only structural difference between them being that "r2" exists as its own value so the API and frontend can show a Cloudflare-specific label instead of a bare URL.
const ( BackupVerificationStatusRunning = "running" BackupVerificationStatusPassed = "passed" BackupVerificationStatusFailed = "failed" )
Backup verification statuses migrations/0069_backup_verification.sql's CHECK constraint accepts, mirroring BackupStatusRunning/Succeeded/Failed's own "running" written first, before real work happens" reasoning (backup_history.go): a verification attempt that downloads a large object can take a while, so a row exists from the moment it starts, not only once it finishes. "passed"/"failed" describe whether the backup itself checked out, not whether the verification process ran without error; VerifyBackup (internal/backup) folds both into the same failed status, since either one means an operator cannot trust this backup without more investigation.
const ( EnginePostgres = "postgres" EngineRedis = "redis" EngineMySQL = "mysql" EngineMongoDB = "mongodb" EngineMariaDB = "mariadb" EngineKeyDB = "keydb" EngineDragonfly = "dragonfly" EngineClickHouse = "clickhouse" )
Supported managed database engines. internal/spec's own engine list (app.yaml declarative support) is tracked separately and not guaranteed to match this one: Dragonfly and ClickHouse are available here but not yet in internal/spec.
const ( PublicPortRangeStart = 20000 PublicPortRangeEnd = 20999 )
PublicPortRangeStart and PublicPortRangeEnd bound the host ports auto-assigned by SetDatabasePublicAccess when the caller doesn't request a specific one. Chosen clear of every port this control plane already binds itself (cmd/levelrail's defaultHTTPAddr ":8080", defaultAgentAddr ":9443") and of Caddy's 80/443, so an auto-assigned database port can never collide with the control plane's own listeners.
const ( DeployAttemptStatusRunning = "running" DeployAttemptStatusSucceeded = "succeeded" DeployAttemptStatusFailed = "failed" )
Deploy attempt lifecycle. There is no "pending" state distinct from "running": every trigger handler saves the row and immediately begins work (SaveDesiredService for the plain path, Pipeline.Deploy for the two build-triggering paths) in the same call, so there is no observable gap between "queued" and "started" worth a separate status value.
const ( DeployAttemptSourceWebhook = "webhook" DeployAttemptSourceManual = "manual" DeployAttemptSourceImage = "image" DeployAttemptSourceCompose = "compose" DeployAttemptSourcePromote = "promote" )
Deploy attempt trigger sources, one per real call site: the unattended git-push webhook (internal/webhook), a manual git-source build triggered from the dashboard (internal/api/deploy_attempts.go's beginBuildDeployAttempt), a plain image-tag create/update/redeploy/ rollback with no build step (internal/api/deploys.go's recordPlainDeployAttempt), a Docker Compose file or service template fanning out into one or more services under one app (internal/api/apps_compose.go's handleDeployCompose), and promoting another app's image across environments within the same project (internal/api/promote.go's handlePromoteApp).
const ( DeviceAuthStatusPending = "pending" DeviceAuthStatusApproved = "approved" DeviceAuthStatusDenied = "denied" )
DeviceAuthStatusPending, DeviceAuthStatusApproved, and DeviceAuthStatusDenied are the only valid DeviceAuthRequest.Status values.
const ( DomainTLSCertCertificateEnvKey = "certificate" DomainTLSCertPrivateKeyEnvKey = "private_key" )
DomainTLSCertCertificateEnvKey and DomainTLSCertPrivateKeyEnvKey are the two fixed envKeys used within that namespace: one secrets-manager service slot per domain, two keys within it, sharing one data-encryption key (internal/secrets.Manager reuses a service's DEK across keys).
const ( DomainWAFModeDetect = "detect" DomainWAFModeBlock = "block" )
Domain WAF modes (domain_waf.waf_mode, migrations/0093). DomainWAFModeDetect is the default: OWASP CRS runs but only logs matches, never rejects a request, matching Coraza's own documented SecRuleEngine DetectionOnly behavior.
const ( EmailBackendSMTP = "smtp" EmailBackendSES = "ses" )
Email backends store.EmailSettings.Backend accepts. Empty string means "unset": the caller falls back to APP_SMTP_* env vars if set.
const ( HookTypePreDeploy = "pre_deploy" HookTypePostDeploy = "post_deploy" )
Hook types HookRun.HookType holds, matching internal/reconcile/application's own unexported constants of the same values (that package can't import this one's vocabulary any more than store.DesiredService's own doc comment lets it import spec's, so the two are kept in sync by value, not by a shared import).
const ( PrincipalTypeUser = "user" PrincipalTypeToken = "token" )
PrincipalTypeUser and PrincipalTypeToken are the only two valid PolicyAttachment.PrincipalType values.
const ( OAuthProviderGoogle = "google" OAuthProviderGitHub = "github" OAuthProviderOIDC = "oidc" )
OAuth provider names the migrations/0035_users.sql and 0052's CHECK constraints accept.
const ( PreviewStatusDeploying = "deploying" PreviewStatusActive = "active" PreviewStatusFailed = "failed" )
Preview environment statuses (migrations/0064_preview_environments.sql). Deploying is the initial state a webhook-triggered create/update writes before the build even starts; Active means the preview is reachable (with or without its intended domain, see StatusReason); Failed means the deploy itself never produced a running preview.
const ( PreviewEphemeralDatabaseStatusProvisioned = "provisioned" PreviewEphemeralDatabaseStatusTeardownFailed = "teardown_failed" )
Preview ephemeral database statuses (migrations/0092_preview_ephemeral_databases.sql). Provisioned is the only state this row is ever saved in; TeardownFailed is set in place, never SaveDesiredDatabase, so a retry can find exactly which ones are still owed a teardown.
const ( ScheduledTaskStatusSuccess = "success" ScheduledTaskStatusFailed = "failed" ScheduledTaskStatusTimeout = "timeout" ScheduledTaskStatusContainerNotRunning = "container_not_running" )
Scheduled task run statuses (migrations/0048_scheduled_tasks.sql's last_run_status column, no CHECK constraint since this is an application-level enum, not something a foreign key or another table joins against). ScheduledTaskStatusContainerNotRunning is distinct from ScheduledTaskStatusFailed so the dashboard can badge "the container isn't up" differently from "the command itself failed", exactly the "clear, visible signal" this feature's own spec asked for rather than folding that case into a generic failure.
const ( DefaultDeployStrategy = "blue-green" DefaultReplicas = 1 )
DefaultDeployStrategy and DefaultReplicas mirror internal/spec's StrategyBlueGreen/DefaultReplicas exactly (same values), kept as this package's own constants rather than importing internal/spec: this package's own doc comment already establishes that DesiredService is deliberately independent of spec.Service, and every other cross- package enum in this file (NodeStatus, and so on) follows the same "define locally, don't import a higher-level package's vocabulary" convention.
const CloudflareDNSTokenEnvKey = "token"
CloudflareDNSTokenEnvKey is the fixed envKey used within that namespace.
const CloudflareTunnelTokenEnvKey = "token"
CloudflareTunnelTokenEnvKey is the fixed envKey used within that namespace, mirroring OAuthProviderSecretEnvKey's shape.
const DomainBasicAuthPasswordEnvKey = "password"
DomainBasicAuthPasswordEnvKey is the fixed envKey used within that namespace, mirroring CloudflareTunnelTokenEnvKey's shape.
const MaxWebhookDeliveryPayloadBytes = 64 * 1024
MaxWebhookDeliveryPayloadBytes bounds how much of a webhook delivery's raw payload SaveWebhookDelivery persists: debug data for an operator to inspect and replay, not a permanent audit log, so an unusually large payload is truncated rather than stored in full.
const OAuthProviderSecretEnvKey = "client_secret"
OAuthProviderSecretEnvKey is the fixed envKey used within that namespace.
const RegistryPasswordEnvKey = "password"
RegistryPasswordEnvKey is the fixed envKey used within that namespace.
Variables ¶
var ( // ErrPolicyNotFound is returned by GetPolicy/DeletePolicy/UpdatePolicy // when no row matches. ErrPolicyNotFound = errors.New("store: iam policy not found") // ErrPolicyNameExists is SavePolicy's failure mode when name is // already taken by a different row. ErrPolicyNameExists = errors.New("store: iam policy name already exists") )
var ErrAPITokenNotFound = errors.New("store: api token not found")
ErrAPITokenNotFound is returned by GetAPITokenByHash and RevokeAPIToken when no token matches.
var ErrAppNotFound = errors.New("store: app not found")
ErrAppNotFound is returned by GetApp, GetAppByName, and DeleteApp when no row matches.
var ErrBackupHistoryNotFound = errors.New("store: backup history record not found")
ErrBackupHistoryNotFound is returned by FinishBackupHistory when id doesn't match any row.
var ErrBackupTargetNotFound = errors.New("store: backup target not found")
ErrBackupTargetNotFound is returned by GetBackupTarget and DeleteBackupTarget when id doesn't match any row.
var ErrBackupVerificationNotFound = errors.New("store: backup verification not found")
ErrBackupVerificationNotFound is returned by FinishBackupVerification when id doesn't match any row, and by GetLatestBackupVerification when backupHistoryID has never been verified.
var ErrBitbucketAppConnectionNotFound = errors.New("store: bitbucket app connection not found")
ErrBitbucketAppConnectionNotFound is returned by GetBitbucketAppConnection and DeleteBitbucketAppConnection when no bitbucket_app_connections row exists, i.e. the OAuth consumer has never been configured.
var ErrCertStorageKeyNotFound = errors.New("store: cert storage key not found")
ErrCertStorageKeyNotFound is returned by GetCertStorageValue and StatCertStorageValue when key has no stored value. Named distinctly from ErrServiceNotFound/ErrNodeNotFound, even though the shape is identical, because internal/ingress's certmagic.Storage adapter needs to translate this into fs.ErrNotExist specifically, per certmagic.Storage's own doc comment ("Load, Delete, List, and Stat methods should return fs.ErrNotExist if the key does not exist"); a store-package-wide NotFound sentinel would make that translation ambiguous about which resource type failed.
var ErrCloneRestoreNotFound = errors.New("store: clone restore record not found")
ErrCloneRestoreNotFound is returned by FinishCloneRestore when id doesn't match any row.
var ErrDatabaseNotFound = errors.New("store: database not found")
ErrDatabaseNotFound is returned by GetDesiredDatabase when no database has that name.
var ErrDeployAttemptNotFound = errors.New("store: deploy attempt not found")
ErrDeployAttemptNotFound is returned by GetDeployAttempt and FinishDeployAttempt when no row has the given ID.
var ErrDeviceAuthRequestNotFound = errors.New("store: device auth request not found")
ErrDeviceAuthRequestNotFound is returned by GetDeviceAuthRequestByDeviceCode/ GetDeviceAuthRequestByUserCode when no row matches.
var ErrEnvironmentNotFound = errors.New("store: environment not found")
ErrEnvironmentNotFound is returned by GetEnvironment and DeleteEnvironment when id doesn't match any row.
var ErrFeatureFlagNotFound = errors.New("store: feature flag not found")
ErrFeatureFlagNotFound is returned by GetFeatureFlag, GetFeatureFlagByKey, UpdateFeatureFlag, and DeleteFeatureFlag when id/key doesn't match any row.
var ErrFirstUserExists = errors.New("store: first user already exists")
ErrFirstUserExists is CreateUser's failure mode when u.IsFirstUser is true but a first user already exists (ux_users_single_first_user).
var ErrGitHubAppConnectionNotFound = errors.New("store: github app connection not found")
ErrGitHubAppConnectionNotFound is returned by GetGitHubAppConnection and UpdateGitHubAppInstallation/DeleteGitHubAppConnection when no github_app_connections row exists, i.e. the App has never been registered through the manifest flow.
var ErrGitLabAppConnectionNotFound = errors.New("store: gitlab app connection not found")
ErrGitLabAppConnectionNotFound is returned by GetGitLabAppConnection and DeleteGitLabAppConnection when no gitlab_app_connections row exists, i.e. the OAuth Application has never been registered.
var ErrGitSourceNotFound = errors.New("store: git source not found")
ErrGitSourceNotFound is returned by GetGitSource and DeleteGitSource when no git source is connected for a given service name.
var ErrInviteAlreadyAccepted = errors.New("store: invite already accepted")
ErrInviteAlreadyAccepted is RevokeInvite/ClaimInvite's failure mode when the invite was already accepted.
var ErrInviteAlreadyRevoked = errors.New("store: invite already revoked")
ErrInviteAlreadyRevoked is RevokeInvite/ClaimInvite's failure mode when the invite was already revoked.
var ErrInviteEmailExists = errors.New("store: a pending invite already exists for this email")
ErrInviteEmailExists is SaveInvite's failure mode when a pending (not yet accepted or revoked) invite already exists for the same email (ux_invites_pending_email).
var ErrInviteNotFound = errors.New("store: invite not found")
ErrInviteNotFound is returned by GetInviteByHash/GetInviteByID when no row matches.
var ErrNodeJoinTokenAlreadyUsed = errors.New("store: node join token already used")
ErrNodeJoinTokenAlreadyUsed is MarkNodeJoinTokenUsed's failure mode when the token has already been exchanged once.
var ErrNodeJoinTokenNotFound = errors.New("store: node join token not found")
ErrNodeJoinTokenNotFound is returned by GetNodeJoinTokenByHash and MarkNodeJoinTokenUsed when no token matches.
var ErrNodeNameTaken = errors.New("store: node name already taken")
ErrNodeNameTaken is returned by SaveNode when name is already used by a different node: node names are operator-facing identifiers (shown in the join command, the node list), so collisions need to surface as a clear error, not a silently overwritten row.
var ErrNodeNotFound = errors.New("store: node not found")
ErrNodeNotFound is returned by GetNode when no node has that ID.
var ErrOAuthIdentityAlreadyLinked = errors.New("store: oauth identity already linked")
ErrOAuthIdentityAlreadyLinked is SaveOAuthIdentity's failure mode when either unique index (migrations/0035) would be violated.
var ErrOAuthIdentityNotFound = errors.New("store: oauth identity not found")
ErrOAuthIdentityNotFound is returned by GetOAuthIdentity when no row matches.
var ErrOrganizationNotFound = errors.New("store: organization not found")
ErrOrganizationNotFound is returned by GetOrganization and DeleteOrganization when id doesn't match any row.
var ErrPasswordResetTokenAlreadyUsed = errors.New("store: password reset token already used")
ErrPasswordResetTokenAlreadyUsed is returned by ClaimPasswordResetToken when the token was already used by a concurrent request.
var ErrPasswordResetTokenNotFound = errors.New("store: password reset token not found")
ErrPasswordResetTokenNotFound is returned by GetPasswordResetTokenByHash when no row matches.
var ErrPreviewEnvironmentNotFound = errors.New("store: preview environment not found")
ErrPreviewEnvironmentNotFound is returned by GetPreviewEnvironment and GetPreviewEnvironmentByAppAndPR when no row matches.
var ErrPreviewEphemeralDatabaseNotFound = errors.New("store: preview ephemeral database not found")
ErrPreviewEphemeralDatabaseNotFound is returned by GetPreviewEphemeralDatabaseByPreviewAndKey when no row matches.
var ErrProjectNotFound = errors.New("store: project not found")
ErrProjectNotFound is returned by GetProject and DeleteProject when id doesn't match any row.
var ErrPublicPortInUse = errors.New("store: public port already in use by another database")
ErrPublicPortInUse is returned by SetDatabasePublicAccess when an explicitly requested port is already assigned to a different database. The unique index migrations/0026 adds on public_port is the hard backstop; this is the friendly error path that avoids ever reaching it in the normal case.
var ErrPublicPortRangeExhausted = errors.New("store: no free public port available")
ErrPublicPortRangeExhausted is returned by SetDatabasePublicAccess when auto-assignment finds no free port left in [PublicPortRangeStart, PublicPortRangeEnd].
var ErrRegistryCredentialNotFound = errors.New("store: registry credential not found")
ErrRegistryCredentialNotFound is returned by GetRegistryCredential and DeleteRegistryCredential when id doesn't match any row.
var ErrRestoreHistoryNotFound = errors.New("store: restore history record not found")
ErrRestoreHistoryNotFound is returned by FinishRestoreHistory when id doesn't match any row.
var ErrScheduledTaskNotFound = errors.New("store: scheduled task not found")
ErrScheduledTaskNotFound is returned by GetScheduledTask, UpdateScheduledTask, RecordScheduledTaskRun, and DeleteScheduledTask when id doesn't match any row.
var ErrSecretValueNotFound = errors.New("store: secret value not found")
ErrSecretValueNotFound is returned by GetSecretValue when no value has been set for that (service, key) pair.
var ErrServiceDEKNotFound = errors.New("store: service DEK not found")
ErrServiceDEKNotFound is returned by GetServiceDEK when no DEK has been generated for a service yet, i.e. no secret value has ever been set for it.
var ErrServiceNotFound = errors.New("store: service not found")
ErrServiceNotFound is returned by GetDesiredService when no service has that name.
var ErrServiceVolumeBackupNotFound = errors.New("store: service volume backup schedule not found")
ErrServiceVolumeBackupNotFound is returned by GetServiceVolumeBackupSchedule when no row exists for the given service/volume pair.
var ErrServiceVolumeNotFound = errors.New("store: service volume not found")
ErrServiceVolumeNotFound is returned by ResolveServiceVolumeDockerName when serviceName has no volume by that logical name.
var ErrUserEmailExists = errors.New("store: user email already exists")
ErrUserEmailExists is CreateUser's failure mode when email is already taken by a different row.
var ErrUserNotFound = errors.New("store: user not found")
ErrUserNotFound is returned by GetUserByID and GetUserByEmail when no row matches.
var ErrVolumeCloneRestoreNotFound = errors.New("store: volume clone restore record not found")
ErrVolumeCloneRestoreNotFound is returned by FinishVolumeCloneRestore when id doesn't match any row.
var ErrWebhookDeliveryNotFound = errors.New("store: webhook delivery not found")
ErrWebhookDeliveryNotFound is returned by GetWebhookDelivery when no row has the given ID.
Functions ¶
func BackupTargetSecretsKey ¶
BackupTargetSecretsKey is the internal/secrets serviceName a backup target's access key ID and secret access key are stored under (envKeys "access_key_id" and "secret_access_key"). A function, not a constant format string inlined at each call site, so internal/api and internal/backup can never drift into computing this two different ways.
func BitbucketAppSecretsKey ¶
func BitbucketAppSecretsKey() string
BitbucketAppSecretsKey is the internal/secrets serviceName the OAuth consumer's secret and access_token/refresh_token/token_expires_at are stored under. A fixed constant, not parameterized: there is only ever one Bitbucket connection per control plane, the same reasoning GitHubAppSecretsKey/GitLabAppSecretsKey's own doc comments give.
func CloudflareDNSSecretsKey ¶
func CloudflareDNSSecretsKey() string
CloudflareDNSSecretsKey is the internal/secrets serviceName the Cloudflare DNS-01 API token is stored under (envKey CloudflareDNSTokenEnvKey), mirroring CloudflareTunnelSecretsKey's shape but for a distinct credential: a scoped Cloudflare API token (Zone:DNS:Edit), not the cloudflared connector token.
func CloudflareTunnelSecretsKey ¶
func CloudflareTunnelSecretsKey() string
CloudflareTunnelSecretsKey is the internal/secrets serviceName the Cloudflare Tunnel token is stored under (envKey CloudflareTunnelTokenEnvKey), mirroring EmailSettingsSecretsKey's exact shape: one platform-wide credential, not per-app.
func DomainBasicAuthSecretsKey ¶
DomainBasicAuthSecretsKey is the internal/secrets serviceName a domain's basic-auth password is stored under (envKey DomainBasicAuthPasswordEnvKey), mirroring BackupTargetSecretsKey's "<kind>/<id>" shape, keyed by domain instead of a target ID.
func DomainTLSCertSecretsKey ¶
DomainTLSCertSecretsKey is the internal/secrets serviceName a domain's BYO TLS certificate and private key are stored under (envKeys DomainTLSCertCertificateEnvKey/DomainTLSCertPrivateKeyEnvKey), mirroring DomainBasicAuthSecretsKey's "<kind>/<domain>" shape.
func EmailSettingsSecretsKey ¶
func EmailSettingsSecretsKey() string
EmailSettingsSecretsKey is the internal/secrets serviceName the platform-wide email settings' credentials are stored under (envKeys "smtp_password" and "ses_secret_access_key").
func FormatAuditTime ¶
FormatAuditTime renders t as this package's audit_log.created_at format. Exported so internal/api's requireAbility, the only writer of AuditEntry.CreatedAt, produces values in the exact format ListAuditEntries' own cursor comparison assumes.
func GitHubAppSecretsKey ¶
func GitHubAppSecretsKey() string
GitHubAppSecretsKey is the internal/secrets serviceName the GitHub App's client_secret, webhook_secret, and PEM private key are stored under (envKeys "client_secret", "webhook_secret", "private_key"). Mirrors BackupTargetSecretsKey's exact shape: a function, not a literal repeated at each call site, so internal/api and internal/githubapp can never drift into computing this two different ways.
A fixed constant, not parameterized by an ID like BackupTargetSecretsKey(targetID) is: there is only ever one GitHub App connection per control plane (github_app_connections is a singleton table, id=1 only), unlike backup targets which are one-per-connected-bucket. The "/" makes this string structurally impossible to collide with a real service name: every real desired_services row name is validated as a Docker-container/ DNS-label-safe token (see internal/spec's service name validation) and can never contain a "/", the same reasoning BackupTargetSecretsKey's own doc comment gives for its "backup-target/"+targetID shape.
func GitLabAppSecretsKey ¶
func GitLabAppSecretsKey() string
GitLabAppSecretsKey is the internal/secrets serviceName the OAuth Application's client_secret and access_token/refresh_token/ token_expires_at are stored under. A fixed constant, not parameterized: there is only ever one GitLab connection per control plane, the same reasoning GitHubAppSecretsKey's own doc comment gives.
func GitSourceSecretsKey ¶
GitSourceSecretsKey is the internal/secrets serviceName a git source's deploy token ("deploy_token" envKey) and webhook HMAC secret ("webhook_secret" envKey) are stored under, the same distinct-namespace-from-the-real-service reasoning BackupTargetSecretsKey's own doc comment already establishes: a git source's own credentials must never share a DEK with the app's actual runtime env secrets (service.go's SaveDesiredService/secret_env), which live under the plain service name.
func IsSupportedEngine ¶
IsSupportedEngine reports whether id is a real, registered database engine. internal/api's validateDatabaseResource and internal/store.SaveDesiredDatabase's own callers use this instead of each hardcoding its own postgres/redis/mysql comparison chain, so adding a new engine's identity here is one file to edit, not a grep across the codebase for every hardcoded chain.
func NewAuditEntryID ¶
NewAuditEntryID generates an opaque, URL-safe audit entry identifier, minted the same way NewDeployAttemptID mints its own (fixed-length crypto/rand bytes, base64 URL encoding, a short prefix).
func NewDeployAttemptID ¶
NewDeployAttemptID generates an opaque, URL-safe deploy-attempt identifier, minted the same way internal/api/tokens.go's randomTokenID mints an API token ID (fixed-length crypto/rand bytes, base64 URL encoding, a short prefix). Exported and placed in this package, unlike randomTokenID which stays private to internal/api: more than one package needs to mint one of these. The plain image-tag and manual build triggers both live in internal/api, but the git webhook receiver (internal/webhook) is a separate package needing the identical scheme, and duplicating the byte-length/encoding choice in two places would risk them silently drifting apart.
func NewDeviceAuthRequestID ¶
NewDeviceAuthRequestID mints a random device auth request ID, the same crypto/rand-plus-base64 scheme NewDeployAttemptID/NewPolicyID already establish.
func NewDeviceCode ¶
NewDeviceCode mints a long, opaque, unguessable code the CLI polls with: this is the credential half of the pair, never shown to a human, so it can be as dense as a token.
func NewPolicyAttachmentID ¶
NewPolicyAttachmentID mints a random attachment ID, same scheme as NewPolicyID.
func NewPolicyID ¶
NewPolicyID mints a random policy ID, the same fixed-length crypto/rand-plus-base64 scheme NewDeployAttemptID already establishes.
func NewPreviewEnvironmentID ¶
NewPreviewEnvironmentID mints a random preview environment ID, the same fixed-length crypto/rand-plus-base64 scheme NewDeployAttemptID already establishes for an analogous webhook-minted identifier.
func NewPreviewEphemeralDatabaseID ¶
NewPreviewEphemeralDatabaseID mints a random ephemeral database tracking row ID, the same scheme NewPreviewEnvironmentID already establishes for its own webhook-minted identifier.
func NewUserCode ¶
NewUserCode mints an 8-character, dash-grouped code a human types into the web UI (GitHub/gh CLI's own device-flow UX), e.g. "WDJB-MJHT". Short and low-entropy by design: it only needs to resist a casual guess for the few minutes it's valid, DeviceCode is what actually authorizes the token exchange.
func NewWebhookDeliveryID ¶
NewWebhookDeliveryID generates an opaque, URL-safe webhook-delivery identifier, the same mint scheme NewDeployAttemptID already establishes (fixed-length crypto/rand bytes, base64 URL encoding, a short prefix).
func OAuthProviderSecretsKey ¶
OAuthProviderSecretsKey is the internal/secrets serviceName a provider's client secret is stored under, mirroring BackupTargetSecretsKey's shape.
func RegistryCredentialSecretsKey ¶
RegistryCredentialSecretsKey is the internal/secrets serviceName a registry credential's password is stored under (envKey "password").
func RegistrySettingsSecretsKey ¶
func RegistrySettingsSecretsKey() string
RegistrySettingsSecretsKey is the internal/secrets serviceName the built-in registry's generated password is stored under (envKey RegistryPasswordEnvKey), mirroring CloudflareTunnelSecretsKey's exact shape: one platform-wide credential, not per-app.
func ServiceVolumeDockerName ¶
func ServiceVolumeDockerName(svc DesiredService, volumeName string) (string, bool)
ServiceVolumeDockerName finds svc's real Docker volume whose logical name (spec.Volume.Name, what an operator wrote in app.yaml) is volumeName, deriving it back from ServiceVolume.Name by stripping the fixed prefix internal/deploy's own volumeName() always applies ("app-"+svc.Name+"-"): ServiceVolume itself only stores the already- resolved Docker volume name (this struct's own doc comment), not the logical one it came from, so this is the one place that direction gets reversed. Exact-prefix stripping, not a generic split, so a logical name that itself contains "-" is never misparsed.
func UserTOTPSecretsKey ¶
UserTOTPSecretsKey returns the internal/secrets serviceName a user's TOTP secret is stored under, parameterized by ID the same way BackupTargetSecretsKey(targetID) is: unlike GitHubAppSecretsKey's fixed singleton-row key, every user has their own. The "/" makes this structurally impossible to collide with a real desired_services name, same reasoning BackupTargetSecretsKey's own doc comment gives.
Types ¶
type APIToken ¶
type APIToken struct {
ID string
Name string
TokenHash string
Abilities []string
CreatedAt time.Time
LastUsedAt *time.Time
ExpiresAt *time.Time
RevokedAt *time.Time
}
APIToken is one non-interactive credential, the backend auth foundation: a CLI, an MCP server, or a third-party integration authenticates with the plaintext token this row's TokenHash is a SHA-256 digest of, scoped to Abilities. The plaintext itself is never stored anywhere, generated once by internal/api and returned to the caller exactly once.
type App ¶
App is stage 1 of multi-service apps (migrations/0039_apps.sql): a named owner that zero or more store.DesiredService rows can belong to via their AppID field. ProjectID mirrors DesiredService.ProjectID: empty string means no project, not merely "unset".
type AuditEntry ¶
type AuditEntry struct {
ID string
ActorType string // "session" or "token"
ActorID string
ActorName string
Ability string
Method string
Path string
StatusCode int
RemoteAddr string
CreatedAt string
ClientKind string // "cli", "dashboard", "mcp", or "api" (migrations/0077), derived from User-Agent
}
AuditEntry is one recorded request that passed internal/api's requireAbility at more than AbilityRead (migrations/0043): who did what, closing the gap docs/comparison.md's own "no audit log exists anywhere in the codebase" line calls out. CreatedAt is a pre-formatted RFC3339Nano string, not a time.Time, the same "caller controls the wire format" convention BackupHistory's own StartedAt/FinishedAt fields already establish in this package.
type AuditEntryFilter ¶
AuditEntryFilter narrows ListAuditEntries to a specific resource's own audit trail, e.g. an app's config-changing requests (Path set to that app's exact path, Method to "PUT"). A zero-value filter applies no narrowing, the same behavior ListAuditEntries always had.
type BackupHistory ¶
type BackupHistory struct {
ID string
DatabaseName string
// ResourceKind is BackupResourceKindDatabase for every row written
// before migrations/0075 added this column: that migration's own
// DEFAULT 'database' makes this the real, correct value for those
// rows, not a placeholder.
ResourceKind string
ServiceName string
VolumeName string
TargetID string
ObjectKey string
SizeBytes int64
Status string
Error string
StartedAt string
FinishedAt string
ChecksumSHA256 string
}
BackupHistory is one attempted backup to one backup target, of either a managed database (DatabaseName, ResourceKind BackupResourceKindDatabase) or an app service's named volume (ServiceName/VolumeName, ResourceKind BackupResourceKindVolume): the two identity shapes are mutually exclusive, never both populated on the same row. Error is empty unless Status is BackupStatusFailed. ChecksumSHA256 is empty until FinishBackupHistory records a succeeded attempt's dump checksum (empty for a running or failed attempt, and for any row written before migrations/0069_backup_verification.sql).
type BackupTarget ¶
type BackupTarget struct {
ID string
Name string
Provider string
Endpoint string
Region string
Bucket string
CreatedAt string
}
BackupTarget is a connected S3-compatible bucket a database backup can be uploaded to. No credential fields: see this table's own migration comment. A caller resolving credentials does so separately through internal/secrets, keyed by BackupTargetSecretsKey(target.ID).
type BackupVerification ¶
type BackupVerification struct {
ID string
BackupHistoryID string
Status string
ChecksumMatch bool
SizeMatch bool
FormatValid bool
DownloadedBytes int64
Error string
CheckedBy string
StartedAt string
FinishedAt string
}
BackupVerification is one attempt to confirm a previously succeeded backup_history row's stored object is still intact: re-downloaded, re-hashed, and checked against what was recorded at backup time, without ever attempting a live restore. Error is empty unless Status is BackupVerificationStatusFailed.
type BitbucketAppConnection ¶
BitbucketAppConnection is the single-row bitbucket_app_connections table (migrations/0062_bitbucket_app_connection.sql). No secret fields: the consumer's own secret and the OAuth access_token/ refresh_token/token_expires_at live in internal/secrets instead, under BitbucketAppSecretsKey(), the same split GitHubAppConnection and GitLabAppConnection already establish.
type CertStorageKeyInfo ¶
type CertStorageKeyInfo struct {
Key string
ModifiedAt time.Time
Size int64
// IsTerminal is true for an exact stored value ("file"), false when
// key only exists as a prefix of other stored keys ("directory"),
// matching certmagic.Storage's own file-system-shaped key semantics.
IsTerminal bool
}
CertStorageKeyInfo mirrors certmagic.KeyInfo's shape (see internal/ingress.SQLiteStorage.Stat), decoupled from the certmagic import so this package never needs to depend on Caddy/certmagic itself, only internal/ingress does.
type CertStorageValue ¶
CertStorageValue is one stored key's value and last-write time.
type CloneRestore ¶
type CloneRestore struct {
ID string
SourceDatabaseName string
NewDatabaseName string
BackupHistoryID string
Status string
Error string
StartedAt string
FinishedAt string
}
CloneRestore is one attempted "restore as new database": a backup of SourceDatabaseName restored into NewDatabaseName, a database created fresh for this attempt rather than overwriting anything. Status reuses BackupStatusRunning/Succeeded/Failed, the same reasoning RestoreHistory's own doc comment gives for its identical lifecycle.
type CloudflareDNSSettings ¶
type CloudflareDNSSettings struct {
Enabled bool
}
CloudflareDNSSettings is the single platform-wide row: whether ACME DNS-01 via Cloudflare is enabled for wildcard domains. No token field: that goes through internal/secrets instead.
type CloudflareTunnelSettings ¶
type CloudflareTunnelSettings struct {
Enabled bool
}
CloudflareTunnelSettings is the single platform-wide row: whether the operator wants the cloudflared container running. No token field: that goes through internal/secrets instead.
type DB ¶
DB wraps a *sql.DB opened against a single SQLite file, WAL mode and foreign keys on, migrated to the latest version before Open returns.
func Open ¶
Open opens (creating if needed) the SQLite database at path, applies pragmas, and runs every pending migration. path is a plain filesystem path, not a DSN; Open builds the DSN itself so callers never need to know the pragma query-string format.
func (*DB) AcquireCertStorageLock ¶
func (db *DB) AcquireCertStorageLock(ctx context.Context, name string, staleAfter time.Duration) (bool, error)
AcquireCertStorageLock attempts to atomically claim the named lock: insert it if free, or steal it if the existing holder's last refresh is older than staleAfter (an abandoned lock from a holder that crashed without calling ReleaseCertStorageLock). Returns false, nil (not an error) if a different, still-fresh holder currently has the lock; the caller is expected to wait and retry, the same shape certmagic.FileStorage.Lock's own polling loop uses.
func (*DB) AttachPolicy ¶
func (db *DB) AttachPolicy(ctx context.Context, id, policyID, principalType, principalID string) error
AttachPolicy links policyID to one principal. Idempotent: attaching an already-attached (policy, principal) pair is a no-op, not an error, since the caller's intent ("this principal should have this policy") is already satisfied.
func (*DB) ClaimInvite ¶
ClaimInvite atomically marks the named invite accepted, only if it hasn't already been accepted or revoked: the same "WHERE clause plus rows-affected check is the single race-decision point" shape ClaimPasswordResetToken already establishes.
func (*DB) ClaimPasswordResetToken ¶
ClaimPasswordResetToken atomically marks the named token used, only if it hasn't been already: the WHERE clause and rows-affected check make this the single point two concurrent requests holding the same token race on, so at most one can ever proceed to change the password.
func (*DB) ConsumeUserRecoveryCode ¶
ConsumeUserRecoveryCode marks the row matching (userID, hash) used, if it exists and hasn't been used already, and reports whether it did: the one-shot, atomic "was this a valid unused code" check internal/api's login and disable flows both need. A matched-but- already-used row and no match at all are indistinguishable to the caller, both report false, since neither should validate a login.
func (*DB) CountUnusedUserRecoveryCodes ¶
CountUnusedUserRecoveryCodes returns how many of userID's recovery codes have not been consumed yet, the settings-page "N codes remaining" figure.
func (*DB) CountUsers ¶
CountUsers returns how many user rows exist, BootstrapAdmin's "has anyone signed up yet" check.
func (*DB) CreateUser ¶
CreateUser inserts a new user row, insert-only, never an upsert. On failure it re-checks by the relevant unique constraint to classify the cause, rather than assuming every failure means the same thing.
func (*DB) DeleteApp ¶
DeleteApp removes an app row. desired_services.app_id is "REFERENCES apps(id) ON DELETE CASCADE" (migrations/0039_apps.sql), so every service belonging to this app is deleted along with it, unlike DeleteProject's ON DELETE SET NULL: an app owns its services' lifecycle, a project is only a label. Returns ErrAppNotFound if id doesn't exist.
func (*DB) DeleteAuditEntriesOlderThan ¶
DeleteAuditEntriesOlderThan removes every audit_log row created strictly before cutoff, returning the number of rows removed. The retention sweep (internal/api's RunAuditLogSweeper) and the manual purge endpoint both call this with a cutoff derived from the operator-configured retention window, rather than each rolling its own delete query.
func (*DB) DeleteBackupTarget ¶
DeleteBackupTarget removes a backup target row. It does not touch internal/secrets: the caller (internal/api's handleDeleteBackupTarget) deletes the credential secret separately, after this succeeds, the same "store row is the success signal, secret cleanup follows it" ordering used everywhere else credentials and store rows are paired. Returns ErrBackupTargetNotFound if id doesn't exist. Foreign key enforcement is on (store.go's "_pragma foreign_keys(ON)"), so deleting a target any backup_history row still references fails with a constraint error rather than silently orphaning history rows or cascading a delete a user didn't ask for; the caller surfaces that as a real error, not a bug to work around here.
func (*DB) DeleteBitbucketAppConnection ¶
DeleteBitbucketAppConnection removes the single bitbucket_app_connections row. Returns ErrBitbucketAppConnectionNotFound if nothing was connected. Like DeleteGitLabAppConnection, this does not erase the secrets values still held under BitbucketAppSecretsKey(); callers are expected to also call BitbucketAppSecrets.DeleteAll.
func (*DB) DeleteCertStorageValue ¶
DeleteCertStorageValue removes key. certmagic.Storage.Delete's doc comment requires deleting every key prefixed by key too ("directory" semantics), so this also removes any key under key+"/", not only an exact match. Deleting a key that exists as neither is not an error, matching certmagic's own FileStorage.Delete (os.RemoveAll on an already-absent path is a no-op).
func (*DB) DeleteDesiredDatabase ¶
DeleteDesiredDatabase removes a database's desired state, the same "not found" sentinel and "does not stop the running container itself" gap DeleteDesiredService's own doc comment documents, applied to a database instead of a service.
func (*DB) DeleteDesiredService ¶
DeleteDesiredService removes a service's desired state, e.g. because the app was deleted through the HTTP API. It returns ErrServiceNotFound if no such service exists, the same sentinel GetDesiredService uses, so callers handle "not found" one way regardless of which method produced it.
Deleting desired state does not, by itself, stop or remove any container currently running for this service: as of this writing the application controller (internal/reconcile/application) treats a missing desired service as "nothing to do yet" (NoDesiredState), not "tear down what's running". Making delete actually converge to zero containers is a reconciler change, not a store one, and is a known gap left for that package.
func (*DB) DeleteDomainBasicAuth ¶
DeleteDomainBasicAuth removes domain's basic-auth row, if any. Idempotent: deleting a domain with none configured is not an error.
func (*DB) DeleteDomainMaintenance ¶
DeleteDomainMaintenance disables maintenance mode for domain, if enabled. Idempotent: clearing a domain with none configured is not an error.
func (*DB) DeleteDomainTLSCert ¶
DeleteDomainTLSCert removes domain's BYO cert row, if any. Idempotent: deleting a domain with none uploaded is not an error.
func (*DB) DeleteDomainWAF ¶
DeleteDomainWAF removes domain's WAF/rate-limit row, if any, resetting it to the default (WAF off, rate limiting off). Idempotent: deleting a domain with none configured is not an error.
func (*DB) DeleteEnvironment ¶
DeleteEnvironment removes an environment row. desired_services. environment_id is ON DELETE SET NULL (migrations/0054), so every service tagged with this environment is left running, untagged again.
func (*DB) DeleteFeatureFlag ¶
DeleteFeatureFlag removes a feature flag row. Returns ErrFeatureFlagNotFound if id doesn't exist.
func (*DB) DeleteGitHubAppConnection ¶
DeleteGitHubAppConnection removes the single github_app_connections row, the "disconnect" action. Returns ErrGitHubAppConnectionNotFound if nothing was connected.
This does not reach out to GitHub to delete or uninstall the App there, and it does not delete the client_secret/webhook_secret/ private_key values internal/secrets still holds under GitHubAppSecretsKey(): the same known, documented gap DeleteBackupTarget's own doc comment already accepts for backup target credentials, since internal/secrets.Manager has no delete operation today. A re-registration (SaveGitHubAppConnection) simply overwrites those secret values with the new App's own.
func (*DB) DeleteGitLabAppConnection ¶
DeleteGitLabAppConnection removes the single gitlab_app_connections row. Returns ErrGitLabAppConnectionNotFound if nothing was connected. Like DeleteGitHubAppConnection, this does not erase the secrets values (client_secret/access_token/refresh_token) still held under GitLabAppSecretsKey(); callers are expected to also call GitLabAppSecrets.DeleteAll.
func (*DB) DeleteGitSource ¶
DeleteGitSource disconnects serviceName's git source, returning ErrGitSourceNotFound if none exists. Known gap, matching DeleteBackupTarget's own honestly-documented one: internal/secrets.Manager has no delete/revoke operation today, so the deploy token and webhook secret this source's connect flow wrote (GitSourceSecretsKey) remain in the secrets store, unreferenced and unreachable through this API but not actually erased at rest.
func (*DB) DeleteNode ¶
DeleteNode removes a node by ID. Idempotent, matching DeleteDesiredService's convention: deleting an already-gone node is not an error.
Still no placement guard at this layer: internal/api's handleDeleteNode is what refuses to call this at all while ListDesiredServicesByNode/ListDesiredDatabasesByNode report any placements remaining, the same "guard at the API boundary, keep the store primitive unconditional" shape this package already uses elsewhere (e.g. SaveDesiredService's node_id exception is enforced by which method gets called, not by a check inside one shared method).
func (*DB) DeleteOrganization ¶
DeleteOrganization removes an organization row. projects.org_id is ON DELETE SET NULL (migrations/0054), so every project in this organization is left running, simply org-less again.
func (*DB) DeletePolicy ¶
DeletePolicy removes a policy and (via ON DELETE CASCADE) every attachment referencing it. Idempotent: deleting a missing ID is not an error, matching DeleteDesiredService's own convention.
func (*DB) DeletePreviewEnvironment ¶
DeletePreviewEnvironment removes a preview environment row once its app/services and domain have actually been torn down; returns ErrPreviewEnvironmentNotFound if id doesn't exist. A partially-failed teardown instead calls UpdatePreviewEnvironment with a Failed status and a StatusReason, keeping the row so the manual teardown action has something to retry.
func (*DB) DeletePreviewEphemeralDatabase ¶
DeletePreviewEphemeralDatabase removes a tracking row once its database has actually been torn down; returns ErrPreviewEphemeralDatabaseNotFound if id doesn't exist.
func (*DB) DeleteProject ¶
DeleteProject removes a project row. Unlike DeleteBackupTarget (which relies on foreign key enforcement to *reject* a delete while backup_history still references the target), desired_services. project_id and desired_databases.project_id are declared "REFERENCES projects(id) ON DELETE SET NULL" (migrations/0022_projects.sql), so this delete always succeeds and every app/database that belonged to this project is left in place, simply project-less again (project_id reverts to NULL), the same real, valid, permanent state an app/database that was never assigned to a project is already in. There is deliberately no cascade here: a project is an organizational label, not a lifecycle owner, so deleting the label must never delete the real resources it labeled. Returns ErrProjectNotFound if id doesn't exist.
func (*DB) DeleteRegistryCredential ¶
DeleteRegistryCredential removes a registry credential row. It does not touch internal/secrets: the caller deletes the password secret separately, after this succeeds, the same ordering BackupTarget uses. Returns ErrRegistryCredentialNotFound if id doesn't exist.
func (*DB) DeleteScheduledTask ¶
DeleteScheduledTask removes a scheduled task row. Returns ErrScheduledTaskNotFound if id doesn't exist.
func (*DB) DeleteServiceSecrets ¶
DeleteServiceSecrets removes every value and the wrapped DEK for serviceName, in a transaction. Deleting the DEK itself (not just the value rows) matters: any ciphertext that somehow survives elsewhere (a backup, a replication lag) becomes permanently unrecoverable once its DEK is gone, rather than merely inaccessible through this API. Idempotent: a serviceName with no rows in either table is not an error, matching DeleteDesiredService's own "delete is idempotent" convention.
func (*DB) DeleteUser ¶
DeleteUser removes a user row; the FK cascade (migrations/0035) takes any linked OAuth identities with it. Guards like "not the last user" live in internal/api/users.go, not here.
func (*DB) DeleteUserRecoveryCodes ¶
DeleteUserRecoveryCodes removes every recovery code row for userID, called when 2FA is disabled: a leftover valid recovery code would otherwise still grant access to an account whose owner just turned two-factor off.
func (*DB) DetachPolicy ¶
DetachPolicy removes the link between policyID and one principal. Idempotent, matching DeletePolicy's own convention.
func (*DB) DisableUserTOTP ¶
DisableUserTOTP clears a user's TOTP state. It does not touch the user_recovery_codes table or the internal/secrets-held secret; callers (internal/api's disable handler) delete those separately, since only that layer has a secrets.Manager to call DeleteAll on. Returns ErrUserNotFound if id doesn't exist.
func (*DB) EnableUserTOTP ¶
EnableUserTOTP marks a user's TOTP setup confirmed: the caller has already verified a code against the secret it stored in internal/secrets before calling this. Returns ErrUserNotFound if id doesn't exist.
func (*DB) ExistsCertStorageValue ¶
ExistsCertStorageValue reports whether key is stored either as an exact value or as a "directory" prefix of other stored keys.
func (*DB) FailOrphanedDeployAttempts ¶
FailOrphanedDeployAttempts marks every still-"running" deploy attempt as failed: called once at control-plane startup, before anything can create a new one, so a "running" row at that moment can only mean the process that owned it is gone (crash, OOM, restart) and it will never get its own FinishDeployAttempt call. Returns the number of rows fixed.
func (*DB) FinishBackupHistory ¶
func (db *DB) FinishBackupHistory(ctx context.Context, id, status string, sizeBytes int64, checksum, errMsg, finishedAt string) error
FinishBackupHistory updates a running backup history row to its final status. sizeBytes, checksum, and errMsg are all ignored (left as-is / not applicable) when status is BackupStatusRunning, which callers should never actually pass here since StartBackupHistory already wrote that state; FinishBackupHistory exists specifically for the succeeded/failed transition. checksum is the dump's SHA-256, hex-encoded, computed by Runner while streaming it to the upload target; empty on a failed attempt, since there is no complete dump to have hashed.
func (*DB) FinishBackupVerification ¶
func (db *DB) FinishBackupVerification(ctx context.Context, id, status string, checksumMatch, sizeMatch, formatValid bool, downloadedBytes int64, errMsg, finishedAt string) error
FinishBackupVerification updates a running verification row to its final status, recording each individual check's own outcome (checksumMatch, sizeMatch, formatValid) alongside the overall status, so a failure can be explained (which check failed), not just reported.
func (*DB) FinishCloneRestore ¶
FinishCloneRestore updates a running clone-restore row to its final status, mirroring FinishRestoreHistory exactly.
func (*DB) FinishDeployAttempt ¶
func (db *DB) FinishDeployAttempt(ctx context.Context, id, status string, finishedAt time.Time, errMsg string) error
FinishDeployAttempt marks a deploy attempt's terminal outcome: called exactly once per attempt, when the triggering handler's call to internal/deploy.Pipeline.Deploy (or, for the plain image-tag path, SaveDesiredService) returns. errMsg should be empty for a succeeded attempt; status is not validated against a fixed enum here (the three call sites already only ever pass one of the two terminal DeployAttemptStatus* constants), matching UpsertConditions' own "caller controls the vocabulary" convention for status strings elsewhere in this package.
func (*DB) FinishRestoreHistory ¶
func (db *DB) FinishRestoreHistory(ctx context.Context, id, status, errMsg, finishedAt string) error
FinishRestoreHistory updates a running restore history row to its final status, the restore counterpart of FinishBackupHistory (no sizeBytes parameter: nothing is uploaded on a restore, so there is no equivalent byte count to record).
func (*DB) FinishVolumeCloneRestore ¶
func (db *DB) FinishVolumeCloneRestore(ctx context.Context, id, status, errMsg, finishedAt string) error
FinishVolumeCloneRestore updates a running clone-restore row to its final status, mirroring FinishCloneRestore exactly.
func (*DB) GetAPITokenByHash ¶
GetAPITokenByHash returns the token row matching hash, regardless of whether it's revoked or expired: deciding "is this token currently usable" is the caller's job (internal/api's auth middleware), this is pure lookup, the same separation reconcile_status.go keeps between storage and decision-making.
func (*DB) GetAppByName ¶
GetAppByName returns the app with this name, or ErrAppNotFound. A separate method from GetApp rather than one "id or name" lookup: id and name are different columns with different uniqueness guarantees (id is the primary key, name has its own UNIQUE constraint), so which one a caller has is always known at the call site, the same way GetProject (by id) and GetDesiredService (by name) are already two distinct methods rather than one overloaded one.
func (*DB) GetBackupHistory ¶
GetBackupHistory returns the backup attempt with this ID, or ErrBackupHistoryNotFound. Added for the restore path (internal/backup.RestoreRunner): a restore is always initiated by naming a specific past backup attempt, so unlike the forward backup path (which only ever lists history, never looks up one row by ID), restoring needs to resolve exactly one row, including its Status, TargetID, and ObjectKey, before anything else can happen.
func (*DB) GetBackupTarget ¶
GetBackupTarget returns the backup target with this ID, or ErrBackupTargetNotFound.
func (*DB) GetBitbucketAppConnection ¶
func (db *DB) GetBitbucketAppConnection(ctx context.Context) (BitbucketAppConnection, error)
GetBitbucketAppConnection returns the single bitbucket_app_connections row, or ErrBitbucketAppConnectionNotFound if none exists.
func (*DB) GetCertStorageValue ¶
GetCertStorageValue returns the value stored at key, or ErrCertStorageKeyNotFound.
func (*DB) GetCloudflareDNSSettings ¶
func (db *DB) GetCloudflareDNSSettings(ctx context.Context) (CloudflareDNSSettings, error)
GetCloudflareDNSSettings returns the single cloudflare_dns_settings row. Always succeeds: the migration itself inserts the row (id = 1).
func (*DB) GetCloudflareTunnelSettings ¶
func (db *DB) GetCloudflareTunnelSettings(ctx context.Context) (CloudflareTunnelSettings, error)
GetCloudflareTunnelSettings returns the single cloudflare_tunnel_settings row. Always succeeds: the migration itself inserts the row (id = 1).
func (*DB) GetConditions ¶
func (db *DB) GetConditions(ctx context.Context, controllerName string) ([]reconcile.Condition, error)
GetConditions returns every stored condition for a controller, ordered by condition type, or nil if none have been recorded yet.
func (*DB) GetConditionsForControllers ¶
func (db *DB) GetConditionsForControllers(ctx context.Context, controllerNames []string) (map[string][]reconcile.Condition, error)
GetConditionsForControllers is GetConditions' batched counterpart: one query for every controller in controllerNames, keyed by controller name in the returned map, instead of a GetConditions call per controller. Built for GET /api/v1/apps (internal/api/apps.go's handleListApps), which needs a status summary per app without reintroducing the N+1 AppRow.tsx's own doc comment warns against. A controller with no stored conditions is simply absent from the map, the same "nil means none recorded yet" convention GetConditions already establishes for a single controller.
func (*DB) GetDeployAttempt ¶
GetDeployAttempt returns one deploy attempt by ID, or ErrDeployAttemptNotFound if no such row exists. Used by the SSE log stream handler (internal/api/deploys.go) to decide whether an attempt is still in progress (serve a live tail) or already finished (serve a full persisted replay), see that handler's own doc comment.
func (*DB) GetDesiredDatabase ¶
GetDesiredDatabase returns the desired state for name, or ErrDatabaseNotFound if no such database has been saved.
func (*DB) GetDesiredService ¶
GetDesiredService returns the desired state for name, or ErrServiceNotFound if no such service has been saved.
func (*DB) GetDeviceAuthRequestByDeviceCode ¶
func (db *DB) GetDeviceAuthRequestByDeviceCode(ctx context.Context, deviceCode string) (*DeviceAuthRequest, error)
GetDeviceAuthRequestByDeviceCode is the CLI poll's own lookup.
func (*DB) GetDeviceAuthRequestByUserCode ¶
func (db *DB) GetDeviceAuthRequestByUserCode(ctx context.Context, userCode string) (*DeviceAuthRequest, error)
GetDeviceAuthRequestByUserCode is the web UI's own lookup, keyed by the code an operator types in.
func (*DB) GetDomainBasicAuth ¶
GetDomainBasicAuth returns the basic-auth row for domain. found is false when the domain has none configured, the default, valid state for any domain, not an error.
func (*DB) GetDomainMaintenance ¶
GetDomainMaintenance reports whether domain currently has maintenance mode enabled. false is the default, valid state for any domain, not an error.
func (*DB) GetDomainTLSCert ¶
GetDomainTLSCert returns the BYO cert row for domain. found is false when the domain has none uploaded, the default, valid state for any domain, not an error.
func (*DB) GetDomainWAF ¶
GetDomainWAF returns domain's current WAF/rate-limit configuration. found is false when the domain has no row, the default, valid state for any domain, not an error; the returned DomainWAF is the zero value plus DomainWAFModeDetect in that case, mirroring what a fresh row would look like before an operator changes anything.
func (*DB) GetEmailSettings ¶
func (db *DB) GetEmailSettings(ctx context.Context) (EmailSettings, error)
GetEmailSettings returns the single email_settings row. Always succeeds: the migration itself inserts the row (id = 1).
func (*DB) GetEnvironment ¶
GetEnvironment returns the environment with this ID, or ErrEnvironmentNotFound.
func (*DB) GetFeatureFlag ¶
GetFeatureFlag returns the feature flag with this ID, or ErrFeatureFlagNotFound.
func (*DB) GetFeatureFlagByKey ¶
GetFeatureFlagByKey returns the feature flag with this Key, or ErrFeatureFlagNotFound. This is what handleEvaluateFeatureFlag looks up by, since the evaluate endpoint's URL carries no app name (see this table's own migration comment).
func (*DB) GetGitHubAppConnection ¶
func (db *DB) GetGitHubAppConnection(ctx context.Context) (GitHubAppConnection, error)
GetGitHubAppConnection returns the single github_app_connections row, or ErrGitHubAppConnectionNotFound if the App has never been registered.
func (*DB) GetGitLabAppConnection ¶
func (db *DB) GetGitLabAppConnection(ctx context.Context) (GitLabAppConnection, error)
GetGitLabAppConnection returns the single gitlab_app_connections row, or ErrGitLabAppConnectionNotFound if none exists.
func (*DB) GetGitSource ¶
GetGitSource returns the git source connected to serviceName, or ErrGitSourceNotFound if none is.
func (*DB) GetHookRuns ¶
GetHookRuns returns every stored hook outcome for serviceName (at most one per hook type), or nil if neither hook has ever run.
func (*DB) GetIngressSettings ¶
func (db *DB) GetIngressSettings(ctx context.Context) (IngressSettings, error)
GetIngressSettings returns the single ingress_settings row. Always succeeds against a migrated database: the migration itself inserts the row (id = 1), so there is no "not found" case for callers to handle, unlike every other Get* accessor in this package.
func (*DB) GetInviteByHash ¶
GetInviteByHash returns the invite matching hash, regardless of expiry/accepted/revoked state: deciding whether it's currently usable is the caller's job, matching GetPasswordResetTokenByHash's own shape.
func (*DB) GetInviteByID ¶
GetInviteByID returns the invite with this ID, or ErrInviteNotFound.
func (*DB) GetLatestBackupVerification ¶
func (db *DB) GetLatestBackupVerification(ctx context.Context, backupHistoryID string) (BackupVerification, error)
GetLatestBackupVerification returns the most recently started verification attempt for backupHistoryID, or ErrBackupVerificationNotFound if it has never been verified. Used by the backup history detail view (and the CLI's own "backups verifications" summary) to show a single current status without listing full history.
func (*DB) GetMasterKeyRotatedAt ¶
GetMasterKeyRotatedAt returns the last time RotateServiceDEKs committed successfully, or ok=false if it never has.
func (*DB) GetNodeJoinTokenByHash ¶
GetNodeJoinTokenByHash returns the token row matching hash, used or not, expired or not: deciding whether a token is currently redeemable is the caller's job (internal/api's enrollment handler), matching GetAPITokenByHash's identical "pure lookup, not a decision" separation.
func (*DB) GetOAuthIdentity ¶
func (db *DB) GetOAuthIdentity(ctx context.Context, provider, providerUserID string) (*OAuthIdentity, error)
GetOAuthIdentity returns the identity linking (provider, providerUserID) to whichever user holds it, or ErrOAuthIdentityNotFound. This is the OAuth callback's primary lookup: "has this external account signed in here before."
func (*DB) GetOAuthProviderSettings ¶
func (db *DB) GetOAuthProviderSettings(ctx context.Context, provider string) (OAuthProviderSettings, error)
GetOAuthProviderSettings returns the settings row for provider.
func (*DB) GetOnboardingCompleted ¶
GetOnboardingCompleted returns whether the first-run onboarding flow has been completed or dismissed. Always succeeds against a migrated database: migrations/0067_onboarding_state.sql seeds the single row (id = 1), the same "no not-found case" shape GetIngressSettings already has.
func (*DB) GetOrganization ¶
GetOrganization returns the organization with this ID, or ErrOrganizationNotFound.
func (*DB) GetPasswordResetTokenByHash ¶
func (db *DB) GetPasswordResetTokenByHash(ctx context.Context, hash string) (*PasswordResetToken, error)
GetPasswordResetTokenByHash returns the reset-token row matching hash, regardless of expiry or used state: deciding whether the token is currently usable is the caller's job.
func (*DB) GetPreviewEnvironmentByAppAndPR ¶
func (db *DB) GetPreviewEnvironmentByAppAndPR(ctx context.Context, appName string, prNumber int) (*PreviewEnvironment, error)
GetPreviewEnvironmentByAppAndPR returns the preview environment for (appName, prNumber), or ErrPreviewEnvironmentNotFound: the lookup a synchronize or closed pull request webhook event uses to find the preview it already owns, matching the table's own unique index.
func (*DB) GetPreviewEphemeralDatabaseByPreviewAndKey ¶
func (db *DB) GetPreviewEphemeralDatabaseByPreviewAndKey(ctx context.Context, previewEnvironmentID, sourceKey string) (*PreviewEphemeralDatabase, error)
GetPreviewEphemeralDatabaseByPreviewAndKey returns the ephemeral database tracking row for (previewEnvironmentID, sourceKey), or ErrPreviewEphemeralDatabaseNotFound: provisioning's own idempotency check, matching the table's own unique index.
func (*DB) GetProject ¶
GetProject returns the project with this ID, or ErrProjectNotFound.
func (*DB) GetRegistryCredential ¶
GetRegistryCredential returns the registry credential with this ID, or ErrRegistryCredentialNotFound.
func (*DB) GetRegistryCredentialByName ¶
func (db *DB) GetRegistryCredentialByName(ctx context.Context, name string) (RegistryCredential, error)
GetRegistryCredentialByName returns the registry credential with this Name, or ErrRegistryCredentialNotFound. app.yaml's build.type: image references a credential by Name (spec.Build.RegistryCredential's own doc comment: an opaque ID would be hostile to hand-author), so a deploy resolves it this way, not by ID.
func (*DB) GetRegistrySettings ¶
func (db *DB) GetRegistrySettings(ctx context.Context) (RegistrySettings, error)
GetRegistrySettings returns the single registry_settings row. Always succeeds against a migrated database: the migration itself inserts the row (id = 1).
func (*DB) GetScheduledTask ¶
GetScheduledTask returns the scheduled task with this ID, or ErrScheduledTaskNotFound.
func (*DB) GetSecretKeyLocked ¶
func (db *DB) GetSecretKeyLocked(ctx context.Context, serviceName, envKey string) (exists, locked bool, err error)
GetSecretKeyLocked reports whether (serviceName, envKey) has a value set and, if so, whether it's locked. exists is false when no value has ever been set for that key; locked is only meaningful when exists is true.
func (*DB) GetSecretValue ¶
GetSecretValue returns the ciphertext for one env var of one service, or ErrSecretValueNotFound if no value has been set.
func (*DB) GetServiceDEK ¶
GetServiceDEK returns the wrapped DEK for serviceName, or ErrServiceDEKNotFound if none has been generated yet.
func (*DB) GetServiceVolumeBackupSchedule ¶
func (db *DB) GetServiceVolumeBackupSchedule(ctx context.Context, serviceName, volumeName string) (ServiceVolumeBackupConfig, error)
GetServiceVolumeBackupSchedule returns serviceName/volumeName's backup schedule config, or ErrServiceVolumeBackupNotFound if it was never set.
func (*DB) GetUserByEmail ¶
GetUserByEmail returns the user with this email, or ErrUserNotFound. The stored value isn't always a syntactically valid email: a pre-migration bare username migrates in unchanged (migrations/0035).
func (*DB) GetUserByID ¶
GetUserByID returns the user with this ID, or ErrUserNotFound.
func (*DB) GetWebhookDelivery ¶
GetWebhookDelivery returns one webhook delivery by ID, or ErrWebhookDeliveryNotFound. Used by the replay handler to load the stored payload and header fields for the exact request it's about to re-run.
func (*DB) HasSecretValue ¶
HasSecretValue reports whether a value has been set for (serviceName, envKey), without decrypting or even fetching the ciphertext. Used by internal/deploy to fail a deploy loudly when a { secret: true, required: true } env var has no value yet, matching spec.EnvVar.Required's documented meaning, rather than deferring that check to container-create time where a missing secret would only surface as a confusing runtime failure.
func (*DB) ListAPITokens ¶
ListAPITokens returns every token, newest first, revoked ones included: the management UI shows revocation status rather than hiding history, matching Dokploy's own token list.
func (*DB) ListApps ¶
ListApps returns every app, ordered by name, the same "predictable listing order" convention ListDesiredServices already uses.
func (*DB) ListAttachmentsForPolicy ¶
func (db *DB) ListAttachmentsForPolicy(ctx context.Context, policyID string) ([]PolicyAttachment, error)
ListAttachmentsForPolicy returns every principal a policy is attached to, ordered by creation time: the management UI/CLI's "who does this policy apply to" view.
func (*DB) ListAuditEntries ¶
func (db *DB) ListAuditEntries(ctx context.Context, limit int, before *time.Time, filter AuditEntryFilter) ([]AuditEntry, error)
ListAuditEntries returns up to limit audit log rows, newest first. before, when non-nil, restricts the result to entries strictly older than that timestamp, so a caller pages backward through a large table by re-issuing this call with the last returned row's CreatedAt: cursor pagination, not offset pagination, the same reasoning this function's own doc comment in the task spec calls for (an OFFSET query degrades linearly as the table grows; this one doesn't). filter narrows by exact path and/or method match.
func (*DB) ListBackupHistory ¶
func (db *DB) ListBackupHistory(ctx context.Context, databaseName string, limit int, before *time.Time) ([]BackupHistory, error)
ListBackupHistory returns up to limit backup attempts for databaseName, newest first. before, when non-nil, cursor-paginates on start time (mirrors ListAuditEntries) so long-lived backup schedules never need a slow OFFSET query.
func (*DB) ListBackupTargets ¶
func (db *DB) ListBackupTargets(ctx context.Context) ([]BackupTarget, error)
ListBackupTargets returns every backup target, oldest first (creation order, the same order a settings page listing them would want).
func (*DB) ListBackupVerifications ¶
func (db *DB) ListBackupVerifications(ctx context.Context, backupHistoryID string, limit int) ([]BackupVerification, error)
ListBackupVerifications returns up to limit verification attempts for backupHistoryID, newest first.
func (*DB) ListCertStorageKeys ¶
func (db *DB) ListCertStorageKeys(ctx context.Context, prefix string, recursive bool) ([]string, error)
ListCertStorageKeys returns every stored key prefixed by prefix/. If recursive is false, only the immediate next path segment after prefix is returned once per distinct value: certmagic's "directory listing" semantics, where a partial key up to the next "/" stands in for every key nested further below it, matching certmagic.FileStorage.List's non-recursive behavior of listing directory entries rather than every file transitively inside them. Returns an empty slice, not an error, when nothing matches; internal/ingress's adapter is the layer that translates "nothing found" into fs.ErrNotExist, per certmagic's contract, so this stays a plain query with no certmagic-specific knowledge.
func (*DB) ListCloneRestores ¶
func (db *DB) ListCloneRestores(ctx context.Context, sourceDatabaseName string) ([]CloneRestore, error)
ListCloneRestores returns every clone-restore attempt sourced from sourceDatabaseName, newest first: the operator triggers this action from the source database's own backups view (RestoreBackupDialog's "restore as new database" counterpart), so that's the view this list serves, the same way ListRestoreHistory serves the in-place restore table on that same page.
func (*DB) ListDeployAttempts ¶
ListDeployAttempts returns every attempt for serviceName, newest first. A service with no attempts yet returns an empty (nil) slice and a nil error, not an error, the same "absence is not an error" convention GetConditions/QueryLogs already establish. No pagination: per this task's own scope note, an app that accumulates a very large number of attempts over its lifetime will make this list grow unbounded; that's a known, deliberately deferred follow-up, not solved here.
func (*DB) ListDesiredDatabases ¶
func (db *DB) ListDesiredDatabases(ctx context.Context) ([]DesiredDatabase, error)
ListDesiredDatabases returns every saved database, ordered by name.
func (*DB) ListDesiredDatabasesByNode ¶
func (db *DB) ListDesiredDatabasesByNode(ctx context.Context, nodeID string) ([]DesiredDatabase, error)
ListDesiredDatabasesByNode returns every saved database currently placed on nodeID, ordered by name. The database-kind counterpart to ListDesiredServicesByNode, same drain/delete-guard callers.
func (*DB) ListDesiredDatabasesByProject ¶
func (db *DB) ListDesiredDatabasesByProject(ctx context.Context, projectID string) ([]DesiredDatabase, error)
ListDesiredDatabasesByProject returns every saved database filed under projectID, ordered by name, the project-kind counterpart to ListDesiredDatabasesByNode. Used by handleStopProject/handleStartProject (internal/api/project_stop_start.go) to find every database in a project without listing every database.
func (*DB) ListDesiredServices ¶
func (db *DB) ListDesiredServices(ctx context.Context) ([]DesiredService, error)
ListDesiredServices returns every saved service, ordered by name.
func (*DB) ListDesiredServicesByNode ¶
func (db *DB) ListDesiredServicesByNode(ctx context.Context, nodeID string) ([]DesiredService, error)
ListDesiredServicesByNode returns every saved service currently placed on nodeID, ordered by name. Node drain (internal/api's handleDrainNode) uses this to find what to move off a node before it's removed, and handleDeleteNode uses it as the guard that makes node deletion refuse to run while placements remain. nodeID="" (the local-node sentinel, see DesiredService.NodeID's own doc comment) is a valid argument, matching every other node_id comparison in this package.
func (*DB) ListDesiredServicesByProject ¶
func (db *DB) ListDesiredServicesByProject(ctx context.Context, projectID string) ([]DesiredService, error)
ListDesiredServicesByProject returns every saved service filed under projectID, ordered by name, the project-kind counterpart to ListDesiredServicesByNode. Used by handleStopProject/handleStartProject (internal/api/project_stop_start.go) and internal/api's bulk-restart endpoint to find every app in a project without listing every service.
func (*DB) ListDomainBasicAuth ¶
func (db *DB) ListDomainBasicAuth(ctx context.Context) ([]DomainBasicAuth, error)
ListDomainBasicAuth returns every domain_basic_auth row, ordered by domain, for the ingress controller to build basic_auth directives fresh every reconcile pass, the same "never cache, re-derive from current state every call" convention ListServiceDomains already follows.
func (*DB) ListDomainMaintenance ¶
ListDomainMaintenance returns every domain currently in maintenance mode, ordered by domain, for the ingress controller to check fresh every reconcile pass, the same "never cache, re-derive from current state" convention ListDomainBasicAuth already follows.
func (*DB) ListDomainTLSCerts ¶
func (db *DB) ListDomainTLSCerts(ctx context.Context) ([]DomainTLSCert, error)
ListDomainTLSCerts returns every domain_tls_cert row, ordered by domain, for the ingress controller to resolve fresh every reconcile pass, the same "never cache, re-derive from current state every call" convention ListDomainBasicAuth already follows.
func (*DB) ListDomainWAF ¶
ListDomainWAF returns every domain_waf row, ordered by domain, for the ingress controller to build WAF/rate-limit handlers fresh every reconcile pass, the same "never cache, re-derive from current state every call" convention ListDomainBasicAuth already follows.
func (*DB) ListEnabledScheduledTasks ¶
func (db *DB) ListEnabledScheduledTasks(ctx context.Context) ([]ScheduledTask, error)
ListEnabledScheduledTasks returns every scheduled task with Enabled true, across every service: internal/scheduledtask.Scheduler.Tick's own per-tick query (idx_scheduled_tasks_enabled, migrations/ 0048_scheduled_tasks.sql, supports exactly this filter).
func (*DB) ListEnvironmentEnvVars ¶
func (db *DB) ListEnvironmentEnvVars(ctx context.Context, environmentID string) (map[string]string, error)
ListEnvironmentEnvVars returns environmentID's shared env vars as a plain map, empty (not nil) when none are set, mirroring ListOrganizationEnvVars/ListProjectEnvVars.
func (*DB) ListEnvironmentsByProject ¶
func (db *DB) ListEnvironmentsByProject(ctx context.Context, projectID string) ([]Environment, error)
ListEnvironmentsByProject returns every environment for one project, oldest first.
func (*DB) ListFeatureFlagsForService ¶
func (db *DB) ListFeatureFlagsForService(ctx context.Context, serviceName string) ([]FeatureFlag, error)
ListFeatureFlagsForService returns every feature flag owned by serviceName, oldest first, the same creation-order convention ListScheduledTasksForService already uses.
func (*DB) ListOAuthIdentitiesForUser ¶
func (db *DB) ListOAuthIdentitiesForUser(ctx context.Context, userID string) ([]OAuthIdentity, error)
ListOAuthIdentitiesForUser returns every provider a user has linked, oldest first.
func (*DB) ListOAuthProviderSettings ¶
func (db *DB) ListOAuthProviderSettings(ctx context.Context) ([]OAuthProviderSettings, error)
ListOAuthProviderSettings returns both provider rows, ordered by provider name: GET /api/v1/settings/oauth's read model.
func (*DB) ListOrganizationEnvVars ¶
ListOrganizationEnvVars returns orgID's shared env vars as a plain map, empty (not nil) when none are set, mirroring ListProjectEnvVars.
func (*DB) ListOrganizationEnvVarsForProject ¶
func (db *DB) ListOrganizationEnvVarsForProject(ctx context.Context, projectID string) (map[string]string, error)
ListOrganizationEnvVarsForProject returns the shared env vars of projectID's organization, empty when the project has no organization (or doesn't exist): the join internal/reconcile/application.Controller.resolveEnv needs to add the organization tier below its existing project tier without that package having to know projects carry an org_id column at all.
func (*DB) ListOrganizations ¶
func (db *DB) ListOrganizations(ctx context.Context) ([]Organization, error)
ListOrganizations returns every organization, oldest first.
func (*DB) ListPendingDeviceAuthRequests ¶
func (db *DB) ListPendingDeviceAuthRequests(ctx context.Context, now time.Time) ([]DeviceAuthRequest, error)
ListPendingDeviceAuthRequests returns every still-pending, not-yet-expired request, oldest first: the web UI's approval queue.
func (*DB) ListPendingInvites ¶
ListPendingInvites returns every invite not yet accepted or revoked, oldest first, including ones past their expires_at: an expired invite still shows up so an operator can see and revoke it, expiry itself is a display-time computation over ExpiresAt, not a filter here.
func (*DB) ListPolicies ¶
ListPolicies returns every policy, ordered by name.
func (*DB) ListPoliciesForPrincipal ¶
func (db *DB) ListPoliciesForPrincipal(ctx context.Context, principalType, principalID string) ([]Policy, error)
ListPoliciesForPrincipal returns every policy attached to one principal (a user or a token), ordered by name: exactly the set internal/api's authorization check evaluates for a given caller.
func (*DB) ListPreviewEnvironmentsByApp ¶
func (db *DB) ListPreviewEnvironmentsByApp(ctx context.Context, appName string) ([]PreviewEnvironment, error)
ListPreviewEnvironmentsByApp returns every preview environment for appName, newest first: GET /api/v1/apps/{name}/previews's read path.
func (*DB) ListPreviewEphemeralDatabasesByPreview ¶
func (db *DB) ListPreviewEphemeralDatabasesByPreview(ctx context.Context, previewEnvironmentID string) ([]PreviewEphemeralDatabase, error)
ListPreviewEphemeralDatabasesByPreview returns every ephemeral database tracking row for previewEnvironmentID, for the API's own status surface and for teardown to find everything it owns.
func (*DB) ListProjectEnvVars ¶
ListProjectEnvVars returns projectID's shared env vars as a plain map, empty (not nil) when none are set: the one caller that matters, internal/reconcile/application.Controller.resolveEnv, merges this straight into a working map with no nil check needed.
func (*DB) ListProjects ¶
ListProjects returns every project, oldest first, the same creation- order convention ListBackupTargets already uses for the same reason: it's the order a settings-style listing page wants, and there is no other field (like an app/database's name) a caller would obviously want to sort by instead.
func (*DB) ListRegistryCredentials ¶
func (db *DB) ListRegistryCredentials(ctx context.Context) ([]RegistryCredential, error)
ListRegistryCredentials returns every registry credential, oldest first.
func (*DB) ListRestoreHistory ¶
func (db *DB) ListRestoreHistory(ctx context.Context, databaseName string) ([]RestoreHistory, error)
ListRestoreHistory returns every restore attempt for databaseName, newest first (migrations/0019's own index is built for exactly this query shape, the same as ListBackupHistory's).
func (*DB) ListScheduledDatabases ¶
func (db *DB) ListScheduledDatabases(ctx context.Context) ([]DesiredDatabase, error)
ListScheduledDatabases returns every database with both a non-empty backup_schedule and a resolved backup_target_id, ordered by name. The two are deliberately required together, not backup_schedule alone: a schedule whose backup_targets row was since deleted (migrations/0023's own ON DELETE SET NULL) can never actually run, and requiring both here means internal/backup.Scheduler.Tick never has to special-case that half-configured state itself, on every tick, for the lifetime of the process. Re-derived fresh on every call, the same "never cache, re-derive every pass" principle dynamicSource (cmd/levelrail/main.go) already applies to which databases exist at all.
func (*DB) ListScheduledServiceVolumes ¶
func (db *DB) ListScheduledServiceVolumes(ctx context.Context) ([]ServiceVolumeBackupConfig, error)
ListScheduledServiceVolumes returns every service volume with both a non-empty backup_schedule and a resolved backup_target_id, ordered by service_name then volume_name, the volume counterpart of ListScheduledDatabases (database.go): see that method's own doc comment for why both are required together rather than schedule alone.
func (*DB) ListScheduledTasksForService ¶
func (db *DB) ListScheduledTasksForService(ctx context.Context, serviceName string) ([]ScheduledTask, error)
ListScheduledTasksForService returns every scheduled task for serviceName, oldest first, the same creation-order convention ListBackupTargets already uses.
func (*DB) ListSecretKeys ¶
ListSecretKeys returns every secret key set for serviceName, ordered by key, each with its locked state. Never touches ciphertext: the caller (internal/api's GET /apps/{name}/secrets) can safely return this straight to a browser.
func (*DB) ListServiceDomains ¶
func (db *DB) ListServiceDomains(ctx context.Context) ([]ServiceDomain, error)
ListServiceDomains returns every row in service_domains, ordered by domain. This is the same table domainOwner (domains.go) already queries for uniqueness enforcement, exposed here as a plain listing for GET /api/v1/domains rather than a single-domain lookup.
func (*DB) ListServiceVolumeBackupHistory ¶
func (db *DB) ListServiceVolumeBackupHistory(ctx context.Context, serviceName, volumeName string, limit int, before *time.Time) ([]BackupHistory, error)
ListServiceVolumeBackupHistory returns up to limit backup attempts for serviceName's volumeName, newest first, the volume counterpart of ListBackupHistory. resource_kind is filtered explicitly (not merely implied by service_name/volume_name being non-empty) so this can never accidentally match a database row, however this schema evolves later.
func (*DB) ListServiceVolumeRestoreHistory ¶
func (db *DB) ListServiceVolumeRestoreHistory(ctx context.Context, serviceName, volumeName string) ([]RestoreHistory, error)
ListServiceVolumeRestoreHistory returns every restore attempt for serviceName's volumeName, newest first, the volume counterpart of ListRestoreHistory.
func (*DB) ListServicesByApp ¶
ListServicesByApp returns every service belonging to appID, ordered by name. This is the read side of stage 1 multi-service apps: an app's member services, for a group-status rollup or a detail view.
func (*DB) ListStalePreviewEnvironments ¶
func (db *DB) ListStalePreviewEnvironments(ctx context.Context, cutoff time.Time) ([]PreviewEnvironment, error)
ListStalePreviewEnvironments returns every preview environment last updated before cutoff, oldest first: the TTL sweep's fallback path for a pull-request-closed webhook that never arrived (see internal/store/webhook_delivery.go's own reasoning for why that happens). String comparison against a UTC RFC3339Nano cutoff, the same convention ListWebhookDeliveries's own before-cursor already uses.
func (*DB) ListStaticSites ¶
func (db *DB) ListStaticSites(ctx context.Context) ([]StaticSite, error)
ListStaticSites returns every saved static site, ordered by name. The ingress controller (internal/reconcile/ingress) calls this on every reconcile pass, the same "read fresh, never cached" treatment ListDesiredServices already gets.
func (*DB) ListVolumeCloneRestores ¶
func (db *DB) ListVolumeCloneRestores(ctx context.Context, sourceServiceName, sourceVolumeName string) ([]VolumeCloneRestore, error)
ListVolumeCloneRestores returns every clone-restore attempt sourced from sourceServiceName/sourceVolumeName, newest first, mirroring ListCloneRestores exactly.
func (*DB) ListWebhookDeliveries ¶
func (db *DB) ListWebhookDeliveries(ctx context.Context, serviceName string, limit int, before *time.Time) ([]WebhookDelivery, error)
ListWebhookDeliveries returns up to limit deliveries for serviceName, newest first. before, when non-nil, cursor-paginates on receipt time, mirroring ListBackupHistory/ListAuditEntries: a webhook receiver sees steady traffic over an app's lifetime, so this must never degrade into a slow OFFSET query as history grows.
func (*DB) MarkNodeJoinTokenUsed ¶
MarkNodeJoinTokenUsed atomically marks id as exchanged, failing with ErrNodeJoinTokenAlreadyUsed if it already was: the conditional `WHERE used_at IS NULL` is what makes this safe under concurrent exchange attempts on the same token, the database deciding which caller wins rather than a check-then-act race in application code.
func (*DB) MarkOnboardingCompleted ¶
MarkOnboardingCompleted sets onboarding_state.completed to true. One-way: nothing in this codebase ever needs to un-complete it.
func (*DB) PruneBackupHistory ¶
func (db *DB) PruneBackupHistory(ctx context.Context, databaseName string, keep int, olderThan time.Time) ([]PrunedBackup, error)
PruneBackupHistory deletes every succeeded backup_history row for databaseName that violates either retention limit: beyond the newest keep (ordered by started_at), or older than olderThan, and returns the TargetID/ObjectKey of every row removed. Only BackupStatusSucceeded rows are ever eligible: a running or failed attempt carries diagnostic value a retention limit was never meant to bound (an operator who sets retain: 7 wants "7 successful backups," not "7 attempts of any kind"), so those are left untouched regardless of how old they are.
keep <= 0 disables the count limit; a zero-value olderThan (the usual Go zero value, IsZero()) disables the age limit. Both disabled deletes nothing and returns (nil, nil) without issuing a query: this mirrors store.DesiredDatabase.BackupRetain/BackupRetainDays's own "0 means no limit for that dimension" meaning at the one call site that matters, internal/backup.Scheduler, rather than making every caller remember to guard the zero case itself.
Runs as a SELECT of the rows about to be removed followed by a DELETE in the same transaction, rather than a single DELETE ... RETURNING: this codebase's SQLite driver (modernc.org/sqlite) is not used with RETURNING anywhere else, so this avoids relying on unproven support. The transaction ensures the two statements observe the identical row set even though db.SetMaxOpenConns(1) (store.go) already serializes writes against this *sql.DB.
func (*DB) PruneServiceVolumeBackupHistory ¶
func (db *DB) PruneServiceVolumeBackupHistory(ctx context.Context, serviceName, volumeName string, keep int, olderThan time.Time) ([]PrunedBackup, error)
PruneServiceVolumeBackupHistory is PruneBackupHistory's volume counterpart: identical retention logic (see that method's own doc comment for the count/age semantics), scoped to serviceName/volumeName and resource_kind = 'volume' instead of a single database_name.
func (*DB) RecordScheduledTaskRun ¶
func (db *DB) RecordScheduledTaskRun(ctx context.Context, id string, ranAt time.Time, status, output string) error
RecordScheduledTaskRun writes the outcome of one run (scheduled or manual "run now") back onto a task's own row: the same in-place "latest attempt" shape this table's own migration comment explains, not an append-only history. consecutive_failures resets to 0 on a success and increments otherwise, computed in SQL rather than read-then-write so a concurrent run can't race it. Returns ErrScheduledTaskNotFound if id doesn't exist, e.g. the task was deleted between being picked up by a tick and this call.
func (*DB) RedeemDeviceAuthRequest ¶
func (db *DB) RedeemDeviceAuthRequest(ctx context.Context, deviceCode, tokenID string, redeemedAt time.Time) error
RedeemDeviceAuthRequest marks an approved request as redeemed, recording the freshly minted token's ID: this is what makes a device_code single-use, since the CLI poll handler only mints a token when redeemed_at is still unset.
func (*DB) ReleaseCertStorageLock ¶
ReleaseCertStorageLock removes name's lock. Idempotent: releasing an already-released or never-held lock is not an error, matching DeleteNode's convention for the same reason (Unlock is often called from a defer alongside error paths that may have already cleaned up).
func (*DB) ReplaceUserRecoveryCodes ¶
ReplaceUserRecoveryCodes atomically deletes every existing recovery code row for userID and inserts one row per hash in hashes. Used both at first confirm (internal/api's handleConfirmTwoFactor) and on an explicit regenerate: either way the full set is replaced, never merged, so a stale code from before a regenerate can never validate.
func (*DB) ResolveServiceVolumeDockerName ¶
func (db *DB) ResolveServiceVolumeDockerName(ctx context.Context, serviceName, volumeName string) (string, error)
ResolveServiceVolumeDockerName looks up serviceName and resolves volumeName to its real Docker volume name, the single DB-round-trip convenience ServiceVolumeDockerName's own callers that don't already have a DesiredService in hand need (internal/backup.Scheduler's own per-tick volume evaluation).
func (*DB) RestartService ¶
RestartService is the only way restart_nonce ever changes: SaveDesiredService's own doc comment (and this field's own doc comment on DesiredService) explains why it's deliberately excluded from that method's full-record-replace semantics, the same reasoning UpdateServiceNode already establishes for NodeID.
The generated value is opaque and only ever compared for equality by internal/reconcile/application.ContainerName, never interpreted, so a short random hex string is enough; it does not need to be cryptographically unpredictable the way a session token or API key does, only different from whatever was there before.
func (*DB) RevokeAPIToken ¶
RevokeAPIToken sets revoked_at on the named token. Idempotent: revoking an already-revoked token succeeds without error, matching DeleteDesiredService's "not found" sentinel shape for the one real failure case (no such token at all).
func (*DB) RevokeInvite ¶
RevokeInvite marks the named invite revoked, only if it hasn't already been accepted or revoked. Returns ErrInviteNotFound, ErrInviteAlreadyAccepted, or ErrInviteAlreadyRevoked to say exactly why nothing changed, rather than a single ambiguous failure.
func (*DB) RotateServiceDEKs ¶
func (db *DB) RotateServiceDEKs(ctx context.Context, rewrap func(serviceName string, wrapped []byte) ([]byte, error)) error
RotateServiceDEKs reads every row in service_secrets, calls rewrap once per row, writes back whatever it returns, and records the rotation timestamp, all in one transaction: if rewrap returns an error for any row, nothing is written, matching DeleteServiceSecrets's own defer-rollback pattern. Callers (internal/secrets.RotateStoredDEKs) supply rewrap to do the actual unwrap-under-old-key/wrap-under-new-key work; this file only ever sees opaque bytes.
func (*DB) SaveAPIToken ¶
SaveAPIToken inserts a new token row. Tokens are never updated in place after creation except for LastUsedAt (TouchAPITokenLastUsed) and RevokedAt (RevokeAPIToken): a token's name and abilities are fixed at mint time, matching every competitor's own token model researched for this feature (rotation means minting a new token and revoking the old, not editing an existing one).
func (*DB) SaveApp ¶
SaveApp creates or fully replaces an app row, keyed by ID. Matches SaveDesiredService's full-record-replace semantics, not SaveProject's insert-only ones: like a service, an app has an UpdatedAt an ordinary edit is expected to move forward.
func (*DB) SaveAuditEntry ¶
func (db *DB) SaveAuditEntry(ctx context.Context, e AuditEntry) error
SaveAuditEntry inserts a new audit log row. Insert-only, like SaveDeployAttempt: an audit log has no update or delete path through the app, an entry ID is minted fresh by every caller, and a duplicate ID would only ever indicate a caller bug, left to fail on the primary key constraint rather than silently overwriting history.
func (*DB) SaveBackupTarget ¶
func (db *DB) SaveBackupTarget(ctx context.Context, t BackupTarget) error
SaveBackupTarget inserts a new backup target row. IDs are minted by the caller (internal/api, the same "generate before the INSERT" pattern api_token/node join tokens already use) so the caller can store credentials under the same ID before or after this call without a round trip to discover what ID got assigned.
func (*DB) SaveBitbucketAppConnection ¶
func (db *DB) SaveBitbucketAppConnection(ctx context.Context, c BitbucketAppConnection) error
SaveBitbucketAppConnection inserts or replaces the single bitbucket_app_connections row (id=1).
func (*DB) SaveCertStorageValue ¶
SaveCertStorageValue writes value at key, creating or overwriting. Backs certmagic.Storage's Store method (internal/ingress): Caddy's TLS automation calls this to persist ACME account keys, issued certificates, and OCSP staples.
func (*DB) SaveDeployAttempt ¶
func (db *DB) SaveDeployAttempt(ctx context.Context, a DeployAttempt) error
SaveDeployAttempt inserts a new deploy attempt row. Unlike SaveDesiredService, this is insert-only, never an upsert: an attempt ID is minted fresh by every trigger call (NewDeployAttemptID), so a second SaveDeployAttempt for the same ID would only ever indicate a caller bug, not a legitimate retry, and is left to fail on the primary key constraint rather than silently overwriting history.
func (*DB) SaveDesiredDatabase ¶
func (db *DB) SaveDesiredDatabase(ctx context.Context, d DesiredDatabase) error
SaveDesiredDatabase creates or fully replaces the desired state for a named database, the same whole-record-replacement semantics as SaveDesiredService, including the identical NodeID exception SaveDesiredService's own doc comment explains.
func (*DB) SaveDesiredService ¶
func (db *DB) SaveDesiredService(ctx context.Context, svc DesiredService) error
SaveDesiredService creates or fully replaces the desired state for a named service. There's no partial update: a service's desired state is always written as a whole record, matching how it'll actually be produced (a deploy pipeline resolving a complete DesiredService from one app.yaml service block, not assembling one field at a time).
One deliberate exception: NodeID is never written by this method, only ever by UpdateServiceNode below. internal/deploy.Pipeline calls this on every ordinary redeploy without ever setting NodeID (it has no opinion on placement), and svc.NodeID passed in here is always silently ignored, not just on an update but even on the very first INSERT: a new service starts on the local node ("") until an operator explicitly places it elsewhere via UpdateServiceNode, and a redeploy of an already-placed service must never un-assign it from wherever that placement decision put it.
The whole write, including reconciling svc.Domains against the service_domains table (0011), happens in one transaction: either the service's desired state and its domain claims both land, or neither does. Returns *ErrDomainTaken (via errors.As) if any domain in svc.Domains is already claimed by a different service; the caller's entire desired-state write is rejected in that case, not partially applied with some domains silently dropped.
func (*DB) SaveDeviceAuthRequest ¶
func (db *DB) SaveDeviceAuthRequest(ctx context.Context, r DeviceAuthRequest) error
SaveDeviceAuthRequest inserts a new pending device auth request.
func (*DB) SaveEnvironment ¶
func (db *DB) SaveEnvironment(ctx context.Context, e Environment) error
SaveEnvironment inserts a new environment row, insert-only.
func (*DB) SaveFeatureFlag ¶
func (db *DB) SaveFeatureFlag(ctx context.Context, f FeatureFlag) error
SaveFeatureFlag inserts a new feature flag row. ID is minted by the caller (internal/api), the same "generate before the INSERT" pattern SaveScheduledTask's own doc comment establishes.
func (*DB) SaveGitHubAppConnection ¶
func (db *DB) SaveGitHubAppConnection(ctx context.Context, c GitHubAppConnection) error
SaveGitHubAppConnection inserts or replaces the single github_app_connections row (id=1). Called once, right after a successful manifest code exchange (internal/api's handleGitHubAppCallback): InstallationID and AccountLogin are always nil at this point, since installation happens in a separate, later redirect. INSERT OR REPLACE rather than a plain INSERT: a second registration (after a prior connection was removed via DeleteGitHubAppConnection) must succeed without a caller having to know whether a row already exists.
func (*DB) SaveGitLabAppConnection ¶
func (db *DB) SaveGitLabAppConnection(ctx context.Context, c GitLabAppConnection) error
SaveGitLabAppConnection inserts or replaces the single gitlab_app_connections row (id=1).
func (*DB) SaveGitSource ¶
SaveGitSource creates a service's git source, or fully replaces it if one already exists: unlike SaveBackupTarget/SaveProject (insert-only, no legitimate "same id, different contents" case), PUT /api/v1/apps/{name}/git-source (internal/api) is a real connect-or-edit-the-connection endpoint, so this is an upsert, the same shape SaveSecretValue already uses for rotating a secret's value. created_at is left untouched by the ON CONFLICT branch, so it reflects when the source was first connected even across later edits.
func (*DB) SaveInvite ¶
SaveInvite inserts a new invite row.
func (*DB) SaveNode ¶
SaveNode inserts a new node row. Unlike SaveDesiredService, this is insert-only: a node's identity (ID, name) is fixed at enrollment time, there is no "replace this node's full record" operation, matching how SaveAPIToken (0007) never updates a token in place either. Status transitions go through UpdateNodeStatus, heartbeats through TouchNodeLastSeen, both narrower and safer than a caller re-supplying a whole Node struct on every heartbeat.
On an INSERT failure, this re-checks whether name is already taken (via nodeNameExists) to distinguish ErrNodeNameTaken from a genuine, unrelated database error, rather than parsing the driver's own error type: the same "let the constraint decide, then classify by re-checking" shape store.CreateUser's own doc comment already establishes for a different unique-constraint conflict.
func (*DB) SaveNodeJoinToken ¶
func (db *DB) SaveNodeJoinToken(ctx context.Context, t NodeJoinToken) error
SaveNodeJoinToken inserts a new join token row.
func (*DB) SaveOAuthIdentity ¶
func (db *DB) SaveOAuthIdentity(ctx context.Context, i OAuthIdentity) error
SaveOAuthIdentity inserts a new linked identity, insert-only, never an upsert.
func (*DB) SaveOrganization ¶
func (db *DB) SaveOrganization(ctx context.Context, o Organization) error
SaveOrganization inserts a new organization row, insert-only like SaveProject.
func (*DB) SavePasswordResetToken ¶
func (db *DB) SavePasswordResetToken(ctx context.Context, t PasswordResetToken) error
SavePasswordResetToken inserts a new reset-token row.
func (*DB) SavePolicy ¶
SavePolicy creates a new policy. Policies are never updated in place except via UpdatePolicy (name/description/document); unlike SaveAPIToken this genuinely is meant to change over the policy's life, since a policy document is the whole point of editing one, unlike a token's fixed-at-mint-time abilities. On failure it re-checks by name to classify the cause, the same pattern CreateUser uses for its own unique constraint.
func (*DB) SavePreviewEnvironment ¶
func (db *DB) SavePreviewEnvironment(ctx context.Context, p PreviewEnvironment) error
SavePreviewEnvironment inserts a new preview environment row. Insert-only: a fresh (app_name, pr_number) pair always mints a new ID, see UpdatePreviewEnvironment for the redeploy-on-synchronize path.
func (*DB) SavePreviewEphemeralDatabase ¶
func (db *DB) SavePreviewEphemeralDatabase(ctx context.Context, p PreviewEphemeralDatabase) error
SavePreviewEphemeralDatabase inserts a new tracking row. Insert-only: callers look the row up first (GetPreviewEphemeralDatabaseByPreviewAndKey) and only call this on a genuine miss, the same idempotent-creation shape deployPreviewEnvironment already uses for preview_environments itself, so a PR synchronize event that re-runs provisioning never mints a second row for the same (preview, source key) pair.
func (*DB) SaveProject ¶
SaveProject inserts a new project row. IDs are minted by the caller (internal/api's randomProjectID), the same "generate before the INSERT" pattern SaveBackupTarget already establishes, and this is insert-only, never an upsert: a project's name is a pure label with no addressing role (migrations/0022_projects.sql's own comment on why it isn't UNIQUE), so there is no legitimate "same id, replace contents" case the way SaveDesiredService's full-replace semantics exist for.
func (*DB) SaveRegistryCredential ¶
func (db *DB) SaveRegistryCredential(ctx context.Context, c RegistryCredential) error
SaveRegistryCredential inserts a new registry credential row. IDs are minted by the caller before this call, the same "generate before the INSERT" pattern BackupTarget uses.
func (*DB) SaveScheduledTask ¶
func (db *DB) SaveScheduledTask(ctx context.Context, t ScheduledTask) error
SaveScheduledTask inserts a new scheduled task row. ID is minted by the caller (internal/api, the same "generate before the INSERT" pattern SaveBackupTarget's own doc comment establishes), and the last-run fields start empty: a freshly created task has never run.
func (*DB) SaveSecretValue ¶
func (db *DB) SaveSecretValue(ctx context.Context, serviceName, envKey string, ciphertext []byte) error
SaveSecretValue creates or replaces the ciphertext for one env var of one service. Unlike SaveServiceDEK this is a real upsert: updating a secret's value (rotating it) is the normal case, updating its DEK is not.
func (*DB) SaveServiceDEK ¶
SaveServiceDEK creates a service's wrapped DEK. Called once per service, the first time a secret value is set for it: internal/secrets. Manager checks GetServiceDEK first and only calls this on ErrServiceDEKNotFound, so this intentionally has no upsert path. A service's DEK, once generated, is never replaced: replacing it would silently orphan every value already encrypted under the old one.
func (*DB) SaveStaticSite ¶
func (db *DB) SaveStaticSite(ctx context.Context, site StaticSite) error
SaveStaticSite creates or fully replaces a static site's desired state, the same "whole record, one write" shape SaveDesiredService uses for container services: internal/deploy.Pipeline always produces a complete StaticSite from one app.yaml service block, never a partial update.
The whole write, including reconciling site.Domains against static_site_domains, happens in one transaction: either the site's state and its domain claims both land, or neither does. Returns *ErrDomainTaken (via errors.As) if any domain in site.Domains is already claimed by a different static site or by a container service (domainOwner checks both service_domains and static_site_domains); the caller's entire write is rejected in that case, matching SaveDesiredService's own domain-conflict behavior.
func (*DB) SaveWebhookDelivery ¶
func (db *DB) SaveWebhookDelivery(ctx context.Context, d WebhookDelivery) error
SaveWebhookDelivery inserts a new webhook delivery row, truncating d.Payload to MaxWebhookDeliveryPayloadBytes if larger (setting PayloadTruncated on the stored row regardless of what the caller passed in): this is the one place that cap is enforced, so no caller can accidentally bypass it.
func (*DB) SetDatabaseBackupSchedule ¶
func (db *DB) SetDatabaseBackupSchedule(ctx context.Context, name, targetID, schedule string, retain, retainDays int) error
SetDatabaseBackupSchedule is DesiredDatabase's counterpart to UpdateDatabaseNode/UpdateDatabaseProject: a scheduled backup's config is set through its own endpoint and its own method, the same separation-from-ordinary-desired-state-saves those two already establish, rather than folding it into SaveDesiredDatabase's own whole-record replace. Passing targetID="" and schedule="" (the DELETE /api/v1/databases/{name}/backup-schedule path, retain also forced to 0 by the caller in that case) clears scheduled backups for name entirely: internal/backup.Scheduler's own ListScheduledDatabases query treats an empty schedule exactly like it was never configured, so this is a real "unset," not a sentinel every future caller has to remember to special-case.
func (*DB) SetDatabasePublicAccess ¶
func (db *DB) SetDatabasePublicAccess(ctx context.Context, name string, enabled bool, requestedPort int) (int, error)
SetDatabasePublicAccess is DesiredDatabase's counterpart to SetDatabaseBackupSchedule: its own endpoint (PUT/DELETE /api/v1/databases/{name}/public-access), its own store method, same separation-from-ordinary-update reasoning. Disabling (enabled=false) always clears public_port back to NULL regardless of requestedPort. Enabling with requestedPort 0 auto-assigns the lowest free port in [PublicPortRangeStart, PublicPortRangeEnd]; a non-zero requestedPort is used as-is if no other database already claims it. Returns the port actually assigned (0 when disabling).
Runs inside a transaction so "is this port free" and "claim it" are atomic: db.SetMaxOpenConns(1) (store.go) already serializes every write against this same *sql.DB, so this is a correctness backstop against nothing racing it today, not a fix for an observed bug, the same reasoning claimServiceDomains (service.go) already applies to domain claims.
func (*DB) SetDeviceAuthRequestStatus ¶
func (db *DB) SetDeviceAuthRequestStatus(ctx context.Context, userCode, status, approvedByUserID string) (int64, error)
SetDeviceAuthRequestStatus moves a pending request to approved or denied, recording who approved it (empty for a denial). Only affects a row still in "pending" status, so a request already decided (or already redeemed) can't be flipped again; the caller distinguishes "no such code" from "already decided" by re-reading afterward if it needs to.
func (*DB) SetDomainBasicAuth ¶
SetDomainBasicAuth upserts the username claimed for domain. Callers (internal/api) are expected to write the matching password through internal/secrets in the same request; this method only ever tracks the username, never a credential.
func (*DB) SetDomainMaintenance ¶
SetDomainMaintenance enables maintenance mode for domain. Idempotent: setting it on a domain that already has it enabled is not an error.
func (*DB) SetDomainTLSCert ¶
func (db *DB) SetDomainTLSCert(ctx context.Context, domain string, uploadedAt, expiresAt time.Time) error
SetDomainTLSCert upserts the uploaded/expiry timestamps for domain's BYO certificate. Callers (internal/api) are expected to write the matching certificate and key through internal/secrets in the same request; this method only ever tracks metadata, never key material.
func (*DB) SetDomainWAF ¶
func (db *DB) SetDomainWAF(ctx context.Context, domain string, wafEnabled bool, mode string, rateLimitRPS, rateLimitBurst int) error
SetDomainWAF upserts domain's WAF/rate-limit configuration. mode must already be validated by the caller (internal/api); this method performs no validation of its own, the same division of responsibility store.SetDomainBasicAuth already draws with its own caller.
func (*DB) SetEnvironmentEnvVars ¶
func (db *DB) SetEnvironmentEnvVars(ctx context.Context, environmentID string, vars map[string]string) error
SetEnvironmentEnvVars full-replaces environmentID's shared env vars with vars, the same "replace, don't diff" semantics SetOrganizationEnvVars/SetProjectEnvVars already establish.
func (*DB) SetEnvironmentProtected ¶
SetEnvironmentProtected updates one environment's protected flag. Returns ErrEnvironmentNotFound if id doesn't match any row.
func (*DB) SetGitSourcePostPRComments ¶
func (db *DB) SetGitSourcePostPRComments(ctx context.Context, serviceName string, enabled bool) error
SetGitSourcePostPRComments toggles a connected git source's GitHub PR comment/commit status opt-in (GitSource.PostPRComments's own doc comment); returns ErrGitSourceNotFound if no source is connected for serviceName. Mirrors SetGitSourcePreviewEnabled exactly, its own sibling opt-in toggle.
func (*DB) SetGitSourcePreviewEnabled ¶
func (db *DB) SetGitSourcePreviewEnabled(ctx context.Context, serviceName string, enabled bool) error
SetGitSourcePreviewEnabled toggles a connected git source's preview environments opt-in; returns ErrGitSourceNotFound if no source is connected for serviceName. A separate setter rather than a SaveGitSource field, the same "an ordinary edit must never silently move it" shape UpdateServiceSuspended already establishes for DesiredService.Suspended.
func (*DB) SetNodeSchedulable ¶
SetNodeSchedulable cordons (schedulable=false) or uncordons (schedulable=true) a node. Returns ErrNodeNotFound if no such node exists, the same "distinguish real failure from a no-op" rigor UpdateNodeStatus applies to its own conditional UPDATE. Does not touch Status and does not evacuate anything already running there: cordon on its own only affects new placements (internal/api's handleSetAppNode and handleDrainNode both check Schedulable before accepting a target node), see this package's own Node.Schedulable doc comment for why that's a separate column from Status in the first place.
func (*DB) SetOrganizationEnvVars ¶
func (db *DB) SetOrganizationEnvVars(ctx context.Context, orgID string, vars map[string]string) error
SetOrganizationEnvVars full-replaces orgID's shared env vars with vars, the same "replace, don't diff" semantics SetProjectEnvVars already establishes one tier down.
func (*DB) SetProjectEnvVars ¶
func (db *DB) SetProjectEnvVars(ctx context.Context, projectID string, vars map[string]string) error
SetProjectEnvVars full-replaces projectID's shared env vars with vars: every key not present in vars is removed, every key in vars is written, in one transaction, the same "replace, don't diff" shape SaveDesiredService's own claimServiceDomains uses for a service's domain set. There is no partial-update path; a caller wanting to add one key reads the current set first (ListProjectEnvVars) and sends the whole merged map back.
func (*DB) SetProjectOrganization ¶
SetProjectOrganization assigns or clears (orgID == "") a project's organization. Returns ErrProjectNotFound if the project doesn't exist.
func (*DB) SetSecretLocked ¶
SetSecretLocked sets (serviceName, envKey)'s locked flag, either direction: unlike Coolify's permanent lock, this is meant to be reversible. Returns ErrSecretValueNotFound if no value has been set for that key yet, matching GetSecretValue's own not-found sentinel: locking is a property of a value that already exists, not something pre-settable before one does.
func (*DB) SetServiceEnvironment ¶
SetServiceEnvironment assigns or clears (envID == "") a service's environment. Returns ErrServiceNotFound if the service doesn't exist.
func (*DB) SetServiceVolumeBackupSchedule ¶
func (db *DB) SetServiceVolumeBackupSchedule(ctx context.Context, serviceName, volumeName, targetID, schedule string, retain, retainDays int) error
SetServiceVolumeBackupSchedule upserts serviceName/volumeName's backup schedule config, the volume counterpart of SetDatabaseBackupSchedule (database.go). Passing targetID="" and schedule="" clears it back to "not scheduled", the same "" sentinel SetDatabaseBackupSchedule already establishes: internal/backup.Scheduler's own ListScheduledServiceVolumes query treats an empty schedule exactly like the row was never written.
func (*DB) StartBackupHistory ¶
func (db *DB) StartBackupHistory(ctx context.Context, h BackupHistory) error
StartBackupHistory records a backup attempt beginning, status BackupStatusRunning, before the dump or upload has done any real work: see this file's own status-constants comment for why "running" is written eagerly rather than only recording success/failure after the fact. h.ResourceKind defaults to BackupResourceKindDatabase when empty, so every existing caller (database backups, which never set it) keeps writing the identical row shape it always has.
func (*DB) StartBackupVerification ¶
func (db *DB) StartBackupVerification(ctx context.Context, v BackupVerification) error
StartBackupVerification records a verification attempt beginning, status BackupVerificationStatusRunning, the same "write running first" reasoning this file's own status-constants comment gives.
func (*DB) StartCloneRestore ¶
func (db *DB) StartCloneRestore(ctx context.Context, h CloneRestore) error
StartCloneRestore records a clone-restore attempt beginning, status BackupStatusRunning, before the new database has even become reachable: the same "write running eagerly" reasoning StartRestoreHistory's own doc comment gives.
func (*DB) StartRestoreHistory ¶
func (db *DB) StartRestoreHistory(ctx context.Context, h RestoreHistory) error
StartRestoreHistory records a restore attempt beginning, status BackupStatusRunning, before the download or restore has done any real work: the same "write running eagerly so a mid-attempt crash leaves a real row behind" reasoning StartBackupHistory's own doc comment gives. h.ResourceKind defaults to BackupResourceKindDatabase when empty, mirroring StartBackupHistory's own identical default.
func (*DB) StartVolumeCloneRestore ¶
func (db *DB) StartVolumeCloneRestore(ctx context.Context, h VolumeCloneRestore) error
StartVolumeCloneRestore records a clone-restore attempt beginning, status BackupStatusRunning, mirroring StartCloneRestore exactly.
func (*DB) StatCertStorageValue ¶
StatCertStorageValue returns key's metadata, or ErrCertStorageKeyNotFound if key is stored neither as an exact value nor as a directory prefix of other keys.
func (*DB) TouchAPITokenLastUsed ¶
TouchAPITokenLastUsed updates last_used_at to now. Best-effort by design: internal/api calls this on every successful bearer-token lookup for observability, but a failure here must never block the request it's authenticating, so callers log and continue rather than fail the request on error.
func (*DB) TouchCertStorageLock ¶
TouchCertStorageLock refreshes name's lock's updated_at to now, so a live holder's lock never looks stale to a competitor calling AcquireCertStorageLock. Best-effort by design, matching TouchNodeLastSeen and TouchAPITokenLastUsed: a missed refresh is not itself fatal to the holder's in-progress operation, only a risk that a competitor could (rarely) steal the lock early if staleAfter is also exceeded, which is an accepted, documented trade-off of the whole staleness-based design (see 0010's migration comment).
func (*DB) TouchNodeLastSeen ¶
TouchNodeLastSeen updates last_seen_at to now, best-effort by design matching TouchAPITokenLastUsed: a heartbeat recording failure must never block whatever triggered it. Called once at session start (Server.Session) and repeatedly on a fixed interval for as long as that session's stream stays open (Server.heartbeatLoop): a single call at connect time can't distinguish "still connected" from "connected an hour ago, then the process hung," which is exactly the case internal/reconcile/nodehealth needs to detect.
func (*DB) UpdateBackupTarget ¶
func (db *DB) UpdateBackupTarget(ctx context.Context, id, name, provider, endpoint, region, bucket string) error
UpdateBackupTarget replaces name/provider/endpoint/region/bucket for an existing row, the same full-replace contract UpdateScheduledTask uses. Credentials are not this function's concern: a caller rotating them writes to internal/secrets separately, under the same BackupTargetSecretsKey(id) this row's ID has always used. Returns ErrBackupTargetNotFound if id doesn't exist.
func (*DB) UpdateCloudflareDNSSettings ¶
func (db *DB) UpdateCloudflareDNSSettings(ctx context.Context, s CloudflareDNSSettings) error
UpdateCloudflareDNSSettings replaces the single row's Enabled flag.
func (*DB) UpdateCloudflareTunnelSettings ¶
func (db *DB) UpdateCloudflareTunnelSettings(ctx context.Context, s CloudflareTunnelSettings) error
UpdateCloudflareTunnelSettings replaces the single row's Enabled flag, the same whole-record convention UpdateEmailSettings uses.
func (*DB) UpdateDatabaseNode ¶
UpdateDatabaseNode is DesiredDatabase's counterpart to UpdateServiceNode.
func (*DB) UpdateDatabaseProject ¶
UpdateDatabaseProject is DesiredDatabase's counterpart to UpdateServiceProject: see that method's own doc comment for why an empty projectID is written as SQL NULL, not the empty string node_id uses.
func (*DB) UpdateDatabaseSuspended ¶
UpdateDatabaseSuspended is DesiredDatabase.Suspended's only writer, the database counterpart to UpdateServiceSuspended. Unlike that method, resuming does not need to clear anything else: a database has no EnvDirty-equivalent latch, since nothing about its desired state can change while suspended (there is no env editor for a database the way there is for an app).
func (*DB) UpdateEmailSettings ¶
func (db *DB) UpdateEmailSettings(ctx context.Context, s EmailSettings) error
UpdateEmailSettings replaces the single email_settings row in full, the same whole-record convention UpdateIngressSettings uses.
func (*DB) UpdateFeatureFlag ¶
func (db *DB) UpdateFeatureFlag(ctx context.Context, id, name, description string, enabled bool, rolloutPercentage int, updatedAt time.Time) error
UpdateFeatureFlag replaces name/description/enabled/rollout_percentage for an existing row: a full-replace contract, the same shape UpdateScheduledTask uses. It never touches Key or ServiceName (an existing flag cannot be reassigned to a different key or app; delete and recreate instead). Returns ErrFeatureFlagNotFound if id doesn't exist.
func (*DB) UpdateGitHubAppInstallation ¶
func (db *DB) UpdateGitHubAppInstallation(ctx context.Context, installationID int64, accountLogin string) error
UpdateGitHubAppInstallation records the installation_id and account login GitHub's post-install redirect (GET /api/v1/github-app/installed) reports. Returns ErrGitHubAppConnectionNotFound if the App itself was never registered: an installation can't exist without an App to install.
func (*DB) UpdateIngressSettings ¶
func (db *DB) UpdateIngressSettings(ctx context.Context, s IngressSettings) error
UpdateIngressSettings replaces the single ingress_settings row in full, the same "no partial update, the whole record is always written as a whole" convention SaveDesiredService already establishes for desired_services: a settings form always submits its complete current state, there's no legitimate "patch just one field" caller for a four-column singleton row. internal/api's PUT /api/v1/settings/ingress is expected to have already validated s (acme_email required and well-formed whenever s.ACMEEnabled is true) before calling this; this method itself performs no validation, matching the "store trusts its caller to have validated business rules, and only enforces what the schema itself can" division of responsibility SaveDesiredService's own domain-uniqueness enforcement is the exception to, not the rule.
func (*DB) UpdateNodeMesh ¶
UpdateNodeMesh records a node's WireGuard identity and assigned mesh address (migrations/0014_node_mesh.sql).
Its own narrow updater rather than a field on SaveNode, matching UpdateNodeStatus and TouchNodeLastSeen: SaveNode is insert-only because a node's identity is fixed at enrollment, and mesh state changes on an entirely different schedule (every time the mesh coordinator learns something new about a node) than enrollment does.
Returns ErrNodeNotFound if no such node exists, so a coordinator distributing to a node that was deleted mid-pass finds out rather than silently writing nothing.
func (*DB) UpdateNodeStatus ¶
UpdateNodeStatus sets a node's status. Returns ErrNodeNotFound if no such node exists, the same "distinguish real failure from a no-op" rigor RevokeAPIToken applies to its own conditional UPDATE.
func (*DB) UpdateNodeWorkloads ¶
func (db *DB) UpdateNodeWorkloads(ctx context.Context, id string, acceptsApp, acceptsBuild bool) error
UpdateNodeWorkloads sets a node's workload capability flags. Returns ErrNodeNotFound if no such node exists, the same "distinguish real failure from a no-op" rigor UpdateNodeStatus already applies to its own conditional UPDATE.
func (*DB) UpdateOAuthProviderSettings ¶
func (db *DB) UpdateOAuthProviderSettings(ctx context.Context, s OAuthProviderSettings) error
UpdateOAuthProviderSettings replaces one provider's settings row in full. It never touches a credential; storing the client secret is the caller's job via internal/secrets.
func (*DB) UpdatePolicy ¶
UpdatePolicy replaces an existing policy's name/description/document, bumping updated_at. Returns ErrPolicyNotFound if id doesn't exist, ErrPolicyNameExists if name collides with a different row.
func (*DB) UpdatePreviewEnvironment ¶
func (db *DB) UpdatePreviewEnvironment(ctx context.Context, p PreviewEnvironment) error
UpdatePreviewEnvironment replaces an existing preview environment row in full, keyed by ID: a synchronize push (new commits on the same PR) or a status transition (deploying -> active/failed) both rewrite the whole record, the same "no partial update" convention UpdateIngressSettings already establishes for a similarly small record.
func (*DB) UpdatePreviewEphemeralDatabaseStatus ¶
func (db *DB) UpdatePreviewEphemeralDatabaseStatus(ctx context.Context, id, status, statusReason, updatedAt string) error
UpdatePreviewEphemeralDatabaseStatus sets id's status/status_reason in place, the same "record why, keep the row for a retry" shape finishPreviewFailed already establishes for preview_environments itself. Returns ErrPreviewEphemeralDatabaseNotFound if id doesn't exist.
func (*DB) UpdateRegistryCredential ¶
func (db *DB) UpdateRegistryCredential(ctx context.Context, id, name, registryHost, username string, expiresAt *time.Time) error
UpdateRegistryCredential replaces name/registry_host/username/expiresAt for an existing row, the same full-replace contract UpdateBackupTarget uses for its own sibling resource. Rotating the password is a separate write to internal/secrets under this row's existing RegistryCredentialSecretsKey, not this function's concern. Returns ErrRegistryCredentialNotFound if id doesn't exist.
func (*DB) UpdateRegistrySettings ¶
func (db *DB) UpdateRegistrySettings(ctx context.Context, s RegistrySettings) error
UpdateRegistrySettings replaces the single registry_settings row in full, the same whole-record convention UpdateCloudflareTunnelSettings already establishes.
func (*DB) UpdateScheduledTask ¶
func (db *DB) UpdateScheduledTask(ctx context.Context, id string, command []string, schedule string, enabled bool, updatedAt time.Time) error
UpdateScheduledTask updates a task's own editable fields (Command, Schedule, Enabled): it never touches ServiceName (an existing task cannot be reassigned to a different app; delete and recreate instead) or the last-run fields (RecordScheduledTaskRun's job, not this method's). Returns ErrScheduledTaskNotFound if id doesn't exist.
func (*DB) UpdateServiceApp ¶
UpdateServiceApp assigns svc to app appID, the only way desired_services.app_id ever changes outside migrations/0039_apps.sql's own backfill: SaveDesiredService's own doc comment explains why this is deliberately excluded from that method's full-record-replace semantics, the same reasoning UpdateServiceNode/UpdateServiceProject already establish for NodeID/ProjectID.
func (*DB) UpdateServiceDatabaseAttachment ¶
func (db *DB) UpdateServiceDatabaseAttachment(ctx context.Context, name string, att *DatabaseAttachment) error
UpdateServiceDatabaseAttachment is DesiredService.DatabaseAttachment's only writer, the same separation-from-ordinary-update reasoning UpdateServiceStorageTarget already establishes for StorageTargetID. att nil clears the attachment (all three columns back to ”).
func (*DB) UpdateServiceLogDrain ¶
UpdateServiceLogDrain sets or clears svc's log drain, the only way log_drain ever changes: SaveDesiredService's own doc comment explains why this is deliberately excluded from that method's full-record- replace semantics, the same reasoning UpdateServiceStorageTarget already establishes for storage_target_id. drain nil clears it.
func (*DB) UpdateServiceNode ¶
UpdateServiceNode reassigns svc to run on nodeID ("" for this control plane's own local node, per the placement migration's comment), the only way node_id ever changes: SaveDesiredService's own doc comment explains why it's deliberately excluded from that method's full-record-replace semantics.
func (*DB) UpdateServiceProject ¶
UpdateServiceProject reassigns svc to project projectID ("" for "no project", the same real-and-permanent sentinel DesiredService. ProjectID's own doc comment describes), the only way project_id ever changes: SaveDesiredService's own doc comment explains why it's deliberately excluded from that method's full-record-replace semantics, the same reasoning UpdateServiceNode already establishes for NodeID. An empty projectID is written as SQL NULL, not the empty string node_id uses, because unlike node_id (NOT NULL DEFAULT ”), this column is genuinely nullable (migrations/0022_projects.sql's own comment on why).
func (*DB) UpdateServiceStorageTarget ¶
UpdateServiceStorageTarget reassigns svc's object-storage credential source to storageTargetID ("" for "no storage attached"), the only way storage_target_id ever changes: SaveDesiredService's own doc comment explains why it's deliberately excluded from that method's full-record-replace semantics, the same reasoning UpdateServiceNode/ UpdateServiceProject already establish for their own single-purpose updates. An empty storageTargetID is written as SQL NULL, not the empty string node_id uses, the same reasoning UpdateServiceProject's own doc comment gives: this column is genuinely nullable, mirroring backup_target_id's own convention on desired_databases (migrations/0023_scheduled_backups.sql) rather than node_id's.
Deliberately does not validate storageTargetID against backup_targets itself: that check belongs to the caller (internal/api's handleSetAppStorage), the same "own endpoint validates, this method just writes" boundary UpdateServiceProject leaves to handleSetAppProject's own validateProjectID call.
func (*DB) UpdateServiceSuspended ¶
UpdateServiceSuspended is the only way suspended ever changes, the same "own single-purpose setter, excluded from SaveDesiredService" reasoning UpdateServiceNode/UpdateServiceProject/ UpdateServiceStorageTarget already establish. Setting it true does not by itself stop any container: internal/reconcile/application's controller is what converges to zero containers once it observes Suspended on its next reconcile, the same level-triggered separation DeleteDesiredService's own doc comment describes for delete.
func (*DB) UpdateUserAbilities ¶
UpdateUserAbilities replaces a user's Abilities wholesale, the same "fixed at mint time except this one field" shape api_tokens uses for LastUsedAt/RevokedAt. Validation (validateAbilities) is the caller's job (internal/api), not this layer's. Returns ErrUserNotFound if id doesn't exist.
func (*DB) UpdateUserLastLogin ¶
UpdateUserLastLogin stamps last_login_at, called once per successful sign-in (password or OAuth). Returns ErrUserNotFound if id doesn't exist.
func (*DB) UpdateUserPasswordHash ¶
UpdateUserPasswordHash sets (or, given a nil hash, clears) a user's password. Returns ErrUserNotFound if id doesn't exist.
func (*DB) UpsertConditions ¶
func (db *DB) UpsertConditions(ctx context.Context, controllerName string, conditions []reconcile.Condition) error
UpsertConditions persists every condition from a controller's most recent Reconcile result. Every reconcile must emit a status condition that gets stored and shown in the UI; this is that storage. reconcile.Engine itself only ever held results in memory, lost on restart.
func (*DB) UpsertHookRun ¶
UpsertHookRun replaces the stored outcome for (run.ServiceName, run.HookType): only the most recent run per hook type is kept, see migrations/0083_service_hook_runs.sql's own comment for why a full history isn't.
type DatabaseAttachment ¶
DatabaseAttachment is which managed database (desired_databases.name) an app resolves one connection env var from, set through PUT/DELETE /api/v1/apps/{name}/database rather than app.yaml: the UI/CLI-facing equivalent of DatabaseEnv above, for an app that was created directly (build.type: image via the API) rather than deployed from a spec file. Exactly one per app, mirroring StorageTargetID's single-attachment shape rather than DatabaseEnv's open-ended map.
type DatabaseEngineInfo ¶
type DatabaseEngineInfo struct {
ID string `yaml:"id"`
Label string `yaml:"label"`
DefaultVersion string `yaml:"default_version"`
}
DatabaseEngineInfo is one row of database_engines.yaml: identity and display metadata for a managed database engine this control plane can create. See that file's own doc comment for what does and doesn't belong here (display data only, not the real per-engine reconcile behavior, which stays Go code).
func SupportedDatabaseEngines ¶
func SupportedDatabaseEngines() ([]DatabaseEngineInfo, error)
SupportedDatabaseEngines returns every database engine this control plane can create, parsed from the embedded registry once and cached: the registry never changes at runtime, so there's no reason to re-parse it per call, the same reasoning internal/spec's own compiledAppSchema already applies to its embedded JSON Schema.
type DatabaseEnvRef ¶
DatabaseEnvRef is one env var's parsed { from: "<database>.<field>" } reference (internal/spec.EnvVar.From), stored on DesiredService. DatabaseEnv. Database is a desired_databases.name; Field is one of "url", "host", "port", "username", "password", "database", resolved by the application controller (resolveDatabaseEnv) immediately before container creation, the same "declaration only, resolved later" split SecretEnv already makes for { secret: true }.
type DeployAttempt ¶
type DeployAttempt struct {
// ID is an opaque, mint-time-random identifier from
// NewDeployAttemptID, not a database-assigned sequence: see that
// function's own doc comment for why.
ID string
ServiceName string
// Image is the tag this attempt deploys (or is trying to build and
// deploy). For the plain image-tag path this is exactly the
// caller-supplied tag; for the two build-triggering paths it is
// computed the same way internal/deploy's own deployDockerfile
// computes it (ImageRepo + ":" + CommitSHA), known before the build
// even starts, so a failed build's attempt row still shows what tag
// it was trying to produce.
Image string
// CommitSHA is the git commit this attempt built from, empty for the
// plain image-tag trigger path (DeployAttemptSourceImage), which has
// no associated commit.
CommitSHA string
// Source is one of the DeployAttemptSource* constants.
Source string
// Status is one of the DeployAttemptStatus* constants.
Status string
StartedAt time.Time
// FinishedAt is nil until FinishDeployAttempt is called.
FinishedAt *time.Time
// Error is the attempt's failure detail, set only when Status is
// DeployAttemptStatusFailed. Unlike an HTTP error response (see
// internal/api/builds.go's handleTriggerBuild doc comment on why
// that response body stays non-leaky), this is stored for an
// authenticated operator's own later inspection via
// GET /api/v1/apps/{name}/deploy-attempts, the same trust boundary
// GetConditions' Message field already crosses for reconcile
// failures.
Error string
// Snapshot is this attempt's service configuration at trigger time
// (migrations/0086), built by NewDeployAttemptSnapshot from the
// DesiredService the trigger handler already has in hand. Zero value
// for every attempt recorded before that migration.
Snapshot DeployAttemptSnapshot
}
DeployAttempt is one row-per-attempt entry in the deploy_attempts table: real deploy history, closing the gap left by reconcile_status/UpsertConditions only ever keeping the latest condition per (controller, type) pair. Minted by all three real trigger paths (the plain image-tag deploy, the manual git-source build, and the unattended git-push webhook), one row per call.
type DeployAttemptEnvKey ¶
type DeployAttemptEnvKey struct {
Key string `json:"key"`
Kind DeployAttemptEnvKind `json:"kind"`
Value string `json:"value,omitempty"`
}
DeployAttemptEnvKey is one env var key captured in a DeployAttemptSnapshot. Value is only ever populated for Kind DeployAttemptEnvKindLiteral: a secret- or database-backed key never carries a value here, matching how DesiredService.SecretEnv itself holds names only (see that field's own doc comment).
type DeployAttemptEnvKind ¶
type DeployAttemptEnvKind string
DeployAttemptEnvKind classifies one env var key captured in a DeployAttemptSnapshot: whether its value is safe to snapshot at all.
const ( // DeployAttemptEnvKindLiteral is an ordinary env var // (DesiredService.Env): its Value is snapshotted and diffable. DeployAttemptEnvKindLiteral DeployAttemptEnvKind = "literal" // DeployAttemptEnvKindSecret is a { secret: true } env var // (DesiredService.SecretEnv): only its key is ever snapshotted, never // a value or anything derived from one. DeployAttemptEnvKindSecret DeployAttemptEnvKind = "secret" // DeployAttemptEnvKindDatabase is a { from: ... } env var // (DesiredService.DatabaseEnv): resolved from a managed database's // live connection details at container-create time, so there is no // stable value to snapshot even though it isn't secret-backed. DeployAttemptEnvKindDatabase DeployAttemptEnvKind = "database" )
type DeployAttemptSnapshot ¶
type DeployAttemptSnapshot struct {
Env []DeployAttemptEnvKey `json:"env,omitempty"`
Port int `json:"port,omitempty"`
HostPort *int `json:"host_port,omitempty"`
Domains []string `json:"domains,omitempty"`
Resources *ServiceResources `json:"resources,omitempty"`
// Health, Replicas, Strategy, Volumes, and Labels mirror
// DesiredService's own fields of the same name, closing the
// remaining gap this migration's own comment named.
Health *ServiceHealth `json:"health,omitempty"`
Replicas int `json:"replicas,omitempty"`
Strategy string `json:"strategy,omitempty"`
Volumes []ServiceVolume `json:"volumes,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
}
DeployAttemptSnapshot is the subset of DesiredService captured per deploy attempt (migrations/0086), closing the gap docs/roadmap.md's deploy-comparison entry describes: before this, only Image/CommitSHA/Source/Status/timestamps were ever recorded per attempt.
func NewDeployAttemptSnapshot ¶
func NewDeployAttemptSnapshot(svc DesiredService) DeployAttemptSnapshot
NewDeployAttemptSnapshot builds svc's config snapshot at the moment a deploy attempt is triggered. Env keys are sorted for a stable JSON encoding, so two snapshots of an unchanged config marshal identically.
type DesiredDatabase ¶
type DesiredDatabase struct {
Name string
Engine string
Version string
// NodeID: see DesiredService.NodeID's own doc comment, identical
// meaning and identical "SaveDesiredDatabase never writes it, only
// UpdateDatabaseNode does" exception below.
NodeID string
// ProjectID: see DesiredService.ProjectID's own doc comment,
// identical meaning and identical "SaveDesiredDatabase never writes
// it, only UpdateDatabaseProject does" exception below.
ProjectID string
// BackupTargetID, BackupSchedule, BackupRetain: wave-2 roadmap item 6,
// scheduled backups (migrations/0023_scheduled_backups.sql). Same
// "SaveDesiredDatabase never writes it, only SetDatabaseBackupSchedule
// does" exception NodeID/ProjectID already establish above, applied
// to the three columns internal/backup.Scheduler reads every tick.
// BackupTargetID is "" when no backup_targets row is configured
// (SQL NULL, mirroring ProjectID's own empty-string-means-NULL
// convention); BackupSchedule is "" when no cron schedule is set
// (SQL ”, mirroring NodeID's own empty-string-is-the-real-value
// convention, see the migration's own doc comment for why the two
// columns deliberately use different null-ness conventions);
// BackupRetain is 0, meaning "keep every successful backup, prune
// nothing."
BackupTargetID string
BackupSchedule string
BackupRetain int
// BackupRetainDays is a second, independent retention dimension
// (migrations/0059_backup_retain_days.sql): 0 means no age limit,
// mirroring BackupRetain's own zero-means-unlimited convention.
BackupRetainDays int
// PubliclyAccessible, PublicPort: whether this database's container
// port is bound to a host port so an operator's own database GUI
// tool can connect to it directly, not just from inside the Docker
// network (migrations/0026_database_public_access.sql). Same
// "SaveDesiredDatabase never writes it, only
// SetDatabasePublicAccess does" exception NodeID/ProjectID/
// BackupSchedule already establish. PublicPort is 0 when
// PubliclyAccessible is false (SQL NULL).
PubliclyAccessible bool
PublicPort int
// Resources caps this database's memory and CPU, the same
// *ServiceResources type and JSON-column storage
// DesiredService.Resources already establishes (migrations/
// 0028_desired_databases_resources.sql mirrors 0002's reasoning).
// Unlike NodeID/ProjectID/the backup fields above, this is ordinary
// desired state: SaveDesiredDatabase writes it on every save, the
// same "whole record, not a special exception" treatment
// DesiredService.Resources gets from SaveDesiredService.
Resources *ServiceResources
// Suspended: see DesiredService.Suspended's own doc comment, identical
// meaning and identical "SaveDesiredDatabase never writes it, only
// UpdateDatabaseSuspended does" exception NodeID/ProjectID already
// establish above (migrations/0094_database_suspended.sql).
Suspended bool
}
DesiredDatabase is what a future database controller reconciles a managed database container against. No credentials field: see the comment in migrations/0003_desired_databases.sql for why.
type DesiredService ¶
type DesiredService struct {
Name string
Image string
Port int
// HostPort pins the host-side port Docker binds Port to
// (internal/docker.PortBinding.HostPort), migrations/0056's own
// operator-facing counterpart to Port itself. nil means "let Docker
// assign one" (today's only behavior, and the ordinary case), the
// same "an ordinary desired-state field, written on every
// SaveDesiredService call" treatment Port itself already gets, not
// a dedicated setter: an app.yaml redeploy or an API update is meant
// to be able to change or clear a pin the same way it already
// changes Port.
HostPort *int
Domains []string
Env map[string]string
// Command overrides the image's own default CMD
// (internal/docker.ContainerSpec.Command), nil/empty meaning the
// image's own default. Populated from a compose service's command:
// (internal/compose.Service.Command); app.yaml has no equivalent
// field yet.
Command []string
// Entrypoint overrides the image's own default ENTRYPOINT
// (internal/docker.ContainerSpec.Entrypoint), same nil/empty and
// compose-only sourcing as Command above, from
// internal/compose.Service.Entrypoint.
Entrypoint []string
// EnvDirty is true when Env was saved through the update endpoint
// since the container was last recreated (migrations/0066): env is
// baked in at create time, so the change isn't live yet. Written by
// SaveDesiredService like Env itself, unlike RestartNonce/Suspended,
// so an ordinary fresh-state redeploy clears it for free; callers
// that bypass SaveDesiredService (RestartService,
// UpdateServiceSuspended(false)) clear it explicitly instead.
EnvDirty bool
// RegistryCredentialID is which store.RegistryCredential
// (migrations/0046_registry_credentials.sql) to authenticate with
// when pulling Image, resolved by internal/docker at container-
// create time; empty string means an unauthenticated (public) pull.
// A normal deploy-time field, unlike NodeID/ProjectID/
// StorageTargetID below: SaveDesiredService writes it on every
// call, the same as Image itself, since it comes from the same
// app.yaml build.type: image block.
RegistryCredentialID string
// SecretEnv names env vars whose values live in secret storage
// (internal/secrets), resolved and decrypted by the
// application controller immediately before container creation.
// Never holds a value itself, only the key name, the same shape
// app.yaml's { secret: true } already has: a name is not a secret,
// only the value is.
SecretEnv []string
// DatabaseEnv names env vars whose values resolve from a managed
// database's own connection details (internal/spec's { from:
// "<database>.<field>" } env var syntax), resolved by the application
// controller immediately before container creation, the same
// "ordinary desired state, written on every save" treatment SecretEnv
// gets: derived fresh from app.yaml on every deploy.
DatabaseEnv map[string]DatabaseEnvRef
Resources *ServiceResources
Health *ServiceHealth
// Hooks are this service's pre/post-deploy commands
// (internal/spec.Service.Hooks), nil meaning neither is configured.
// A normal deploy-time field, resolved and stored as a whole on every
// SaveDesiredService call, the same shape Resources/Health already
// follow.
Hooks *ServiceHooks
// Volumes are named Docker volumes this service's container mounts
// (migrations/0041_service_volumes.sql), previously a
// database-controller-only capability. Empty for the ordinary case
// (a stateless app), same "declarative, resolved before storing"
// shape as Resources/Health above.
Volumes []ServiceVolume
// BindMounts are real host directories this service's container
// mounts directly (migrations/0088_service_bind_mounts.sql), see
// ServiceBindMount's own doc comment for how this differs from
// Volumes and how it's gated. Empty for the ordinary case, same
// "declarative, resolved before storing" shape Volumes itself
// follows.
BindMounts []ServiceBindMount
// Labels are arbitrary operator-supplied Docker labels applied to the
// service's container at create time (internal/spec.Service.Labels'
// storage home, migrations/0027_service_labels.sql). Already
// validated by the time a DesiredService exists: internal/spec.
// ValidateLabels runs at every input boundary (app.yaml parsing,
// the HTTP API's validateAppResource), so this package and
// internal/docker both trust it's collision-free with this
// platform's own reserved label namespace by the time it gets here,
// the same "resolve/validate once, store the resolved form" shape
// Resources/Health already follow.
Labels map[string]string
// NodeID is which node (internal/store's own nodes table)
// this service should run on. Empty string is the explicit
// "this control plane's own local node" value (the placement
// migration comment explains why that's not NULL or a foreign key),
// the only value that existed before this field did, so an existing
// single-node deployment's services keep running exactly where they
// already were on upgrade.
NodeID string
// Strategy and Replicas are always the *resolved* (never empty/zero)
// values: internal/spec.Service.EffectiveStrategy()/
// EffectiveReplicas() already define what "unset in app.yaml" means,
// and this package stores that already-resolved decision rather than
// re-deriving it on every read, the same "resolve once, store the
// resolved form" shape Resources/Health already follow (app.yaml's
// human units are converted before a DesiredService exists at all).
// SaveDesiredService independently defends against an empty
// Strategy/zero Replicas from any caller, so this field is never
// ambiguous regardless of who constructs the struct.
Strategy string
Replicas int
// RestartNonce is opaque and only ever compared for equality, never
// interpreted: internal/reconcile/application.ContainerName folds it
// into the container name hash (only when non-empty, so a service
// that has never been restarted keeps the exact container name it
// always has). Changing it is therefore indistinguishable, from the
// reconciler's level-triggered point of view, from an image change:
// the existing blue-green/recreate cutover logic already handles it
// correctly with no new branch. Like NodeID, this is deliberately
// excluded from SaveDesiredService's full-record-replace semantics;
// only RestartService writes it, see that method's own doc comment.
RestartNonce string
// ProjectID is which store.Project (migrations/0022_projects.sql)
// this service is organizationally grouped under; empty string is
// "no project", a real, permanent, equally-valid state, not merely
// "unset" (see that migration's own comment on why the column is
// genuinely nullable rather than reusing NodeID's NOT NULL DEFAULT
// ” convention). Like NodeID and RestartNonce, SaveDesiredService
// never writes this field, on either an INSERT or an UPDATE: only
// UpdateServiceProject does, see that method's own doc comment for
// why, and internal/api/apps.go's handleCreateApp for how a create-
// time project choice still reaches it without this method's
// full-replace semantics being allowed to silently move an
// already-placed service between projects.
ProjectID string
// EnvironmentID is which store.Environment (migrations/0054) this
// service is tagged with; empty is "no environment", set only via
// SetServiceEnvironment, same non-full-replace shape as ProjectID.
EnvironmentID string
// StorageTargetID is which store.BackupTarget (migrations/0018_backup_targets.sql)
// this app's own object-storage credentials resolve from
// (migrations/0030_service_storage_target.sql): the same bucket
// connection an operator may already use for a database's scheduled
// backups, reused rather than duplicated as a second "storage
// target" concept. Empty string is "no storage attached", a real,
// permanent, equally-valid state, not merely "unset" (SQL NULL,
// mirroring ProjectID's own empty-string-means-NULL convention just
// above, for the identical reasoning: unlike NodeID, there is no
// meaningful non-empty default this could fall back to). Like
// NodeID/ProjectID/RestartNonce, SaveDesiredService never writes this
// field, on either an INSERT or an UPDATE: only
// UpdateServiceStorageTarget does, see that method's own doc comment
// for why. internal/reconcile/application's controller resolves the
// target's Endpoint/Region/Bucket plus its credentials (internal/secrets,
// store.BackupTargetSecretsKey) into env vars at container-create
// time when this is non-empty.
StorageTargetID string
// DatabaseAttachment is which managed database this app resolves one
// connection env var from (migrations/0050_service_database_env.sql),
// set via PUT/DELETE /api/v1/apps/{name}/database rather than
// app.yaml: see DatabaseAttachment's own doc comment for how it
// relates to DatabaseEnv above. nil means "no attachment", a real,
// permanent state, not merely "unset". Like NodeID/ProjectID/
// StorageTargetID, SaveDesiredService never writes this field: only
// UpdateServiceDatabaseAttachment does.
DatabaseAttachment *DatabaseAttachment
// Suspended is an operator-requested stop, distinct from delete: the
// desired service row, image, env, and domains are untouched, only
// the reconciler's converge target changes to zero running
// containers (internal/reconcile/application.Controller.Reconcile).
// Like NodeID/ProjectID/RestartNonce/StorageTargetID,
// SaveDesiredService never writes this field: only
// UpdateServiceSuspended does.
Suspended bool
// AppID is which store.App (migrations/0039_apps.sql) this service
// belongs to; empty string means none. SaveDesiredService only
// writes it on first INSERT, never on an ON CONFLICT update, the
// same "an ordinary edit must never silently move it" invariant
// NodeID/ProjectID/StorageTargetID/Suspended already have (via
// their own dedicated Update* setters); a service's AppID is fixed
// at creation.
AppID string
// LogDrain is this service's external log-forwarding config
// (migrations/0047_service_log_drain.sql), nil meaning none
// configured. Like NodeID/ProjectID/StorageTargetID/Suspended,
// SaveDesiredService never writes this field: only
// UpdateServiceLogDrain does.
LogDrain *LogDrain
}
DesiredService is what the application controller reconciles running containers against: an already-resolved image plus what it needs to run. See the migration comment in migrations/0002_desired_services.sql for why this is a distinct type from internal/spec.Service rather than reusing it directly.
type DeviceAuthRequest ¶
type DeviceAuthRequest struct {
ID string
DeviceCode string
UserCode string
Status string
ClientName string
ApprovedByUserID *string
TokenID *string
CreatedAt time.Time
ExpiresAt time.Time
RedeemedAt *time.Time
}
DeviceAuthRequest is one CLI-login-from-terminal request (RFC 8628-shaped): the CLI polls DeviceCode while an operator approves UserCode from the web dashboard. See migrations/0079's own comment for the status lifecycle.
type DomainBasicAuth ¶
DomainBasicAuth is one row of the domain_basic_auth table (migrations/0052_domain_basic_auth.sql): a username claimed for a domain already present in service_domains. No password field: that goes through internal/secrets instead, the same split CloudflareTunnelSettings uses for its own token.
type DomainTLSCert ¶
DomainTLSCert is one row of the domain_tls_cert table (migrations/0084_domain_tls_cert.sql): a domain already present in service_domains has an operator-supplied certificate uploaded. Neither the certificate nor its private key lives here: both go through internal/secrets under DomainTLSCertSecretsKey(domain), the same split DomainBasicAuth uses for its own password. ExpiresAt is stored in the clear (a certificate's NotAfter is not sensitive) so GET can report it without ever decrypting anything.
type DomainWAF ¶
type DomainWAF struct {
Domain string
WAFEnabled bool
WAFMode string
RateLimitRPS int
RateLimitBurst int
}
DomainWAF is one row of the domain_waf table: opt-in WAF and rate limiting for a domain already present in service_domains. RateLimitRPS of 0 means rate limiting is off, independent of WAFEnabled.
type EmailSettings ¶
type EmailSettings struct {
// Backend is "", EmailBackendSMTP, or EmailBackendSES.
Backend string
SMTPHost string
SMTPPort int
SMTPUsername string
SMTPFrom string
SESRegion string
SESAccessKeyID string
SESFrom string
}
EmailSettings is the single platform-wide email-sending configuration row. No credential fields: those go through internal/secrets instead.
type Environment ¶
Environment labels a service (e.g. "staging", "production") within one project (migrations/0054). Unlike Project/Organization, environments are owned by their project: deleting the project cascades.
Protected (migrations/0070) requires confirm: true on a deploy, rollback, or promotion targeting an app tagged with this environment (internal/api's deploys.go and promote.go).
type ErrDomainTaken ¶
ErrDomainTaken is returned by SaveDesiredService when one of svc's Domains is already claimed by a different service. Enforced here, not only by internal/spec's Validate() (which only ever sees one app.yaml at a time and so cannot see a domain already claimed by an earlier, separate deploy), because internal/reconcile/ingress's controller builds one Caddy route per domain from every desired service in a single reconcile pass: two services claiming the same host would silently produce two routes matching the same Host header, with whichever sorted last winning inside Caddy's own matcher evaluation and silently shadowing the other. See that controller's package doc comment and migrations/0011_service_domains.sql.
func (*ErrDomainTaken) Error ¶
func (e *ErrDomainTaken) Error() string
type FeatureFlag ¶
type FeatureFlag struct {
ID string
Key string
Name string
Description string
ServiceName string
Enabled bool
RolloutPercentage int
CreatedAt time.Time
UpdatedAt time.Time
}
FeatureFlag is a boolean (plus an optional gradual rollout percentage) an app's own code reads live at runtime, never baked into a container at create time. See migrations/0065_feature_flags.sql for why Key is globally unique rather than scoped to ServiceName.
type GitHubAppConnection ¶
type GitHubAppConnection struct {
AppID int64
ClientID string
// InstanceURL is the GitHub instance this App is registered
// against: "https://github.com" for every connection until GitHub
// Enterprise Server support (migrations/0061), a real GHES base URL
// after. Never empty: the migration backfills the column, and
// SaveGitHubAppConnection requires a caller to pass one.
InstanceURL string
CreatedAt string
// InstallationID and AccountLogin are nil until the App has been
// installed on a GitHub account/org (the redirect
// GET /api/v1/github-app/installed records). Pointers, not a
// zero-value sentinel, since 0 is not a distinguishable "unset" value
// for an installation ID.
InstallationID *int64
AccountLogin *string
}
GitHubAppConnection is the single-row github_app_connections table (migrations/0034_github_app_connection.sql). No secret fields: see that migration's own comment for why client_secret/webhook_secret/the PEM private key live in internal/secrets instead, under GitHubAppSecretsKey().
type GitLabAppConnection ¶
GitLabAppConnection is the single-row gitlab_app_connections table (migrations/0044_gitlab_app_connection.sql). No credential fields: client_secret and the OAuth access_token/refresh_token live in internal/secrets instead, under GitLabAppSecretsKey().
type GitSource ¶
type GitSource struct {
ServiceName string
RepoURL string
Branch string
BuildType string
BuildPath string
// AdditionalServices lets one push fan out to sibling services under
// the same store.App (apps_group.go): keyed by the sibling
// DesiredService's own name, each entry carries just enough to call
// specServiceFromDesired for it (migrations/0057_git_source_additional_services.sql).
// A monorepo's other services rarely share this app's exact build
// config, so this is a map, not a single shared BuildType/BuildPath.
//
// Mutually exclusive with Services (internal/api's
// validateAdditionalServices enforces this at write time): an app
// that has grown a real Services map fans out through that instead,
// see Services's own doc comment.
AdditionalServices map[string]GitSourceBuild
// Services is an app.yaml-style services: map, persisted so a push
// can re-run the same fan-out deploy.Pipeline.DeploySpec (internal/
// api/apps_multi.go's handleDeploySpec) already performs for a
// manual/API-triggered multi-service deploy, without an operator
// re-submitting it by hand on every commit
// (migrations/0063_git_source_services_spec.sql). Empty/nil for
// every git source created before this field existed, and for any
// git source that only ever used AdditionalServices: a webhook keeps
// walking AdditionalServices exactly as before when this is empty,
// see handleGitPushWebhook's own doc comment.
Services map[string]spec.Service
// Databases is an app.yaml-style databases: map, persisted the same
// way and for the same reason Services is (migrations/
// 0091_git_source_databases_spec.sql): a pull request webhook needs
// to see which databases the app declares, in particular which ones
// set ephemeralInPreviews, without re-fetching and parsing app.yaml
// on every push. Independent of Services/AdditionalServices: a
// single-service preview (no Services map at all) can still declare
// databases.
Databases map[string]spec.Database
// PreviewEnabled opts an app into preview environments per pull
// request (migrations/0064_preview_environments.sql): off by
// default, like every other opt-in feature toggle in this codebase.
// Set only via SetGitSourcePreviewEnabled, the same "SaveGitSource
// never writes it" shape AppID/ProjectID's own doc comments already
// establish for a value that must never move silently on an
// unrelated connect-form edit.
PreviewEnabled bool
// PostPRComments opts an app's preview environments into posting a
// GitHub PR comment (the live preview URL, or a teardown notice) and
// a commit status (pending/success/failure) on the pull request's
// head commit (migrations/0081_git_source_pr_status.sql). Off by
// default; only meaningful once PreviewEnabled is also on, but kept
// as its own field rather than folded into PreviewEnabled: an
// operator may want previews without the GitHub-visible noise, or
// vice versa want the notifications wired up before flipping previews
// on. Set only via SetGitSourcePostPRComments, the same
// "SaveGitSource never writes it" shape PreviewEnabled's own doc
// comment already establishes.
PostPRComments bool
CreatedAt time.Time
UpdatedAt time.Time
}
GitSource is one app's connected git repository (migrations/0029_service_git_sources.sql): what internal/webhook.Config held as static, single-app, server-only configuration, now persisted per app so a control plane can auto-deploy more than one app from a git push. RepoURL/Branch/BuildType/BuildPath are everything internal/api needs to rebuild a spec.Service the same way handleTriggerBuild's specServiceFromDesired already does for a manual build trigger; the deploy token (private repo auth) and webhook HMAC secret are deliberately not fields here, see GitSourceSecretsKey's own doc comment for where they actually live.
type GitSourceBuild ¶
type GitSourceBuild struct {
BuildType string `json:"build_type"`
BuildPath string `json:"build_path,omitempty"`
}
GitSourceBuild is one additional service's own build config within GitSource.AdditionalServices, mirroring this same struct's BuildType/BuildPath fields but scoped to a single sibling.
type HookRun ¶
type HookRun struct {
ServiceName string
HookType string
Command string
ExitCode int
Success bool
Output string
RanAt time.Time
}
HookRun is one outcome of running a service's pre/post-deploy hook command (internal/spec.Hooks, store.ServiceHooks), persisted by UpsertHookRun so GET /api/v1/apps/{name}/hook-runs can show what actually happened without a live log viewer having been open at the time.
type IngressSettings ¶
type IngressSettings struct {
// PrimaryDomain is the control plane dashboard's own hostname, if an
// operator has set one. Empty string means "not set", the same
// "absence is real, permanent state" convention
// DesiredService.ProjectID's own doc comment already establishes for
// a nullable text column.
PrimaryDomain string
// ACMEEnabled switches every currently-routed host from Caddy's
// offline internal issuer to real ACME. False (the default a fresh
// migration seeds) is byte-identical to this codebase's behavior
// before this table existed: see internal/ingress/routes.go's
// BuildRoutesConfig for where this flag actually changes anything.
ACMEEnabled bool
// ACMEEmail is the ACME account contact address. Required by
// internal/api's PUT /api/v1/settings/ingress validation whenever
// ACMEEnabled is true; may be empty while ACMEEnabled is false.
ACMEEmail string
// ACMEDirectoryURL overrides the ACME CA's directory endpoint. Empty
// means internal/ingress.NewACMEIssuer leaves Caddy's own compiled-in
// default in place (Let's Encrypt's real production directory). See
// this migration's own comment for why an operator would point this
// at Let's Encrypt's staging directory instead.
ACMEDirectoryURL string
}
IngressSettings is the platform-wide ingress configuration row (migrations/0024_ingress_settings.sql): whether to obtain real ACME certificates instead of Caddy's offline internal issuer, and an optional primary domain for the control plane's own dashboard. There is always exactly one of these (id = 1), never zero and never more than one, so GetIngressSettings never returns a not-found error the way GetProject/GetDesiredService do: the row is seeded by the migration itself.
type Invite ¶
type Invite struct {
ID string
Email string
Role string
Abilities []string
TokenHash string
CreatedBy string
CreatedAt time.Time
ExpiresAt time.Time
AcceptedAt *time.Time
RevokedAt *time.Time
}
Invite is one outstanding team invite (migrations/0086). TokenHash is the only form of the invite token ever persisted, same convention as PasswordResetToken.TokenHash. Role is the curated preset name (internal/api/roles.go) the invite was created with, empty when Abilities was hand-picked instead; accepting the invite always applies Abilities, the already-resolved set either way.
type LogDrain ¶
type LogDrain struct {
Type LogDrainType `json:"type"`
Target string `json:"target"`
Enabled bool `json:"enabled"`
}
LogDrain is one service's external log-forwarding configuration (migrations/0047_service_log_drain.sql), the Coolify-parity per-app log_drain field: forward this service's container log stream to Target alongside the existing node-local store, in addition to it, never instead of it. Enabled lets an operator keep Target configured but pause forwarding without losing the value.
type LogDrainType ¶
type LogDrainType string
LogDrainType selects which external sink protocol a service's log drain uses.
const ( LogDrainHTTP LogDrainType = "http" LogDrainSyslog LogDrainType = "syslog" )
The two sink protocols internal/telemetry's forwarder knows how to build (internal/telemetry/drain.go).
type Node ¶
type Node struct {
ID string
Name string
Address string
Status NodeStatus
CertFingerprint string
JoinedAt *time.Time
LastSeenAt *time.Time
// Schedulable is cordon's backing state (migration
// 0013): false means "unschedulable for new placements, but not
// evacuated," an operator-initiated state independent of Status.
// New nodes are always schedulable (SaveNode never trusts this
// field, matching SaveDesiredService's own "not every field of the
// input struct is honored, some have a dedicated mutation method"
// convention); the only way to change it is SetNodeSchedulable.
Schedulable bool
// AcceptsAppWorkloads and AcceptsBuildWorkloads are the
// node capability flags (migrations/0010_node_workloads.sql): which
// kinds of work this node is willing to run, independent of each
// other. A node can be either, both, or neither. See the migration's
// own doc comment for the default values new and pre-existing nodes
// get.
AcceptsAppWorkloads bool
AcceptsBuildWorkloads bool
// MeshPublicKey and MeshAddress are the WireGuard mesh
// state (migrations/0014_node_mesh.sql). Both empty means this node
// has not joined the mesh yet, which is a normal transient state for
// a node that enrolled but has not brought a device up.
//
// Deliberately plain strings rather than internal/network's Key and
// netip.Addr: this package stores rows, and having it import
// internal/network to parse and validate them would put the mesh's
// own rules (a key is 32 bytes, an address is inside the mesh CIDR)
// in two places. internal/network.ValidateInventory is the one place
// those rules live; the reconciler that reads these converts and
// validates on the way in.
MeshPublicKey string
MeshAddress string
CreatedAt time.Time
UpdatedAt time.Time
}
Node is one managed machine in the fleet. A row is created by the join-token enrollment flow, not by this package's own CRUD surface: SaveNode exists as a real, directly testable primitive for that future enrollment code to call, but nothing in internal/api wires an operator-facing "create a node" HTTP route to it yet, deliberately, per this migration's own doc comment.
type NodeJoinToken ¶
type NodeJoinToken struct {
ID string
TokenHash string
CreatedAt time.Time
ExpiresAt time.Time
// UsedAt is nil until the token is exchanged for a node enrollment.
// Single-use is enforced by MarkNodeJoinTokenUsed's
// atomic conditional UPDATE, not by application code checking this
// field first: two concurrent exchange attempts racing on the same
// token must not both succeed, the identical concurrency hazard
// store.CreateUser's own doc comment documents for first-run
// registration.
UsedAt *time.Time
}
NodeJoinToken is a one-time credential (ADR 003: "the control plane issues a one-time join token, agent exchanges it for a client certificate") an operator pastes into a new node's enrollment command. Only the hash is ever stored here, the same shape APIToken/api_tokens (0007) already established: the plaintext is generated once by internal/api, shown to the operator once, and never recoverable from this table again.
type NodeStatus ¶
type NodeStatus string
NodeStatus is a node's current lifecycle state.
const ( NodeStatusPending NodeStatus = "pending" NodeStatusOnline NodeStatus = "online" NodeStatusOffline NodeStatus = "offline" // NodeStatusCordoned is currently unused: cordon's real // backing state is the Schedulable field / schedulable column // (migration 0010), a separate axis from Status, exactly matching // this constant's own original doc comment promise that a cordoned // node "can still be online." Left defined rather than removed, // since nothing ever set it and removing an exported // constant is a needless breaking change for zero benefit. NodeStatusCordoned NodeStatus = "cordoned" )
The four states a node can be in. Pending is the state a newly enrolled node starts in (join token exchanged, no heartbeat received yet); Online/Offline track heartbeat presence; Cordoned means "unschedulable for new placements, but not evacuated", a distinct axis from Online/Offline, not a replacement for it: a cordoned node can still be online.
type OAuthIdentity ¶
type OAuthIdentity struct {
ID string
UserID string
Provider string
ProviderUserID string
CreatedAt time.Time
}
OAuthIdentity is one linked external account. Uniqueness (at most one per provider per user, never linked to two users) is enforced by migrations/0035's own indexes, not application code.
type OAuthProviderSettings ¶
type OAuthProviderSettings struct {
Provider string
Enabled bool
ClientID string
AllowedEmailDomain string
IssuerURL string
DisplayName string
}
OAuthProviderSettings is one row of oauth_provider_settings. IssuerURL and DisplayName are only meaningful for the oidc provider.
type Organization ¶
Organization groups projects (migrations/0054, mirroring Project's own opaque-id, no-auth-attached shape). Deleting an organization leaves its projects in place, org-less again (ON DELETE SET NULL).
type PasswordResetToken ¶
type PasswordResetToken struct {
ID string
UserID string
TokenHash string
CreatedAt time.Time
ExpiresAt time.Time
UsedAt *time.Time
}
PasswordResetToken is one outstanding forgot-password reset attempt. TokenHash is the only form of the token ever persisted. UserID names which user's password this token can reset.
type Policy ¶
type Policy struct {
ID string
Name string
Description string
Document string // raw JSON; internal/api's iam package parses/validates it
CreatedAt time.Time
UpdatedAt time.Time
}
Policy is one IAM-style policy document (iam.go's Document type holds the actual Allow/Deny statements): additive on top of a principal's flat Abilities list, either narrowing a broad ability down to specific resources (a Deny statement) or granting an ability scoped to specific resources without granting it globally (an Allow statement).
type PolicyAttachment ¶
type PolicyAttachment struct {
ID string
PolicyID string
PrincipalType string
PrincipalID string
CreatedAt time.Time
}
PolicyAttachment links one Policy to one principal (a user or an API token). PrincipalType is "user" or "token", matching audit_log's own actor_type discriminator convention rather than a real foreign key, since a principal isn't a single referenceable table.
type PreviewEnvironment ¶
type PreviewEnvironment struct {
ID string
AppName string
PRNumber int
PreviewAppID string
// EnvironmentID is the shared Preview-tier store.Environment this
// preview is tagged with, empty when tagging failed or hasn't run
// yet; see internal/api's ensurePreviewEnvironmentTier.
EnvironmentID string
Branch string
HeadSHA string
// Domain is empty when no base domain is configured, or when a
// domain collision forced this preview to deploy without one (see
// StatusReason for that case).
Domain string
Status string
// StatusReason explains a non-obvious Status, e.g. a domain
// collision that left the preview Active but domain-less, or a
// build failure's own error message when Status is Failed. Empty for
// the ordinary success case.
StatusReason string
CreatedAt string
UpdatedAt string
}
PreviewEnvironment is one pull request's preview deployment (migrations/0064_preview_environments.sql): a store.App/DesiredService named PreviewAppID, deployed from Branch at HeadSHA, optionally tagged with EnvironmentID and reachable at Domain.
type PreviewEphemeralDatabase ¶
type PreviewEphemeralDatabase struct {
ID string
PreviewEnvironmentID string
DatabaseName string
SourceKey string
Engine string
Version string
Status string
StatusReason string
CreatedAt string
UpdatedAt string
}
PreviewEphemeralDatabase links a PreviewEnvironment to one database.Controller-managed DesiredDatabase provisioned just for it: one row per (PreviewEnvironmentID, SourceKey), SourceKey being the app.yaml databases: key (spec.Database.EphemeralInPreviews) this instance stands in for. DatabaseName is a desired_databases.name this row's own container reconciles against through the exact same dynamicSource/database.Controller path every other managed database uses; this table adds no reconciliation logic of its own, only the linkage a preview's teardown needs to find and remove it.
type Project ¶
Project is a lightweight, non-auth organizational grouping (see migrations/0022_projects.sql's own comment for the "why" and its explicit boundary against the deferred teams/RBAC work): a name an app or database can optionally be filed under, nothing more. There is no owner, no member list, no permission of any kind attached to a project; the single admin user sees every project exactly the way it already sees every app and database.
type PrunedBackup ¶
PrunedBackup is one backup_history row PruneBackupHistory removed: its TargetID and ObjectKey, enough for a caller (internal/backup. Scheduler) to also delete the object those pointed to in the target bucket. PruneBackupHistory itself only removes the store row.
type RegistryCredential ¶
type RegistryCredential struct {
ID string
Name string
RegistryHost string
Username string
CreatedAt string
// ExpiresAt is operator-provided, never inferred: this platform has
// no way to read an expiry out of an opaque credential string. Nil
// means no expiry was set.
ExpiresAt *time.Time
}
RegistryCredential is a username for pulling a private container image from RegistryHost. No password field: a caller resolving it does so separately through internal/secrets, keyed by RegistryCredentialSecretsKey(credential.ID), the same split BackupTarget already uses.
type RegistrySettings ¶
type RegistrySettings struct {
Enabled bool
// Host is the domain the embedded Caddy ingress routes to the
// registry container, e.g. a WireGuard mesh-resolvable name for
// multi-node reachability, or any hostname on a single node. Empty
// means "not set yet": Enabled with an empty Host reconciles the
// container but never routes it, the same "known, incomplete
// configuration" shape IngressSettings.PrimaryDomain's absence
// already has for the dashboard route.
Host string
// Username is the registry login name, generated once alongside the
// password when the registry is first enabled.
Username string
CreatedAt string
}
RegistrySettings is the single platform-wide row: whether the operator wants Levelrail's built-in container registry running, the hostname it should be reachable at, and the generated login username. No password field: that goes through internal/secrets instead.
type RestoreHistory ¶
type RestoreHistory struct {
ID string
DatabaseName string
ResourceKind string
ServiceName string
VolumeName string
BackupHistoryID string
Status string
Error string
StartedAt string
FinishedAt string
}
RestoreHistory is one attempted restore of one database, or one app service's named volume, from one backup_history row. ResourceKind/ ServiceName/VolumeName mirror BackupHistory's own identity fields exactly (backup_history.go), the same mutually-exclusive shape. Status reuses BackupStatusRunning/Succeeded/Failed (backup_history.go) rather than a second, identically-valued set of constants: a restore attempt moves through the exact same running-then-succeeded-or-failed lifecycle a backup attempt does, and migrations/0019_restore_history.sql's own CHECK constraint accepts the identical three strings, so two names for the same three values would only invite them drifting apart. Error is empty unless Status is BackupStatusFailed.
type ScheduledTask ¶
type ScheduledTask struct {
ID string
ServiceName string
Command []string
Schedule string
Enabled bool
// LastRunAt is nil until this task has run at least once (scheduled
// or manual "run now"), the same "zero value means never happened
// yet" convention APIToken's own LastUsedAt already establishes for
// state that starts out unset.
LastRunAt *time.Time
LastRunStatus string
// LastRunOutput is already bounded by the runner before it reaches
// this field (see this table's own migration comment); this struct
// never re-truncates it.
LastRunOutput string
// ConsecutiveFailures counts runs in a row that were not
// ScheduledTaskStatusSuccess, reset to 0 by RecordScheduledTaskRun on
// a success. What a kind=scheduled_task_failure alert rule
// (internal/alerting) polls, so repeated failure is visible without
// this table keeping a full run history.
ConsecutiveFailures int
CreatedAt time.Time
UpdatedAt time.Time
}
ScheduledTask is one cron-scheduled command an operator runs inside a service's currently running container. See migrations/ 0048_scheduled_tasks.sql for the full field-by-field reasoning.
type SecretKeyInfo ¶
SecretKeyInfo is one secret key known for a service, with its locked state, never a value.
type ServiceBindMount ¶
type ServiceBindMount struct {
HostPath string `json:"host_path"`
ContainerPath string `json:"container_path"`
ReadOnly bool `json:"read_only,omitempty"`
}
ServiceBindMount is one host directory an application service's container mounts directly, distinct from ServiceVolume (a Docker- managed named volume): HostPath is a real path on whichever node the service runs on, not a Docker volume name. internal/compose is the only producer today (compose.go's own doc comment on volumes:'s bind-mount short form); internal/api gates persisting any non-empty BindMounts to AbilityRoot callers, the same tier POST /apps/{name}/exec sits behind, since a bind mount is a real host-filesystem access capability. Kept as its own type rather than an optional HostPath field on ServiceVolume so a bind mount and a named volume are never ambiguous in code or storage.
type ServiceDomain ¶
ServiceDomain is one row of the service_domains table (migrations/0012_service_domains.sql): a domain currently claimed by a named service. Read-only projection for GET /api/v1/domains (internal/api), the centralized cross-app domain list; this is not a new tracking mechanism, service_domains is already kept in sync by SaveDesiredService on every write (see that method's own doc comment).
type ServiceHealth ¶
type ServiceHealth struct {
Readiness *ServiceProbe `json:"readiness,omitempty"`
Liveness *ServiceProbe `json:"liveness,omitempty"`
}
ServiceHealth holds a service's probe configuration.
type ServiceHooks ¶
type ServiceHooks struct {
PreDeploy string `json:"pre_deploy,omitempty"`
PostDeploy string `json:"post_deploy,omitempty"`
}
ServiceHooks holds a service's pre/post-deploy hook commands (internal/spec.Hooks' storage home, migrations/0082_service_hooks.sql). See internal/reconcile/application.Controller's own doc comment for when each one runs and what a failure does.
type ServiceProbe ¶
type ServiceProbe struct {
Path string `json:"path"`
Interval time.Duration `json:"interval,omitempty"`
Timeout time.Duration `json:"timeout,omitempty"`
Failures int `json:"failures,omitempty"`
}
ServiceProbe is one readiness or liveness check.
type ServiceResources ¶
type ServiceResources struct {
MemoryBytes int64 `json:"memory_bytes,omitempty"`
NanoCPUs int64 `json:"nano_cpus,omitempty"`
// SwapMemoryBytes is Docker's own MemorySwap: total memory plus swap
// combined, only meaningful alongside MemoryBytes.
SwapMemoryBytes int64 `json:"swap_memory_bytes,omitempty"`
// CPUSetCPUs pins the container to specific host CPUs, Docker's own
// cpuset-cpus format (e.g. "0-3" or "0,2").
CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
}
ServiceResources caps a service's memory and CPU, in the same units internal/docker.Resources already uses (bytes, nano-CPUs), not app.yaml's human-friendly "512Mi"/0.5-cores strings. Translating those is the deploy pipeline's job, not this package's; by the time a DesiredService exists, its units are already resolved.
type ServiceVolume ¶
type ServiceVolume struct {
Name string `json:"name"`
ContainerPath string `json:"container_path"`
}
ServiceVolume is one named Docker volume an application service's container mounts, the same shape internal/docker.VolumeMount already has for the database controller's own (single, fixed-path) volume. Name is this platform's own volume name (already scoped/prefixed, see internal/reconcile/application's own volume-naming helper), not whatever a compose file's own top-level volumes: key called it.
type ServiceVolumeBackupConfig ¶
type ServiceVolumeBackupConfig struct {
ServiceName string
VolumeName string
BackupTargetID string
BackupSchedule string
BackupRetain int
BackupRetainDays int
}
ServiceVolumeBackupConfig is one service volume's scheduled-backup config: migrations/0075_service_volume_backups.sql's own row, the volume counterpart of DesiredDatabase's BackupTargetID/BackupSchedule/ BackupRetain/BackupRetainDays fields. ServiceName/VolumeName identify the volume the same way internal/api's resolveServiceVolume does: VolumeName is the volume's logical name (spec.Volume.Name), not the resolved Docker volume name internal/deploy's volumeName() computes.
type StaticSite ¶
type StaticSite struct {
Name string
Domains []string
// RootDir is the local filesystem directory internal/deploy copied
// this site's built static files into (under the control plane's
// data directory, never the ephemeral git checkout dir itself, which
// a caller like internal/webhook removes as soon as the deploy call
// returns). The ingress controller passes this straight to Caddy's
// file_server handler as its root.
RootDir string
}
StaticSite is what internal/reconcile/ingress's controller reads to point Caddy's file_server handler directly at a directory on disk, no container involved. See migrations/0015_static_sites.sql for why this is a separate table from DesiredService rather than a variant of it: build.type: static (served directly by the embedded Caddy) has no image, no port, and no running container to converge to, so it never belongs in desired_services at all.
type User ¶
type User struct {
ID string
Email string
DisplayName string
PasswordHash *string
Abilities []string
IsFirstUser bool
CreatedAt time.Time
LastLoginAt *time.Time
TOTPEnabled bool
TOTPConfirmedAt *time.Time
}
User is a real, individually-identified account (migrations/0035_users.sql). PasswordHash is nil for an OAuth-only user. IsFirstUser is display-only. TOTPEnabled/TOTPConfirmedAt come from migrations/0042_user_totp.sql; the TOTP secret itself is not on this struct, it lives in internal/secrets keyed by UserTOTPSecretsKey(ID). Abilities (migrations/0045_user_abilities.sql) is the same shape and validation (internal/api's validateAbilities) as APIToken.Abilities: a session now carries real, checkable scoping instead of every session being treated as implicitly root.
type VolumeCloneRestore ¶
type VolumeCloneRestore struct {
ID string
SourceServiceName string
SourceVolumeName string
NewVolumeName string
BackupHistoryID string
Status string
Error string
StartedAt string
FinishedAt string
}
VolumeCloneRestore is one attempted "restore as new volume": a backup of SourceServiceName's SourceVolumeName restored into NewVolumeName, a brand-new Docker volume created fresh for this attempt rather than overwriting anything. The app service volume counterpart of CloneRestore, with the same status lifecycle.
type WebhookDelivery ¶
type WebhookDelivery struct {
// ID is an opaque, mint-time-random identifier from
// NewWebhookDeliveryID, the same shape NewDeployAttemptID already
// establishes.
ID string
ServiceName string
// Provider and EventType are detected from request headers alone
// (detectWebhookProviderAndEvent), debug metadata only: nothing in
// this package's own processing branches on them.
Provider string
EventType string
// HeaderFields carries the small set of provider event-discriminator
// headers (X-GitHub-Event, X-Gitlab-Event, X-Event-Key) needed to
// replay this delivery through the identical processing branch it
// originally took. Deliberately not the full header set: no
// signature or token header value is ever stored here, only the
// three name-of-event headers, none of which are secrets.
HeaderFields map[string]string
SignatureValid bool
// Matched reports whether ServiceName resolved to a connected git
// source at receipt time, the "app not found" visibility this table
// exists for in the first place.
Matched bool
StatusCode int
Payload []byte
PayloadTruncated bool
// Error is the same non-leaky status message the webhook response
// itself returned (e.g. "invalid signature", "deploy failed"), never
// a secret or the payload's own contents.
Error string
ReceivedAt time.Time
}
WebhookDelivery is one recorded inbound git-provider webhook request (internal/api/git_webhook.go's handleGitPushWebhook): what arrived, whether it verified, what it resolved to, and what this control plane did about it. Exists so an operator can see why a delivery failed (bad signature, no git source connected, a downstream deploy error) without re-triggering a real push, and can replay a stored payload through the exact same processing path once whatever was wrong is fixed.
Source Files
¶
- apps.go
- audit.go
- backup_history.go
- backup_target.go
- backup_verification.go
- bitbucket_app.go
- cert_storage.go
- clone_restore.go
- cloudflare_dns.go
- cloudflare_tunnel.go
- database.go
- database_engines.go
- deploy_attempt.go
- device_auth.go
- domain_basic_auth.go
- domain_maintenance.go
- domain_tls_cert.go
- domain_waf.go
- domains.go
- email_settings.go
- environment.go
- environment_env.go
- feature_flag.go
- git_source.go
- github_app.go
- gitlab_app.go
- hook_run.go
- iam_policy.go
- ingress_settings.go
- invite.go
- log_drain.go
- migrate.go
- node_join_tokens.go
- nodes.go
- oauth_identity.go
- oauth_settings.go
- onboarding.go
- organization.go
- organization_env.go
- password_reset_token.go
- preview_environment.go
- preview_ephemeral_database.go
- project.go
- project_env.go
- reconcile_status.go
- recovery_codes.go
- registry_credential.go
- registry_settings.go
- restore_history.go
- scheduled_task.go
- secret.go
- service.go
- service_volume_backup.go
- static_site.go
- store.go
- tokens.go
- user.go
- volume_clone_restore.go
- webhook_delivery.go