diff --git a/lib/rail0/error_hints.rb b/lib/rail0/error_hints.rb index 4f99fd5..36baba7 100644 --- a/lib/rail0/error_hints.rb +++ b/lib/rail0/error_hints.rb @@ -62,7 +62,11 @@ module Rail0 "unknown_token" => "the token isn't configured on this chain", "no_active_contract" => "no active RAIL0 contract on that chain", "missing_param" => "a required parameter is missing from the request", - "forbidden" => "not permitted for this session — on create the payer must be the signed-in address" + # A BARE forbidden is not a party mismatch: the gateway split those into codes of + # their own (not_the_payee, not_the_payer, wallet_deactivated, not_your_account) + # because they need different fixes. This entry kept describing one of them long + # after the split — and the rule it named no longer exists in the gateway at all. + "forbidden" => "not permitted for this session — typically the operator grant, a resource owned by another account, or a transaction signed by the wrong wallet" }.freeze # An actionable hint for a rail0 error code, or nil when the code is unknown. diff --git a/spec/errors_spec.rb b/spec/errors_spec.rb index fd57d71..927114f 100644 --- a/spec/errors_spec.rb +++ b/spec/errors_spec.rb @@ -112,10 +112,19 @@ def stub_error(status, body) end end - # `forbidden` is the one whose hint has to say something the code cannot: the - # payer/caller rule on create is the most common way to hit it. - it "explains what forbidden usually means on create" do - expect(Rail0.describe_error("forbidden")).to include("payer") + # `forbidden` is the one whose hint has to say something the code cannot, because the + # gateway sends it with NO detail for the case that matters most — a missing operator + # grant — so the hint is everything the caller reads. + # + # It used to promise the payer rule on create, and this example pinned that promise. + # Both were wrong: the gateway split the party mismatches into codes of their own + # (not_the_payee, not_the_payer, wallet_deactivated, not_your_account) and no longer + # has the rule at all. The negative assertion is the guard — it is exactly the sentence + # that crept in and stayed. + it "names what a bare forbidden actually is, not the rule that was split out" do + hint = Rail0.describe_error("forbidden") + expect(hint).to include("operator grant") + expect(hint).not_to include("payer") end end end