Files
Codex Local bf1233d5df
ci / verify (push) Canceled after 0s
feat: expand companion platform, device controls, and memoir workflows
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
2026-10-08 10:06:44 +08:00

160 lines
6.0 KiB
Go

package callmemory
import (
"context"
"data-terminal-cloud/internal/volcsubtitle"
"github.com/google/uuid"
"net/url"
"strings"
"testing"
)
func TestRecordingIdentityAndSignedURL(t *testing.T) {
prefixes, err := recordingPrefixes("KP01-020026091601", "bot_20260927080903000")
if err != nil {
t.Fatal(err)
}
key := prefixes[0] + "1790467744348_000058_c014e733.mp4"
record, ok := parseRecording(key, prefixes[0], "USER", 1045859)
if !ok || record.Duration != 58 || record.ID == "" {
t.Fatal(record, ok)
}
for _, bad := range []string{strings.Replace(key, "KP01-020026091601", "other", 1), key + "/extra", strings.Replace(key, "000058", "invalid", 1)} {
if _, ok := parseRecording(bad, prefixes[0], "USER", 1); ok {
t.Fatal("accepted foreign/malformed object")
}
}
if _, err = recordingPrefixes("../device", "bot_20260927080903000"); err == nil {
t.Fatal("unsafe device")
}
if _, err = recordingPrefixes("device", "persistent-bot"); err == nil {
t.Fatal("unverified room")
}
store, err := NewTOSRecordings("memory927", "cn-beijing", "test-ak", "test-sk", "")
if err != nil {
t.Fatal(err)
}
for _, action := range []string{"PLAY", "DOWNLOAD"} {
if action == "PLAY" {
if _, e := store.Sign(context.Background(), key, action, 60); e == nil {
t.Fatal("default domain playback allowed")
}
if e := store.ConfigurePlayback("https://recordings.example.com"); e != nil {
t.Fatal(e)
}
}
signed, e := store.Sign(context.Background(), key, action, 60)
if e != nil {
t.Fatal(e)
}
u, e := url.Parse(signed)
if e != nil {
t.Fatal(e)
}
host := "memory927.tos-cn-beijing.volces.com"
if action == "PLAY" {
host = "recordings.example.com"
}
if u.Host != host || u.Scheme != "https" || u.Query().Get("response-content-type") != "audio/mp4" || u.Query().Get("X-Tos-Expires") != "60" {
t.Fatal("incorrect direct URL options")
}
disposition := "inline"
if action == "DOWNLOAD" {
disposition = "attachment"
}
if !strings.HasPrefix(u.Query().Get("response-content-disposition"), disposition) {
t.Fatal("wrong disposition")
}
}
}
func TestRecordingIdentityFromAuthenticatedSubtitle(t *testing.T) {
f, d := directFixture(t)
ctx := context.Background()
sid := uuid.NewString()
if _, err := f.s.DirectRequest(ctx, d, "start", DirectInput{SessionID: sid, BootID: f.boot}); err != nil {
t.Fatal(err)
}
n := int64(1)
packet := volcsubtitle.Packet{Type: "subtitle", Data: []volcsubtitle.Segment{{UserID: "bot_20260927080903000", RoundID: &n, Sequence: &n, Definite: true, Text: "你好"}}}
if err := f.s.DirectSubtitle(ctx, sid, packet); err != nil {
t.Fatal(err)
}
if err := f.s.DirectSubtitle(ctx, sid, packet); err != nil {
t.Fatal("duplicate", err)
}
var stored string
if err := f.p.QueryRow(ctx, `SELECT budget_snapshot->>'rtc_agent_user_id' FROM call_session WHERE id=$1::uuid`, sid).Scan(&stored); err != nil || stored != packet.Data[0].UserID {
t.Fatal("identity not retained", err)
}
packet.Data[0].UserID = "bot_20260927090903000"
if err := f.s.DirectSubtitle(ctx, sid, packet); err == nil {
t.Fatal("room reassignment accepted")
}
}
type fakeRecordings struct {
items []CloudRecording
listed, signed int
seconds int64
}
func (f *fakeRecordings) PlaybackReady() bool { return true }
func (f *fakeRecordings) List(context.Context, string, string) ([]CloudRecording, error) {
f.listed++
return f.items, nil
}
func (f *fakeRecordings) Sign(_ context.Context, key, action string, seconds int64) (string, error) {
f.signed++
f.seconds = seconds
return "https://memory927.tos-cn-beijing.volces.com/fixture", nil
}
func TestCloudRecordingAuthorization(t *testing.T) {
f := setup(t)
m, _, _ := f.call(t)
f.exec(t, `UPDATE call_session SET budget_snapshot='{"device_name":"device","rtc_agent_user_id":"bot_20260927080903000"}' WHERE id=$1::uuid`, m.SessionID)
// The fixture copies active consent types; explicitly add raw audio if absent.
f.exec(t, `INSERT INTO consent_record(tenant_id,subject_id,consent_type,scope,policy_version,notice_digest,actor_user_id,evidence_ref) SELECT tenant_id,subject_id,'raw_audio_storage',scope,policy_version,notice_digest,actor_user_id,evidence_ref FROM consent_record c WHERE subject_id=$1::uuid AND NOT EXISTS(SELECT 1 FROM consent_record r WHERE r.subject_id=c.subject_id AND r.consent_type='raw_audio_storage') LIMIT 1`, f.subject)
store := &fakeRecordings{items: []CloudRecording{{ID: hash([]byte("fixture")), Key: "fixture", Speaker: "USER", Duration: 58, Bytes: 100}}}
f.s.ConfigureRecordings(store)
in := recordingInput{ElderID: f.elder, SessionID: m.SessionID, RecordingID: store.items[0].ID, Action: "PLAY"}
deny := func(code string) {
t.Helper()
_, e := f.s.MemoryRequest(context.Background(), f.principal, "calls/recording-access", jsonBytes(in))
if e == nil || !strings.Contains(e.Error(), code) {
t.Fatalf("wanted %s got %v", code, e)
}
}
deny("RECORDING_ACCESS_DENIED")
if store.signed != 0 || store.listed != 0 {
t.Fatal("storage accessed before authorization")
}
f.exec(t, `INSERT INTO recording_access_grant(tenant_id,subject_id,grantee_user_id,permission,purpose,granted_by,expires_at) VALUES($1::uuid,$2::uuid,'10000000-0000-0000-0000-000000000101','PLAY','test','10000000-0000-0000-0000-000000000101',now()+interval '90 seconds')`, f.tenant, f.subject)
f.request(t, "calls/recording-access", in)
if store.signed != 1 || store.seconds > 90 {
t.Fatal("grant TTL not enforced")
}
in.Action = "DOWNLOAD"
deny("RECORDING_ACCESS_DENIED")
in.Action = "PLAY"
in.RecordingID = hash([]byte("another-file"))
deny("RECORDING_NOT_FOUND")
in.RecordingID = store.items[0].ID
in.SessionID = uuid.NewString()
deny("CALL_NOT_FOUND")
in.SessionID = m.SessionID
other := setup(t)
otherCall, _, _ := other.call(t)
in.SessionID = otherCall.SessionID
deny("CALL_NOT_FOUND")
in.SessionID = m.SessionID
before := store.signed
f.exec(t, `UPDATE consent_record SET withdrawn_at=now() WHERE subject_id=$1::uuid AND consent_type='raw_audio_storage'`, f.subject)
deny("RECORDING_ACCESS_DENIED")
if store.signed != before {
t.Fatal("revoked consent exposed URL")
}
}