Commit Graph

13 Commits

Author SHA1 Message Date
Kirill Pimenov
0c77cc4534
fix: correct reprint threshold display and de-duplicate the formula (#124)
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
End to end test / e2e-test (push) Has been cancelled
Trivy scan / Analyze (push) Has been cancelled
Yarn tests / yarn (push) Has been cancelled
* fix: correct reprint threshold display and de-duplicate the formula (F5)

Print.vue recomputed the recovery threshold as floor(total/2)+2 and stored
the *total* in a field misleadingly named `requiredShards`. The reprint
sheets therefore overstated how many more QR codes are needed (e.g. total=5
showed "need 4" instead of the correct 3) — misleading during recovery,
though the QR payloads themselves were always untouched.

Root cause: the threshold policy was duplicated. Share.vue computes
floor(total/2)+1; Print.vue re-implemented it and drifted. Extract a single
`defaultThreshold()` helper (src/util/shards.ts) and use it in both, so they
can never disagree again. Rename Print.vue's field to `totalShards` to match
what it actually holds.

Add unit tests for the helper, including the exact F5 case (total=5 -> 3) and
a strict-majority invariant across the whole 3..255 UI range.

* fix: reject fractional shard counts, clamp the remaining-code count

Review follow-ups on the reprint view.

`<input type="number">` only constrains the spinner, not the value: typing
"3.5" (or clearing the box, which `v-model.number` leaves as "") sailed
through the old `>= 3 && <= 255` check and reached defaultThreshold(),
producing fractional totals and remaining counts. Add `step="1"` for the
spinner and gate on a shared `isValidShardCount()` predicate that also
requires a whole number, so the input and the threshold policy keep agreeing
about what a shard count is.

`needMoreShards` compared with `!==`, so scanning more codes than announced
kept the scanner open and drove `remainingCodes` negative. Compare with `<`
and clamp the remainder at 0.

`threshold` returned 0 for "nothing entered yet", a valid-looking value that
could reach ShardInfo's required-shards prop. Return `undefined` instead and
guard the consuming block on it, making the not-yet-entered state explicit.

The `threshold` and validation paths are covered by shards.spec.ts; the
scanner-overshoot clamp is not, as the repo has no component-test harness yet.

* fix: apply the same shard-count validation to the generator

Share.vue's shard-count input had the defect Copilot flagged on Print.vue's:
no `step`, no integer check, and `totalShards` fed straight into
crypto.share() — a fractional count surfaced as an opaque secrets.js error
routed through the generic error hub, and an emptied box passed "" through.

Reuse `isValidShardCount()` and gate the generate button on it, matching the
existing `secretTooLong` pattern (disabled button plus an inline error span),
so both shard-count inputs now agree on what a shard count is.

* fix: stop rendering a threshold derived from an invalid shard count

Gating the generate button left the sentence above it still interpolating
defaultThreshold(totalShards) for values that had just been rejected: an
emptied field coerces to 0 and renders "Will require any 1 shards", and 3.5
renders 2. Give Share.vue's `requiredShards` the same contract as Print.vue's
`threshold` — `undefined` unless the count is usable — show an em dash in the
sentence, and guard both the generated-shards block and crypto.share() on it.

Also strengthen the threshold invariant test. Asserting only
`defaultThreshold(n) > n / 2` does not pin the policy: floor(n/2)+2, the very
formula this branch removed, satisfies it for every even n. Assert the
smallest strict majority instead, which floor(n/2)+1 alone satisfies.
2026-08-04 16:10:30 +02:00
Pavel Rybalko
cbdfc7e08b
add end-to-end UI tests. Resolves #30
* add 2e2 tests

* fix prettier

* add workflow

* prettify

* update vue/cli-service

* update readme
2021-11-17 11:21:00 +07:00
Pavel Rybalko
49ee8905e6
Show error messages on UI (#74)
* fix #63 add error messages on the page

* small changes
2021-10-19 14:37:31 +07:00
Pavel Rybalko
c79f43b613
fix #35 migrate to Typescript 2021-09-23 12:00:36 +07:00
Kirill Pimenov
e27865e53b
Fix linter issues
Now that the rules are much more pedantic there are quite some places
where we are inconsistent with codestyle; all security issues detected
were false positives, though.
2020-08-03 20:38:37 +02:00
Kirill Pimenov
ff93057bd3
Configured ESLint 2020-08-03 19:45:08 +02:00
Kirill Pimenov
d073dc2f91
Fixed shard to Base64 conversion 2019-07-13 17:13:03 +02:00
Kirill Pimenov
bd1b546d7d
More ergonomic and futureproof parsing 2019-02-14 15:37:56 +01:00
Kirill Pimenov
7870336e2e
Test to check compliance with the reference 2019-02-13 17:36:48 +01:00
Kirill Pimenov
96739fd352
Make tests pass 2019-01-23 18:01:48 +03:00
Kirill Pimenov
dbecc65f2f
It now works with non-ASCII characters 2018-11-26 21:15:35 +01:00
Kirill Pimenov
fae52b9f27
More tests 2018-11-26 20:38:15 +01:00
Kirill Pimenov
5906902543
First test for crypto.js 2018-11-26 20:18:17 +01:00