Skip to content

docs: apply review feedback to input validation guide - #440

Merged
pedromcunha merged 5 commits into
mainfrom
pedro/int2-1380-input-validation-review
Sep 2, 2026
Merged

docs: apply review feedback to input validation guide#440
pedromcunha merged 5 commits into
mainfrom
pedro/int2-1380-input-validation-review

Conversation

@pedromcunha

Copy link
Copy Markdown
Member

No description provided.

@pedromcunha
pedromcunha requested a review from n-xlkt September 1, 2026 18:11
@mintlify

mintlify Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
unevenlabs 🟢 Ready View Preview Sep 1, 2026, 6:13 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @pedromcunha's task in 1m 56s —— View job


Code review — PR #440

Reviewed the 24/24 line rewrite of references/api/api_core_concepts/input-validation.mdx against the full page and AGENTS.md (§2 global rules, §3.3a API concept page).

Overall this is a good pass: the deprecation warning is now scoped to "quotes that contain protocol.v2" instead of blanket, the protocol.v2 applicability note is promoted to the top where a reader hits it before investing in the guide, and the new "does not guarantee that the order will fill" sentence at line 188 closes a real overclaim in the original. The we/us/ourRelay normalization is consistent with §2.3 (both are permitted, so this is a choice, not a fix — but it's applied uniformly, which is what matters).

A few things to fix before merge.


1. input-validation.mdx:112 — the new sentence contradicts its own second clause

This check verifies the transaction — the order ID checks that follow only bind the transaction to the properties you inspect here.

Step 2 reads values off orderData and compares them against your expectations. It never touches the transaction — steps 3 and 4 are what reach the transaction, which the second half of the same sentence says explicitly. As written the two clauses contradict each other, and a skimming reader could conclude step 2 alone is sufficient and skip 3 and 4, which is exactly the failure mode this page exists to prevent.

The original ("This is the step that actually protects you") was making a different and correct point: step 2 is where you decide whether the order is acceptable, and steps 3–4 only bind you to that decision. Suggest something like "This is the step where you decide whether the order is acceptable" or "This check establishes what you are agreeing to".

Fix this →

2. input-validation.mdx:188 — "output amount" should be "minimum output amount"

the settlement uses the recipient, output amount, currency, deadline, and destination chain encoded in the verified order

The <Warning> at line 123 makes a point of the distinction: expectedAmount is an estimate, minimumAmount is the enforced floor. Settlement does not guarantee "the output amount" in the order — it guarantees at least minimumAmount. A reader who checked expectedAmount in step 2 and then reads this line has their mistake confirmed rather than caught. Say "minimum output amount".

Fix this →

3. input-validation.mdx:18 — the guarantee lost its precondition

If the order settles, it can only settle according to the order that you inspected.

The original was "If all three hold, the transaction cannot settle into anything other than the order you inspected." The rewrite drops the "if all three hold" conditional, so the sentence now reads as an unconditional property of Relay orders rather than the payoff of completing the three numbered steps directly above it. It also repeats "order ... order" in one short sentence. Suggest: "If all three checks pass, the transaction can only settle into the order you inspected."

Fix this →


Smaller notes

  • input-validation.mdx:10 — intro paragraph is now 4 sentences. §2.10 caps paragraphs at 2–3; the original was 2. The rewrite also drops the why behind the unvalidated default ("which keeps gas cost to a minimum"), which was the one line explaining why Relay doesn't just validate onchain by default. Worth keeping that clause and splitting the paragraph.
  • input-validation.mdx:12 — "The signature API asked Relay for a signature." The API is Relay, so it can't be the one asking. The original's "The old approach asked Relay…" read as shorthand for "the approach involved asking"; naming the API as the subject makes the sentence circular. Suggest "With the signature API, you asked Relay for a signature over…".
  • input-validation.mdx:219 — leftover italics. The pass removed italics at lines 12 (*we*) and 214 (*which*) but left *transaction* here. §2.9 says avoid italics, prefer bold.
  • input-validation.mdx:234 — bullet breaks the list's parallelism. Every other bullet in that list starts with "It" (the signature API); this one restates the subject. "Attested to a legacy request shape" → "described a request shape" also loses both "legacy" and the attestation framing, which is the more precise verb for a signature.
  • input-validation.mdx:140 — "protocol chain ids" wasn't caught by the idID normalization. Not covered either way by the style guide, so this is only an intra-page consistency nit; the rest of the repo uses the code-form orderId / chainId in prose, so leaving both lowercase would also be defensible.

Nothing here is blocking beyond item 1, which I'd want corrected since it can lead a reader to stop after step 2.
• Branch pedro/int2-1380-input-validation-review

@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown

Greptile Summary

This update expands the local quote-verification guide with chain metadata lookup, order-ID recomputation, and checks that bind the selected deposit transaction to the reviewed order.

Confidence Score: 5/5

No blocking failure remains.

No accepted blocking finding remains.

T-Rex T-Rex Logs

What T-Rex did

  • The T-Rex reviewer examined the general-contract-validation-proof and confirmed that the source capture shows expectedPayer = "WALLET_ADDRESS" compared case-insensitively against a valid 0x... address.
  • The reviewer inspected the execution capture and observed that the comparison follows the failure branch and emits the shown error.
  • The reviewer concluded that this behavior matches the claimed behavior when the flow is copied without substituting the placeholder.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (4): Last reviewed commit: "Merge branch 'main' into pedro/int2-1380..." | Re-trigger Greptile

Comment thread references/api/api_core_concepts/input-validation.mdx Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedromcunha Scout thinks this example needs to be updated to compare paymentDetails.depository with Relay’s canonical depository address for the payment chain before using it to select the transaction.

```

At this point the transaction is bound to the order you inspected in step 2. Sending it cannot result in a different recipient, a smaller guaranteed output, or a different destination chain.
At this point the transaction is bound to the order you inspected in step 2. If the order settles, the settlement uses the recipient, output amount, currency, deadline, and destination chain encoded in the verified order. Verification confirms the encoded order. It does not guarantee that the order will fill.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedromcunha Scout: The current example checks the depository and order ID, but it does not yet check the native value or ERC-20 token and amount.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedromcunha Scout: Extend this example to validate the payment fields. For native deposits, compare depositTx.value with the order’s payment amount. For ERC-20 deposits, compare the decoded token and amount with the order’s payment fields and require depositTx.value === 0. Also compare the decoded depositor with the expected payer.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @pedromcunha's task in 2m 37s —— View job


Code review — PR #440

Re-reviewed after f510f2e ("harden input validation example per PR review"). All five items from my previous pass are addressed: step 2 no longer claims to verify the transaction (:114), settlement now says "minimum output amount" (:250), the "if all three checks pass" precondition is back (:20), the intro keeps the gas-cost clause and is one sentence (:10), the signature-API sentence reads "With the signature API, you asked Relay…" (:14), the leftover italics is now bold (:281), and the migration bullet starts with "It" again (:296).

The new hardening in step 4 is a real improvement — cross-checking paymentDetails.depository against GET /chains closes the "validate the quote with the quote" hole, and the payment-amount checks close the one Scout raised. Reviewing the new code on its own terms, three gaps remain in it, and one is a value-loss path.


1. input-validation.mdx:205 — the deposit transaction is never bound to the payment chain

const depositTx = quote.steps
  .flatMap((step) => step.items)
  .map((item) => item.data)
  .find((tx) => tx?.to?.toLowerCase() === depository);

depository is looked up by payment.chainId, but the transaction is matched on to alone. Per references/protocol/depository/addresses.mdx, the depository is deployed at the same address on most chains0x4cd00e387622c35bddb9b4c962c136462338bc31 appears on Ethereum, Optimism, BNB, Base, Polygon, and dozens more. So a step item whose data.chainId is Base satisfies a lookup keyed on ethereum and passes every check below it, including the order-ID and amount comparisons.

Concretely: order says pay 0.1 ETH on Ethereum; the response hands you a deposit tx on Base to the same address with the right id and value. Every assertion on the page passes, the reader signs on Base, and the deposit does not credit the order they verified. The loop in step 3 already has chain.id in hand, so a second map (protocol chain ID → numeric chain ID) and a tx.chainId === CHAIN_IDS[payment.chainId] term in the find predicate closes it.

Fix this →

2. input-validation.mdx:233 — the deposit function is never checked against the order's payment currency

if (functionName === "depositNative") {
  if (BigInt(depositTx.value) !== BigInt(payment.amount)) {

The native branch compares depositTx.value to payment.amount without ever confirming that payment.currency is actually native (the zero address). An order whose input payment is an 18-decimal ERC-20 — { currency: DAI, amount: "1000000000000000000" } — paired with a depositNative(depositor, orderId) call carrying value: 1000000000000000000 passes: step 2 shows the reader "1 DAI in", and the transaction they sign sends 1 ETH. The ERC-20 branch is guarded the right way round (value must be 0); the native branch needs the mirror-image check.

Add a currency/function agreement assertion before the value comparison — payment.currency === zeroAddress must hold iff functionName === "depositNative".

Fix this →

3. input-validation.mdx:228expectedPayer is used but never defined

if ((args[0] as string).toLowerCase() !== expectedPayer.toLowerCase()) {

It appears nowhere else on the page. §2.8 requires each block to be self-contained and paste-and-run, and this is a value the reader has to supply, so it wants a placeholder declaration in the block: const expectedPayer = "WALLET_ADDRESS"; — that also matches the §2.8 placeholder convention, which the page otherwise uses for YOUR_API_KEY.

Fix this →

4. input-validation.mdx:190 — 57-line block needs expandable

§2.8: "When a block exceeds 45 lines, wrap it with expandable so it collapses by default." The step-4 block runs 191–247. Sibling pages already do this (step-execution.mdx:64, wallet-detection.mdx:154).

Fix this →


Smaller notes

  • :159 — an unknown vmType silently writes undefined into CHAINS. VM_TYPES[chain.vmType as keyof typeof VM_TYPES] returns undefined for a VM type Relay adds later, and the entry is still assigned, so Record<string, string> is a lie and getOrderId receives an undefined VM type for that chain instead of a missing key. continue when the lookup misses reads better and keeps the failure loud. This also softens the "it changes only when Relay adds a chain" claim on :136CHAINS is derived, but VM_TYPES is hand-maintained and does need an edit for a new VM.
  • :193 — the example validates inputs[0] only. The step 2 table writes inputs[].payment.amount in array form, and payment.weight in the sample response implies multi-input orders exist. Either say the example assumes a single input, or loop.
  • :185 — the Warning could link the canonical list. references/protocol/depository/addresses.mdx publishes exactly these addresses, and §2.6 asks for a link on first mention. A pointer there gives readers a way to eyeball what their GET /chains fetch returned.
  • Step 4 is EVM-only, but VM_TYPES now lists eight VMs. The viem decodeFunctionData flow doesn't transfer to svm/bvm/tvm, so a reader on a non-EVM chain reaches step 4 with nothing to apply. One sentence scoping the example to EVM deposits would set expectations.
  • :234 vs :244 — inconsistent handling of an absent value. The ERC-20 branch guards with depositTx.value ?? 0; the native branch calls BigInt(depositTx.value) directly, which throws a bare TypeError rather than the page's descriptive error if value is missing. Also BigInt(args[2] as bigint) on :241 is a no-op wrap.

Items 1 and 2 I'd want fixed before merge — this page's whole purpose is to be copied into a validation path, and both are exploitable by the tampered response the page is defending against. 3 and 4 are quick.
• Branch pedro/int2-1380-input-validation-review

Comment thread references/api/api_core_concepts/input-validation.mdx
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @pedromcunha's task in 3m 3s —— View job


Code review — PR #440

Re-reviewed at d8446e9 ("define expectedPayer and fix CHAINS typing"). That commit closes the expectedPayer gap Greptile and I both raised — it's now declared at :198 with a comment explaining why it must come from your own state rather than the response, which is the right framing. The "assume quote is the parsed /quote/v2 response" line at :130 also cleans up the paste-and-run story.

Of the four items from my previous pass, 1, 2 and 4 are still open — the two hardening gaps and the expandable fence. I've re-verified both hardening items against the repo rather than restating them, and found one more unvalidated transaction on the page.


1. input-validation.mdx:215 — the deposit transaction is still not bound to the payment chain

const depositTx = quote.steps
  .flatMap((step) => step.items)
  .map((item) => item.data)
  .find((tx) => tx?.to?.toLowerCase() === depository);

depository is looked up by payment.chainId, but the predicate matches on to alone. Confirmed against references/protocol/depository/addresses.mdx: 0x4cd00e387622c35bddb9b4c962c136462338bc31 is the depository on Ethereum, Optimism, BNB, Gnosis, Unichain, Polygon and ~50 more — one address covers nearly every EVM chain in the table. So a transaction on the wrong chain satisfies a lookup keyed on ethereum and then passes every check below it, including the order-ID, depositor and amount comparisons.

Failure: order says pay 0.1 ETH on Ethereum; a tampered response hands you a deposit tx with chainId: 8453 to the same address, correct id, correct value. Every assertion on the page passes, the reader signs on Base, and the deposit never credits the order they verified.

The fix is cheap and the data is already in hand — step-execution.mdx:285 confirms step item data carries a numeric chainId, and addresses.mdx:7 confirms GET /chains returns id alongside protocol.v2.chainId. Build a second map in the step-3 loop (CHAIN_IDS[protocolChainId] = chain.id) and add tx.chainId === CHAIN_IDS[payment.chainId] to the find predicate.

Fix this →

2. input-validation.mdx:240 — the deposit function is still not checked against the order's payment currency

if (functionName === "depositNative") {
  if (BigInt(depositTx.value) !== BigInt(payment.amount)) {

The native branch compares depositTx.value against payment.amount without confirming payment.currency is the zero address. An order whose input is an 18-decimal ERC-20 — { currency: DAI, amount: "1000000000000000000" } — paired with a depositNative(depositor, orderId) call carrying value: 1000000000000000000 passes every assertion: step 2 shows the reader "1 DAI in", and the transaction they sign sends 1 ETH.

The ERC-20 branch is guarded the right way round (token matched, value forced to 0). The native branch needs the mirror image: assert functionName === "depositNative" iff payment.currency is the zero address, before the value comparison.

Fix this →

3. input-validation.mdx:244 — the ERC-20 flow makes the reader sign a second, unvalidated transaction

The page validates exactly one transaction out of quote.steps, but an ERC-20 deposit is preceded by an approve step (step-execution.mdx:299: "An approval transaction… Always followed by an additional step (deposit or swap)"). That approval is calldata the reader signs, on the premise this whole page adopts — that the response may have been tampered with — and nothing here looks at it. A response with a perfectly valid deposit tx and an approve(attacker, MAX_UINT) in the step before it passes every check on the page.

## What you can verify (:33) promises the deposit transaction "pays Relay's canonical depository, commits to this exact order, and transfers exactly the order's input payment", which is true and yet leaves a reader who followed the page believing they validated what they signed. At minimum this wants a sentence in step 4 scoping the check to the deposit transaction and telling ERC-20 integrators to check the approval's spender and amount too; better still, the expected spender named outright.

Fix this →

4. input-validation.mdx:192 — 62-line block needs expandable

§2.8: "When a block exceeds 45 lines, wrap it with expandable so it collapses by default." The step-4 block runs 192–255. Sibling pages in the same folder already do this (step-execution.mdx:64, wallet-detection.mdx:154).

Fix this →


Smaller notes

  • :154/:161 — the new Record<string, VmType> annotation makes the unsound write worse, not better. VM_TYPES[chain.vmType as keyof typeof VM_TYPES] returns undefined for a VM type Relay adds later, and the entry is assigned anyway — so the map now carries a VmType annotation over a value that can be undefined, and getOrderId receives an undefined VM type rather than a missing key. continue when the lookup misses fixes both. (Also worth checking VmType is actually exported from @relay-protocol/settlement-sdk under that name and with those members — nothing else in this repo imports it, so I couldn't verify it here.)
  • :198 — the comment conflates the depositor with the sender. "The wallet your app will send the deposit from" describes msg.sender; args[0] is the encoded depositor, the account the deposit is credited to (hub.mdx:67 derives the order address from it). They coincide in the default flow but are different things, and depositTx.from is right there in the step data if you want to check the sender too.
  • :200 — the example validates inputs[0] only, while the step 2 table writes inputs[].payment.amount in array form and payment.weight in the sample response implies multi-input orders. Either say the example assumes a single input, or loop — :33 currently claims "exactly the order's input payment".
  • Step 4 is EVM-only. The viem decodeFunctionData flow doesn't transfer to solana-vm or bitcoin-vm, and addresses.mdx lists depositories on Solana, Eclipse and Bitcoin — so those readers reach step 4 with nothing to apply. One scoping sentence would set expectations.
  • :186 — the Warning could link the canonical list. references/protocol/depository/addresses.mdx publishes exactly these addresses; §2.6 asks for a link on first mention, and it gives readers a way to eyeball what their GET /chains fetch returned.
  • :241 vs :251 — inconsistent handling of an absent value. The ERC-20 branch guards with depositTx.value ?? 0; the native branch calls BigInt(depositTx.value) directly and throws a bare TypeError instead of the page's descriptive error. BigInt(args[2] as bigint) on :248 is also a no-op wrap.
  • :257 — closing paragraph is 4 sentences, over the 2–3 cap in §2.10. The content is right; it just wants a split.

Items 1 and 2 I'd still want fixed before merge — this page exists to be copied into a validation path, and both are exploitable by exactly the tampered response it's defending against. 4 is a one-word change.
• Branch pedro/int2-1380-input-validation-review

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @pedromcunha's task in 2m 6s —— View job


Code review — PR #440

Re-reviewed at 1616a50 ("derive deposit function from order currency; collapse long blocks").

That commit closes item 2 from my last pass cleanly, and does it better than I suggested: deriving orderWantsNative from payment.currency and asserting orderWantsNative !== (functionName === "depositNative") is a biconditional, so it catches the mirror case too — a depositErc20 call standing in for a native-input order. The comment at :242 explains why branching on functionName alone is wrong, which is the part a reader copying this into a validation path needs. Item 4 (expandable) is done on both blocks, and expectedPayer is now the WALLET_ADDRESS placeholder per §2.8.

Item 1 is still open, and the new import brings one new correctness question with it.


1. input-validation.mdx:218 — the deposit transaction is still not bound to the payment chain

const depositTx = quote.steps
  .flatMap((step) => step.items)
  .map((item) => item.data)
  .find((tx) => tx?.to?.toLowerCase() === depository);

depository is resolved from payment.chainId (:204), but the predicate matches on to alone. Re-verified against references/protocol/depository/addresses.mdx: 0x4cd00e387622c35bddb9b4c962c136462338bc31 is the depository on ethereum, optimism, bnb, gnosis, unichain, polygon, sonic, manta, mint, boba, zksync and ~50 more — one address covers nearly every EVM chain in that table.

So a transaction on the wrong chain satisfies a lookup keyed on ethereum and then passes every check below it. Concretely: the order says pay 0.1 ETH on Ethereum; a tampered response returns a deposit tx with chainId: 8453 to the same address, correct id, correct depositor, correct value. Steps 4–7 all pass, the reader signs on Base, and the deposit never credits the order they verified.

Both halves of the fix are already in the file's data path: step-execution.mdx:285 confirms step item data carries a numeric chainId, and addresses.mdx:7 shows GET /chains returns id alongside protocol.v2.chainId. Add CHAIN_IDS[protocolChainId] = chain.id to the step-3 loop and tx.chainId === CHAIN_IDS[payment.chainId] to the find predicate.

Fix this →

2. input-validation.mdx:194getVmTypeNativeCurrency can be handed undefined

const nativeCurrency = getVmTypeNativeCurrency(CHAINS[payment.chainId]);
const orderWantsNative = payment.currency.toLowerCase() === nativeCurrency.toLowerCase();

CHAINS is populated at :161 with VM_TYPES[chain.vmType as keyof typeof VM_TYPES], which returns undefined for any vmType Relay adds after VM_TYPES was hand-written — and the entry is assigned anyway, so the Record<string, VmType> annotation added in d8446e9 is now covering a value that can be undefined. This commit gives that unsound write a second consumer: getVmTypeNativeCurrency(undefined) either throws something opaque or returns undefined, and nativeCurrency.toLowerCase() then dies with a bare TypeError instead of one of the page's descriptive errors. A continue when the lookup misses fixes both consumers at once and keeps the failure legible.

Separately — I could not verify that getVmTypeNativeCurrency (or the VmType type at :139) is actually exported from @relay-protocol/settlement-sdk under that name; nothing else in this repo imports either, and npm isn't reachable from this job. Worth a quick check against the published package before merge, since a wrong import name breaks the block outright.

Fix this →

3. input-validation.mdx:215 — the page validates one transaction; the reader signs every step

find returns the first item whose to is the depository, and nothing on the page looks at the rest of quote.steps. Two consequences:

  • An ERC-20 deposit is preceded by an approve step (step-execution.mdx:299: "Always followed by an additional step (deposit or swap)"). Its to is the token, so it never matches the predicate — a response with a valid deposit tx and approve(attacker, MAX_UINT) in front of it passes every check here.
  • Any additional item after the matched one is equally unexamined.

## What you can verify (:33) promises "the deposit transaction pays Relay's canonical depository, commits to this exact order, and transfers exactly the order's input payment" — all true, and yet a reader who follows the page ends up believing they validated what they signed. This wants a sentence in step 4 scoping the verification to the deposit transaction and telling ERC-20 integrators to check the approval's spender and amount as well.

Fix this →


Smaller notes

  • Step 4 is EVM-only, and this commit sharpens the mismatch. getVmTypeNativeCurrency is deliberately VM-generic, but it sits inside a viem decodeFunctionData flow that doesn't transfer to solana-vm, bitcoin-vm or tron-vm — and addresses.mdx lists depositories on all three. The nativeCurrency.toLowerCase() normalization is also EVM-shaped; a base58 Solana mint is case-sensitive. One sentence scoping the example to EVM deposits would set expectations and justify the lowercasing.
  • :254 vs :264 — inconsistent handling of an absent value. The ERC-20 branch guards with depositTx.value ?? 0; the native branch calls BigInt(depositTx.value) directly and throws a bare TypeError instead of the page's descriptive error. BigInt(args[2] as bigint) on :261 is also a no-op wrap.
  • :201 — the example validates inputs[0] only, while the step 2 table writes inputs[].payment.amount in array form and payment.weight in the sample response implies multi-input orders. Either say the example assumes a single input, or loop — :33 claims "exactly the order's input payment".
  • :196 — the comment conflates the depositor with the sender. "The wallet your app will send the deposit from" describes msg.sender; args[0] is the encoded depositor, the account the deposit is credited to. The follow-on clause ("the same address you passed as user") is right; the lead is describing a different thing.
  • :186 — the Warning could link the canonical list. references/protocol/depository/addresses.mdx publishes exactly these addresses, and §2.6 asks for a link on first mention; it also gives readers a way to eyeball what their GET /chains fetch returned.
  • :270 — closing paragraph is 4 sentences, over the 2–3 cap in §2.10. The content is right, it just wants a split.

Item 1 is the one I'd hold the merge on — it's exploitable by exactly the tampered response this page exists to defend against, and the fix is a map and one predicate term. 2 and 3 are close behind.
• Branch pedro/int2-1380-input-validation-review

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 1m 54s —— View job


Code review — PR #440

  • Read the PR diff and the full page
  • Cross-check claims against references/protocol/** and api_core_concepts/**
  • Check against AGENTS.md §2 / §3.3a
  • Post review
    • Branch pedro/int2-1380-input-validation-review

@pedromcunha
pedromcunha merged commit bf68f56 into main Sep 2, 2026
3 of 4 checks passed
@pedromcunha
pedromcunha deleted the pedro/int2-1380-input-validation-review branch September 2, 2026 01:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants