Files
ksv741 329d66e767
Specs security / security (push) Successful in 8s
Specs verify / verify (push) Successful in 11s
spec: finalize wealth-ledger SDD migration
2026-10-09 21:14:22 +03:00

13 KiB

QA Analysis

Verification Scope

In Scope

  • Authorised, black-box verification of the affected personal-resource HTTP reads: Accounts, account and all Portfolio, operations, and account and all events.
  • The distinction between a local ordinary GET/retry and the permitted acquisition paths: the hourly walk, a first unconfirmed historical operations interval, and a first unopened candle range.
  • Observable hourly-walk scheduling and outcome semantics, including connection-scoped Accounts sync and resource meta.lastAttempt.
  • Resource-envelope semantics for confirmed data, empty confirmed data, first load, stale fallback, partial/failed attempts, and connection unavailability.
  • Current-connection access boundaries after T-Bank connection creation, replacement, and deletion, including retained value-history non-disclosure.
  • Events scope, date-window, saved-forecast, and failed-refresh behavior.
  • Compatibility of the backend-generated OpenAPI/runtime interface with the approved target envelope and preservation of established route identities and Problem Details behavior.
  • User-visible resilience: retry performs an HTTP reread only; cached successful screen data, server fallback, and failed background HTTP reads remain distinguishable.

Out of Scope

  • Scheduler implementation, persistence layout, internal job reservations, upstream-client mechanics, and frontend test structure.
  • New public reading of portfolio value-history, manual personal synchronization, currency conversion, multi-process scheduling, and changes to unrelated investment or banking resources.
  • Verifying T-Bank or public-reference-provider correctness beyond controlled responses needed to observe WealthLedger's published behavior.

Coverage Matrix

Approved behavior Black-box verification Expected observable result
Ordinary personal GETs are read-only Read Accounts, Portfolio, operations, and events repeatedly, including user retry and screen reopen, while upstream personal calls are observable. Each read returns only locally held state and causes no personal upstream work or new hourly attempt.
First-load exceptions stay narrow Open an unconfirmed historical operations interval and, separately, an unopened candle range; then reread each after confirmation. Only the requested missing interval/range may acquire data. It exposes incomplete local state until confirmed; no Accounts, Portfolio, events, other interval, or range refresh occurs. Confirmed reads stay local.
Hourly ownership and cadence Connect successfully; observe initial work, an elapsed eligible term, a restart after downtime, and a term arriving during an active walk. Connection starts one initial attempt. Subsequent attempts begin no earlier than 60 minutes from the preceding start; restart performs at most one current attempt; overlapping terms neither run nor queue.
Hourly result is observational Observe no attempt, running, succeeded, partial, and failed results through affected resources and Accounts. meta.lastAttempt distinguishes all five states with safe scoped problems; Accounts sync is null before an attempt and otherwise the connection-wide result. Reading it starts nothing.
Independent section persistence Make one account/section succeed and another fail during a walk. Successful current data persists; the earlier complete result for the failed section remains visible; the attempt is partial with only safe section/account/error-code problem data.
Envelope state meanings Exercise a fresh complete result, stale complete fallback, no complete result while work runs, no complete result after failure, and confirmed empty Accounts/Portfolio/events. Every success has { data, meta }; meta separately reports freshness, completeness, lastSuccessfulAt, lastAttempt, and availability. [] is available and complete, while no complete result is data: null and never presented as complete or fresh.
Failed refresh preserves known data Cause a temporary hourly failure after a confirmed Accounts, Portfolio, operations, or events result. 200 retains the original complete data and success time; freshness reflects that result; the failed attempt is separately visible. A completed background failure is not a synchronous 503.
Invalid connection boundary Request personal resources with no connection, then after a known-invalid token result. No connection returns established 409 TBANK_NOT_CONNECTED; invalid token returns established 400 INVALID_TBANK_TOKEN, retains the connection record, and discloses no personal fallback data.
Connection replacement and deletion Replace a valid connection while an old walk is pending or running, then delete the replacement twice. PUT validates before changing the prior connection, establishes a new boundary and initial walk on success; old data/status cannot reappear. DELETE returns 204 idempotently, stops use of its token, and hides current personal data and retained history until the same account is confirmed again.
Events query and saved forecast Read account and all events for default, explicit, intersecting, non-intersecting, and empty windows; submit from > to; fail a later refresh. Dates are strict inclusive UTC dates; defaults are current UTC date through +30 calendar days; invalid range returns 400 INVALID_EVENTS_PERIOD without source work. Results are the intersection with the forecast's original window and retain its calculatedAt/window. Empty intersections are successful empty data. all is complete only with every included account contribution. Failed refresh retains the previous forecast and reports the attempt failure separately.
Frontend recovery and accessibility Observe a successful resource screen during HTTP reread failure, a server stale/fallback result, a failed hourly attempt, and each no-data first-load state. Successful cached screen data remains visible during/after background HTTP failure. Retry only rereads HTTP. Client-read failure, server stale data, and failed hourly work are distinct, and the five meta meanings are exposed in text or accessible names rather than color alone.

