feat: operator schema accept command for curated FK review (P5)

This commit is contained in:
2026-08-13 05:06:23 +02:00
parent 5249798c03
commit 0459a6cd3e
9 changed files with 293 additions and 1 deletions
+1
View File
@@ -56,6 +56,7 @@ Commands:
workspace preprocess dwh --workspace ID [--resume RUN] [--json]
workspace schema suggest-fks --workspace ID [--from-sql FILE]... [--assume COLUMN=TABLE]... [--output FILE] [--json]
workspace schema check --workspace ID [--annotations FILE --reviewed-candidates sha256:HEX] [--json]
workspace schema accept --workspace ID --run RUN --yes [--json]
workspace index-schema --workspace ID [--json]
workspace preprocess evidence --workspace ID [--dry-run] [--resume RUN] [--json]
workspace preprocess run --workspace ID [--resume RUN] [--json]
@@ -71,6 +71,12 @@ type CheckSchemaRequest struct {
ReviewedCandidates string
}
type AcceptSchemaRequest struct {
baseRequest
Run string
Yes bool
}
type IndexSchemaRequest struct{ baseRequest }
type EvidenceRequest struct {
@@ -88,6 +94,7 @@ func (InspectRequest) workspaceRequest() {}
func (DwhRequest) workspaceRequest() {}
func (SuggestFksRequest) workspaceRequest() {}
func (CheckSchemaRequest) workspaceRequest() {}
func (AcceptSchemaRequest) workspaceRequest() {}
func (IndexSchemaRequest) workspaceRequest() {}
func (EvidenceRequest) workspaceRequest() {}
func (RunRequest) workspaceRequest() {}
@@ -98,6 +105,7 @@ func (SuggestFksRequest) operatorCommand() string { return "schema-suggest-fks"
func (CheckSchemaRequest) operatorCommand() string {
return "schema-check"
}
func (AcceptSchemaRequest) operatorCommand() string { return "schema-accept" }
func (IndexSchemaRequest) operatorCommand() string { return "index-schema" }
func (EvidenceRequest) operatorCommand() string { return "preprocess-evidence" }
func (RunRequest) operatorCommand() string { return "preprocess-run" }
@@ -144,6 +152,10 @@ func (r IndexSchemaRequest) stdinEnvelope() (requestEnvelope, error) {
return requestEnvelope{SchemaVersion: 1, WorkspaceID: r.Workspace}, nil
}
func (r AcceptSchemaRequest) stdinEnvelope() (requestEnvelope, error) {
return requestEnvelope{SchemaVersion: 1, WorkspaceID: r.Workspace, RunID: r.Run, Yes: r.Yes}, nil
}
func (r EvidenceRequest) stdinEnvelope() (requestEnvelope, error) {
return requestEnvelope{SchemaVersion: 1, WorkspaceID: r.Workspace, Resume: r.Resume, DryRun: r.DryRun}, nil
}
@@ -164,6 +176,8 @@ type requestEnvelope struct {
Collection string `json:"collection,omitempty"`
Confirm string `json:"confirm,omitempty"`
Destroy bool `json:"destroy,omitempty"`
RunID string `json:"runId,omitempty"`
Yes bool `json:"yes,omitempty"`
}
type inputFile struct {
@@ -464,6 +478,8 @@ func parseSchema(args []string) (Request, error) {
return parseSuggestFks(args[1:])
case "check":
return parseSchemaCheck(args[1:])
case "accept":
return parseSchemaAccept(args[1:])
default:
return nil, fmt.Errorf("unknown workspace schema command %q", args[0])
}
@@ -588,6 +604,44 @@ func parseSchemaCheck(args []string) (CheckSchemaRequest, error) {
return request, nil
}
func parseSchemaAccept(args []string) (AcceptSchemaRequest, error) {
request := AcceptSchemaRequest{}
base, seen, err := parseSharedFlags(args, map[string]func(string) error{
"--run": func(value string) error {
if request.Run != "" {
return errors.New("--run may be supplied once")
}
if !runIDPattern.MatchString(value) {
return errors.New("--run must be 32 lowercase hex characters")
}
request.Run = value
return nil
},
}, map[string]func() error{
"--yes": func() error {
if request.Yes {
return errors.New("--yes may be supplied once")
}
request.Yes = true
return nil
},
})
if err != nil {
return AcceptSchemaRequest{}, err
}
if !seen.workspace {
return AcceptSchemaRequest{}, errors.New("--workspace is required")
}
if request.Run == "" {
return AcceptSchemaRequest{}, errors.New("--run is required")
}
if !request.Yes {
return AcceptSchemaRequest{}, errors.New("--yes is required")
}
request.baseRequest = base
return request, nil
}
func parseBaseFlags(args []string, allowDryRun bool) (baseRequest, error) {
base, seen, err := parseSharedFlags(args, nil, nil)
if err != nil {
@@ -268,3 +268,38 @@ func TestParseVectorUnknownSubcommand(t *testing.T) {
t.Fatal("expected error for unknown vector command")
}
}
func TestParseSchemaAccept(t *testing.T) {
req, err := Parse([]string{"schema", "accept", "--workspace", "psd", "--run", strings.Repeat("d", 32), "--yes"})
if err != nil {
t.Fatalf("parse: %v", err)
}
r, ok := req.(AcceptSchemaRequest)
if !ok {
t.Fatalf("got %T", req)
}
if r.Workspace != "psd" || r.Run != strings.Repeat("d", 32) || !r.Yes {
t.Fatalf("unexpected request: %+v", r)
}
env, err := req.stdinEnvelope()
if err != nil {
t.Fatalf("envelope: %v", err)
}
if env.WorkspaceID != "psd" || env.RunID != strings.Repeat("d", 32) || !env.Yes {
t.Fatalf("unexpected envelope: %+v", env)
}
}
func TestParseSchemaAcceptRequiresRunAndYes(t *testing.T) {
for _, args := range [][]string{
{"schema", "accept", "--workspace", "psd"},
{"schema", "accept", "--workspace", "psd", "--yes"},
{"schema", "accept", "--workspace", "psd", "--run", strings.Repeat("d", 32)},
{"schema", "accept", "--workspace", "psd", "--run", "not-hex", "--yes"},
{"schema", "accept", "--workspace", "psd", "--run", strings.Repeat("d", 32), "--yes", "--run", strings.Repeat("e", 32)},
} {
if _, err := Parse(args); err == nil {
t.Fatalf("expected error for %v", args)
}
}
}