// Copyright 2026 MarketAlly. All rights reserved. // SPDX-License-Identifier: MIT package plugins import ( "context" "xorm.io/xorm" ) // Plugin defines the interface that all GitCaddy plugins must implement type Plugin interface { // Name returns the unique identifier for this plugin Name() string // Version returns the plugin version Version() string // Description returns a human-readable description Description() string // Init is called when the plugin is loaded Init(ctx context.Context) error // Shutdown is called when the server is shutting down Shutdown(ctx context.Context) error } // DatabasePlugin is implemented by plugins that need database tables type DatabasePlugin interface { Plugin // RegisterModels returns the models to be registered with the database RegisterModels() []any // Migrate runs any database migrations for this plugin Migrate(ctx context.Context, x *xorm.Engine) error } // WebRoutesPlugin is implemented by plugins that add web UI routes type WebRoutesPlugin interface { Plugin // RegisterWebRoutes adds routes to the web UI router // The router is a *web.Router from the gitcaddy server RegisterWebRoutes(m any) } // APIRoutesPlugin is implemented by plugins that add API routes type APIRoutesPlugin interface { Plugin // RegisterAPIRoutes adds routes to the API router // The router is a *web.Router from the gitcaddy server RegisterAPIRoutes(m any) } // RepoRoutesPlugin is implemented by plugins that add per-repository routes type RepoRoutesPlugin interface { Plugin // RegisterRepoWebRoutes adds routes under /{owner}/{repo}/ // The router is a *web.Router from the gitcaddy server RegisterRepoWebRoutes(m any) // RegisterRepoAPIRoutes adds routes under /api/v1/repos/{owner}/{repo}/ // The router is a *web.Router from the gitcaddy server RegisterRepoAPIRoutes(m any) } // LicensedPlugin is implemented by plugins that require a license type LicensedPlugin interface { Plugin // ValidateLicense checks if the plugin is properly licensed ValidateLicense(ctx context.Context) error // LicenseInfo returns information about the current license LicenseInfo() *LicenseInfo } // License tier constants const ( TierSolo = "solo" TierPro = "pro" TierTeam = "team" TierEnterprise = "enterprise" ) // LicenseInfo contains license details type LicenseInfo struct { Valid bool Tier string // e.g., "solo", "pro", "team", "enterprise" CustomerID string ExpiresAt int64 GracePeriod bool // true if in grace period after expiry } // LicenseLimits defines the limits for each tier type LicenseLimits struct { Users int // Max users with vault access (-1 = unlimited) SecretsPerRepo int // Max secrets per repo (-1 = unlimited) AuditRetentionDays int // Days to keep audit logs VersioningEnabled bool // Can use secret versioning/rollback MaxVersions int // Max versions to keep per secret (-1 = unlimited, 0 = disabled) CICDTokensEnabled bool // Can create CI/CD tokens MaxTokens int // Max CI/CD tokens per repo (-1 = unlimited, 0 = disabled) MaxTokenTTLHours int // Max token TTL in hours (-1 = unlimited) TokensReadOnly bool // If true, tokens can only read secrets (not write) SSOEnabled bool // Can use SSO/SAML } // DefaultSoloLicense returns the default Solo tier license (free, no registration required) func DefaultSoloLicense() *LicenseInfo { return &LicenseInfo{ Valid: true, Tier: TierSolo, CustomerID: "", ExpiresAt: 0, // Never expires GracePeriod: false, } } // GetLimitsForTier returns the limits for a given license tier func GetLimitsForTier(tier string) *LicenseLimits { switch tier { case TierSolo: return &LicenseLimits{ Users: 1, SecretsPerRepo: 5, AuditRetentionDays: 7, VersioningEnabled: true, // Limited versioning MaxVersions: 2, // Keep last 2 versions only CICDTokensEnabled: true, // Limited CI/CD MaxTokens: 1, // 1 token only MaxTokenTTLHours: 24, // Max 24h TTL TokensReadOnly: true, // Read-only access SSOEnabled: false, } case TierPro: return &LicenseLimits{ Users: 5, SecretsPerRepo: -1, // Unlimited AuditRetentionDays: 90, VersioningEnabled: true, MaxVersions: -1, // Unlimited CICDTokensEnabled: true, MaxTokens: -1, // Unlimited MaxTokenTTLHours: -1, // Unlimited TokensReadOnly: false, SSOEnabled: false, } case TierTeam: return &LicenseLimits{ Users: 25, SecretsPerRepo: -1, // Unlimited AuditRetentionDays: 365, VersioningEnabled: true, MaxVersions: -1, // Unlimited CICDTokensEnabled: true, MaxTokens: -1, // Unlimited MaxTokenTTLHours: -1, // Unlimited TokensReadOnly: false, SSOEnabled: true, } case TierEnterprise: return &LicenseLimits{ Users: -1, // Unlimited SecretsPerRepo: -1, // Unlimited AuditRetentionDays: -1, // Custom/unlimited VersioningEnabled: true, MaxVersions: -1, // Unlimited CICDTokensEnabled: true, MaxTokens: -1, // Unlimited MaxTokenTTLHours: -1, // Unlimited TokensReadOnly: false, SSOEnabled: true, } default: // Unknown tier defaults to Solo limits return GetLimitsForTier(TierSolo) } }