Skip to content

SPEC 016 Platform Performance Accessibility

Rafael Queiroz edited this page Sep 13, 2026 · 2 revisions

SPEC-016 — Platform: Performance, Availability & Accessibility

Status Draft
PRD source §8.4 (FR-8.29–8.32), §8.5 (FR-8.33–8.36), §8.6 (FR-8.37–8.40)
Depends on SPEC-002
Required by SPEC-021
Applies to Every user-facing spec
Milestone Budgets set in M0, enforced continuously; verified per milestone

Description

The cross-cutting platform qualities no single feature owns: how fast the product must be, how reliably it must run, and who must be able to use it.

These sit in their own spec because they are the requirements most easily lost in a feature-by-feature breakdown — every spec assumes them and none would naturally claim them. Made explicit here, with numeric budgets, they become testable rather than aspirational.

The performance budgets in particular are load-bearing on architecture decisions made elsewhere: the 3s report budget is why SPEC-009 persists daily snapshots and SPEC-011 reads from them rather than recomputing five years of history per request.

Business rules

Performance

ID Rule
BR-016-01 Reference workload for all budgets: 100 assets, 10,000 transactions, 5 years of history. A budget without a stated scale is meaningless.
BR-016-02 Dashboard loads in under 2s (p95) at the reference workload.
BR-016-03 Any report renders in under 3s (p95) at the reference workload over a 5-year period, for any scope and grouping combination.
BR-016-04 An import of 10,000 rows previews in under 30s and commits in under 60s.
BR-016-05 Reports read from DailyValuationSnapshot and never recompute from the ledger per request (SPEC-009, SPEC-011).
BR-016-06 Budgets are measured at p95 against a seeded reference dataset in a scheduled CI run, not by spot-checking a developer's small portfolio.
BR-016-07 Budgets are measured nightly against main, not per-PR — seeding the reference workload is too slow for every push. A regression raises an alert naming the commit range; it does not block the merge. (Amended by ARCHITECTURE.md; originally per-PR blocking.)
BR-016-07a The cheap structural check that predicts slowness does stay blocking: reports must read from DailyValuationSnapshot and never trigger a full ledger recomputation. Measuring the symptom moves to nightly; catching the cause does not.

Availability & operations

ID Rule
BR-016-08 99% monthly availability target. This is not a trading system — no order is placed from it, and brief downtime has no financial consequence for the user.
BR-016-09 Weekly automated database backups, retained 30 days, with restore tested quarterly. An untested backup is not a backup. Implementation deferred — BL-001; Cloudflare R2 decided, trigger is the first non-test user account. For the personal deployment, SPEC-021 BR-021-16 supersedes the cadence: before every migration and daily on start, to a local encrypted destination.
BR-016-10 Backup restore testing must verify that deleted-user data is absent from restored backups (SPEC-004, BR-004-16).
BR-016-11 Market-data job failures alert operators and mark affected data stale in the UI rather than silently serving an old figure as current (SPEC-008, BR-008-27).
BR-016-12 Application logging is structured and contains no personal data (SPEC-004, BR-004-04).
BR-016-13 Operational alerting covers at minimum: market-data job failure, provider budget threshold, background job backlog, error rate, and failed backup.
BR-016-14 Alert thresholds are configuration, not code (SPEC-002).

Accessibility & localization

ID Rule
BR-016-15 WCAG 2.1 AA for core flows: sign-in, import, transaction management, wallet assignment, and all four reports.
BR-016-16 Charts are not the sole carrier of any information. Every figure a chart shows is also available as text or a table — a requirement that serves screen-reader users and colour-blind users alike.
BR-016-17 Portuguese (pt-BR) is the primary language, using the market's own vocabulary: proventos, preço médio, patrimônio, rentabilidade. Terms are not translated into English equivalents that Brazilian investors do not use.
BR-016-18 BRL formatting (R$ 1.234,56) and dd/mm/yyyy dates throughout.
BR-016-19 Responsive from 360px; reports remain legible on mobile, with wide tables scrolling within their own container rather than forcing the page to scroll horizontally.
BR-016-20 Where an English term is used deliberately in place of a Portuguese one — "Portfolio Value" for Patrimônio (SPEC-013) — the pt-BR interface still shows the Portuguese term.

