Worked lock example
A goal has ₦12,000 saved, of which ₦10,000 is locked until 1 December. A customer requests ₦3,000 in October. Only ₦2,000 is free, so the request fails without a partial debit unless the product explicitly offers partial withdrawal. A ₦2,000 request may pass if the product permits free-balance withdrawals. After maturity, a ₦3,000 request can pass. Run the same sequence through mobile, web, and a scheduled worker. These figures are invented and serve only to test the boundary.
Try every withdrawal path
Find the mobile, web, agent, support, scheduled payout, and internal API paths that can debit savings. Run the same locked-account case through each one. Check that an old mobile app cannot call an unguarded endpoint.
Checks to run
- Test active, matured, suspended, and manually released lock states.
- Apply the lock inside the debit transaction; test a maturity change while a withdrawal is in flight.
- Make override access separate from normal support access and require a reason and second approval.
Override path
Try a blocked withdrawal as a customer and as support staff. Both should fail while the lock is active. Then grant a documented early-release approval and retry. The new debit must cite that approval. Remove the approval and confirm an old token cannot repeat the override.
Test a scheduled payout queued before maturity but executed after a lock change. The worker must check the current lock when it actually posts money.
One more boundary test
Test maturity and timezone edges. A lock set to end at midnight in Lagos should have a stored UTC instant; a device in another timezone must not decide the release time. Run one withdrawal just before and one just after that instant. Then test a reversal of a withdrawal made after maturity. A reversal should restore the correct free or locked portion according to the product rule, not simply add to an undifferentiated balance. Record the rule version with the reversal.
Check a lock at the release point
Create a savings account with ₦20,000 and a lock that ends on 30 June at 00:00 Africa/Lagos. Try to withdraw ₦5,000 by app, agent API, scheduled job, and staff tool one second before the end. All four paths must use the same server rule and fail unless a recorded override applies. Retry at the exact release time and one second after. Write down whether the end is inclusive; then test it. If an override is allowed, require actor, reason, approval, and a linked ledger entry. A disabled app button cannot enforce a rule for another channel.
Define the exact unlock comparison
Use a stored release instant of 30 June at 00:00 Africa/Lagos, converted to UTC. Define unlocked as server_time greater than or equal to that instant. Test one second before, exactly at, and one second after. In another run, staff add a freeze while a payout waits. Read lock state and debit the balance within the same transaction rule so a pre-check cannot become stale before posting. The maturity rule and an account freeze are separate conditions; maturity does not override a fraud freeze. Retain both state versions and the decision. A reversal restores the portion named by the product policy with a linked ledger action.
Primary sources
Next step
Call every withdrawal path against one locked account and verify that none can post a debit without an approved release. Read the related guide. For a review of your own system, request a security review.