13 KiB
13 KiB
QA Analysis
Verification Scope
In Scope
- Authorised, black-box verification of the affected personal-resource HTTP reads: Accounts, account and
allPortfolio, operations, and account andallevents. - 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
syncand resourcemeta.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
- 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.
- 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.
- 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. - Compare the generated backend OpenAPI published for delivery with runtime responses and the consumer-generated types. Confirm the target
{ data, meta }resources, Accounts-onlysync, all required meta meanings, nullability, and enum values are represented without relying on legacysync=observeto 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
allevents 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 withoutfinishedAt, 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;syncisnullbefore 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
allscopes, date validation/defaults, response ordering where specified, and established Problem Details codes unless the approved generated contract explicitly changes them. - Existing
sync=observeand/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-onlysync; 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.