internal/app/runtime_foundation.go
Rama main · réplica de lectura del repositorio original.
package app
import (
"context"
"fmt"
"log/slog"
"strings"
"time"
"github.com/yeomyeonggeori/blueclaw/internal/config"
"github.com/yeomyeonggeori/blueclaw/internal/policy"
runtimelogging "github.com/yeomyeonggeori/blueclaw/internal/runtime"
"github.com/yeomyeonggeori/blueclaw/internal/security"
"github.com/yeomyeonggeori/blueclaw/internal/store/postgres"
)
func openRuntimeDatabase(runtimeConfiguration config.RuntimeConfiguration, logger *slog.Logger) (postgres.Database, error) {
if strings.TrimSpace(runtimeConfiguration.Database.ConnectionString) == "" {
return postgres.Database{}, nil
}
ctx, cancel := context.WithTimeout(context.Background(), databaseInitializationTimeout)
defer cancel()
logger.Info("application.open_database.phase", "phase", "connect")
database, errorValue := postgres.OpenDatabase(ctx, runtimeConfiguration.Database.ConnectionString, runtimeConfiguration.Database.MaxOpenConnections)
if errorValue != nil {
return postgres.Database{}, errorValue
}
logger.Info("application.open_database.phase", "phase", "validate_migration_directory")
migrationDirectoryPath := strings.TrimSpace(runtimeConfiguration.Database.MigrationDirectoryPath)
if migrationDirectoryPath == "" {
migrationDirectoryPath = "migrations"
}
migrationRunner := postgres.MigrationRunner{MigrationDirectoryPath: migrationDirectoryPath, Logger: logger}
if errorValue := postgres.ValidateConnectorMigrationDirectory(migrationRunner); errorValue != nil {
_ = database.Close()
return postgres.Database{}, errorValue
}
logger.Info("application.open_database.phase", "phase", "apply_migrations")
if errorValue := migrationRunner.ApplyMigrations(ctx, database); errorValue != nil {
_ = database.Close()
return postgres.Database{}, errorValue
}
logger.Info("application.open_database.phase", "phase", "validate_schema")
if errorValue := postgres.ValidateConnectorDeliverySchema(ctx, database); errorValue != nil {
_ = database.Close()
return postgres.Database{}, errorValue
}
logger.Info("application.open_database.phase", "phase", "ready")
return database, nil
}
type runtimeFoundation struct {
runtimeLogger *runtimelogging.PersistentLogger
logger *slog.Logger
database postgres.Database
policyLoader policy.PolicyLoader
policyDocument policy.PolicyDocument
posixSynchronizer security.POSIXSynchronizer
startupError error
}
func newRuntimeFoundation(runtimeConfiguration config.RuntimeConfiguration, policyPath string) runtimeFoundation {
runtimeLogger, startupError := runtimelogging.NewPersistentLogger(runtimeConfiguration, time.Now())
if startupError != nil {
runtimeLogger = runtimelogging.NewDiscardLogger()
}
logger := runtimeLogger.Logger
logger.Info("application.initializing", "stage", "open_database")
database, databaseError := openRuntimeDatabase(runtimeConfiguration, logger)
if databaseError != nil && startupError == nil {
startupError = databaseError
}
logger.Info("application.initializing", "stage", "load_policy")
policyLoader := policy.PolicyLoader{}
policyDocument, policyLoadError := policyLoader.LoadPolicyDocument(policyPath)
logger.Info("application.initializing", "stage", "posix_synchronize")
posixSynchronizer := security.NewPOSIXSynchronizer(runtimeConfiguration.Terminal, policyPath)
if errorValue := posixSynchronizer.Synchronize(context.Background()); errorValue != nil && startupError == nil {
startupError = errorValue
}
logger.Info("application.initializing", "stage", "capability_socket_invariant")
if errorValue := checkCapabilitySocketInvariant(runtimeConfiguration, policyDocument, logger); errorValue != nil && startupError == nil {
startupError = errorValue
}
logger.Info("application.initializing", "stage", "project_policy")
if database.SQL != nil && policyLoadError == nil {
if errorValue := postgres.NewPersonRepository(database).ReplacePeople(policyDocument); errorValue != nil && startupError == nil {
startupError = fmt.Errorf("project the policy's people into the database: %w", errorValue)
}
}
return runtimeFoundation{
runtimeLogger: runtimeLogger,
logger: logger,
database: database,
policyLoader: policyLoader,
policyDocument: policyDocument,
posixSynchronizer: posixSynchronizer,
startupError: startupError,
}
}
func checkCapabilitySocketInvariant(runtimeConfiguration config.RuntimeConfiguration, policyDocument policy.PolicyDocument, logger *slog.Logger) error {
result, errorValue := security.EnsureCapabilitySocketInvariant(runtimeConfiguration.Capabilities.UnixSocketPath, policyDocument)
if result.Skipped {
logger.Info("application.capability_socket_invariant.skipped", "reason", result.SkipReason)
return errorValue
}
if errorValue == nil {
logger.Info("application.capability_socket_invariant.passed", "socketPath", result.SocketPath, "group", result.GroupName)
}
return errorValue
}