Feat: add POSIX-lite bootstrap foundation

This commit is contained in:
MangoPig
2026-06-21 21:02:59 +01:00
parent 626ae02df0
commit 5735e3008d
14 changed files with 385 additions and 10 deletions

View File

@@ -0,0 +1,113 @@
package bootstrap
import (
"encoding/json"
"os"
"path/filepath"
"testing"
)
func TestEnsureBootstrapPOSIXSkeletonInitializesEmptyRoot(t *testing.T) {
rootPath := filepath.Join(t.TempDir(), "POSIX")
t.Setenv("POSIX_ROOT", rootPath)
if _, err := os.Stat(rootPath); !os.IsNotExist(err) {
t.Fatalf("expected isolated POSIX root to start absent, got err=%v", err)
}
service := NewService(nil, os.Getenv("POSIX_ROOT"))
err := service.ensureBootstrapPOSIXSkeleton(
InstallationRecord{
ID: "installation-1",
Name: "MangoPig",
Mode: "personal",
Access: "local",
Protocol: "http",
Host: "localhost",
IsBootstrapped: true,
},
AdminSummary{
ID: "admin-1",
Email: "ronald@example.com",
DisplayName: "Ronald",
},
namedRecord{ID: "org-1", Name: "Primary Organization", Slug: "primary-organization"},
namedRecord{ID: "dept-1", Name: "Primary Department", Slug: "primary-department"},
namedRecord{ID: "team-1", Name: "Primary Team", Slug: "primary-team"},
namedRecord{ID: "project-1", Name: "Primary Project", Slug: "primary-project"},
)
if err != nil {
t.Fatalf("ensure bootstrap POSIX skeleton: %v", err)
}
requiredPaths := []string{
filepath.Join(rootPath, "settings.json"),
filepath.Join(rootPath, "layout.json"),
filepath.Join(rootPath, "catalog", "packs"),
filepath.Join(rootPath, "catalog", "standalone"),
filepath.Join(rootPath, "departments", "department-primary-department", "settings.json"),
filepath.Join(rootPath, "departments", "department-primary-department", "users.json"),
filepath.Join(rootPath, "departments", "department-primary-department", "teams", "team-primary-team", "settings.json"),
filepath.Join(rootPath, "departments", "department-primary-department", "teams", "team-primary-team", "users.json"),
filepath.Join(rootPath, "projects", "project-primary-project", "settings.json"),
filepath.Join(rootPath, "projects", "project-primary-project", "home.json"),
filepath.Join(rootPath, "projects", "project-primary-project", "tree"),
filepath.Join(rootPath, "users", "settings.json"),
filepath.Join(rootPath, "users", "data.json"),
filepath.Join(rootPath, "users", "personals"),
}
for _, path := range requiredPaths {
if _, err := os.Stat(path); err != nil {
t.Fatalf("expected path to exist %s: %v", path, err)
}
}
settingsPayload := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "settings.json"))
installationPayload, ok := settingsPayload["installation"].(map[string]any)
if !ok {
t.Fatalf("settings.json missing installation object: %#v", settingsPayload)
}
if installationPayload["name"] != "MangoPig" {
t.Fatalf("expected installation name MangoPig, got %#v", installationPayload["name"])
}
if installationPayload["isBootstrapped"] != true {
t.Fatalf("expected installation to be bootstrapped, got %#v", installationPayload["isBootstrapped"])
}
layoutPayload := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "layout.json"))
homePayload, ok := layoutPayload["home"].(map[string]any)
if !ok {
t.Fatalf("layout.json missing home object: %#v", layoutPayload)
}
if homePayload["defaultProjectSlug"] != "primary-project" {
t.Fatalf("expected default project slug primary-project, got %#v", homePayload["defaultProjectSlug"])
}
projectSettings := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "projects", "project-primary-project", "settings.json"))
if projectSettings["type"] != "project" {
t.Fatalf("expected project settings type project, got %#v", projectSettings["type"])
}
usersSettings := readJSONFileForTest[map[string]any](t, filepath.Join(rootPath, "users", "settings.json"))
if usersSettings["primaryAdminId"] != "admin-1" {
t.Fatalf("expected primary admin id admin-1, got %#v", usersSettings["primaryAdminId"])
}
}
func readJSONFileForTest[T any](t *testing.T, path string) T {
t.Helper()
data, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read %s: %v", path, err)
}
var payload T
if err := json.Unmarshal(data, &payload); err != nil {
t.Fatalf("unmarshal %s: %v", path, err)
}
return payload
}