From 66d5ea07cdd644cf353b73d39910e3b7fc46a00e Mon Sep 17 00:00:00 2001 From: Joshua Date: Wed, 18 Feb 2026 14:21:21 -0800 Subject: [PATCH] Add assurance policy regression tests for member channel --- backend/secretapi/app_test.go | 61 +++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/backend/secretapi/app_test.go b/backend/secretapi/app_test.go index f0ab352..e1a882c 100644 --- a/backend/secretapi/app_test.go +++ b/backend/secretapi/app_test.go @@ -683,6 +683,34 @@ func TestMemberChannelRegisterPollAckAndUnregister(t *testing.T) { _ = getJSONExpect[map[string]string](t, a, "/member/channel/events?wallet="+ownerAddr+"&device_id=desktop-01&limit=10", http.StatusForbidden) } +func TestMemberChannelEventsAllowUnattestedMembership(t *testing.T) { + a, _, cleanup := newTestApp(t) + defer cleanup() + + memberKey := mustKey(t) + memberAddr := strings.ToLower(crypto.PubkeyToAddress(memberKey.PublicKey).Hex()) + if err := seedMembershipWithAssurance(context.Background(), a.store, memberAddr, assuranceCryptoDirect); err != nil { + t.Fatalf("seed member membership: %v", err) + } + + _ = postJSONExpect[memberChannelDeviceRegisterResponse](t, a, "/member/channel/device/register", memberChannelDeviceRegisterRequest{ + Wallet: memberAddr, + ChainID: 84532, + DeviceID: "desktop-unattested-01", + Platform: "desktop", + OrgRootID: "org.events.unattested", + PrincipalID: "human.member", + PrincipalRole: "workspace_member", + AppVersion: "0.1.0", + PushProvider: "none", + }, http.StatusOK) + + events := getJSONExpect[memberChannelEventsResponse](t, a, "/member/channel/events?wallet="+memberAddr+"&device_id=desktop-unattested-01&limit=25", http.StatusOK) + if len(events.Events) == 0 { + t.Fatalf("expected seeded events for unattested member, got none") + } +} + func TestMemberChannelSupportTicketOwnerOnly(t *testing.T) { a, _, cleanup := newTestApp(t) defer cleanup() @@ -747,6 +775,39 @@ func TestMemberChannelSupportTicketOwnerOnly(t *testing.T) { } } +func TestMemberChannelSupportTicketRequiresOnrampAttestation(t *testing.T) { + a, _, cleanup := newTestApp(t) + defer cleanup() + + ownerKey := mustKey(t) + ownerAddr := strings.ToLower(crypto.PubkeyToAddress(ownerKey.PublicKey).Hex()) + if err := seedMembershipWithAssurance(context.Background(), a.store, ownerAddr, assuranceCryptoDirect); err != nil { + t.Fatalf("seed owner membership: %v", err) + } + _ = postJSONExpect[memberChannelDeviceRegisterResponse](t, a, "/member/channel/device/register", memberChannelDeviceRegisterRequest{ + Wallet: ownerAddr, + ChainID: 84532, + DeviceID: "desktop-owner-unattested-01", + Platform: "desktop", + OrgRootID: "org.support.assurance", + PrincipalID: "human.owner", + PrincipalRole: "org_root_owner", + AppVersion: "0.1.0", + PushProvider: "none", + }, http.StatusOK) + + errResp := postJSONExpect[map[string]string](t, a, "/member/channel/support/ticket", memberChannelSupportTicketRequest{ + Wallet: ownerAddr, + OrgRootID: "org.support.assurance", + PrincipalID: "human.owner", + Category: "admin_support", + Summary: "Need owner diagnostics.", + }, http.StatusForbidden) + if code := errResp["code"]; code != "identity_assurance_insufficient" { + t.Fatalf("expected identity_assurance_insufficient, got %+v", errResp) + } +} + func TestMarketplaceCheckoutBundlesMembershipAndMintsEntitlement(t *testing.T) { a, cfg, cleanup := newTestApp(t) defer cleanup()