fix: the bundled token list names tokens on Ethereum Mainnet only (closes #632) #703

Merged
clawbot merged 1 commits from issue-632-bundled-list-mainnet-only into next 2026-11-03 03:41:16 +01:00
Collaborator

The bundled token list holds Ethereum Mainnet contracts, but it named and scaled tokens on every network. A Sepolia contract at a bundled token's address read as that mainnet token.

  • bundledToken(address, chainId) in src/shared/tokenList.js answers only for mainnet's chain id. Nothing else in src/ reads TOKEN_BY_ADDRESS. Two tests still do, so it stays exported.
  • resolveTokenSymbol() and resolveTokenDecimals() take the chain id from their sources. tokenSourcesByChainId() sets it. The Uniswap decoder sets the transaction's chain id.
  • fetchTokenBalances() and fetchTrackedTokenBalances() take the chain id of the network they ask about.
  • isSpoofedSymbol() takes the chain id of the token's network. It checks the bundled list's symbols only on Ethereum Mainnet. The native asset's labels stay reserved on every network.
  • History lines use the entry's chain id. The balance list and the Send, token detail and add-token screens use the active network's.

Checked: prices.js reads its price feeds only on Ethereum Mainnet. addToken.js and settingsAddToken.js show the bundled list only there.

Deviation: twenty existing tests and four shared test helpers read the bundled list without naming a network. Each now names Ethereum Mainnet, because a missing chain id no longer means mainnet. One helper, history() in tests/historyAfterNetworkSwitch.test.js, landed on next after the steering comment, which left the other tests alone. Its test fails without the chain id.

Judgement call: a call to isSpoofedSymbol() without a chain id checks only the native asset's labels. A test on Ethereum Mainnet covers each caller.

Model: opus-5-5

The bundled token list holds Ethereum Mainnet contracts, but it named and scaled tokens on every network. A Sepolia contract at a bundled token's address read as that mainnet token. - `bundledToken(address, chainId)` in `src/shared/tokenList.js` answers only for mainnet's chain id. Nothing else in `src/` reads `TOKEN_BY_ADDRESS`. Two tests still do, so it stays exported. - `resolveTokenSymbol()` and `resolveTokenDecimals()` take the chain id from their `sources`. `tokenSourcesByChainId()` sets it. The Uniswap decoder sets the transaction's chain id. - `fetchTokenBalances()` and `fetchTrackedTokenBalances()` take the chain id of the network they ask about. - `isSpoofedSymbol()` takes the chain id of the token's network. It checks the bundled list's symbols only on Ethereum Mainnet. The native asset's labels stay reserved on every network. - History lines use the entry's chain id. The balance list and the Send, token detail and add-token screens use the active network's. Checked: `prices.js` reads its price feeds only on Ethereum Mainnet. `addToken.js` and `settingsAddToken.js` show the bundled list only there. Deviation: twenty existing tests and four shared test helpers read the bundled list without naming a network. Each now names Ethereum Mainnet, because a missing chain id no longer means mainnet. One helper, `history()` in `tests/historyAfterNetworkSwitch.test.js`, landed on `next` after the steering comment, which left the other tests alone. Its test fails without the chain id. Judgement call: a call to `isSpoofedSymbol()` without a chain id checks only the native asset's labels. A test on Ethereum Mainnet covers each caller. Model: opus-5-5
clawbot added the needs-review label 2026-10-27 18:55:19 +01:00
clawbot self-assigned this 2026-10-27 18:55:19 +01:00
Author
Collaborator

Review: FAIL (needs-rework)

  1. src/shared/symbolSpoof.js: the spoof rule still reads the bundled list on every network. isSpoofedSymbol() takes no chain id and checks KNOWN_SYMBOLS, which src/shared/tokenList.js builds from the bundled list. With Sepolia active, a Sepolia contract at a bundled token's address may carry that token's symbol. A Sepolia token that reports that symbol from any other address is hidden from balances, history and Send. The approval screens give it no name. The definition of done covers this lookup. While the rule reads the list on Sepolia, the README sentence "The bundled token list is used only for a token on Ethereum Mainnet." is false. Acceptable:

    • isSpoofedSymbol() takes the chain id of the token's network and checks the bundled list's symbols only on Ethereum Mainnet. The native asset's labels stay reserved on every network.
    • Each caller passes the chain id of what it draws.
    • A Jest test with Sepolia active covers it.
    • The spoof rule's descriptions in README.md and docs/README.md say so, and the PR body's "Unchanged" line goes.
  2. Commit message: "Every reader of the bundled list now goes through it" is false. symbolSpoof.js, prices.js, addToken.js and settingsAddToken.js read the list without bundledToken(). Acceptable: a true sentence, such as "Every reader of TOKEN_BY_ADDRESS now goes through it."

  3. src/shared/balances.js: no test fails when refreshBalances() passes no chain id to fetchTokenBalances() and fetchTrackedTokenBalances(). On Ethereum Mainnet, an untracked bundled token with an unknown holder count would then drop out of the balance list. Acceptable: a Jest test through refreshBalances() in which such a token is listed on Ethereum Mainnet and not on Sepolia.

Follow-up note (PR body wording): the deviation's "seven existing tests" are five tests and two shared fetchOnto() helpers.

Model: opus-5-5

**Review: FAIL (needs-rework)** 1. `src/shared/symbolSpoof.js`: the spoof rule still reads the bundled list on every network. `isSpoofedSymbol()` takes no chain id and checks `KNOWN_SYMBOLS`, which `src/shared/tokenList.js` builds from the bundled list. With Sepolia active, a Sepolia contract at a bundled token's address may carry that token's symbol. A Sepolia token that reports that symbol from any other address is hidden from balances, history and Send. The approval screens give it no name. The definition of done covers this lookup. While the rule reads the list on Sepolia, the README sentence "The bundled token list is used only for a token on Ethereum Mainnet." is false. Acceptable: - `isSpoofedSymbol()` takes the chain id of the token's network and checks the bundled list's symbols only on Ethereum Mainnet. The native asset's labels stay reserved on every network. - Each caller passes the chain id of what it draws. - A Jest test with Sepolia active covers it. - The spoof rule's descriptions in `README.md` and `docs/README.md` say so, and the PR body's "Unchanged" line goes. 2. Commit message: "Every reader of the bundled list now goes through it" is false. `symbolSpoof.js`, `prices.js`, `addToken.js` and `settingsAddToken.js` read the list without `bundledToken()`. Acceptable: a true sentence, such as "Every reader of `TOKEN_BY_ADDRESS` now goes through it." 3. `src/shared/balances.js`: no test fails when `refreshBalances()` passes no chain id to `fetchTokenBalances()` and `fetchTrackedTokenBalances()`. On Ethereum Mainnet, an untracked bundled token with an unknown holder count would then drop out of the balance list. Acceptable: a Jest test through `refreshBalances()` in which such a token is listed on Ethereum Mainnet and not on Sepolia. Follow-up note (PR body wording): the deviation's "seven existing tests" are five tests and two shared `fetchOnto()` helpers. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-27 19:25:07 +01:00
clawbot force-pushed issue-632-bundled-list-mainnet-only from bdaf821be2 to c85eb5bf52 2026-10-27 20:45:49 +01:00 Compare
Author
Collaborator

Rework:

  1. isSpoofedSymbol() now takes the chain id of the token's network and checks the bundled list's symbols only on Ethereum Mainnet. Every caller passes it. Tests with Sepolia active cover the history, the Send token list, the balance list and resolveTokenSymbol(). Both READMEs are updated, and the "Unchanged" line is gone.
  2. The commit message now reads "Every reader of TOKEN_BY_ADDRESS now goes through it."
  3. tests/trackedTokenBalances.test.js runs refreshBalances() for an untracked bundled token with an unknown holder count. The token is listed on Ethereum Mainnet and not on Sepolia.

Follow-up note: the PR body now says eighteen existing tests and three shared helpers.

Model: opus-5-5

Rework: 1. `isSpoofedSymbol()` now takes the chain id of the token's network and checks the bundled list's symbols only on Ethereum Mainnet. Every caller passes it. Tests with Sepolia active cover the history, the Send token list, the balance list and `resolveTokenSymbol()`. Both READMEs are updated, and the "Unchanged" line is gone. 2. The commit message now reads "Every reader of `TOKEN_BY_ADDRESS` now goes through it." 3. `tests/trackedTokenBalances.test.js` runs `refreshBalances()` for an untracked bundled token with an unknown holder count. The token is listed on Ethereum Mainnet and not on Sepolia. Follow-up note: the PR body now says eighteen existing tests and three shared helpers. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-27 20:46:00 +01:00
Author
Collaborator

Review: FAIL (needs-rework)

  1. README.md line 3201, "Known token symbol verification": the sentence "On Ethereum Mainnet, any token transfer claiming a symbol from this list (e.g. "ETH", "USDT", "USDC") but originating from an unrecognized contract address is identified as a spoof and filtered from display." runs to 32 words and calls "ETH" a symbol from the list. The added sentence after it, "On another network, the list's symbols are not checked", then says "ETH" is not checked on Sepolia. That is false: the native asset's labels are checked on every network, as the end of the same paragraph says. Acceptable: short sentences that name only bundled symbols, for example "On Ethereum Mainnet, a token that claims a symbol from this list, such as "USDT" or "USDC", is a spoof unless its contract is the listed one. The wallet hides it."

  2. README.md lines 1477 to 1483, the balance-list paragraph: after the split, "That filter is unconditional" follows three rules: the 1,000-holder floor, the mainnet symbol rule and the native-label rule. It can point at any of them, while its dash clause is about the holder setting. The touched sentence "a token claiming a symbol from the bundled list from any other contract address" also stacks two "from" phrases. Acceptable, for example:

    • "On Ethereum Mainnet, a token that claims a bundled token's symbol from another contract is always dropped, tracked or not."
    • "The balance list applies all three rules whatever the settings say. The "Hide tokens with fewer than 1,000 holders" setting governs only the transaction history and the send-screen token selector."
  3. src/shared/tokenList.js line 3981: the comment above KNOWN_SYMBOLS still ends "it does not loosen the rule, because a contract outside the set is still a spoof." isSpoofedSymbol() now checks the sets only on Ethereum Mainnet, so this holds on mainnet only. The PR corrected the same sentence in src/shared/symbolSpoof.js. Acceptable: "On Ethereum Mainnet, a contract outside the set is still a spoof", as there.

Model: opus-5-5

**Review: FAIL (needs-rework)** 1. `README.md` line 3201, "Known token symbol verification": the sentence "On Ethereum Mainnet, any token transfer claiming a symbol from this list (e.g. "ETH", "USDT", "USDC") but originating from an unrecognized contract address is identified as a spoof and filtered from display." runs to 32 words and calls "ETH" a symbol from the list. The added sentence after it, "On another network, the list's symbols are not checked", then says "ETH" is not checked on Sepolia. That is false: the native asset's labels are checked on every network, as the end of the same paragraph says. Acceptable: short sentences that name only bundled symbols, for example "On Ethereum Mainnet, a token that claims a symbol from this list, such as "USDT" or "USDC", is a spoof unless its contract is the listed one. The wallet hides it." 2. `README.md` lines 1477 to 1483, the balance-list paragraph: after the split, "That filter is unconditional" follows three rules: the 1,000-holder floor, the mainnet symbol rule and the native-label rule. It can point at any of them, while its dash clause is about the holder setting. The touched sentence "a token claiming a symbol from the bundled list from any other contract address" also stacks two "from" phrases. Acceptable, for example: - "On Ethereum Mainnet, a token that claims a bundled token's symbol from another contract is always dropped, tracked or not." - "The balance list applies all three rules whatever the settings say. The "Hide tokens with fewer than 1,000 holders" setting governs only the transaction history and the send-screen token selector." 3. `src/shared/tokenList.js` line 3981: the comment above `KNOWN_SYMBOLS` still ends "it does not loosen the rule, because a contract outside the set is still a spoof." `isSpoofedSymbol()` now checks the sets only on Ethereum Mainnet, so this holds on mainnet only. The PR corrected the same sentence in `src/shared/symbolSpoof.js`. Acceptable: "On Ethereum Mainnet, a contract outside the set is still a spoof", as there. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-27 21:09:32 +01:00
clawbot force-pushed issue-632-bundled-list-mainnet-only from c85eb5bf52 to a72f301fe1 2026-10-27 21:21:23 +01:00 Compare
Author
Collaborator

Rework:

  1. The "Known token symbol verification" sentences now use the suggested wording and name only "USDT" and "USDC".
  2. The balance-list paragraph now uses the two suggested sentences.
  3. The comment above KNOWN_SYMBOLS now ends "On Ethereum Mainnet, a contract outside the set is still a spoof."

Found by the search:

  • README.md, "Known token symbol verification": the sentence about the fake "Ethereum" token said the check catches it because its contract is not WETH's. It now says no contract may bear "ETH", so that token is a spoof.

Judgement call: sentences about a token that is in the bundled list stay unchanged. They hold on every network, because only Ethereum Mainnet tokens are in it.

Not fixed: while "Show tracked tokens with zero balance" is on, a tracked token that the spoof rule drops still gets a zero row in the balance list. This predates this PR.

Model: opus-5-5

Rework: 1. The "Known token symbol verification" sentences now use the suggested wording and name only "USDT" and "USDC". 2. The balance-list paragraph now uses the two suggested sentences. 3. The comment above `KNOWN_SYMBOLS` now ends "On Ethereum Mainnet, a contract outside the set is still a spoof." Found by the search: - `README.md`, "Known token symbol verification": the sentence about the fake "Ethereum" token said the check catches it because its contract is not WETH's. It now says no contract may bear "ETH", so that token is a spoof. Judgement call: sentences about a token that is in the bundled list stay unchanged. They hold on every network, because only Ethereum Mainnet tokens are in it. Not fixed: while "Show tracked tokens with zero balance" is on, a tracked token that the spoof rule drops still gets a zero row in the balance list. This predates this PR. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-27 21:21:39 +01:00
Author
Collaborator

Review: FAIL (needs-rework)

  1. README.md lines 1480 to 1481: "The balance list applies all three rules whatever the settings say." is false. The wording was my suggestion in the last review. The add-token screens do not apply the spoof rule, so a user can track a spoofed token. While "Show tracked tokens with zero balance" is on, balanceLinesForAddress() in src/popup/views/helpers.js lists that token with a zero balance. Acceptable: say only what the sentence is there for, for example "The "Hide tokens with fewer than 1,000 holders" setting does not change this list. It governs only the transaction history and the send-screen token selector."

Model: opus-5-5

**Review: FAIL (needs-rework)** 1. `README.md` lines 1480 to 1481: "The balance list applies all three rules whatever the settings say." is false. The wording was my suggestion in the last review. The add-token screens do not apply the spoof rule, so a user can track a spoofed token. While "Show tracked tokens with zero balance" is on, `balanceLinesForAddress()` in `src/popup/views/helpers.js` lists that token with a zero balance. Acceptable: say only what the sentence is there for, for example "The "Hide tokens with fewer than 1,000 holders" setting does not change this list. It governs only the transaction history and the send-screen token selector." Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-27 21:24:13 +01:00
Author
Collaborator

Paused for sneak's review: this PR has failed review three times (sneak/project-management#43).

The code passed the last two reviews. The open finding is one README sentence, "The balance list applies all three rules whatever the settings say.", which is false; the third review gives the replacement wording.

Model: opus-5-5

Paused for sneak's review: this PR has failed review three times (https://git.eeqj.de/sneak/project-management/issues/43). - https://git.eeqj.de/sneak/AutistMask/pulls/703#issuecomment-159559 - https://git.eeqj.de/sneak/AutistMask/pulls/703#issuecomment-159769 - https://git.eeqj.de/sneak/AutistMask/pulls/703#issuecomment-159814 The code passed the last two reviews. The open finding is one README sentence, "The balance list applies all three rules whatever the settings say.", which is false; the third review gives the replacement wording. Model: opus-5-5
clawbot removed their assignment 2026-10-27 21:29:21 +01:00
sneak was assigned by clawbot 2026-10-27 21:29:21 +01:00
sneak was unassigned by clawbot 2026-11-02 22:24:11 +01:00
clawbot self-assigned this 2026-11-02 22:24:11 +01:00
Author
Collaborator

Steering after three failed reviews (#703 (comment), #703 (comment), #703 (comment)). The pause is withdrawn. The third review found one sentence. Since then, #705 landed on next and added callers this PR must cover; that matters more than the sentence.

This PR waits for #679, which shares src/shared/uniswap.js, and for #664. Then:

The rework changes exactly this:

  1. Rebase onto current next, one commit.
  2. Pass the chain id at the three isSpoofedSymbol() calls that #705 added: balanceLinesForAddress() in src/popup/views/helpers.js, addToken.js and settingsAddToken.js. Without it a fake USDT on Ethereum Mainnet can be added and listed. Likewise pass it to any resolveSymbol() call that #664 moved.
  3. tests/spoofedTrackedToken.test.js: its tests name Ethereum Mainnet, as this PR's other tests do. Add one test with Sepolia active: a Sepolia contract that reports USDT can be added and is listed.
  4. README.md, the balance-list paragraph, in place of the sentences about the two symbol rules and "That filter is unconditional": "On Ethereum Mainnet, the balance list always drops a token that claims a bundled token's symbol from another contract. On every network, it drops a token that claims a label of the native asset. Those labels are "ETH" and each network's nativeCurrency, such as "SepoliaETH". The "Hide tokens with fewer than 1,000 holders" setting does not change this list. It governs only the transaction history and the send-screen token selector."
  5. docs/README.md: keep the sentence "Your balance list always applies the check too." from next, and this PR's sentence about Sepolia.
  6. PR body: drop the "Not fixed" line, which #705 fixed. Stay under about 250 words.

It leaves alone: bundledToken(), the body of isSpoofedSymbol(), every other README sentence, and the other tests. The judgement call in the PR body stands.

The next review checks the diff since a72f301: the six items above, that every isSpoofedSymbol() and resolveSymbol() caller on the rebased tree passes a chain id, script/cibuild on the rebased head, and the definition of done of #632. A new finding fails it only if a fake token gets through on Ethereum Mainnet, or a bundled token's name or decimals are used on another network. Anything else is a follow-up note and does not fail it.

Model: opus-5-5

Steering after three failed reviews (https://git.eeqj.de/sneak/AutistMask/pulls/703#issuecomment-159559, https://git.eeqj.de/sneak/AutistMask/pulls/703#issuecomment-159769, https://git.eeqj.de/sneak/AutistMask/pulls/703#issuecomment-159814). The pause is withdrawn. The third review found one sentence. Since then, https://git.eeqj.de/sneak/AutistMask/issues/705 landed on `next` and added callers this PR must cover; that matters more than the sentence. This PR waits for https://git.eeqj.de/sneak/AutistMask/pulls/679, which shares `src/shared/uniswap.js`, and for https://git.eeqj.de/sneak/AutistMask/pulls/664. Then: **The rework changes exactly this:** 1. Rebase onto current `next`, one commit. 2. Pass the chain id at the three `isSpoofedSymbol()` calls that https://git.eeqj.de/sneak/AutistMask/issues/705 added: `balanceLinesForAddress()` in `src/popup/views/helpers.js`, `addToken.js` and `settingsAddToken.js`. Without it a fake `USDT` on Ethereum Mainnet can be added and listed. Likewise pass it to any `resolveSymbol()` call that https://git.eeqj.de/sneak/AutistMask/pulls/664 moved. 3. `tests/spoofedTrackedToken.test.js`: its tests name Ethereum Mainnet, as this PR's other tests do. Add one test with Sepolia active: a Sepolia contract that reports `USDT` can be added and is listed. 4. `README.md`, the balance-list paragraph, in place of the sentences about the two symbol rules and "That filter is unconditional": "On Ethereum Mainnet, the balance list always drops a token that claims a bundled token's symbol from another contract. On every network, it drops a token that claims a label of the native asset. Those labels are `"ETH"` and each network's `nativeCurrency`, such as `"SepoliaETH"`. The "Hide tokens with fewer than 1,000 holders" setting does not change this list. It governs only the transaction history and the send-screen token selector." 5. `docs/README.md`: keep the sentence "Your balance list always applies the check too." from `next`, and this PR's sentence about Sepolia. 6. PR body: drop the "Not fixed" line, which https://git.eeqj.de/sneak/AutistMask/issues/705 fixed. Stay under about 250 words. **It leaves alone:** `bundledToken()`, the body of `isSpoofedSymbol()`, every other README sentence, and the other tests. The judgement call in the PR body stands. **The next review checks** the diff since `a72f301`: the six items above, that every `isSpoofedSymbol()` and `resolveSymbol()` caller on the rebased tree passes a chain id, `script/cibuild` on the rebased head, and the definition of done of https://git.eeqj.de/sneak/AutistMask/issues/632. A new finding fails it only if a fake token gets through on Ethereum Mainnet, or a bundled token's name or decimals are used on another network. Anything else is a follow-up note and does not fail it. Model: opus-5-5
clawbot added 1 commit 2026-11-03 03:18:41 +01:00
fix: the bundled token list names tokens on Ethereum Mainnet only (closes #632)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
80ae229931
bundledToken(address, chainId) in tokenList.js answers only for Ethereum
Mainnet's chain id. Every reader of TOKEN_BY_ADDRESS now goes through it,
with the chain id of the transaction, balance or history entry it draws.
The token sources the screens build carry that chain id. The Uniswap
decoder sets the transaction's chain id on them. fetchTokenBalances()
takes the chain id of the network it asks about.

isSpoofedSymbol() takes the chain id of the token's network. It checks the
bundled list's symbols only on Ethereum Mainnet. The native asset's labels
stay reserved on every network.

Twenty existing tests and four shared test helpers read the bundled
list without naming a network. Each now names Ethereum Mainnet.

Model: opus-5-5
clawbot force-pushed issue-632-bundled-list-mainnet-only from a72f301fe1 to 80ae229931 2026-11-03 03:18:41 +01:00 Compare
Author
Collaborator
  1. Rebased onto current next as one commit. history() in tests/historyAfterNetworkSwitch.test.js, which landed after the steering comment, now carries Ethereum Mainnet's chain id.
  2. balanceLinesForAddress(), addToken.js and settingsAddToken.js pass the chain id to isSpoofedSymbol(). The resolveSymbol() call that #664 moved in addressToken.js passes it too.
  3. tests/spoofedTrackedToken.test.js names Ethereum Mainnet, and a new test adds and lists a Sepolia USDT through both add-token screens.
  4. The balance-list paragraph in README.md uses the given wording.
  5. docs/README.md keeps the sentence from next and this PR's sentence about Sepolia.
  6. The PR body drops the "Not fixed" line, and its deviation and summary now cover the items above.

Model: opus-5-5

1. Rebased onto current `next` as one commit. `history()` in `tests/historyAfterNetworkSwitch.test.js`, which landed after the steering comment, now carries Ethereum Mainnet's chain id. 2. `balanceLinesForAddress()`, `addToken.js` and `settingsAddToken.js` pass the chain id to `isSpoofedSymbol()`. The `resolveSymbol()` call that https://git.eeqj.de/sneak/AutistMask/pulls/664 moved in `addressToken.js` passes it too. 3. `tests/spoofedTrackedToken.test.js` names Ethereum Mainnet, and a new test adds and lists a Sepolia `USDT` through both add-token screens. 4. The balance-list paragraph in `README.md` uses the given wording. 5. `docs/README.md` keeps the sentence from `next` and this PR's sentence about Sepolia. 6. The PR body drops the "Not fixed" line, and its deviation and summary now cover the items above. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-11-03 03:19:03 +01:00
Author
Collaborator

PASS: the six items in #703 (comment) are done, every isSpoofedSymbol() and resolveSymbol() caller passes a chain id, and the definition of done of #632 is met.

Model: opus-5-5

PASS: the six items in https://git.eeqj.de/sneak/AutistMask/pulls/703#issuecomment-163146 are done, every `isSpoofedSymbol()` and `resolveSymbol()` caller passes a chain id, and the definition of done of https://git.eeqj.de/sneak/AutistMask/issues/632 is met. Model: opus-5-5
clawbot merged commit 754cf9686f into next 2026-11-03 03:41:16 +01:00
clawbot deleted branch issue-632-bundled-list-mainnet-only 2026-11-03 03:41:16 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/AutistMask#703