package app import ( "context" "errors" "testing" "time" "agent-system-backend/pkg/extension" ) type scriptedRecheckProvider struct { testProjectContextProvider recheck func(context.Context, extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error) } func (p scriptedRecheckProvider) Recheck(ctx context.Context, req extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error) { return p.recheck(ctx, req) } func registeredRecheckSlot(t *testing.T, recheck func(context.Context, extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error)) *projectContextSlot { t.Helper() slot := &projectContextSlot{} if err := (pluginRegistry{pluginID: "rdm", caps: hostcaps{contexts: slot}}).RegisterProjectContextProvider(scriptedRecheckProvider{recheck: recheck}); err != nil { t.Fatal(err) } return slot } func TestProjectSourceRecheckFailsClosedAtThreeSecondCeiling(t *testing.T) { var remaining time.Duration slot := registeredRecheckSlot(t, func(ctx context.Context, req extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error) { deadline, ok := ctx.Deadline() if !ok { return extension.ProjectContextSourceRecheckResult{}, errors.New("unbounded recheck") } remaining = time.Until(deadline) select { case <-ctx.Done(): case <-time.After(10 * time.Second): } // A late success must not authorize old machine context. return extension.ProjectContextSourceRecheckResult{Bundle: extension.ProjectContextBundle{Status: extension.ProjectContextReady, ProjectID: req.Scope.ProjectID}}, nil }) started := time.Now() _, err := slot.recheck(context.Background(), extension.ProjectContextSourceRecheckRequest{Scope: extension.ProjectContextRequest{Actor: "alice", ProjectID: "p1"}}) if err == nil { t.Fatal("source recheck past its deadline returned authorized context") } if remaining <= 0 || remaining > 3*time.Second { t.Fatalf("source recheck deadline is not bounded by 3s: %v", remaining) } if elapsed := time.Since(started); elapsed > 5*time.Second { t.Fatalf("source recheck outlived its 3s ceiling: %v", elapsed) } } func TestProjectSourceRecheckRejectsProviderRefusalAndForeignBundles(t *testing.T) { scope := extension.ProjectContextRequest{Actor: "alice", ProjectID: "p1"} answers := map[string]func(extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error){ "refused": func(extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error) { return extension.ProjectContextSourceRecheckResult{}, errors.New("provider refused") }, "denied": func(req extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error) { return extension.ProjectContextSourceRecheckResult{Bundle: extension.ProjectContextBundle{Status: extension.ProjectContextDenied, ProjectID: req.Scope.ProjectID}}, nil }, "incomplete": func(req extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error) { return extension.ProjectContextSourceRecheckResult{Bundle: extension.ProjectContextBundle{Status: extension.ProjectContextIncomplete, ProjectID: req.Scope.ProjectID}}, nil }, "other project": func(extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error) { return extension.ProjectContextSourceRecheckResult{Bundle: extension.ProjectContextBundle{Status: extension.ProjectContextReady, ProjectID: "p2"}}, nil }, } for name, answer := range answers { slot := registeredRecheckSlot(t, func(_ context.Context, req extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error) { return answer(req) }) if _, err := slot.recheck(context.Background(), extension.ProjectContextSourceRecheckRequest{Scope: scope}); err == nil { t.Fatalf("%s source recheck accepted", name) } } var sawPlugin string slot := registeredRecheckSlot(t, func(_ context.Context, req extension.ProjectContextSourceRecheckRequest) (extension.ProjectContextSourceRecheckResult, error) { sawPlugin = req.Scope.PluginID return extension.ProjectContextSourceRecheckResult{Bundle: extension.ProjectContextBundle{Status: extension.ProjectContextReady, ProjectID: req.Scope.ProjectID}}, nil }) forged := scope forged.PluginID = "forged-plugin" if _, err := slot.recheck(context.Background(), extension.ProjectContextSourceRecheckRequest{Scope: forged}); err != nil || sawPlugin != "rdm" { t.Fatalf("recheck scope plugin was not the registered holder: plugin=%q err=%v", sawPlugin, err) } for _, missing := range []extension.ProjectContextRequest{{ProjectID: "p1"}, {Actor: "alice"}} { if _, err := slot.recheck(context.Background(), extension.ProjectContextSourceRecheckRequest{Scope: missing}); err == nil { t.Fatalf("recheck without trusted actor/project accepted: %+v", missing) } } }