mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix: say out loud what every sort was already doing
Sonar's S2871 flags a bare .sort(), which orders by UTF-16 code unit rather than by value. All 30 remaining sites turned out to sort ASCII strings — ISO dates, currency and country codes, setting keys, route names, OAuth scopes, zip entry names — where that order is already the intended one. Each says so explicitly now, with a comparator that reproduces it exactly rather than a localeCompare that would quietly reorder things. That mattered more than it sounds. Several of these feed something other than a display: useAtlas joins the sorted codes into the signature that decides whether to rebuild the region layer, daysSlice re-pins sorted dates positionally onto reordered days, and three timeline views pick a day's colour by indexOf into the sorted array. Switching any of them to a locale collator would have been a silent regression. Two smaller ones came with it. The .map(placeBtn) calls in FileManagerAssignModal pass the index as a second argument, which placeBtn declares and uses for its React key — correct already, now written out as .map((p, i) => placeBtn(p, i)). And budgetSlice's optimistic paid-toggle stored the raw boolean behind `paid as unknown as number`, while the schema declares z.number() and both the REST response and the WebSocket event carry 0/1. So the optimistic state and the confirmed state disagreed on type until a refresh. It normalises now, and the two tests that asserted `true` assert the contract. Four `| 0` truncations are listed in sonar-project.properties instead of changed. Two are a djb2 string hash where the 32-bit wrap is the algorithm. The other two look like plain truncation of a row id, but `| 0` is also coercing undefined to 0 there — the settlement flows the API returns carry no user_id, so that is the normal path, and Math.trunc returns NaN and crashes the lookup.
This commit is contained in:
@@ -62,7 +62,7 @@ sonar.cpd.exclusions=shared/src/i18n/**
|
||||
# Locale files are UI copy — strings like "Password", "API key", "token" are labels,
|
||||
# not credentials, and the secret detectors false-positive on them constantly.
|
||||
# Ignore the secrets analyzer and the hard-coded-credential rules on i18n only.
|
||||
sonar.issue.ignore.multicriteria=i18nsec1,i18nsec2,i18nsec3,rand1,rand2,rand3,rand4,rand5,cli1,hash1,hash2,hash3,hash4,ns1,ns2,frame1
|
||||
sonar.issue.ignore.multicriteria=i18nsec1,i18nsec2,i18nsec3,rand1,rand2,rand3,rand4,rand5,rand6,cli1,hash1,hash2,hash3,hash4,hash5,hash6,hash7,hash8,ns1,ns2,frame1
|
||||
sonar.issue.ignore.multicriteria.i18nsec1.ruleKey=secrets:*
|
||||
sonar.issue.ignore.multicriteria.i18nsec1.resourceKey=shared/src/i18n/**
|
||||
sonar.issue.ignore.multicriteria.i18nsec2.ruleKey=typescript:S2068
|
||||
@@ -145,3 +145,34 @@ sonar.issue.ignore.multicriteria.ns2.resourceKey=server/src/nest/plugins/host/rp
|
||||
# event.source instead.
|
||||
sonar.issue.ignore.multicriteria.frame1.ruleKey=typescript:S2819
|
||||
sonar.issue.ignore.multicriteria.frame1.resourceKey=client/src/components/Plugins/PluginFrame.tsx
|
||||
# randomId is the module that MINTS idempotency keys, and its first two rungs are
|
||||
# crypto.randomUUID and crypto.getRandomValues. The Math.random line is the third,
|
||||
# reached only by a runtime with no Web Crypto at all, and the value it produces is
|
||||
# a deduplication key the server scopes per (user, method, path) — not a token, not
|
||||
# a secret. Replacing it is not possible: there is no stronger primitive left at
|
||||
# that point, and deleting the rung would leave such a runtime with no key.
|
||||
sonar.issue.ignore.multicriteria.rand6.ruleKey=typescript:S2245
|
||||
sonar.issue.ignore.multicriteria.rand6.resourceKey=client/src/utils/randomId.ts
|
||||
|
||||
# S7767 (bitwise truncation) — Math.trunc is NOT equivalent to `| 0`, and all four
|
||||
# sites depend on a difference the rule does not model.
|
||||
#
|
||||
# packingListPanel.helpers and todoListModel hold the same djb2-variant string
|
||||
# hash, `h = ((h << 5) - h + chr) | 0`, whose only job is to stay bounded while it
|
||||
# folds a category name into a colour index. Math.trunc would let h grow past 2^53,
|
||||
# lose precision, and hand out different colours for the same names.
|
||||
#
|
||||
# BudgetPanel.helpers and TravelerPicker look like plain truncation of a user row
|
||||
# id, but `| 0` is also coercing there: it turns undefined and NaN into 0, while
|
||||
# Math.trunc returns NaN and the array lookup then yields undefined. That is not
|
||||
# theoretical — the settlement `flows` the API returns carry a username and an
|
||||
# avatar but no user_id, so colorForUserId(undefined) is the normal path for that
|
||||
# section. Swapping it crashed two BudgetPanel tests on `.gradient` of undefined.
|
||||
sonar.issue.ignore.multicriteria.hash5.ruleKey=typescript:S7767
|
||||
sonar.issue.ignore.multicriteria.hash5.resourceKey=client/src/components/Packing/packingListPanel.helpers.ts
|
||||
sonar.issue.ignore.multicriteria.hash6.ruleKey=typescript:S7767
|
||||
sonar.issue.ignore.multicriteria.hash6.resourceKey=client/src/components/Todo/todoListModel.ts
|
||||
sonar.issue.ignore.multicriteria.hash7.ruleKey=typescript:S7767
|
||||
sonar.issue.ignore.multicriteria.hash7.resourceKey=client/src/components/Budget/BudgetPanel.helpers.ts
|
||||
sonar.issue.ignore.multicriteria.hash8.ruleKey=typescript:S7767
|
||||
sonar.issue.ignore.multicriteria.hash8.resourceKey=client/src/components/Planner/TravelerPicker.tsx
|
||||
|
||||
Reference in New Issue
Block a user