Publish documentation / publish (push) Successful in 1m27s
Add PostgreSQL-backed memory, editable evidence with source review and activation, and human-approved archive repairs across the harness, API, and UI. Include migrations, deployment support, regression coverage, and validation documentation. Refresh permissions from validated session roles so existing administrator logins can access newly deployed archive management features.
193 lines
6.4 KiB
Go
193 lines
6.4 KiB
Go
package workspaceops
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/aritmolab/thothii/tools/tht/internal/compose"
|
|
"github.com/aritmolab/thothii/tools/tht/internal/config"
|
|
)
|
|
|
|
type fakeRunner struct {
|
|
run func(args []string, stdin string) (compose.Result, error)
|
|
all [][]string
|
|
stdins []string
|
|
}
|
|
|
|
func TestEvidenceConsolidationUsesClosedMaintenanceContract(t *testing.T) {
|
|
request, err := Parse([]string{"evidence", "consolidate", "--workspace", "sales", "--json"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if request.operatorCommand() != "evidence-consolidate" || !request.JSONMode() {
|
|
t.Fatal("incorrect command")
|
|
}
|
|
envelope, err := request.stdinEnvelope()
|
|
if err != nil || envelope.WorkspaceID != "sales" {
|
|
t.Fatal("incorrect workspace envelope")
|
|
}
|
|
if _, err := Parse([]string{"evidence", "consolidate", "--workspace", "../foreign"}); err == nil {
|
|
t.Fatal("accepted an unsafe workspace")
|
|
}
|
|
}
|
|
|
|
func (r *fakeRunner) Run(_ context.Context, args []string, stdin io.Reader) (compose.Result, error) {
|
|
payload := ""
|
|
if stdin != nil {
|
|
contents, err := io.ReadAll(stdin)
|
|
if err != nil {
|
|
return compose.Result{}, err
|
|
}
|
|
payload = string(contents)
|
|
}
|
|
r.all = append(r.all, append([]string(nil), args...))
|
|
r.stdins = append(r.stdins, payload)
|
|
return r.run(args, payload)
|
|
}
|
|
|
|
func TestExecuteRunSendsOnlyTheOneShotEnvelope(t *testing.T) {
|
|
installation := testInstallation(t)
|
|
runner := &fakeRunner{run: func(args []string, stdin string) (compose.Result, error) {
|
|
switch {
|
|
case contains(args, "config", "--format", "json"):
|
|
return compose.Result{Stdout: `{"services":{"core":{"image":"thothii-core:local"}}}`}, nil
|
|
case reflect.DeepEqual(args, []string{"image", "inspect", "--format", "{{.Id}}", "thothii-core:local"}):
|
|
return compose.Result{Stdout: "sha256:" + strings.Repeat("a", 64)}, nil
|
|
case contains(args, "workspace-maintenance", "preprocess-run"):
|
|
var envelope map[string]any
|
|
if err := json.Unmarshal([]byte(stdin), &envelope); err != nil {
|
|
t.Fatalf("stdin JSON = %q, err=%v", stdin, err)
|
|
}
|
|
if !reflect.DeepEqual(envelope, map[string]any{
|
|
"schemaVersion": float64(1),
|
|
"workspaceId": "abc",
|
|
}) {
|
|
t.Fatalf("unexpected envelope: %#v", envelope)
|
|
}
|
|
return compose.Result{Stdout: successResult("preprocess run")}, nil
|
|
default:
|
|
t.Fatalf("unexpected Docker invocation: %#v", args)
|
|
return compose.Result{}, nil
|
|
}
|
|
}}
|
|
|
|
result, err := Execute(
|
|
context.Background(),
|
|
installation,
|
|
runner,
|
|
RunRequest{baseRequest: baseRequest{Workspace: "abc", JSON: true}},
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("Execute() error = %v", err)
|
|
}
|
|
if result.Status != "succeeded" || result.Operation != "preprocess run" {
|
|
t.Fatalf("unexpected result: %#v", result)
|
|
}
|
|
}
|
|
|
|
func TestParseAcceptsOnlyInspectAndCompletePreprocessing(t *testing.T) {
|
|
for _, args := range [][]string{
|
|
{"inspect", "--workspace", "abc", "--json"},
|
|
{"preprocess", "run", "--workspace", "abc", "--json"},
|
|
{"preprocess", "clear", "--workspace", "abc", "--json"},
|
|
} {
|
|
if _, err := Parse(args); err != nil {
|
|
t.Fatalf("Parse(%v) error = %v", args, err)
|
|
}
|
|
}
|
|
|
|
retired := [][]string{
|
|
{"preprocess", "dwh", "--workspace", "abc"},
|
|
{"preprocess", "evidence", "--workspace", "abc"},
|
|
{"preprocess", "run", "--workspace", "abc", "--resume", strings.Repeat("a", 32)},
|
|
{"preprocess", "run", "--workspace", "abc", "--dry-run"},
|
|
{"schema", "suggest-fks", "--workspace", "abc"},
|
|
{"schema", "check", "--workspace", "abc"},
|
|
{"schema", "accept", "--workspace", "abc"},
|
|
{"index-schema", "--workspace", "abc"},
|
|
{"vector", "inspect", "--workspace", "abc"},
|
|
{"vector", "rebuild", "--workspace", "abc"},
|
|
}
|
|
for _, args := range retired {
|
|
if _, err := Parse(args); err == nil {
|
|
t.Fatalf("retired command accepted: %v", args)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testInstallation(t *testing.T) config.Installation {
|
|
t.Helper()
|
|
temporaryRoot, err := filepath.EvalSymlinks(os.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
root, err := os.MkdirTemp(temporaryRoot, "tht-workspaceops-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { _ = os.RemoveAll(root) })
|
|
project := filepath.Join(root, "project")
|
|
if err := os.MkdirAll(filepath.Join(project, "deploy"), 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(project, "compose.yaml"), []byte("services: {}\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(project, "deploy", "compose.local.yaml"), []byte("services: {}\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
envFile := filepath.Join(root, "installation.env")
|
|
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,
|
|
}
|
|
}
|
|
|
|
func contains(values []string, sequence ...string) bool {
|
|
for start := range values {
|
|
if start+len(sequence) <= len(values) && reflect.DeepEqual(values[start:start+len(sequence)], sequence) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func successResult(operation string) string {
|
|
return `{"schemaVersion":1,"status":"succeeded","code":"ok","workspaceId":"abc","workspaceRevision":"1234567890abcdef1234567890abcdef12345678","descriptorBlob":"sha256:` + strings.Repeat("f", 64) + `","operation":"` + operation + `","completedStages":[]}`
|
|
}
|
|
|
|
func TestEvidenceSourceCommandsAreClosedAndCarryReviewIdentity(t *testing.T) {
|
|
request, err := Parse([]string{"evidence", "refresh", "--workspace", "sales", "--json"})
|
|
if err != nil || request.operatorCommand() != "evidence-refresh" {
|
|
t.Fatalf("refresh: %v", err)
|
|
}
|
|
args := []string{"evidence", "decide", "--workspace", "sales", "--source-id", strings.Repeat("a", 64), "--revision", strings.Repeat("b", 64), "--decision", "keep"}
|
|
request, err = Parse(args)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
envelope, _ := request.stdinEnvelope()
|
|
if envelope.SourceID != strings.Repeat("a", 64) || envelope.Decision != "keep" || request.operatorCommand() != "evidence-decide" {
|
|
t.Fatal("review identity lost")
|
|
}
|
|
for _, invalid := range [][]string{
|
|
{"evidence", "refresh", "--workspace", "sales", "--url", "http://localhost"},
|
|
{"evidence", "decide", "--workspace", "sales"},
|
|
append(append([]string{}, args...), "--decision", "replace"),
|
|
{"evidence", "consolidate", "--workspace", "sales", "--source-id", strings.Repeat("a", 64)},
|
|
} {
|
|
if _, err := Parse(invalid); err == nil {
|
|
t.Fatalf("accepted invalid flags: %v", invalid)
|
|
}
|
|
}
|
|
}
|