// Package preparation owns installation-local documents before any runtime exists. package preparation import ( "fmt" "path/filepath" "strconv" "strings" "github.com/aritmolab/thothii/tools/tht/internal/safeio" ) func Prepare(directory string) error { if err := safeio.ValidateCanonicalPath(directory); err != nil { return fmt.Errorf("choose an absolute canonical destination") } exists, err := safeio.PreflightPrivateDirectory(directory) if err != nil || exists { return fmt.Errorf("choose a new private directory with an existing parent; existing documents are never replaced") } if err := safeio.EnsurePrivateDirectory(directory); err != nil { return fmt.Errorf("cannot create private preparation directory") } root := func(name string) string { return strconv.Quote(filepath.Join(directory, name)) } installation := fmt.Sprintf(`# Installation schema v2; replace CHANGE_ME before validation. # Paths refer to local preparation files, never to workspace Git. schemaVersion: 2 profile: local projectDirectory: %s envFile: %s shell: {mode: full, defaultLocale: en} workspaceRepository: remote: https://CHANGE_ME/workspaces.git branch: main access: https authentication: configDirectory: %s modelCatalog: defaults: {interaction: openai/gpt-4.1-mini} embedding: {id: 'ollama/qwen3-embedding:0.6b', dimensions: 1024} providers: openai: authentication: {mode: secret_env, apiKeyEnv: OPENAI_API_KEY} session: {mode: pi_builtin} models: gpt-4.1-mini: {session: {}} # Metadata generation is optional: omitted here. Configure its eligibility in this catalog. # This Compose asset will come from the release; no application checkout is required here. overrides: [%s] `, strconv.Quote(directory), root("operator.env"), root("auth"), root("deploy/compose.git-https.yaml")) environment := "# Non-secret paths and parameters; no interpolation or duplicate keys.\n" for _, entry := range [][2]string{ {"COMPOSE_PROJECT_NAME", "thothii-local"}, {"THT_WORKSPACE_INSTALLATION_ID", "local"}, {"THT_WORKSPACE_GIT_REMOTE", "https://CHANGE_ME/workspaces.git"}, {"THT_WORKSPACE_GIT_BRANCH", "main"}, {"THT_INSTALLATION_CONFIG_SOURCE", filepath.Join(directory, "thothii-installation.yaml")}, {"THT_AUTH_CONFIG_ROOT", filepath.Join(directory, "auth")}, {"THT_SECRETS_FILE", filepath.Join(directory, "secrets", "secrets.env")}, {"PI_AUTH_FILE", filepath.Join(directory, "secrets", "pi-auth.json")}, {"THT_WORKSPACE_GIT_CREDENTIALS_FILE", filepath.Join(directory, "secrets", "git-credentials")}, {"THT_WORKSPACE_GIT_CA_FILE", filepath.Join(directory, "secrets", "git-ca.pem")}, {"THT_CATALOG_RUNTIME_PASSWORD_SOURCE", filepath.Join(directory, "secrets", "catalog-runtime-password")}, {"THT_CATALOG_MIGRATOR_PASSWORD_SOURCE", filepath.Join(directory, "secrets", "catalog-migrator-password")}, {"THOTH_HTTP_PORT", "8080"}, {"THOTH_CORE_HTTP_PORT", "8787"}, {"MAX_PI_PROCESSES", "4"}, } { environment += entry[0] + "=" + strconv.Quote(entry[1]) + "\n" } bootstrap := fmt.Sprintf(`# Bootstrap input only; PostgreSQL Metadata Catalog remains the runtime authority. schemaVersion: 1 databases: - workspaceId: CHANGE_ME engine: postgres databaseName: CHANGE_ME schema: public binding: transport: postgres_direct host: CHANGE_ME port: 5432 username: CHANGE_ME secretFiles: password: %s `, root("secrets/database-password")) documents := map[string]string{ ".gitignore": "*\n", "thothii-installation.yaml": installation, "operator.env": environment, "database-bootstrap.yaml": bootstrap, "README.md": "# Preparation / Preparazione\n\nReplace every CHANGE_ME / Sostituire ogni CHANGE_ME. Keep all files outside workspace Git / Tenere tutti i file fuori dal Git dei workspace.\n\n1. Edit installation models, workspace remote and operator.env consistently. / Modificare modelli, remoto e operator.env in modo coerente.\n2. Add one database bootstrap entry for every workspace; use read-only DWH credentials in protected files. / Una voce database per workspace, credenziali DWH in sola lettura in file protetti.\n3. Run tht installation credentials --directory PATH before setup; fill provider/database secrets yourself. / Generare credenziali tecniche prima del setup; compilare i segreti esterni.\n4. Repeat tht --installation PATH/thothii-installation.yaml installation validate --workspaces WORKSPACES. / Correggere e ripetere.\n\nNo services, network calls or database writes / Nessun servizio, chiamata di rete o scrittura database.\n", } for _, name := range []string{".gitignore", "thothii-installation.yaml", "operator.env", "database-bootstrap.yaml", "README.md"} { if err := safeio.WriteCanonicalNewPrivateFile(filepath.Join(directory, name), []byte(strings.TrimSpace(documents[name])+"\n"), 0o600); err != nil { return fmt.Errorf("cannot create preparation files; inspect the new directory and retry in a new destination") } } return nil }