Acceptance Criteria

  • A seeded reference dataset of 100 assets / 10,000 transactions / 5 years exists and is used by performance tests.
  • Dashboard p95 under 2s at reference scale, measured in the nightly run.
  • Every report p95 under 3s at reference scale, measured nightly across all scope × grouping combinations.
  • Import of 10,000 rows previews under 30s and commits under 60s.
  • A report request is verified not to trigger a full ledger recomputation — this check runs per-PR and blocks (BR-016-07a).
  • A deliberate performance regression raises a nightly alert naming the commit range (BR-016-07); a change making a report bypass snapshots fails the PR build (BR-016-07a).
  • Backups run weekly, retain 30 days, and a documented restore has been executed successfully.
  • A restore test confirms deleted-user data is absent from the restored copy.
  • Each alert in BR-016-13 fires in a simulated failure and reaches an operator.
  • Log output across a full import, valuation and report cycle contains no personal data — asserted by scanning logs for known seeded PII values.
  • Core flows pass an automated WCAG 2.1 AA audit, plus manual keyboard-only and screen-reader passes.
  • Every chart's data is reachable as text or a table.
  • The interface renders in pt-BR with correct market vocabulary; no core flow shows an untranslated string.
  • Currency renders as R$ 1.234,56 and dates as dd/mm/yyyy throughout.
  • Every screen is usable at 360px, and no page scrolls horizontally — wide tables scroll within their own container.
  • Colour is never the sole means of conveying information on any chart.

Out of Scope

  • Feature behaviour of any kind — this spec sets qualities, not functionality.
  • Infrastructure and hosting selection, autoscaling, CDN configuration.
  • Disaster recovery beyond backup and restore: no multi-region failover, no RPO/RTO commitments beyond the 99% target.
  • Load testing beyond the reference workload; no capacity planning for scale not yet reached.
  • English or any second language — pt-BR only in v1. The document is in English; the product is not.
  • WCAG AAA.
  • Native mobile apps — responsive web only.
  • Real-user monitoring and analytics.
  • Uptime SLA commitments to users, which would be a commercial decision.

Decision Logs

# Decision Alternatives considered Rationale
DL-016-01 Cross-cutting qualities get their own spec. Distribute them into each feature spec Requirements every spec assumes and none owns are exactly the ones that get dropped. Accessibility and localization had no natural home in a feature-by-feature breakdown and would have been lost — this spec exists because that gap was found while verifying PRD coverage.
DL-016-02 Budgets stated against a named reference workload. State budgets without a scale "Loads in 2s" is unfalsifiable without knowing on what. A developer's 20-transaction test portfolio meets any budget, so an unqualified target passes forever and catches nothing.
DL-016-03 Performance budgets measured nightly and advisory; the structural check stays blocking. Fail the build on every PR; track as a metric with no gate at all Per-PR measurement needs the seeded reference workload on every push, which is too slow to be tolerated and would be disabled within a month. Purely advisory budgets get ignored. The split keeps the expensive measurement nightly while the cheap check that predicts a regression — reports reading snapshots rather than recomputing — blocks merges.
DL-016-04 99% availability, deliberately modest. 99.9% or higher This is a long-horizon tracker checked weekly or monthly. No order is placed from it and no decision turns on it being up at a given minute. Engineering for higher availability would spend real money to solve a problem the product does not have.
DL-016-05 Quarterly restore testing, explicitly required. Rely on backups running successfully A backup that has never been restored is an assumption, not a recovery plan. It also gives the only practical way to verify BR-004-16 — that deleted-user data is genuinely gone from backups.
DL-016-08 Weekly backups, not daily. Daily (originally specified); continuous WAL archiving / PITR Sets the recovery point objective at up to 7 days of data loss, accepted deliberately at current scale. Much of a lost week is recoverable — the user can re-import the B3 extract — but manual entries, wallet structure, allocations and reconciliation adjustments exist only here and would be gone. The trade is judged acceptable while the user base is small and each user's loss is bounded; it should be revisited as that changes. Daily costs almost nothing extra in storage (§sizing), so this is a decision about operational simplicity, not cost.
DL-016-06 Charts must never be the sole carrier of information. Standard accessibility audit only A reporting product is mostly charts, so a generic audit would pass while the actual content remained unreachable to screen-reader users. This makes the specific failure mode explicit, and it helps colour-blind users too.
DL-016-07 pt-BR only, using market vocabulary untranslated. Ship bilingual; translate terms into English equivalents The target user is a Brazilian retail investor who thinks in proventos and preço médio. Translating those into "distributions" and "average cost" in a Portuguese interface would make the product read as foreign. English is deferred until there is a reason for it.

Clone this wiki locally