API Tender Legacy Bridge Status
Date: 2026-03-19 Sprint: Platform Cleanup Sprint 104
Scope
This document isolates the tender legacy compatibility route shell from the gateway-side legacy outbox bridge that still lives in the same services/api module.
It is not removal planning. It is a boundary-clarification step before later removal planning.
Route / Action Inventory
| Route | Local action | Route classification | Bridge classification | Operational need today | Separable? | Looks isolatable next? |
| --- | --- | --- | --- | --- | --- | --- |
| POST /api/v1/tenders/legacy/propose | proposeTenderFromKes | legacy compatibility route that also triggers gateway-side bridge behavior | emits TENDER_CREATED through the bridge helper | yes | yes | yes |
| POST /api/v1/tenders/legacy/:id/bids | submitLegacyBid | legacy compatibility route that also triggers gateway-side bridge behavior | emits BID_SUBMITTED through the bridge helper | yes | yes | yes |
| POST /api/v1/tenders/legacy/:id/close | closeLegacyBidding | legacy compatibility route that also triggers gateway-side bridge behavior | emits BIDDING_CLOSED through the bridge helper | yes | yes | yes |
| POST /api/v1/tenders/legacy/:id/award/propose | proposeLegacyAward | legacy compatibility route that also triggers gateway-side bridge behavior | emits AWARD_PROPOSED through the bridge helper | yes | yes | yes |
| POST /api/v1/tenders/legacy/:id/award/ratify | ratifyLegacyAward | legacy compatibility route that also triggers gateway-side bridge behavior | emits AWARD_RATIFIED through the bridge helper | yes | yes | yes |
What The Route Shell Still Does
The route shell in legacyRoutes.ts:
- checks
LEGACY_TENDERS_LOCAL_ENGINE_ENABLED - resolves the gateway-local legacy viewer
- reads request input
- runs local-engine tender compatibility actions from engine.ts
- maps route-level error responses
That route shell is compatibility behavior. It is not canonical upstream tender action ownership.
Actual Bridge Ownership Inventory
Bridge helper
- Current implementation lives in:
- Current helper:
enqueueLegacyTenderBridgeEvent(...)
What the bridge does
- posts to
TENDERS_SERVICE_URL - uses
LEGACY_TENDERS_OUTBOX_PATH, default/legacy/tenders/events - attaches:
tenderIdeventTypeactorIdintentIddedupeKeypayload
What calls the bridge
- only the tender legacy compatibility routes in legacyRoutes.ts
Why the bridge still exists
- it preserves the older gateway-side append path into the legacy tender outbox flow
- that flow is still operationally real in docs and code:
Which Parts Are Route Compatibility Only
- route path mounting under
/api/v1/tenders/legacy/* - request parsing and route-level response shaping
- local-engine action execution against engine.ts
Which Parts Are Bridge Behavior
- the optional enqueue to
TENDERS_SERVICE_URL + LEGACY_TENDERS_OUTBOX_PATH - event-type selection:
TENDER_CREATEDBID_SUBMITTEDBIDDING_CLOSEDAWARD_PROPOSEDAWARD_RATIFIED
intentIdanddedupeKeyderivation- bridge failure mapping to
502 legacy_outbox_enqueue_failed
What Remains Operationally Needed
- the route shell remains live mounted API surface
- the bridge remains operationally meaningful because it appends to a documented legacy event/outbox path
- I did not find verified direct in-repo app callers, but that absence does not make the bridge dead
What Looks Isolatable Next
The strongest next isolation step is:
- keep the public
/api/v1/tenders/legacy/*route shape unchanged - move the gateway-side outbox bridge into a dedicated helper/module with explicit compatibility naming
- leave the local-engine route shell separate from that bridge contract
That would reduce ambiguity without starting removal.
Notes
- Route compatibility and bridge behavior are separable in code today even though they still live in the same file.
- The current blocker is conceptual/ownership ambiguity, not missing runtime scaffolding.