feat(scum): wire platform schema probe jobs

This commit is contained in:
npc0-hue
2026-08-12 11:06:14 +08:00
parent 6d4319187f
commit 2638eda55b
15 changed files with 405 additions and 13 deletions
+2 -1
View File
@@ -189,6 +189,7 @@ type RunJobExecutionResultBody struct {
SizeBytes int64 `json:"sizeBytes,omitempty"`
AuditSummary string `json:"auditSummary,omitempty"`
Content string `json:"content,omitempty"`
SQLiteSchemaProbe *SCUMSchemaProbeResultDTO `json:"sqliteSchemaProbe,omitempty"`
ServerDeploymentEvidence *ServerDeploymentEvidenceBody `json:"serverDeploymentEvidence,omitempty"`
DeploymentReceipt *ServerDeploymentExecutionReceiptBody `json:"deploymentReceipt,omitempty"`
}
@@ -448,7 +449,7 @@ func (request RunJobResultRequest) ToDomain() domain.RunJobResult {
Message: request.Message,
ErrorCode: request.ErrorCode,
Retryable: request.Retryable,
ExecutionResult: domain.JobExecutionResult{Kind: request.ExecutionResult.Kind, ProcessState: request.ExecutionResult.ProcessState, ExitClassification: request.ExecutionResult.ExitClassification, ExitCode: request.ExecutionResult.ExitCode, Version: request.ExecutionResult.Version, Checksum: request.ExecutionResult.Checksum, SizeBytes: request.ExecutionResult.SizeBytes, AuditSummary: request.ExecutionResult.AuditSummary, Content: request.ExecutionResult.Content, ServerDeploymentEvidence: serverDeploymentEvidenceToDomain(request.ExecutionResult.ServerDeploymentEvidence), DeploymentReceipt: deploymentReceiptToDomain(request.ExecutionResult.DeploymentReceipt)},
ExecutionResult: domain.JobExecutionResult{Kind: request.ExecutionResult.Kind, ProcessState: request.ExecutionResult.ProcessState, ExitClassification: request.ExecutionResult.ExitClassification, ExitCode: request.ExecutionResult.ExitCode, Version: request.ExecutionResult.Version, Checksum: request.ExecutionResult.Checksum, SizeBytes: request.ExecutionResult.SizeBytes, AuditSummary: request.ExecutionResult.AuditSummary, Content: request.ExecutionResult.Content, SQLiteSchemaProbe: SCUMSchemaProbeResultPtrToDomain(request.ExecutionResult.SQLiteSchemaProbe), ServerDeploymentEvidence: serverDeploymentEvidenceToDomain(request.ExecutionResult.ServerDeploymentEvidence), DeploymentReceipt: deploymentReceiptToDomain(request.ExecutionResult.DeploymentReceipt)},
}
}
+2 -1
View File
@@ -884,6 +884,7 @@ type JobExecutionResultResponse struct {
Checksum string `json:"checksum,omitempty"`
SizeBytes int64 `json:"sizeBytes,omitempty"`
AuditSummary string `json:"auditSummary,omitempty"`
SQLiteSchemaProbe *SCUMSchemaProbeResultDTO `json:"sqliteSchemaProbe,omitempty"`
ServerDeploymentEvidence *ServerDeploymentEvidenceBody `json:"serverDeploymentEvidence,omitempty"`
}
@@ -1930,7 +1931,7 @@ func JobFromDomain(job domain.Job) JobResponse {
State: job.State,
Progress: progressFromDomain(job.Progress),
ResultRef: job.ResultRef,
ExecutionResult: JobExecutionResultResponse{Kind: job.ExecutionResult.Kind, ProcessState: job.ExecutionResult.ProcessState, ExitClassification: job.ExecutionResult.ExitClassification, ExitCode: job.ExecutionResult.ExitCode, Version: job.ExecutionResult.Version, Checksum: job.ExecutionResult.Checksum, SizeBytes: job.ExecutionResult.SizeBytes, AuditSummary: job.ExecutionResult.AuditSummary, ServerDeploymentEvidence: serverDeploymentEvidenceFromDomain(job.ExecutionResult.ServerDeploymentEvidence)},
ExecutionResult: JobExecutionResultResponse{Kind: job.ExecutionResult.Kind, ProcessState: job.ExecutionResult.ProcessState, ExitClassification: job.ExecutionResult.ExitClassification, ExitCode: job.ExecutionResult.ExitCode, Version: job.ExecutionResult.Version, Checksum: job.ExecutionResult.Checksum, SizeBytes: job.ExecutionResult.SizeBytes, AuditSummary: job.ExecutionResult.AuditSummary, SQLiteSchemaProbe: SCUMSchemaProbeResultPtrFromDomain(job.ExecutionResult.SQLiteSchemaProbe), ServerDeploymentEvidence: serverDeploymentEvidenceFromDomain(job.ExecutionResult.ServerDeploymentEvidence)},
RetryPolicy: JobRetryPolicyResponse{
MaxAttempts: job.RetryPolicy.MaxAttempts,
InitialBackoffSeconds: job.RetryPolicy.InitialBackoffSeconds,
+34
View File
@@ -31,6 +31,40 @@ func TestAIProviderResponseExposesOnlySecretPresence(t *testing.T) {
}
}
func TestRunJobResultRequestParsesSQLiteSchemaProbeEnvelope(t *testing.T) {
payload := `{
"runEndpointId":"run-local",
"sessionToken":"run-session",
"jobId":"job-probe",
"leaseToken":"lease-probe",
"attempt":1,
"state":"succeeded",
"progress":{"percent":100,"message":"done"},
"executionResult":{
"kind":"sqlite.schema.probe",
"sqliteSchemaProbe":{
"requestId":"job-probe",
"jobId":"job-probe",
"binding":{"serverInstanceId":"server-scum","runBindingId":"runtime-binding-server-scum","runEndpointId":"run-local","pluginId":"server.scum","pluginVersion":"1.0.0","adapterVersion":"scum-live-data-v0","gameVersion":"1.0.0","databaseIdentity":"logical:scum-database"},
"status":"compatible",
"schemaFingerprint":"sha256:` + strings.Repeat("a", 64) + `",
"observedAt":"2026-08-12T00:00:00Z",
"resultDigest":"sha256:` + strings.Repeat("b", 64) + `",
"limits":{"maxObjects":256,"maxColumnsPerObject":128,"maxIndexesPerObject":64,"maxForeignKeys":64,"maxCardinalityReads":64,"maxSampleRows":3,"timeoutMs":5000,"maxResultBytes":524288}
}
}
}`
var request RunJobResultRequest
if err := json.Unmarshal([]byte(payload), &request); err != nil {
t.Fatalf("unmarshal Run job result: %v", err)
}
domainRequest := request.ToDomain()
probe := domainRequest.ExecutionResult.SQLiteSchemaProbe
if probe == nil || probe.JobID != "job-probe" || probe.Binding.DatabaseIdentity != "logical:scum-database" || probe.ResultDigest != "sha256:"+strings.Repeat("b", 64) {
t.Fatalf("sqliteSchemaProbe envelope did not parse: %+v", probe)
}
}
func TestAIProviderFromDomainCopiesModels(t *testing.T) {
provider := domain.AIProvider{
ID: "ai.openai",
+36
View File
@@ -98,6 +98,34 @@ func SCUMSchemaProbeRequestToDomain(value SCUMSchemaProbeRequestDTO) domain.SCUM
return domain.SCUMSchemaProbeRequest{RequestID: value.RequestID, JobID: value.JobID, Binding: scumBindingIdentityToDomain(value.Binding), Bounds: scumProbeBoundsToDomain(value.Bounds), RequestedAt: value.RequestedAt}
}
func SCUMSchemaProbeResultToDomain(value SCUMSchemaProbeResultDTO) domain.SCUMSchemaProbeResult {
objects := make([]domain.SCUMSchemaObjectEvidence, len(value.Objects))
for index, object := range value.Objects {
columns := make([]domain.SCUMSchemaColumnEvidence, len(object.DeclaredColumns))
for i, column := range object.DeclaredColumns {
columns[i] = domain.SCUMSchemaColumnEvidence{NameFingerprint: column.NameFingerprint, DeclaredType: column.DeclaredType, Nullable: column.Nullable, PrimaryKey: column.PrimaryKey, Ordinal: column.Ordinal}
}
indexes := make([]domain.SCUMSchemaIndexEvidence, len(object.Indexes))
for i, item := range object.Indexes {
indexes[i] = domain.SCUMSchemaIndexEvidence{NameFingerprint: item.NameFingerprint, Unique: item.Unique, ColumnHashes: append([]string(nil), item.ColumnHashes...)}
}
foreignKeys := make([]domain.SCUMSchemaForeignKeyEvidence, len(object.ForeignKeys))
for i, item := range object.ForeignKeys {
foreignKeys[i] = domain.SCUMSchemaForeignKeyEvidence{FromColumnHash: item.FromColumnHash, ToObjectHash: item.ToObjectHash, ToColumnHash: item.ToColumnHash}
}
objects[index] = domain.SCUMSchemaObjectEvidence{ObjectHash: object.ObjectHash, Kind: object.Kind, NameFingerprint: object.NameFingerprint, DeclaredColumns: columns, Indexes: indexes, ForeignKeys: foreignKeys, ApproximateRows: object.ApproximateRows, SampleFingerprints: append([]string(nil), object.SampleFingerprints...)}
}
return domain.SCUMSchemaProbeResult{RequestID: value.RequestID, JobID: value.JobID, Binding: scumBindingIdentityToDomain(value.Binding), Status: domain.SCUMCapabilityEvidenceStatus(value.Status), SchemaFingerprint: value.SchemaFingerprint, ObservedAt: value.ObservedAt, ResultDigest: value.ResultDigest, Objects: objects, SafeError: domain.SCUMSafeError{Code: domain.SCUMSafeErrorCode(value.SafeError.Code), Message: value.SafeError.Message, Retryable: value.SafeError.Retryable}, Limits: scumProbeBoundsToDomain(value.Limits)}
}
func SCUMSchemaProbeResultPtrToDomain(value *SCUMSchemaProbeResultDTO) *domain.SCUMSchemaProbeResult {
if value == nil {
return nil
}
result := SCUMSchemaProbeResultToDomain(*value)
return &result
}
func SCUMSchemaProbeResultFromDomain(value domain.SCUMSchemaProbeResult) SCUMSchemaProbeResultDTO {
value = domain.CopySCUMSchemaProbeResult(value)
objects := make([]SCUMSchemaObjectEvidenceDTO, len(value.Objects))
@@ -119,6 +147,14 @@ func SCUMSchemaProbeResultFromDomain(value domain.SCUMSchemaProbeResult) SCUMSch
return SCUMSchemaProbeResultDTO{RequestID: value.RequestID, JobID: value.JobID, Binding: scumBindingIdentityFromDomain(value.Binding), Status: string(value.Status), SchemaFingerprint: value.SchemaFingerprint, ObservedAt: value.ObservedAt, ResultDigest: value.ResultDigest, Objects: objects, SafeError: SCUMSafeErrorDTO{Code: string(value.SafeError.Code), Message: value.SafeError.Message, Retryable: value.SafeError.Retryable}, Limits: scumProbeBoundsFromDomain(value.Limits)}
}
func SCUMSchemaProbeResultPtrFromDomain(value *domain.SCUMSchemaProbeResult) *SCUMSchemaProbeResultDTO {
if value == nil {
return nil
}
result := SCUMSchemaProbeResultFromDomain(*value)
return &result
}
func SCUMCapabilityGateFromDomain(value domain.SCUMCapabilityGate) SCUMCapabilityGateDTO {
return SCUMCapabilityGateDTO{Capability: string(value.Capability), State: string(value.State), Enabled: value.Enabled, ReasonCode: string(value.ReasonCode), Reason: value.Reason}
}