Repository navigation
Project bond maturity as terminal; preview the closing payout in the UI - #276
Merged
Merged
Conversation
…on route
Ingestion maps the new BondMatured event to a MATURED history entry that
carries paymentCount, principalPaid, couponPaid, and unsoldBurned, and to
a reducer transition that sets both the matured and redemption-complete
flags, since the final coupon now pays principal and burns every unit.
The composer's terminal status is matured; redeemed leaves the BondStatus
enum. The POST /v1/bonds/{isin}/redemptions route, its handler, and its
OpenAPI path are removed; the REDEMPTION operation type stays as a legacy
value so stored audit rows still validate. openapi.json is regenerated.
A reducer test proves the projected state is identical whether the
maturity flag or the token burns are applied first, matching ingestion's
manager-first ordering within a block. nb-bond-api: 245 jest tests green.
The pay-coupon modal detects the final period from the bond's remaining payment count and previews, per holder, the coupon, the principal, and the total, lists unsold units held by the bond manager as burned without payment (and as earning no coupon on interim periods), and warns when the government reserve's WNOK balance from the Central Bank resource cannot cover the total, since the whole transaction would revert. The action reads "Pay final coupon and close bond". The old treasury-held failure warning goes away: those units no longer block a payout. The Coupon payout page explains that it is a work queue and that the final coupon closes the bond; the Bonds filter loses the redeemed status; the Bond detail tooltips describe closure at maturity; the unused BondsApi.redeem client and the redeemed badge style are removed. nb-ui: 123 vitest tests green.
…dlock entry The coupon sequence diagram becomes a coupon-and-maturity sequence with the final-period branch (setMatured, Redeem settlement for coupon plus principal, unsold units burned without payment, BondMatured). The bond lifecycle classifier and state diagram drop the redeemed state; matured is terminal. Architecture, the diagrams index, the contracts README, and the API development guide (route list and scenario 6.4) follow. The "partially allocated bonds deadlock coupon payment" known issue is removed: unsold manager-held units are now skipped on coupons and burned at maturity, so the coupon route's allowlisting hint goes too. The closed-loop plan's Phase 6 note records that maturity closure exists.
… final coupon Phase 4 of docs/plans/redeem-with-final-coupon/: on a fresh local sandbox a fully allocated bond and a bond with 40 unsold units on the manager both closed in their final coupon transaction. Holders received coupon plus principal, unsold units were burned without payment, WNOK supply never changed, the manager never needed allowlisting, and each closure projected one MATURED history entry with its totals and a terminal matured status with zero supply.
2 tasks done
Greaker
added a commit
that referenced
this pull request
Sep 8, 2026
Move docs/plans/redeem-with-final-coupon/ to docs/plans/archive/ with its status set to Implemented (shipped via #275 and #276), tick its done criteria, close out progress.md, and move the documentation-index entry to the archive list. ADR 0005 moves to Accepted in the ADR index and the documentation index. The contracts versioning note no longer names the removed BondManager.redeem entry point.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/plans/redeem-with-final-coupon/). The API ingestsBondMaturedas aMATUREDhistory entry carryingpaymentCount,principalPaid,couponPaid, andunsoldBurned, and as the terminal bond transition;maturednow means closed with zero supply andredeemedleavesBondStatus.POST /v1/bonds/{isin}/redemptionsand the unused UI client are removed; theREDEMPTIONaudit type stays as a legacy value.openapi.jsonis regenerated.progress.mdrecords the fresh-sandbox evidence: a fully allocated bond and a bond with 40 unsold units both closed in one final-coupon transaction, WNOK supply unchanged,MATUREDprojected with totals.Test plan
cd services/nb-bond-api && npm run lint && npm run format:check && npm test && npm run build— 245 tests (incl. reducer order-independence)cd services/nb-ui && npm run format:check && npm run lint && npm test && npm run build— 123 tests (final-payout preview, unsold units, reserve warning)python3 scripts/verification/check-public-repo-hygiene.py && python3 scripts/verification/check-markdown-links.py./sandbox.sh delete && ./sandbox.sh starton the branch; two bonds run to maturity throughhttp://bond-api.cbdc-sandbox.local/with balance trails indocs/plans/redeem-with-final-coupon/progress.md