Repository navigation
Production hardening: CI, vault, CSV import, P&L correctness - #8
Merged
Merged
Conversation
added 14 commits
September 27, 2026 20:38
The extension ships a static SVG sprite (icons/phosphor-symbols.svg) and never imports the React package, which also pulled react/react-dom as peers into the lockfile. The project now has zero npm dependencies.
npm test runs every legacy test_fixtures script plus node:test files in tests/ through node --test, so a non-zero exit from any script fails the run. scripts/check-syntax.mjs replaces the README shell loop: it parses classic content scripts as scripts and the rest as ES modules, and fails when the manifest references a file that does not exist.
Pinned action SHAs, read-only token, no persisted credentials.
…session key - New vault records use 600k PBKDF2-SHA256 iterations (OWASP 2023). 310k records from v0.5.0 still decrypt and are re-wrapped on unlock. - Validate record version, KDF cost, salt and IV length before use. - A session key that no longer matches the stored vault threw inside the poll and stopped Yahoo and crypto prices too. It now drops the stale material and reports the vault as locked. - vault-status reports a legacy plaintext key so Options asks for an unlock code instead of claiming the key is merely locked. - Set chrome.storage.session access to TRUSTED_CONTEXTS explicitly. - Time out the Finnhub test-connection request after 12s.
Only query1 is ever fetched. Add a test that the set of hosts in shipped code equals host_permissions exactly, and that the manifest has no externally_connectable or extra permissions.
- RFC 4180 parsing: quoted commas, doubled quotes, and quoted newlines no longer shift columns. - Size (1 MB), row (5,000), column (64), cell (256 chars) and holdings (1,000) caps with a user-readable CsvLimitError. - Rows are null-prototype objects; __proto__/constructor/prototype headers are dropped and column lookups use own properties only. - parseBrokerNumber accepts Indian grouping (1,23,456.78), currency prefixes and accounting negatives; rejects Infinity, exponents and junk. Negative, zero, NaN and infinite quantities are skipped. - Symbols must look like tickers; duplicates merge with a weighted cost. - A missing or contradictory currency column no longer labels US stocks as INR: currency follows the quote source (.NS/.BO INR, else USD).
Correctness: - Yahoo meta.chartPreviousClose is the close before the first bar of the requested range. With range=5d that is about five sessions ago, so every NSE/BSE 'day' P&L was really a five-day change. The previous close is now the last daily close before the regularMarketTime session (split-adjusted), falling back to meta.previousClose. - Finnhub pc = 0 now means 'no previous close' instead of a zero baseline that turned the whole position value into day P&L. - Quotes carry currency, provider timestamp and marketState (open/closed from Yahoo's regular trading period). Robustness: - Every provider request (CoinGecko and Binance had none) uses a 12s timeout; malformed JSON and HTTP errors yield no quote, never a throw. - 429/5xx pause that provider with exponential backoff (1 min doubling to 30 min, honouring Retry-After). State persists in pts_provider_backoff so a restarted service worker keeps honouring it. - Console logs name the provider only, never symbols, URLs or keys. Tests use recorded-shape fixtures in test_fixtures/providers; no real API calls.
…live
- Day P&L needs a positive provider previous close. Missing or zero now
yields null ('—' in the tape and popup) instead of either the whole
position value (pc = 0) or a 15-minute change mislabelled as 'day'.
- Aggregates sum only positions that share a currency; INR + USD totals
are null instead of a meaningless sum. aggregate.partial marks totals
that exclude unpriced holdings. Quote currency beats a stale CSV value.
- Positions without a quote from the current poll are marked stale.
- describeFreshness (shared.js + content bridge) labels state Stale when
flagged or not rewritten for max(5 min, 3 refresh intervals), Closed
when every known market is shut, else Live. Popup pill and tape use it.
- Cent rounding is half-away-from-zero and never renders '-0.00'.
- mergePriceSnapshots drops non-positive prices and corrupt entries.
…dings - staleWarning is also set when any holding missed this poll (partial provider outage, paused provider, locked Finnhub key). - Re-read holdings before writing state; if they changed while quotes were in flight (import or clear), skip the write instead of restoring deleted positions. A poll requested mid-poll now runs afterwards, not dropped. - Settings are migrated before use, displayCurrency comes from priced positions, and state records marketState and refreshMinutes. - ProviderBackoff: a success racing a 429 in the same batch no longer cancels the pause. - Integration tests load background.js against a chrome.* fake: alarms on restart, partial and total outages, persisted backoff, holdings race, storage failure, and message sender/type allowlisting.
PRIVACY lists the exact four hosts, the vault parameters, session-storage scope, the backoff key, and what logs contain. README explains day P&L, currency handling, freshness labels, CSV limits, and the new npm test and npm run check commands.
The 6-character minimum is unchanged so existing vaults keep working. Codes may now be any characters, including spaces, up to 128 characters, and are used exactly as typed. Options shows a live, non-blocking hint (weak / fair / strong) nudging towards 12+ characters or a passphrase. The worker enforces the same bounds on create and unlock.
…yption Options gains a 'Change unlock code' form (current code, new code with the strength hint, confirmation). The worker's vault-change-code handler decrypts with the current code, builds and verifies the new record in memory, then replaces the vault in a single storage write only if it is still the record it decrypted. A wrong current code, invalid new code, failed verification, storage error, or concurrent replace leaves the old vault intact. Old 310k-iteration vaults are upgraded in the same step.
A v0.2.0 snapshot of the extension (manifest 0.2.0, pre-vault code) that was committed by accident in 5fccd64. Nothing references it: not the manifest, scripts, tests, CI, or docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Production-hardening pass on MyTicker v0.5.0. One fix per commit; see CHANGELOG.md for the full list.
Correctness
chartPreviousCloseon a 5-day range is the close before the first bar. Now uses the previous session's close.Security
query2.finance.yahoo.comhost permission; a test keeps host permissions equal to the hosts the code contacts.Robustness
Tooling
npm test(89 tests) andnpm run check, run by a new GitHub Actions workflow.myticker-v0.2.0-browser-test/copy and an unused dependency.Test plan
npm test: 89/89npm run check: green