67 lines
2.5 KiB
Go
67 lines
2.5 KiB
Go
package store
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
|
|
"git.ipao.vip/rogee/go-sip/internal/ai"
|
|
"git.ipao.vip/rogee/go-sip/internal/contract"
|
|
)
|
|
|
|
// LoadAuthorizedAI never treats a cached configuration as permission to run.
|
|
// The latest received reply governs admission; rejection, revocation and expiry
|
|
// cannot fall back to an earlier successful reply.
|
|
func (s *Store) LoadAuthorizedAI(tenantID, tenantKey, version string) (ai.Snapshot, []byte, error) {
|
|
snapshot, err := s.LoadAIConfig(tenantID, tenantKey, version)
|
|
if err != nil {
|
|
return ai.Snapshot{}, nil, err
|
|
}
|
|
var raw []byte
|
|
if err := s.db.QueryRow(`SELECT r.response FROM ai_mq_requests r JOIN outbox o ON o.event_id=r.message_id
|
|
WHERE r.tenant_id=? AND r.tenant_key=? AND r.agent_version_id=? AND r.response IS NOT NULL
|
|
ORDER BY o.id DESC LIMIT 1`, tenantID, tenantKey, version).Scan(&raw); err != nil {
|
|
return ai.Snapshot{}, nil, err
|
|
}
|
|
response, err := contract.DecodeService(raw)
|
|
if err != nil {
|
|
return ai.Snapshot{}, nil, err
|
|
}
|
|
if response.Status != "ok" {
|
|
return ai.Snapshot{}, nil, errors.New("latest AI configuration authorization request was rejected")
|
|
}
|
|
var payload struct {
|
|
Authorization json.RawMessage `json:"authorization"`
|
|
}
|
|
if err := json.Unmarshal(response.Payload, &payload); err != nil {
|
|
return ai.Snapshot{}, nil, err
|
|
}
|
|
authorization, err := ai.ValidateAuthorization(payload.Authorization, snapshot, tenantID, tenantKey, s.now())
|
|
if err != nil {
|
|
return ai.Snapshot{}, nil, err
|
|
}
|
|
// Revocation is a permanent fact for this grant identity, even if a later
|
|
// correlated request returns an older non-revoked representation.
|
|
rows, err := s.db.Query(`SELECT json_extract(response,'$.payload.authorization') FROM ai_mq_requests
|
|
WHERE tenant_id=? AND tenant_key=? AND agent_version_id=?
|
|
AND json_extract(response,'$.payload.authorization.authorization_id')=?
|
|
AND json_extract(response,'$.payload.authorization.revoked')=1`, tenantID, tenantKey, version, authorization.AuthorizationID)
|
|
if err != nil {
|
|
return ai.Snapshot{}, nil, err
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var revokedRaw []byte
|
|
if err := rows.Scan(&revokedRaw); err != nil {
|
|
return ai.Snapshot{}, nil, err
|
|
}
|
|
if _, err := ai.DecodeBoundAuthorization(revokedRaw, snapshot, tenantID, tenantKey); err != nil {
|
|
return ai.Snapshot{}, nil, err
|
|
}
|
|
return ai.Snapshot{}, nil, errors.New("AI authorization has a persisted revocation")
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return ai.Snapshot{}, nil, err
|
|
}
|
|
return snapshot, append([]byte(nil), payload.Authorization...), nil
|
|
}
|