Freeze SCUM SQLite template run contract
This commit is contained in:
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"browser.local/platform/domain"
|
||||
)
|
||||
@@ -212,6 +213,41 @@ func TestCoreServiceRunJobTerminalResultIsIdempotent(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceRunJobSQLiteTemplateEnvelopeIsFencedToLease(t *testing.T) {
|
||||
svc, sessionToken := newRegisteredRunJobService(t)
|
||||
request := domain.SCUMSQLiteTemplateRequest{RequestID: "request-query", JobID: "job-query", Binding: scumTemplateTestBinding(), Capability: domain.SCUMDataCapabilityPlayerRead, TargetKey: "scum-database", TemplateKey: "players.active.v1", AdapterVersion: "adapter-1", RequiredSchemaFingerprint: scumTemplateTestHash(), AssetDigest: scumTemplateTestHash(), ParameterDigest: scumTemplateTestHash(), Parameters: map[string]any{"limit": 100.0}, Bounds: domain.DefaultSCUMSQLiteTemplateBounds(), RequestedAt: time.Now()}
|
||||
createSCUMTemplateServerFixture(t, svc, request.Binding)
|
||||
job, err := svc.CreateJob(domain.Job{ID: request.JobID, ServerInstanceID: request.Binding.ServerInstanceID, RunEndpointID: request.Binding.RunEndpointID, Capability: domain.JobCapabilityRemoteRunDBSQLiteQuery, TargetKey: request.TargetKey, InputRef: "input://sqlite-template/request-query", IdempotencyKey: "idem-query", ExecutionInput: domain.JobExecutionInput{SQLiteTemplate: &request}})
|
||||
if err != nil {
|
||||
t.Fatalf("create sqlite query job: %v", err)
|
||||
}
|
||||
claim, err := svc.ClaimRunJob(domain.RunJobClaim{RunEndpointID: request.Binding.RunEndpointID, SessionToken: sessionToken, Capabilities: []string{domain.JobCapabilityRemoteRunDBSQLiteQuery}, Capacity: domain.RunCapacity{MaxJobs: 4}})
|
||||
if err != nil || !claim.HasJob || claim.Job.JobID != job.ID || claim.Job.ExecutionInput.SQLiteTemplate == nil {
|
||||
t.Fatalf("claim sqlite query job: claim=%+v err=%v", claim, err)
|
||||
}
|
||||
result := scumTemplateTestResult(request)
|
||||
if _, err := svc.CompleteRunJob(domain.RunJobResult{RunEndpointID: request.Binding.RunEndpointID, SessionToken: sessionToken, JobID: claim.Job.JobID, LeaseToken: claim.Job.LeaseToken, Attempt: claim.Job.Attempt, State: domain.JobStateSucceeded, Progress: domain.RunJobProgressReport{Percent: 100, Message: "query complete"}, Message: "query complete", ExecutionResult: domain.JobExecutionResult{Kind: scumSQLiteTemplateExecutionKind, SQLiteTemplate: &result, AuditSummary: "redacted sqlite template query"}}); err != nil {
|
||||
t.Fatalf("complete matching sqlite query: %v", err)
|
||||
}
|
||||
|
||||
badRequest := request
|
||||
badRequest.RequestID = "request-query-bad"
|
||||
badRequest.JobID = "job-query-bad"
|
||||
if _, err := svc.CreateJob(domain.Job{ID: badRequest.JobID, ServerInstanceID: badRequest.Binding.ServerInstanceID, RunEndpointID: badRequest.Binding.RunEndpointID, Capability: domain.JobCapabilityRemoteRunDBSQLiteQuery, TargetKey: badRequest.TargetKey, InputRef: "input://sqlite-template/request-query-bad", IdempotencyKey: "idem-query-bad", ExecutionInput: domain.JobExecutionInput{SQLiteTemplate: &badRequest}}); err != nil {
|
||||
t.Fatalf("create bad sqlite query job: %v", err)
|
||||
}
|
||||
badClaim, err := svc.ClaimRunJob(domain.RunJobClaim{RunEndpointID: badRequest.Binding.RunEndpointID, SessionToken: sessionToken, Capabilities: []string{domain.JobCapabilityRemoteRunDBSQLiteQuery}, Capacity: domain.RunCapacity{MaxJobs: 4}})
|
||||
if err != nil {
|
||||
t.Fatalf("claim bad sqlite query job: %v", err)
|
||||
}
|
||||
badResult := scumTemplateTestResult(badRequest)
|
||||
badResult.AssetDigest = "sha256:" + strings.Repeat("b", 64)
|
||||
_, err = svc.CompleteRunJob(domain.RunJobResult{RunEndpointID: badRequest.Binding.RunEndpointID, SessionToken: sessionToken, JobID: badClaim.Job.JobID, LeaseToken: badClaim.Job.LeaseToken, Attempt: badClaim.Job.Attempt, State: domain.JobStateSucceeded, Progress: domain.RunJobProgressReport{Percent: 100, Message: "query complete"}, Message: "query complete", ExecutionResult: domain.JobExecutionResult{Kind: scumSQLiteTemplateExecutionKind, SQLiteTemplate: &badResult, AuditSummary: "redacted sqlite template query"}})
|
||||
if err == nil || !strings.Contains(err.Error(), "digest") {
|
||||
t.Fatalf("expected digest-fenced query result rejection, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreServiceRunJobReconcile(t *testing.T) {
|
||||
svc, sessionToken := newRegisteredRunJobService(t)
|
||||
createQueuedRunJob(t, svc, "job-1", "idem-1")
|
||||
@@ -242,7 +278,7 @@ func newRegisteredRunJobService(t *testing.T) (*CoreService, string) {
|
||||
t.Helper()
|
||||
svc := newTestCoreService()
|
||||
helloRequest := validRunControlHello()
|
||||
helloRequest.CapabilityReport.Capabilities = append(helloRequest.CapabilityReport.Capabilities, "process.start")
|
||||
helloRequest.CapabilityReport.Capabilities = append(helloRequest.CapabilityReport.Capabilities, "process.start", domain.JobCapabilityRemoteRunDBSQLiteQuery)
|
||||
helloRequest.CapabilityReport.Fingerprint = "cap-jobs"
|
||||
hello, err := svc.RegisterRunHello(helloRequest)
|
||||
if err != nil {
|
||||
@@ -251,6 +287,26 @@ func newRegisteredRunJobService(t *testing.T) (*CoreService, string) {
|
||||
return svc, hello.SessionToken
|
||||
}
|
||||
|
||||
func scumTemplateTestHash() string { return "sha256:" + strings.Repeat("a", 64) }
|
||||
|
||||
func scumTemplateTestBinding() domain.SCUMBindingIdentity {
|
||||
return domain.SCUMBindingIdentity{ServerInstanceID: "server-scum", RunBindingID: "binding-scum", RunEndpointID: "run-local", PluginID: "game.scum", PluginVersion: "0.1.6", AdapterVersion: "adapter-1", GameVersion: "scum-1", DatabaseIdentity: "scum-database"}
|
||||
}
|
||||
|
||||
func createSCUMTemplateServerFixture(t *testing.T, svc *CoreService, binding domain.SCUMBindingIdentity) {
|
||||
t.Helper()
|
||||
if _, err := svc.CreateGamePlugin(domain.GamePlugin{ID: binding.PluginID, Name: "SCUM", Version: binding.PluginVersion, ServerType: "scum", ManifestRef: "artifact://manifests/game.scum/0.1.6", CreateFormSchemaRef: "artifact://schemas/game.scum/create-form/0.1.6", RequiredRunCapabilities: []string{domain.JobCapabilityRemoteRunDBSQLiteQuery}, DeclaredPermissions: []string{"server.remote.access"}, Permissions: domain.PluginPermissions{RemoteAccess: true}}); err != nil {
|
||||
t.Fatalf("create SCUM plugin fixture: %v", err)
|
||||
}
|
||||
if _, err := svc.CreateServerInstance(domain.ServerInstance{ID: binding.ServerInstanceID, PluginID: binding.PluginID, RunEndpointID: binding.RunEndpointID, Name: "SCUM"}); err != nil {
|
||||
t.Fatalf("create SCUM server fixture: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func scumTemplateTestResult(request domain.SCUMSQLiteTemplateRequest) domain.SCUMSQLiteTemplateResult {
|
||||
return domain.SCUMSQLiteTemplateResult{RequestID: request.RequestID, JobID: request.JobID, Binding: request.Binding, Status: domain.SCUMTerminalResultSucceeded, Capability: request.Capability, TargetKey: request.TargetKey, TemplateKey: request.TemplateKey, AdapterVersion: request.AdapterVersion, SchemaFingerprint: request.RequiredSchemaFingerprint, AssetDigest: request.AssetDigest, ParameterDigest: request.ParameterDigest, SourceFingerprint: scumTemplateTestHash(), ObservedAt: time.Now(), ResultDigest: scumTemplateTestHash(), RowCount: 1, Rows: []map[string]any{{"externalPlayerId": "player-redacted", "displayName": "Known Player"}}, Limits: request.Bounds, SafeError: domain.SCUMSafeError{Code: domain.SCUMSafeErrorNone}}
|
||||
}
|
||||
|
||||
func createQueuedRunJob(t *testing.T, svc *CoreService, id string, idempotencyKey string) domain.Job {
|
||||
t.Helper()
|
||||
job, err := svc.CreateJob(domain.Job{
|
||||
|
||||
Reference in New Issue
Block a user