Cross-system Verification

  1. Use a controlled upstream boundary to prove that normal GETs and retry actions do not cause personal upstream requests, while an eligible hourly walk and each permitted first-load exception have only their approved source effect.
  2. Verify the API response and the rendered Accounts, Portfolio, operations, and events states together for the same server conditions. In particular, a saved complete result plus a failed attempt must remain readable and visibly distinguishable from a client HTTP-read failure.
  3. Verify that successful PUT replacement and DELETE invalidate visible personal-resource state. Late responses or late old-connection work must not restore accounts, Portfolio, events, sync, or retained history across the new boundary.
  4. Compare the generated backend OpenAPI published for delivery with runtime responses and the consumer-generated types. Confirm the target { data, meta } resources, Accounts-only sync, all required meta meanings, nullability, and enum values are represented without relying on legacy sync=observe to start work.

Risk-based Priorities

Priority Risk Verification focus
P0 A screen read initiates brokerage work or leaks data across a connection boundary. Upstream-call absence on GET/retry; replacement/deletion fence; invalid-token and no-connection responses.
P0 A failed refresh hides or mislabels financial data. Complete fallback retention; data: null when no complete result exists; empty complete results; independent meta and attempt states.
P0 Events return an incorrect period, silently omit an account in all, or relabel an old forecast. Strict UTC window validation/defaults/intersection; all completeness; preserved calculatedAt and original forecast window after failure.
P1 Scheduler work overlaps, catches up, or reports unsafe/incorrect status. First walk, 60-minute eligibility from start, downtime, overlap drop, partial result, safe problem scope.
P1 Contract evolution breaks the generated frontend consumer or existing API callers. Generated OpenAPI/runtime semantic comparison, route and established Problem Details compatibility, legacy observation endpoint non-command behavior.
P2 Presentation obscures recovery and freshness meaning. Accessible status text, separate client/server/hourly indicators, retained screen snapshot, empty states.

Test Data and Environment Needs

  • An authenticated user with controlled valid, invalid, and unavailable T-Bank outcomes; at least two supported accounts plus an unsupported account to establish membership and partial-result cases.
  • Persisted fixtures for fresh and stale complete Accounts, Portfolio, operations, and forecasts; no-result first-load state; confirmed empty Accounts; empty Portfolio; empty event intersection; and a forecast whose source window differs from the request window.
  • Controllable clock and observable upstream boundary to establish hourly eligibility, running overlap, restart behavior, and proof that normal reads have no personal upstream activity.
  • Two valid connection identities with disjoint accounts and one shared account, plus retained value-history data, to verify replacement/deletion concealment and re-confirmed access.
  • Published backend OpenAPI for the delivered build and the corresponding generated frontend contract, both from the same build candidate.

Manual / Exploratory Scope

  • Navigate Accounts, account Portfolio, operations, and upcoming events through first load, available empty, stale fallback, failed hourly update, invalid token, and no-connection states. For operations, include an incomplete first-loaded interval and its later confirmed result. Confirm status meaning is understandable without color and no manual personal-sync control is exposed.
  • Keep an investment screen open across its periodic reread and induce a failed HTTP read. Confirm the prior screen snapshot remains visible and that retry changes only the HTTP-read state.
  • Replace or delete a connection while navigating between account and event views. Confirm neither navigation, browser history, nor a late response exposes data from the prior connection.
  • Explore boundary dates around UTC midnight, the inclusive forecast window endpoints, leap-day dates, and empty intersections for both account and all events scopes.

Automation Candidates

  • Repeatable system checks for the resource-envelope state matrix, hourly cadence/overlap, local-read upstream-call absence, connection revision fence, and event window/scope matrix.
  • Consumer-contract compatibility checks that compare the generated backend OpenAPI, runtime resource responses, and regenerated frontend transport types for affected public operations.
  • Browser-level checks for retry-only reads, retained successful UI data, invalidation after connection change, and accessible status names.

Observability Verification

  • Confirm resource responses expose no attempt as none, running work without finishedAt, and terminal succeeded/partial/failed work with only safe section, account, and error-code problem details.
  • Confirm lastSuccessfulAt, freshness, completeness, and availability continue to describe the returned data rather than the later attempt; sync is null before any Accounts walk and remains connection-scoped thereafter.
  • Confirm no response, OpenAPI example, UI status, or observable problem detail discloses a token, upstream payload, cursor, internal connection revision, or old-connection status.

Regression Impact

  • Existing clients of the affected GET routes must retain route identities, account and all scopes, date validation/defaults, response ordering where specified, and established Problem Details codes unless the approved generated contract explicitly changes them.
  • Existing sync=observe and /api/v1/tbank-sync/{id} observation behavior may remain compatible but must not regain request-started personal synchronization semantics.
  • Accounts, Portfolio, operations, and events callers must handle the approved envelope evolution, including nullable data, independent attempt state, empty complete data, and Accounts-only sync; generated frontend types must match the published backend OpenAPI.
  • Unaffected public history-reading capability is not introduced. Retained value history remains unavailable outside a confirmed current connection boundary.

Gaps / Blockers

None identified in the approved System Analysis and deltas. Field names used by the generated OpenAPI remain a delivery compatibility check: they must faithfully represent the approved target semantics before release.