FlareWatch

Safeguards Overview

FlareWatch maintains a registry of architectural rules — each one a specific mistake the project does not want to repeat. This page explains the registry's shape and the categories it covers.

Last updated May 2026

What the registry is

Every recurring class of bug in FlareWatch's history has been distilled into a numbered safeguard: a one-paragraph rule, a justification, and a pointer to the place in the code that enforces it. New safeguards are added when a class of bug or pattern emerges that should be prevented from recurring.

The registry is a working document, not marketing copy. Its purpose is to keep the team — and the audit-first review loop the team uses — honest about which rules apply where. The registry is referenced from inline code comments (e.g., // Safeguard 24) so a reader of any individual file can find the rule that governs the surrounding lines.

This page is the public summary. The full registry lives in the source repository alongside the code it governs. The purpose here is to give a security researcher, grant reviewer, or prospective contributor a sense of the categories the registry covers and the kind of discipline it enforces.

Why a registry

A safeguard registry only earns its keep if it prevents the same bug twice. The registry's track record is the answer:

  • Each safeguard names the bug it prevents. A rule without a remembered incident behind it is not a safeguard, it's a style preference. Style preferences belong in lint rules, not in the registry.
  • Safeguards are referenced from code, not just from docs. A code change that violates a safeguard reads as a flag at review time because the safeguard number is in the surrounding comments.
  • Some safeguards are enforced automatically. A subset is enforced through ESLint rules or shell scripts that run in CI. The rest rely on author discipline plus the audit-first review pattern, which has held up well in practice.
  • The registry is kept honest by tests. Several safeguards are pinned by regression tests that read source files as strings and assert that anti-patterns do not appear. Brittleness is the feature: a future refactor that reverts to an anti-pattern fails the test before the regression reaches production.

Categories

The registry is organised by domain. The categories below are stable; specific safeguards within each are added as new failure modes are discovered.

CategoryWhat it covers
Authentication & authorizationSingle choke point for session validation, per-wallet ownership checks on every route, cross-token rejection between access and refresh tokens, admin-route gating.
Data integrityAddress normalisation, unit-conversion contracts at producer/consumer boundaries, key-builder discipline, and rules against silently coalescing failures into zero values.
On-chain readsSingle-implementation rules for any value read from a smart contract, contract address resolution from the on-chain registry, and rules against duplicating reward logic.
Display correctnessCentralised number, currency, and date formatting; null-safety on every numeric display; APR vs. APY labelling discipline; tax-rate-as-effective discipline.
Alerts & notificationsSingle source of truth for alert evaluation across client and server; explicit allowlists for which alerts fan out to watched wallets; supersession rules so a "rewards landed" alert cancels a stale "rewards available" alert; cross-device dismiss synchronisation.
Persistence & cacheRules for when the canonical store is the key-value backend versus localStorage; migration discipline; deploy-scoped service worker cache; explicit dynamic opt-out for routes that read live state.
UI & lifecyclePage-readiness gates, monotonic floors that prevent transient zeros from displacing known balances, and rules for skeleton-rendering during cold-fetch windows.
Process & toolingRules for explicit feature-launch consent, full-suite test runs on alert-surface changes, structured logging in server-side code, and review discipline against shortcut-style fixes.

A handful of representative rules

These are public-safe summaries of safeguards that illustrate the registry's character. They are paraphrased and abbreviated; the canonical text lives next to the code.

Single source of truth for on-chain reads

Any value read from a smart contract — claimable rewards, balances, stake state, epoch data, prices — is computed by exactly one function in the services layer. Every feature that needs that value imports the same function. If two functions compute the same value, one of them is wrong; the rule is to delete it, not to add a third.

Single choke point for session validation

Every authenticated route in FlareWatch validates session cookies through a single helper. No route handler verifies session tokens independently. This invariant is what makes server-side revocation universal — there are no side doors that bypass the check.

Per-wallet ownership gating, both sides

Per-wallet routes verify ownership server-side, not client-side. The original audit established the rule because earlier work had closed the client-side gates but left server-side endpoints fully ungated. The two halves are now tracked as separate explicit deliverables — closed on the client, closed on the server — to prevent that failure mode from recurring.

Use centralized formatters, never inline

All number, currency, and date formatting goes through a small set of centralised helpers. No component formats inline. The rule has nothing to do with style: when a single locale or currency definition changes, every surface in the application updates with it. Drift between surfaces is silent and hard to spot until a user notices.

Unit conversions are documented at both ends

When two parts of the system trade values whose unit might be ambiguous (seconds vs. milliseconds, decimal vs. percentage, lower-case vs. checksummed addresses), the convention is documented at both the producer and the consumer. A comment on only one end rots; only a boundary contract that is asserted at both ends survives a refactor.

One implementation per user action

Every user-initiated action — adding a watched wallet, changing a tax rate, dismissing an alert, signing out — has exactly one implementation. The rule exists because actions triggered from different parts of the UI used to drift in subtle ways: one entry point would clear a cache, another would not, and a class of "stale value after operation X" bugs would result.

Failure modes that must be loud

Some failure modes are silent by nature — a misclassified reward, a unit mismatch that turns a notification into a no-op, a dismiss record that never makes it to the key-value store. Where possible, the registry requires that producers of these values declare their contract loudly enough that a future change which violates it fails noisily, in tests, before reaching production.

How the registry evolves

  • New safeguards. Added when a class of bug recurs or a single bug cost enough to justify a permanent rule.
  • Superseded safeguards. Kept in the registry with a "superseded" marker and a pointer to the replacement, so historical references in code remain interpretable.
  • Promoted from working notes. Some safeguards begin as informal rules in a session handoff document and are promoted to the registry once they have proven their weight.
  • Quarterly sweep. Temporary lint exceptions and "to-do by next quarter" markers are checked on a quarterly cadence. Anything that has aged out is either resolved or explicitly extended.

Why this is published

FlareWatch publishes this overview, rather than the full internal registry, for two reasons.

  • The internal registry contains code-level detail (file paths, key-value schema names, incident timestamps) that is useful to the team and to a security reviewer with code access, but is not appropriate to publish without that access.
  • The categories and the discipline are the actual story. A grant reviewer or security researcher evaluating FlareWatch wants to know what kind of project it is, how seriously it takes correctness, and what its working loop looks like — not which file contains rule #91.

Researchers who would like to discuss a specific safeguard, propose a new one, or report a gap are welcome to reach out at hello@flarewatch.io.

Further reading

FlareWatch FTSO delegation addresses. Flare (chainId 14): 0x973B899Fe1422efDdeBE1d54E9A6487a70966aC5. Songbird (chainId 19): 0xaf4eF2A0Ecf8d914Db6b721D3eb79C46CA612796.