Fintech repository evidence map
Reviewed: 2026-08-22 (Asia/Dubai)
Reference repository (read-only):
/Users/mustafa/Documents/Codex/2026-08-22/c/fintech-project
This is the audit trail for deliverable/01-repository-case-study.md. All code
locators below are relative to the reference repository. The review uses three
labels deliberately:
- Observed: a fact visible at the cited file and line.
- Documented: an AWS or pattern semantic controlled by the cited claim and
source IDs in
claim-register.mdandsource-ledger.md. - Inference: an architecture conclusion from observed code plus documented semantics; it is not a vendor guarantee.
As-built runtime and infrastructure trace
Section titled “As-built runtime and infrastructure trace”| Path | Observed implementation | Exact repository route | Boundary / role |
|---|---|---|---|
| Order API | The production HTTP API exposes POST /orders through an AWS proxy integration to the order-handler alias. | infra/environments/production/main.tf:419-477 | Synchronous client/API/Lambda request path. API success is not downstream business completion (C51/A53). |
| Input and identity | The handler parses JSON, validates the order, generates a new order ID, and builds a PENDING order record. | code/lambdas/order-handler/handler.ts:114-153; code/shared/validation/schemas.ts:15-27 | Command validation and operational order-state creation. |
| Idempotency lookup | A supplied Idempotency-Key is read before order processing; lookup failure is explicitly fail-open. | code/lambdas/order-handler/handler.ts:219-241 | Best-effort response cache, not business idempotency (C40/F11). |
| Order persistence | The order is written to the main DynamoDB table with a standalone PutCommand. | code/lambdas/order-handler/handler.ts:155-165 | First durable side effect of order submission. |
| Idempotency persistence | A cached 201 response is conditionally put in a separate table after the order write and before publication; any store error is logged and ignored. | code/lambdas/order-handler/handler.ts:81-104,167-181; infra/environments/production/main.tf:617-658 | Separate write and cache boundary. TTL is cleanup, not a correctness deadline (C32/A23). |
OrderPlaced publication | The handler calls PutEvents after both database writes, catches thrown errors, but does not retain or inspect the API result. | code/lambdas/order-handler/handler.ts:183-212 | Synchronous producer API call followed by intended asynchronous routing. PutEvents can partially fail; even zero failed entries plus EventId is only producer-API acknowledgement and can accompany a nonexistent-bus drop (C08/A06,A82). |
| Event bus and order target | The custom bus/rule configuration intends to route trading.OrderPlaced to trade-executor. The reusable target attaches a per-rule SQS DLQ ARN, but its module creates no queue resource policy granting EventBridge sqs:SendMessage. | infra/environments/production/main.tf:345-359; infra/modules/eventbridge/main.tf:29-38,62-95; bounded absence check below | EventBridge target delivery is distinct from Lambda runtime processing. The declared DLQ is not a usable recovery path until the queue policy exists (C05-C07,C57/A01,A04,A05,A81). |
| Trade execution | The handler validates the event, generates a trade ID, and calculates a random simulated price using binary floating point. | code/lambdas/trade-executor/handler.ts:65-96 | This is a simulation inside Lambda, not an order-book/matching-engine implementation. |
| Trade persistence | A trade item keyed by the order ID is conditionally inserted. | code/lambdas/trade-executor/handler.ts:83-104 | Duplicate trade-row guard for that key; not an atomic business workflow. |
| Order mutation | A separate update changes the order to EXECUTED; it has no condition requiring the previous state to be PENDING. | code/lambdas/trade-executor/handler.ts:106-118 | Second DynamoDB side effect. |
TradeExecuted publication | A third standalone operation sends an integration event and ignores the PutEvents result. | code/lambdas/trade-executor/handler.ts:120-148 | Producer/database dual-write boundary (C08, C22, C38). |
| Notification fan-out | One EventBridge rule targets notification-sender; the handler validates and publishes JSON to an SNS topic. | infra/environments/production/main.tf:360-370; code/lambdas/notification-sender/handler.ts:43-90 | Derived client-notification path, not authoritative financial state (C46). |
| Portfolio fan-out | A separate rule targets portfolio-updater and declares a separate SQS DLQ ARN. The handler reads a portfolio, applies the trade, and conditionally replaces the item using its current version, retrying conflicts three times. No queue resource policy is declared for this DLQ either. | infra/environments/production/main.tf:565-615; code/lambdas/portfolio-updater/handler.ts:103-198; bounded absence check below | Asynchronous mutable projection. The event has no projection inbox/deduplication record or source sequence, and the declared DLQ lacks its required write permission. |
| Trade query | GET /trades invokes trades-reader, which queries GSI1 by user and time prefix with a maximum result limit of 100. | infra/environments/production/main.tf:695-729; code/lambdas/trades-reader/handler.ts:45-97 | Read path through an eventually consistent GSI (C21/A19). No pagination token is returned. |
| Daily snapshot | A scheduled rule invokes portfolio-snapshot. One filtered Scan result is converted in memory to one JSONL object and written to S3. | infra/environments/production/main.tf:373-393; code/lambdas/portfolio-snapshot/handler.ts:64-107 | Derived batch/export path. It is not a proven complete point-in-time financial snapshot. |
| Event archive and target DLQs | The EventBridge module declares a 30-day archive, 14-day SQS queues, and queue-depth alarms; production separately declares the portfolio queue/alarm. Neither Terraform path declares aws_sqs_queue_policy or an events.amazonaws.com sqs:SendMessage grant, so EventBridge cannot be shown able to populate those queues. The depth alarms can remain zero while InvocationsFailedToBeSentToDLQ rises. | infra/modules/eventbridge/main.tf:15-60,76-95; infra/environments/production/main.tf:575-605; bounded absence check below | Archive is a bounded replay source; the SQS queues are only intended holding paths until permissions are fixed. Neither is reconciliation (C43,C57/A81). |
| Manual redrive | dlq-replayer receives at most ten messages, reconstructs PutEvents entries, deletes after the SDK call returns, and does not inspect per-entry failures or independently validate the named bus. | code/lambdas/dlq-replayer/handler.ts:61-145 | Operator-triggered redrive. HTTP 200, zero failures, or EventId is only producer-API acknowledgement; deletion needs validated bus configuration, durable replay identity, and downstream reconciliation (C08/A06,A82). |
| Observability | Every Lambda module enables active X-Ray tracing, a 14-day log group, and a Lambda error alarm; handlers use Powertools Logger and propagate a correlation ID in events. | infra/modules/lambda/main.tf:12-70; code/shared/types/events.ts:1-12 | Technical telemetry exists; business-correctness and reconciliation metrics are not apparent (C48, C50). |
| Deployment | Lambda aliases are the integration targets and CodeDeploy declares a 10%-for-five-minutes canary only for order-handler. | infra/modules/lambda/main.tf:42-49; infra/environments/production/main.tf:479-517 | Deployment safety is narrower than end-to-end workflow compatibility. |
| IAM | Production defines per-function roles: order handler can write/read DynamoDB and publish events; trade executor can write/update/read and publish; notifier can publish SNS; snapshot can scan/write S3; portfolio updater can get/put; trades reader can query; replayer can receive/delete from named DLQs and publish. The events.amazonaws.com principals at lines 391, 401, 410, and 613 are Lambda resource permissions, not SQS queue policies. | infra/environments/production/main.tf:102-239,386-411,521-549,608-615,645-773 | Function/resource permissions are visible, but the DLQ sqs:SendMessage grants are absent; this is not a complete security audit. |
- Path
- Order API
- Observed implementation
- The production HTTP API exposes
POST /ordersthrough an AWS proxy integration to the order-handler alias. - Exact repository route
infra/environments/production/main.tf:419-477- Boundary / role
- Synchronous client/API/Lambda request path. API success is not downstream business completion (C51/A53).
- Path
- Input and identity
- Observed implementation
- The handler parses JSON, validates the order, generates a new order ID, and builds a
PENDINGorder record. - Exact repository route
code/lambdas/order-handler/handler.ts:114-153;code/shared/validation/schemas.ts:15-27- Boundary / role
- Command validation and operational order-state creation.
- Path
- Idempotency lookup
- Observed implementation
- A supplied
Idempotency-Keyis read before order processing; lookup failure is explicitly fail-open. - Exact repository route
code/lambdas/order-handler/handler.ts:219-241- Boundary / role
- Best-effort response cache, not business idempotency (C40/F11).
- Path
- Order persistence
- Observed implementation
- The order is written to the main DynamoDB table with a standalone
PutCommand. - Exact repository route
code/lambdas/order-handler/handler.ts:155-165- Boundary / role
- First durable side effect of order submission.
- Path
- Idempotency persistence
- Observed implementation
- A cached
201response is conditionally put in a separate table after the order write and before publication; any store error is logged and ignored. - Exact repository route
code/lambdas/order-handler/handler.ts:81-104,167-181;infra/environments/production/main.tf:617-658- Boundary / role
- Separate write and cache boundary. TTL is cleanup, not a correctness deadline (C32/A23).
- Path
OrderPlacedpublication- Observed implementation
- The handler calls
PutEventsafter both database writes, catches thrown errors, but does not retain or inspect the API result. - Exact repository route
code/lambdas/order-handler/handler.ts:183-212- Boundary / role
- Synchronous producer API call followed by intended asynchronous routing.
PutEventscan partially fail; even zero failed entries plusEventIdis only producer-API acknowledgement and can accompany a nonexistent-bus drop (C08/A06,A82).
- Path
- Event bus and order target
- Observed implementation
- The custom bus/rule configuration intends to route
trading.OrderPlacedto trade-executor. The reusable target attaches a per-rule SQS DLQ ARN, but its module creates no queue resource policy granting EventBridgesqs:SendMessage. - Exact repository route
infra/environments/production/main.tf:345-359;infra/modules/eventbridge/main.tf:29-38,62-95; bounded absence check below- Boundary / role
- EventBridge target delivery is distinct from Lambda runtime processing. The declared DLQ is not a usable recovery path until the queue policy exists (C05-C07,C57/A01,A04,A05,A81).
- Path
- Trade execution
- Observed implementation
- The handler validates the event, generates a trade ID, and calculates a random simulated price using binary floating point.
- Exact repository route
code/lambdas/trade-executor/handler.ts:65-96- Boundary / role
- This is a simulation inside Lambda, not an order-book/matching-engine implementation.
- Path
- Trade persistence
- Observed implementation
- A trade item keyed by the order ID is conditionally inserted.
- Exact repository route
code/lambdas/trade-executor/handler.ts:83-104- Boundary / role
- Duplicate trade-row guard for that key; not an atomic business workflow.
- Path
- Order mutation
- Observed implementation
- A separate update changes the order to
EXECUTED; it has no condition requiring the previous state to bePENDING. - Exact repository route
code/lambdas/trade-executor/handler.ts:106-118- Boundary / role
- Second DynamoDB side effect.
- Path
TradeExecutedpublication- Observed implementation
- A third standalone operation sends an integration event and ignores the
PutEventsresult. - Exact repository route
code/lambdas/trade-executor/handler.ts:120-148- Boundary / role
- Producer/database dual-write boundary (C08, C22, C38).
- Path
- Notification fan-out
- Observed implementation
- One EventBridge rule targets notification-sender; the handler validates and publishes JSON to an SNS topic.
- Exact repository route
infra/environments/production/main.tf:360-370;code/lambdas/notification-sender/handler.ts:43-90- Boundary / role
- Derived client-notification path, not authoritative financial state (C46).
- Path
- Portfolio fan-out
- Observed implementation
- A separate rule targets portfolio-updater and declares a separate SQS DLQ ARN. The handler reads a portfolio, applies the trade, and conditionally replaces the item using its current version, retrying conflicts three times. No queue resource policy is declared for this DLQ either.
- Exact repository route
infra/environments/production/main.tf:565-615;code/lambdas/portfolio-updater/handler.ts:103-198; bounded absence check below- Boundary / role
- Asynchronous mutable projection. The event has no projection inbox/deduplication record or source sequence, and the declared DLQ lacks its required write permission.
- Path
- Trade query
- Observed implementation
GET /tradesinvokes trades-reader, which queriesGSI1by user and time prefix with a maximum result limit of 100.- Exact repository route
infra/environments/production/main.tf:695-729;code/lambdas/trades-reader/handler.ts:45-97- Boundary / role
- Read path through an eventually consistent GSI (C21/A19). No pagination token is returned.
- Path
- Daily snapshot
- Observed implementation
- A scheduled rule invokes portfolio-snapshot. One filtered
Scanresult is converted in memory to one JSONL object and written to S3. - Exact repository route
infra/environments/production/main.tf:373-393;code/lambdas/portfolio-snapshot/handler.ts:64-107- Boundary / role
- Derived batch/export path. It is not a proven complete point-in-time financial snapshot.
- Path
- Event archive and target DLQs
- Observed implementation
- The EventBridge module declares a 30-day archive, 14-day SQS queues, and queue-depth alarms; production separately declares the portfolio queue/alarm. Neither Terraform path declares
aws_sqs_queue_policyor anevents.amazonaws.comsqs:SendMessagegrant, so EventBridge cannot be shown able to populate those queues. The depth alarms can remain zero whileInvocationsFailedToBeSentToDLQrises. - Exact repository route
infra/modules/eventbridge/main.tf:15-60,76-95;infra/environments/production/main.tf:575-605; bounded absence check below- Boundary / role
- Archive is a bounded replay source; the SQS queues are only intended holding paths until permissions are fixed. Neither is reconciliation (C43,C57/A81).
- Path
- Manual redrive
- Observed implementation
- dlq-replayer receives at most ten messages, reconstructs
PutEventsentries, deletes after the SDK call returns, and does not inspect per-entry failures or independently validate the named bus. - Exact repository route
code/lambdas/dlq-replayer/handler.ts:61-145- Boundary / role
- Operator-triggered redrive. HTTP 200, zero failures, or
EventIdis only producer-API acknowledgement; deletion needs validated bus configuration, durable replay identity, and downstream reconciliation (C08/A06,A82).
- Path
- Observability
- Observed implementation
- Every Lambda module enables active X-Ray tracing, a 14-day log group, and a Lambda error alarm; handlers use Powertools Logger and propagate a correlation ID in events.
- Exact repository route
infra/modules/lambda/main.tf:12-70;code/shared/types/events.ts:1-12- Boundary / role
- Technical telemetry exists; business-correctness and reconciliation metrics are not apparent (C48, C50).
- Path
- Deployment
- Observed implementation
- Lambda aliases are the integration targets and CodeDeploy declares a 10%-for-five-minutes canary only for order-handler.
- Exact repository route
infra/modules/lambda/main.tf:42-49;infra/environments/production/main.tf:479-517- Boundary / role
- Deployment safety is narrower than end-to-end workflow compatibility.
- Path
- IAM
- Observed implementation
- Production defines per-function roles: order handler can write/read DynamoDB and publish events; trade executor can write/update/read and publish; notifier can publish SNS; snapshot can scan/write S3; portfolio updater can get/put; trades reader can query; replayer can receive/delete from named DLQs and publish. The
events.amazonaws.comprincipals at lines 391, 401, 410, and 613 are Lambda resource permissions, not SQS queue policies. - Exact repository route
infra/environments/production/main.tf:102-239,386-411,521-549,608-615,645-773- Boundary / role
- Function/resource permissions are visible, but the DLQ
sqs:SendMessagegrants are absent; this is not a complete security audit.
As-built flow
Section titled “As-built flow”Solid arrows are synchronous request/API calls from the caller's perspective. Dashed arrows are scheduled or broker-driven asynchronous handoffs. Cylinders are stores; double-bracket nodes are holding/replay paths.
Diagram text source
flowchart LR Client[Client] -->|POST /orders| API[API Gateway HTTP API] API --> OH[order-handler Lambda] OH -->|Put order| Main[(Main DynamoDB table)] OH -->|Put cached 201| Idem[(Idempotency DynamoDB table)] OH -->|PutEvents API| Bus{Custom EventBridge bus} Bus -. OrderPlaced target .-> TE[trade-executor Lambda] TE -->|Put trade; Update order| Main TE -->|PutEvents API| Bus Bus -. TradeExecuted target .-> PU[portfolio-updater Lambda] PU -->|Get; conditional Put| Main Bus -. TradeExecuted target .-> NS[notification-sender Lambda] NS --> SNS[SNS notification topic] Client -->|GET /trades| API API --> TR[trades-reader Lambda] TR -->|Query GSI1| Main Schedule[Daily schedule] -.-> PS[portfolio-snapshot Lambda] PS -->|filtered Scan| Main PS --> S3[(S3 JSONL snapshots)] Bus -. failed target delivery .-> DLQGap{{DLQ send denied:<br/>queue resource policy absent}} DLQGap -. InvocationsFailedToBeSentToDLQ .-> Metric[CloudWatch metric] DLQGap -. after required policy only .-> DLQ[[Declared per-target SQS DLQs]] Ops[Operator/manual invoke] --> DR[dlq-replayer Lambda] DLQ -->|Receive/Delete only if populated| DR DR -->|PutEvents API| BusExact topology routes: API and routes
infra/environments/production/main.tf:419-477,695-729; bus rules and targets
infra/environments/production/main.tf:345-411,565-615; generic DLQ declarations
infra/modules/eventbridge/main.tf:27-95; missing-policy absence check below; schedule
infra/environments/production/main.tf:373-393.
Authority classification
Section titled “Authority classification”| Data/component | As-built role | Authority conclusion |
|---|---|---|
| Order row | Mutable command status (PENDING, then EXECUTED). | Observed: it is the only persisted order-state row. Inference: it is the apparent operational authority for order status, but the code does not enforce a full order state machine or reservations. |
| Trade row | One conditional record per order key containing the simulated fill. | Observed: it is the apparent persisted execution fact. Inference: without matching, clearing/settlement, or ledger postings, it is not sufficient authority for cash or securities ownership. |
| Portfolio row | Mutable holdings and cost-basis view updated from TradeExecuted. | Inference: a derived projection. It cannot safely enforce available-balance or ownership invariants (C46/F17,F18). |
| GSI1 trade view | Replicated DynamoDB index queried by user. | Documented: GSI reads are eventually consistent (C21/A19). It is a query projection, not an independent authority. |
| Idempotency row | Cached HTTP status/body with TTL. | A response cache. It is neither the protected order mutation nor proof of valid event routing or downstream progress. |
| EventBridge bus/archive and SQS DLQs | Intended transport, bounded archive, and declared terminal-delivery queues. | Not a ledger or reconciliation system; the current SQS DLQs are not shown writable because their EventBridge queue policies are absent (C43, C47, C57). |
| S3 snapshot | Daily JSONL derived from mutable portfolios. | Analytics/audit convenience output; current implementation does not prove completeness or point-in-time consistency. |
| SNS notification | User-facing derivative of a trade event. | A notification, never evidence that the authoritative business process completed. |
- Data/component
- Order row
- As-built role
- Mutable command status (
PENDING, thenEXECUTED). - Authority conclusion
- Observed: it is the only persisted order-state row. Inference: it is the apparent operational authority for order status, but the code does not enforce a full order state machine or reservations.
- Data/component
- Trade row
- As-built role
- One conditional record per order key containing the simulated fill.
- Authority conclusion
- Observed: it is the apparent persisted execution fact. Inference: without matching, clearing/settlement, or ledger postings, it is not sufficient authority for cash or securities ownership.
- Data/component
- Portfolio row
- As-built role
- Mutable holdings and cost-basis view updated from
TradeExecuted. - Authority conclusion
- Inference: a derived projection. It cannot safely enforce available-balance or ownership invariants (C46/F17,F18).
- Data/component
- GSI1 trade view
- As-built role
- Replicated DynamoDB index queried by user.
- Authority conclusion
- Documented: GSI reads are eventually consistent (C21/A19). It is a query projection, not an independent authority.
- Data/component
- Idempotency row
- As-built role
- Cached HTTP status/body with TTL.
- Authority conclusion
- A response cache. It is neither the protected order mutation nor proof of valid event routing or downstream progress.
- Data/component
- EventBridge bus/archive and SQS DLQs
- As-built role
- Intended transport, bounded archive, and declared terminal-delivery queues.
- Authority conclusion
- Not a ledger or reconciliation system; the current SQS DLQs are not shown writable because their EventBridge queue policies are absent (C43, C47, C57).
- Data/component
- S3 snapshot
- As-built role
- Daily JSONL derived from mutable portfolios.
- Authority conclusion
- Analytics/audit convenience output; current implementation does not prove completeness or point-in-time consistency.
- Data/component
- SNS notification
- As-built role
- User-facing derivative of a trade event.
- Authority conclusion
- A notification, never evidence that the authoritative business process completed.
Guarantee-boundary audit
Section titled “Guarantee-boundary audit”| Boundary | What success proves | What it does not prove | Required design response |
|---|---|---|---|
| API Gateway to order-handler | The synchronous integration returned an HTTP response. | That a trade, reservation, ledger posting, projection, or notification completed (C51/A53). | Return an explicitly scoped acceptance state and expose order status. |
DynamoDB order PutCommand | That one order-row write returned successfully. | Publication to EventBridge or creation of a trade. DynamoDB transactions cannot include EventBridge (C22/A20). | Commit state plus an outbox record locally, then publish asynchronously (C38). |
PutEvents producer call | HTTP 200, zero failed entries, and EventId establish only producer-API acknowledgement for the named request. | Valid bus existence/configuration, matching/routing, target delivery, consumer durability, database effects, or business completion; a nonexistent bus can return those response signals and drop the event (C08/A06,A82). | Inspect entries, validate bus/configuration independently, retain stable replay identity, and reconcile downstream effects. |
| EventBridge bus to Lambda target | EventBridge owns target-delivery retry according to the target policy (C05/A05). | Function-runtime retry, handler rollback, one business effect, or a working target DLQ. The current queues lack the required EventBridge send policy (C57/A81). | Configure/observe target delivery separately; add rule-scoped queue policies and alarm both delivery failures and InvocationsFailedToBeSentToDLQ. |
| Lambda asynchronous invocation/runtime | Its retry and terminal destination are a separate boundary (C06/A01,A04,A05). | Atomicity across the handler's several SDK calls. | Configure runtime failure handling and make each business transition idempotent. |
| Trade handler's DynamoDB calls | Each returned write succeeded individually. | Atomic trade creation plus order transition; neither call includes EventBridge. | Use one DynamoDB transaction for compatible local items, with conditional state transition and outbox. |
| Portfolio optimistic lock | The replacement used the version read by that invocation. | That the event was new or in causal order. | Atomically store an inbox/event ID and expected business sequence with the projection update (C40-C41). |
| Target DLQ or event archive | The archive is configured for bounded retention; an SQS message is retained only if EventBridge can write it. Current queue declarations do not establish that permission. | A configured DLQ ARN, zero queue depth, diagnosis, safe redrive, exact business recovery, or reconciliation (C43,C57/A81). | Add/test the queue policies, alarm failed DLQ sends, and own triage, correction, paced replay, idempotency, and reconciliation. |
| Business completion | No single as-built signal establishes matched execution, reservations, balanced postings, clearing/settlement, and reconciled projections. | End-to-end financial correctness. | Define authoritative domain boundaries, ledger postings, and independent reconciliation (C46-C48). |
- Boundary
- API Gateway to order-handler
- What success proves
- The synchronous integration returned an HTTP response.
- What it does not prove
- That a trade, reservation, ledger posting, projection, or notification completed (C51/A53).
- Required design response
- Return an explicitly scoped acceptance state and expose order status.
- Boundary
- DynamoDB order
PutCommand - What success proves
- That one order-row write returned successfully.
- What it does not prove
- Publication to EventBridge or creation of a trade. DynamoDB transactions cannot include EventBridge (C22/A20).
- Required design response
- Commit state plus an outbox record locally, then publish asynchronously (C38).
- Boundary
PutEventsproducer call- What success proves
- HTTP 200, zero failed entries, and
EventIdestablish only producer-API acknowledgement for the named request. - What it does not prove
- Valid bus existence/configuration, matching/routing, target delivery, consumer durability, database effects, or business completion; a nonexistent bus can return those response signals and drop the event (C08/A06,A82).
- Required design response
- Inspect entries, validate bus/configuration independently, retain stable replay identity, and reconcile downstream effects.
- Boundary
- EventBridge bus to Lambda target
- What success proves
- EventBridge owns target-delivery retry according to the target policy (C05/A05).
- What it does not prove
- Function-runtime retry, handler rollback, one business effect, or a working target DLQ. The current queues lack the required EventBridge send policy (C57/A81).
- Required design response
- Configure/observe target delivery separately; add rule-scoped queue policies and alarm both delivery failures and
InvocationsFailedToBeSentToDLQ.
- Boundary
- Lambda asynchronous invocation/runtime
- What success proves
- Its retry and terminal destination are a separate boundary (C06/A01,A04,A05).
- What it does not prove
- Atomicity across the handler's several SDK calls.
- Required design response
- Configure runtime failure handling and make each business transition idempotent.
- Boundary
- Trade handler's DynamoDB calls
- What success proves
- Each returned write succeeded individually.
- What it does not prove
- Atomic trade creation plus order transition; neither call includes EventBridge.
- Required design response
- Use one DynamoDB transaction for compatible local items, with conditional state transition and outbox.
- Boundary
- Portfolio optimistic lock
- What success proves
- The replacement used the version read by that invocation.
- What it does not prove
- That the event was new or in causal order.
- Required design response
- Atomically store an inbox/event ID and expected business sequence with the projection update (C40-C41).
- Boundary
- Target DLQ or event archive
- What success proves
- The archive is configured for bounded retention; an SQS message is retained only if EventBridge can write it. Current queue declarations do not establish that permission.
- What it does not prove
- A configured DLQ ARN, zero queue depth, diagnosis, safe redrive, exact business recovery, or reconciliation (C43,C57/A81).
- Required design response
- Add/test the queue policies, alarm failed DLQ sends, and own triage, correction, paced replay, idempotency, and reconciliation.
- Boundary
- Business completion
- What success proves
- No single as-built signal establishes matched execution, reservations, balanced postings, clearing/settlement, and reconciled projections.
- What it does not prove
- End-to-end financial correctness.
- Required design response
- Define authoritative domain boundaries, ledger postings, and independent reconciliation (C46-C48).
Twelve required issue routes
Section titled “Twelve required issue routes”These IDs are mirrored in claim-register.md and the deliverable. Each row
separates repository observation from controlled semantics and inference.
| ID | Required issue | Exact observed route | Controlled route |
|---|---|---|---|
| CS01 | DynamoDB-to-EventBridge dual write is non-atomic. | code/lambdas/order-handler/handler.ts:155-165,167-181,183-208 | C22, C38 / A20, A21, F04 |
| CS02 | Cached idempotency success can mask an order with no valid routing/downstream evidence. | code/lambdas/order-handler/handler.ts:167-180,229-241 | C08, C32, C40 / A06, A23, A82, F11 |
| CS03 | PutEvents partial failures and the nonexistent-bus acknowledgement boundary are ignored. | code/lambdas/order-handler/handler.ts:193-205; code/lambdas/trade-executor/handler.ts:134-145; code/lambdas/dlq-replayer/handler.ts:114-133 | C08 / A06, A82 |
| CS04 | Trade insert, order update, and publication are non-atomic. | code/lambdas/trade-executor/handler.ts:83-118,120-145 | C22, C38 / A20, A21, F04 |
| CS05 | A publication failure becomes unrecoverable through ordinary retry after the duplicate-trade guard. | code/lambdas/trade-executor/handler.ts:79-104,120-145 | C08, C40 / A06, A82, F11 |
| CS06 | Portfolio locking lacks event idempotency. | code/lambdas/portfolio-updater/handler.ts:145-186; code/shared/types/dynamodb.ts:63-79 | C40-C41 / F11 |
| CS07 | The portfolio depends on ordering that EventBridge does not establish. | code/shared/types/events.ts:36-47; code/lambdas/portfolio-updater/handler.ts:145-178; infra/environments/production/main.tf:565-605 | C09, C34, C41 / A07, F01, F09, F24 |
| CS08 | Target DLQ, DLQ-write permission, and Lambda asynchronous failure are different boundaries; the queue policies are missing. | infra/modules/eventbridge/main.tf:29-38,73-95; infra/environments/production/main.tf:575-605; infra/modules/lambda/main.tf:12-70; bounded absence check below | C05-C07, C57 / A01, A03-A05, A81 |
| CS09 | Daily snapshot is one unpaginated filtered Scan assembled in memory. | code/lambdas/portfolio-snapshot/handler.ts:64-107 | C21, C24 / A19, A22; direct bounded DynamoDB export route |
| CS10 | Monetary values use binary floating point. | code/shared/validation/schemas.ts:21-27; code/lambdas/trade-executor/handler.ts:55-63; code/lambdas/portfolio-updater/handler.ts:64-84,121-135; code/lambdas/portfolio-snapshot/handler.ts:50-61 | C47 / A41, F08, F17 |
| CS11 | No authoritative append-only ledger or reconciliation mechanism is apparent. | code/shared/types/dynamodb.ts:16-93; infra/modules/dynamodb/main.tf:1-60; repository-wide absence check below | C46-C48 / A32-A35, A41, F08, F17, F18 |
| CS12 | Lambda is not automatically suitable for a latency-critical matching loop. | code/lambdas/trade-executor/handler.ts:55-81; infra/modules/lambda/main.tf:12-31 | C49, C53 / A44-A51, A58-A60, F09, F19, F20 |
- ID
- CS01
- Required issue
- DynamoDB-to-EventBridge dual write is non-atomic.
- Exact observed route
code/lambdas/order-handler/handler.ts:155-165,167-181,183-208- Controlled route
- C22, C38 / A20, A21, F04
- ID
- CS02
- Required issue
- Cached idempotency success can mask an order with no valid routing/downstream evidence.
- Exact observed route
code/lambdas/order-handler/handler.ts:167-180,229-241- Controlled route
- C08, C32, C40 / A06, A23, A82, F11
- ID
- CS03
- Required issue
PutEventspartial failures and the nonexistent-bus acknowledgement boundary are ignored.- Exact observed route
code/lambdas/order-handler/handler.ts:193-205;code/lambdas/trade-executor/handler.ts:134-145;code/lambdas/dlq-replayer/handler.ts:114-133- Controlled route
- C08 / A06, A82
- ID
- CS04
- Required issue
- Trade insert, order update, and publication are non-atomic.
- Exact observed route
code/lambdas/trade-executor/handler.ts:83-118,120-145- Controlled route
- C22, C38 / A20, A21, F04
- ID
- CS05
- Required issue
- A publication failure becomes unrecoverable through ordinary retry after the duplicate-trade guard.
- Exact observed route
code/lambdas/trade-executor/handler.ts:79-104,120-145- Controlled route
- C08, C40 / A06, A82, F11
- ID
- CS06
- Required issue
- Portfolio locking lacks event idempotency.
- Exact observed route
code/lambdas/portfolio-updater/handler.ts:145-186;code/shared/types/dynamodb.ts:63-79- Controlled route
- C40-C41 / F11
- ID
- CS07
- Required issue
- The portfolio depends on ordering that EventBridge does not establish.
- Exact observed route
code/shared/types/events.ts:36-47;code/lambdas/portfolio-updater/handler.ts:145-178;infra/environments/production/main.tf:565-605- Controlled route
- C09, C34, C41 / A07, F01, F09, F24
- ID
- CS08
- Required issue
- Target DLQ, DLQ-write permission, and Lambda asynchronous failure are different boundaries; the queue policies are missing.
- Exact observed route
infra/modules/eventbridge/main.tf:29-38,73-95;infra/environments/production/main.tf:575-605;infra/modules/lambda/main.tf:12-70; bounded absence check below- Controlled route
- C05-C07, C57 / A01, A03-A05, A81
- ID
- CS09
- Required issue
- Daily snapshot is one unpaginated filtered Scan assembled in memory.
- Exact observed route
code/lambdas/portfolio-snapshot/handler.ts:64-107- Controlled route
- C21, C24 / A19, A22; direct bounded DynamoDB export route
- ID
- CS10
- Required issue
- Monetary values use binary floating point.
- Exact observed route
code/shared/validation/schemas.ts:21-27;code/lambdas/trade-executor/handler.ts:55-63;code/lambdas/portfolio-updater/handler.ts:64-84,121-135;code/lambdas/portfolio-snapshot/handler.ts:50-61- Controlled route
- C47 / A41, F08, F17
- ID
- CS11
- Required issue
- No authoritative append-only ledger or reconciliation mechanism is apparent.
- Exact observed route
code/shared/types/dynamodb.ts:16-93;infra/modules/dynamodb/main.tf:1-60; repository-wide absence check below- Controlled route
- C46-C48 / A32-A35, A41, F08, F17, F18
- ID
- CS12
- Required issue
- Lambda is not automatically suitable for a latency-critical matching loop.
- Exact observed route
code/lambdas/trade-executor/handler.ts:55-81;infra/modules/lambda/main.tf:12-31- Controlled route
- C49, C53 / A44-A51, A58-A60, F09, F19, F20
Repository-wide absence check used for CS11:
rg -n -i 'ledger|posting|reconcil|reservation|settlement|clearing' code infraResult: no application implementation was found; the only unrelated match was the word “reserved” in comments describing future sort-key use. Absence is therefore stated as “not apparent,” not as proof that no external system could exist outside this repository.
Repository-wide absence check used for CS08:
rg -n 'aws_sqs_queue_policy|sqs:SendMessage' infra -g '*.tf'Result: no match. A separate search for events.amazonaws.com finds only
aws_lambda_permission principals in the production/staging composition files;
none grants sqs:SendMessage on either declared DLQ. The queue resources and
dead_letter_config blocks therefore show intent, not an operationally
authorized EventBridge-to-SQS path.
Review notes outside the twelve-item acceptance set
Section titled “Review notes outside the twelve-item acceptance set”- The production and staging composition files are not identical. In
production, dlq-replayer IAM includes the separately declared portfolio DLQ
(
infra/environments/production/main.tf:749-765); staging grants only the module-managed DLQs (infra/environments/staging/main.tf:697-722). This does not create a thirteenth case-study issue, but a deployment review should resolve the environment drift before relying on portfolio redrive in staging. - The case study does not infer authentication, WAF, CloudTrail, or KMS posture from their absence in the inspected application paths. Those belong to the later security chapter and require their own complete scope review.
Reading layout adapted from SSE reading notes by Mohammed Balila, MIT. Source manifest · Attribution