125 lines
4.4 KiB
Go
125 lines
4.4 KiB
Go
package rpc
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.ipao.vip/rogee/go-sip/contracts"
|
|
agentv1 "git.ipao.vip/rogee/go-sip/gen/agent/v1"
|
|
"git.ipao.vip/rogee/go-sip/internal/ai"
|
|
"git.ipao.vip/rogee/go-sip/internal/contract"
|
|
"git.ipao.vip/rogee/go-sip/internal/testfixture"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
func TestExecutionPermitEnforcesAIAuthorization(t *testing.T) {
|
|
snapshotRaw, err := contracts.Read("examples/agent-version-asr-only.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
snapshot, err := ai.ValidateForMode(snapshotRaw, ai.ModeASROnly)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
authorizationRaw, err := contracts.Files.ReadFile("upstream/v1/examples/ai-authorization.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
server := NewServer(ServerOptions{
|
|
Now: func() time.Time { return time.Date(2026, 9, 18, 0, 0, 30, 0, time.UTC) },
|
|
AISnapshotRaw: snapshotRaw,
|
|
AIAuthorizationRaw: authorizationRaw,
|
|
AIEgressPoolID: "egress-mock",
|
|
})
|
|
activateTestServer(t, server)
|
|
|
|
raw, err := testfixture.Execute()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, payload, err := contract.DecodeExecute(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
binding := &agentv1.ExecutionBinding{
|
|
TenantId: "tenant-1",
|
|
TenantKey: "tenant-demo-key",
|
|
ExecutionId: payload.ExecutionID,
|
|
TaskId: payload.TaskID,
|
|
TaskItemId: payload.TaskItemID,
|
|
TaskRevision: payload.TaskRevision,
|
|
AgentVersionId: snapshot.AgentVersionID,
|
|
RoutePolicyId: payload.RoutePolicyID,
|
|
CallerProfileId: payload.CallerProfileID,
|
|
}
|
|
response, err := server.GetExecutionPermit(context.Background(), &agentv1.GetExecutionPermitRequest{
|
|
Meta: testMeta("permit-ai", "permit-ai-key", 1),
|
|
Binding: binding,
|
|
ResourceReservationId: "reservation-ai",
|
|
ExpectedTaskRevision: payload.TaskRevision,
|
|
ConfigSha256: snapshot.Digest,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if response.Permit == nil || response.Receipt == nil || response.Receipt.Result != agentv1.ResultCode_RESULT_CODE_APPLIED {
|
|
t.Fatalf("unexpected authorized permit response: %+v", response)
|
|
}
|
|
|
|
badDigest := &agentv1.GetExecutionPermitRequest{
|
|
Meta: testMeta("permit-ai-bad-digest", "permit-ai-bad-digest-key", 1),
|
|
Binding: binding,
|
|
ResourceReservationId: "reservation-ai-2",
|
|
ExpectedTaskRevision: payload.TaskRevision,
|
|
ConfigSha256: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
}
|
|
if _, err := server.GetExecutionPermit(context.Background(), badDigest); status.Code(err) != codes.FailedPrecondition {
|
|
t.Fatalf("bad digest error=%v, code=%s", err, status.Code(err))
|
|
}
|
|
}
|
|
|
|
func TestExecutionPermitRejectsRevokedAIAuthorization(t *testing.T) {
|
|
snapshotRaw, err := contracts.Read("examples/agent-version-asr-only.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
snapshot, err := ai.ValidateForMode(snapshotRaw, ai.ModeASROnly)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
authorizationRaw, err := contracts.Read("examples/invalid-ai-authorization-revoked.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
server := NewServer(ServerOptions{
|
|
Now: func() time.Time { return time.Date(2026, 9, 18, 1, 0, 30, 0, time.UTC) },
|
|
AISnapshotRaw: snapshotRaw,
|
|
AIAuthorizationRaw: authorizationRaw,
|
|
AIEgressPoolID: "egress-mock",
|
|
})
|
|
activateTestServer(t, server)
|
|
response, err := server.GetExecutionPermit(context.Background(), &agentv1.GetExecutionPermitRequest{
|
|
Meta: testMeta("permit-revoked", "permit-revoked-key", 1),
|
|
Binding: &agentv1.ExecutionBinding{TenantId: "tenant-1", TenantKey: "tenant-demo-key", ExecutionId: "execution-revoked", AgentVersionId: snapshot.AgentVersionID},
|
|
ResourceReservationId: "reservation-revoked",
|
|
ConfigSha256: snapshot.Digest,
|
|
})
|
|
if err == nil || status.Code(err) != codes.PermissionDenied || response != nil {
|
|
t.Fatalf("revoked authorization response=%+v err=%v code=%s", response, err, status.Code(err))
|
|
}
|
|
}
|
|
|
|
func activateTestServer(t *testing.T, server *Server) {
|
|
t.Helper()
|
|
_, err := server.ActivateAgent(context.Background(), &agentv1.ActivateAgentRequest{
|
|
Meta: testMeta("activate-ai", "", 0),
|
|
Binding: &agentv1.AgentBinding{AgentId: "agent-1", CellId: "cell-1", ExpectedBootId: "boot-1", DispatcherEpoch: "epoch-1", SessionGeneration: 1},
|
|
ActivationOperationId: "activate-ai",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|