{"ns":"vault","title":"Vault Ledger","version":"2.6","summary":"Vault Ledger is a retail-banking view for internal transfers. A customer sees a Portfolio of a Checking and a Savings account with net liquidity, moves money between them through Move Funds, Review Transfer and an explicit Authorize step, and gets a reference for every completed transfer.","problem":"Customers must be certain that an authorized transfer debits and credits exactly the amount shown at review, so that balances and net liquidity always reconcile to the cent.","personas":[{"name":"Retail customer","need":"Shift money between own accounts and see exact balances afterwards."}],"goals":["Every transfer debits the origin and credits the destination by exactly the reviewed amount; net liquidity never changes.","Nothing moves until the customer authorizes it.","Invalid amounts and account choices are refused at review with a specific message."],"features":[{"id":"PRT","title":"Portfolio","summary":"Balances and net liquidity.","reqs":[{"id":"FR-PRT-01","weight":"Must","text":"A fresh session shows the seeded balances and net liquidity equal to their sum.","accept":["Heading \"Portfolio\"; Checking •••• 4417 $4,823.50; Savings •••• 9032 $12,150.00; Net liquidity $16,973.50"]},{"id":"FR-PRT-02","weight":"Should","text":"Each browser tab has its own ledger and balances are stored on the server, so they survive a reload but never leak into another tab.","accept":["After a $100.00 transfer in one tab Checking is $4,723.50; a second new tab shows $4,823.50","Balances are identical after a reload"]}]},{"id":"TRF","title":"Transfer flow","summary":"Move Funds, Review Transfer and Authorize.","reqs":[{"id":"FR-TRF-01","weight":"Must","text":"Review shows the origin, destination and amount; Authorize Transfer then moves money and shows a confirmation with a reference starting \"TRF-\". Returning to the Portfolio shows the new balances.","accept":["Checking → Savings $50.00: \"Review transfer\" From Checking, To Savings, Amount $50.00; \"Transfer authorized\" — \"Moved $50.00 from Checking to Savings.\"","Checking $4,773.50; Savings $12,200.00; Net liquidity $16,973.50"]},{"id":"FR-TRF-02","weight":"Must","text":"Transfers work in both directions and keep net liquidity unchanged.","accept":["Savings → Checking $1,250.75: \"Moved $1,250.75 from Savings to Checking.\"; Checking $6,074.25; Savings $10,899.25; Net liquidity $16,973.50"]},{"id":"FR-TRF-03","weight":"Should","text":"Balances carry over between transfers in the same session.","accept":["$20.00 then $30.00 from Checking: Checking $4,773.50, Savings $12,200.00, same after a reload"]},{"id":"FR-TRF-04","weight":"Could","text":"The From list labels each account with its current balance; the To list shows names only, with Savings preselected.","accept":["From: \"Checking ($4,823.50)\", \"Savings ($12,150.00)\"; To: \"Checking\", \"Savings\""]},{"id":"FR-TRF-05","weight":"Should","text":"Edit on the review screen returns to Move Funds with the previous values; Cancel at any step leaves balances unchanged.","accept":["Edit shows Amount \"75.00\", From Checking, To Savings","Cancel returns to the Portfolio with Checking $4,823.50"]},{"id":"FR-TRF-06","weight":"Could","text":"Reloading in the middle of a transfer returns to the Portfolio and nothing is transferred.","accept":["After review of $60.00 and a reload: Portfolio, Checking $4,823.50"]}]},{"id":"AMT","title":"Amount validation","summary":"Limits, rounding and account choice.","reqs":[{"id":"FR-AMT-01","weight":"Must","text":"A transfer may use the entire available balance but not one cent more.","accept":["4823.50 from Checking: Checking $0.00, Savings $16,973.50","4823.51: alert \"Amount exceeds the available balance.\"; stays on Move Funds"]},{"id":"FR-AMT-02","weight":"Must","text":"Only positive amounts are accepted; zero, negative, blank and non-numeric values are refused.","accept":["\"0\", \"-5\", empty and \"fifty\": \"Enter an amount greater than $0.00.\""]},{"id":"FR-AMT-03","weight":"Should","text":"Amounts are rounded to whole cents; the smallest valid transfer is $0.01.","accept":["\"0.004\" rounds to $0.00 and is refused with \"Enter an amount greater than $0.00.\"","\"0.01\": Checking $4,823.49; Savings $12,150.01"]},{"id":"FR-AMT-04","weight":"Must","text":"Origin and destination must differ.","accept":["\"Choose two different accounts.\""]},{"id":"FR-AMT-05","weight":"Should","text":"An amount typed with a thousands separator is accepted and shown correctly on the review screen.","accept":["\"1,000\" reviews as Amount $1,000.00"]}]},{"id":"API","title":"Ledger API","summary":"REST access to the portfolio, review and transfers.","reqs":[{"id":"FR-API-01","weight":"Should","text":"The portfolio is returned in cents per session; review validates without moving money.","accept":["checking 482350, savings 1215000, netLiquidity 1697350","Review checking → savings \"50\": 200, amount 5000, fromName \"Checking\", toName \"Savings\"; balances unchanged","Same account both sides: 422 \"Choose two different accounts.\""]},{"id":"FR-API-02","weight":"Should","text":"Authorize returns the new balances and the session’s transfers are listed; over-limit amounts are refused.","accept":["Authorize $50: 201, id \"TRF-…\", status \"authorized\", checking 477350, savings 1220000, netLiquidity 1697350","List shows exactly one transfer of amount 5000","Amount \"999999\": 422 \"Amount exceeds the available balance.\""]}]}],"nfr":[{"id":"NFR-01","weight":"Must","text":"Ledger integrity: for every authorized transfer the origin falls and the destination rises by exactly the reviewed amount, so net liquidity is unchanged."},{"id":"NFR-02","weight":"Should","text":"Data format: money is shown with a $ sign, thousands separators and two decimals; the API uses integer cents."}],"glossary":[{"term":"Net liquidity","meaning":"Checking balance plus Savings balance."},{"term":"Review Transfer","meaning":"The validation step that precedes authorization and moves no money."}],"outOfScope":["External transfers and payees","Authentication"]}