feat: unify installation model catalog

This commit is contained in:
Codex
2026-09-02 18:45:33 +02:00
parent ae053961a3
commit 7b7927bfe5
169 changed files with 3696 additions and 4572 deletions
+9 -1
View File
@@ -15,6 +15,7 @@ import (
"github.com/aritmolab/thothii/tools/tht/internal/authconfig"
"github.com/aritmolab/thothii/tools/tht/internal/compose"
"github.com/aritmolab/thothii/tools/tht/internal/config"
"github.com/aritmolab/thothii/tools/tht/internal/modelprojection"
"github.com/aritmolab/thothii/tools/tht/internal/output"
"github.com/aritmolab/thothii/tools/tht/internal/pi"
"github.com/aritmolab/thothii/tools/tht/internal/service"
@@ -101,7 +102,7 @@ func RunWithProbe(ctx context.Context, installation config.Installation, runner
return Report{}, errors.New("doctor requires an HTTP probe")
}
secretValues, secretErr := secretValues(installation)
report := Report{Checks: make([]Check, 0, 12)}
report := Report{Checks: make([]Check, 0, 13)}
add := func(name, status, detail string) {
report.Checks = append(report.Checks, Check{Name: name, Status: status, Detail: output.SanitizeDetail(detail, secretValues)})
}
@@ -111,6 +112,13 @@ func RunWithProbe(ctx context.Context, installation config.Installation, runner
} else {
add("descriptor", StatusPassed, "installation descriptor is loaded")
}
if drift, err := modelprojection.Check(installation); err != nil {
add("model-projection", StatusFailed, "model runtime projections could not be recomputed")
} else if len(drift) > 0 {
add("model-projection", StatusFailed, "generated model runtime projections differ: "+strings.Join(drift, ", "))
} else {
add("model-projection", StatusPassed, "generated model runtime projections match modelCatalog")
}
if err := filePermissions(installation); err != nil || secretErr != nil {
if secretErr != nil {
add("files", StatusFailed, "declared secret files could not be read")
+9 -4
View File
@@ -11,6 +11,7 @@ import (
"github.com/aritmolab/thothii/tools/tht/internal/compose"
"github.com/aritmolab/thothii/tools/tht/internal/config"
"github.com/aritmolab/thothii/tools/tht/internal/modelprojection"
)
// Catches treating an unavailable Docker executable as a successful diagnosis.
@@ -132,7 +133,7 @@ func TestRunFailsAuthenticationWithoutExecWhenCoreIsRunningButUnhealthy(t *testi
if report.OK || checkStatus(report, "authentication") != StatusFailed {
t.Fatalf("Run() report = %#v, want deterministic failed authentication", report)
}
assertChecklist(t, report, []string{"descriptor", "files", "docker", "compose", "configuration", "authentication", "services", "core-http", "frontend-http", "workspace-registry", "workflow", "pi"})
assertChecklist(t, report, []string{"descriptor", "model-projection", "files", "docker", "compose", "configuration", "authentication", "services", "core-http", "frontend-http", "workspace-registry", "workflow", "pi"})
if strings.Contains(strings.Join(runner.calls, "\n"), " exec -T ") {
t.Fatalf("Run() invoked exec -T while core was unhealthy: %v", runner.calls)
}
@@ -170,7 +171,7 @@ func TestRunUsesOnlyContainerLocalWorkflowAndPiDiagnosticsWhenCoreRuns(t *testin
if !report.OK || checkStatus(report, "authentication") != "passed" || checkStatus(report, "workflow") != "passed" || checkStatus(report, "pi") != "passed" {
t.Fatalf("Run() report = %#v, want successful container diagnostics", report)
}
assertChecklist(t, report, []string{"descriptor", "files", "docker", "compose", "configuration", "authentication", "services", "core-http", "frontend-http", "workspace-registry", "workflow", "pi"})
assertChecklist(t, report, []string{"descriptor", "model-projection", "files", "docker", "compose", "configuration", "authentication", "services", "core-http", "frontend-http", "workspace-registry", "workflow", "pi"})
calls := strings.Join(runner.calls, "\n")
if !strings.Contains(calls, "exec -T core node dist/auth/diagnostic-command.js --json") {
t.Fatalf("Run() calls = %s, want core-local authentication diagnostic", calls)
@@ -261,7 +262,7 @@ func TestRunFailsBeforeDockerWhenDeclaredSecretCorpusIsIncomplete(t *testing.T)
if strings.Contains(reportText(report), missing) {
t.Fatalf("incomplete corpus report exposed a secret path: %#v", report)
}
assertChecklist(t, report, []string{"descriptor", "files", "docker", "compose", "configuration", "authentication", "services", "core-http", "frontend-http", "workspace-registry", "workflow", "pi"})
assertChecklist(t, report, []string{"descriptor", "model-projection", "files", "docker", "compose", "configuration", "authentication", "services", "core-http", "frontend-http", "workspace-registry", "workflow", "pi"})
}
func doctorInstallation(t *testing.T, _ string) config.Installation {
@@ -290,7 +291,11 @@ func doctorInstallation(t *testing.T, _ string) config.Installation {
if err := os.WriteFile(envFile, []byte("SAFE_VALUE=1\n"), 0o600); err != nil {
t.Fatal(err)
}
return config.Installation{Path: filepath.Join(root, "thothii-installation.yaml"), Profile: "local", ProjectDirectory: project, EnvFile: envFile}
installation := config.Installation{Path: filepath.Join(root, "thothii-installation.yaml"), Profile: "local", ProjectDirectory: project, EnvFile: envFile}
if err := modelprojection.Generate(installation); err != nil {
t.Fatal(err)
}
return installation
}
type doctorRunner struct {