package sendico import ( "encoding/json" "io" "net/http" "net/http/httptest" "testing" "time" "git.sendico.io/tech/sxchnge/product/identity" merrors "git.sendico.io/tech/sxchnge/shared/errors" "github.com/stretchr/testify/require" ) func TestProofWireContractAndLimitsProjection(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Contains(t, r.Header.Get("Authorization"), "Bearer ") expected := "/api/v1/identity_facts/" + org + "/proofs/" + subject if r.URL.Path == expected+"/limits" { require.Equal(t, http.MethodGet, r.Method) _, _ = io.WriteString(w, `{"status":"success","data":{"tier":"verified","profile_ref":"profile_personal_verified","entries":[{"operation":"Transfer","period":"day","currency":"BTC","cap":"0.12345678","remaining":"0.10000001","used":"0.02","reserved":"0.00345677"}]}}`) return } require.Equal(t, expected, r.URL.Path) if r.Method == http.MethodPost { reader, err := r.MultipartReader() require.NoError(t, err) fields := map[string]string{} for { part, err := reader.NextPart() if err == io.EOF { break } require.NoError(t, err) data, err := io.ReadAll(part) require.NoError(t, err) fields[part.FormName()] = string(data) } require.Equal(t, "document bytes", fields["document"]) require.Equal(t, "selfie bytes", fields["selfie"]) require.Equal(t, "stable-source", fields["source_submission_ref"]) var profile map[string]string require.NoError(t, json.Unmarshal([]byte(fields["profile"]), &profile)) require.Equal(t, "Legal Name", profile["full_name"]) require.Equal(t, "local-customer", profile["external_customer_ref"]) require.Equal(t, "verified@example.test", profile["email"]) } _, _ = io.WriteString(w, `{"status":"success","data":{"subject_ref":"`+subject+`","submission_ref":"`+submission+`","status":"approved","upgrade_pending":true,"profile":{"full_name":"Legal Name","date_of_birth":"1990-04-23","residence_country":"PL"}}}`) })) defer server.Close() client, err := Open(config(t, server.URL)) require.NoError(t, err) result, err := client.SubmitVerification(t.Context(), subject, "stable-source", identity.Profile{FullName: "Legal Name", DateOfBirth: "1990-04-23", ResidenceCountry: "PL"}, identity.Facts{Email: "verified@example.test", CustomerRef: "local-customer"}, []byte("document bytes"), []byte("selfie bytes")) require.NoError(t, err) require.Equal(t, "pending", result.Status) require.True(t, result.UpgradePending) policy, err := client.Limits(t.Context(), subject) require.NoError(t, err) require.Equal(t, "0.12345678", policy.Entries[0].Cap) require.Equal(t, "verified", policy.Tier) require.Equal(t, 4*time.Second, client.http.Timeout) } func TestProofRateLimitPreservesTypedRecoveryWithoutUpstreamBody(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Retry-After", "120") w.WriteHeader(429) _, _ = io.WriteString(w, "private identity assertions") })) defer server.Close() client, err := Open(config(t, server.URL)) require.NoError(t, err) _, err = client.Verification(t.Context(), subject) require.Error(t, err) require.NotContains(t, err.Error(), "private identity assertions") throttle, ok := merrors.ThrottleDetailsFrom(err) require.True(t, ok) require.Equal(t, 120*time.Second, throttle.RetryAfter) }