Production Change Request

Understanding the Production Change Request

LugemineEelvaade

Vaatad tasuta eelvaate õppetundi.

Until now, the system has evolved through:

initial requirements
    ↓
technical design
    ↓
implementation
    ↓
production readiness
    ↓
shipping
    ↓
production incident
    ↓
corrective improvement

The application is no longer greenfield.

We now have:

an existing production database

existing API clients

historical Orders

existing Flyway migrations

existing tests

existing Payment behavior

existing security rules

existing observability

existing production contracts

Now Product introduces a new requirement.

This time:

nothing is broken

The business simply needs the system to do something it could not do before.


The Production Change Request

Product and Support bring the following request:

Administrators need to be able to issue a full refund for a successfully paid Order through the existing Payment Provider. The Order must reflect the successful refund so Support and the Customer can see that the payment was refunded.

This capability was intentionally outside v1.

Our existing system supports:

UNPAID
    ↓ payment succeeds
PAID

and:

UNPAID
    ↓ cancellation
CANCELLED

But once an Order becomes:

PAID

our existing model treats it as terminal.

There is currently no:

refund workflow

refund API

refund persistence

refund provider operation

refund state

That must now change.


Why This Is a Good Production Change

Refunds were not forgotten accidentally.

They were deliberately excluded from the original v1 scope.

At that time:

refunds

were a non-goal.

That allowed us to keep the initial Order lifecycle simple:

UNPAID
  ├── PAID
  └── CANCELLED

Now the business requirement has changed.

Therefore the engineering scope can change too.

This is different from speculative design.

Before:

Maybe we will need refunds someday.

Correct response:

Do not build them yet.

Now:

Support needs refunds in production.

Correct response:

Understand the requirement
and evolve the existing system safely.

Do Not Start by Adding REFUNDED

The first instinct might be:

public enum OrderStatus {
    UNPAID,
    PAID,
    CANCELLED,
    REFUNDED
}

That may ultimately be part of the design.

But it is too early.

A production change request should first answer:

What does "refund" actually mean?

Who can request it?

Which Orders are eligible?

Is it full or partial?

What happens to Inventory?

What happens if the provider fails?

What happens if the result is unknown?

Can the refund be retried?

How is history represented?

What do existing API clients see?

What happens to existing Orders?

Only then should we change the model.


Start With Product Intent

The business problem is:

A Customer has successfully paid.

Support determines that the payment
must be returned.

The current backend has no supported
way to perform that operation.

The desired outcome is:

administrator initiates refund
        ↓
existing Payment Provider processes it
        ↓
successful refund becomes durable system state
        ↓
Customer and Support can see
that the Order was refunded

That is the requirement we need to preserve.


First Scope Decision — Full Refund Only

For this change request, Product confirms:

v1 refund support is full-refund only.

If an Order total is:

€120.00

the supported refund is:

€120.00

Not:

€20.00

or:

one OrderItem only

or:

arbitrary refund amount

Partial refunds remain outside scope.


Why Clarifying Full vs Partial Matters

Without this clarification, "refund" hides major complexity.

Partial refunds require questions such as:

Can one Order be refunded multiple times?

Can total refunded amount exceed Order total?

Can individual OrderItems be refunded?

What if one item has quantity 5
and only quantity 2 is refunded?

How do we represent remaining refundable amount?

How are repeated partial refunds displayed?

Those are real requirements.

They are not needed for the current change.

Scope remains:

one successful full refund
for an eligible paid Order

Second Scope Decision — Administrator-Initiated

Customers do not directly refund their own Orders.

The operation is available to:

administrator / authorized support operation

The existing application already distinguishes:

Customer permissions

Administrator permissions

So the new capability should use the established authorization model.

We are not creating:

customer self-service refund

in this change.


Why Authorization Matters

Refunding money is a privileged financial operation.

The requirement is not:

any authenticated user can refund
an Order they can see

Instead:

authorized administrator

must initiate it.

Later implementation must therefore verify:

authentication

administrator authority

before executing the financial workflow.


Third Scope Decision — Only Successfully Paid Orders

The requirement applies to:

paid Orders

It makes no sense to refund an Order for which:

no successful payment occurred

Therefore:

UNPAID
→ not refundable

and:

CANCELLED
→ not refundable

The exact Domain/API error behavior will be designed later.

For now, the business rule is:

Only an Order with a successfully completed payment can become eligible for refund.


Refund Is Not Cancellation

This distinction is fundamental.

Existing cancellation means:

UNPAID
    ↓
CANCELLED

and restores previously consumed Inventory.

Refund means:

payment already succeeded

and now:

money is returned

These are different operations.

Do not implement refund as:

order.cancel()

The semantics are not the same.


Inventory Behavior

Product confirms another important rule:

A financial refund does not automatically restore Inventory.

Why?

Because this change request does not introduce:

returns

physical item receipt

warehouse restocking

fulfilment reversal

A Customer receiving money back does not necessarily mean the physical product has returned to sellable Inventory.

Therefore:

successful refund

does not imply:

Inventory.restore(...)

This keeps refund and return/warehouse behavior separate.


Why This Matters

Our existing cancellation flow restores Inventory because:

Order was unpaid

Inventory had been reserved/consumed
during Order creation

the Order will no longer proceed

A refund happens later:

Order was paid

financial transaction completed

Whether stock should return requires a separate physical-return requirement.

We do not invent that.


Returns Remain Out of Scope

The production request is:

refund payment

not:

manage returned goods

So we are not adding:

return request

return reasons

warehouse receipt

item inspection

restocking

damaged-item handling

These could become future requirements.

Not now.


Shipping and Fulfilment Remain Out of Scope

Likewise, refund support does not require us to suddenly introduce:

shipment

delivery

fulfilment status

tracking number

Our Order Management Backend still does not model those capabilities.

The requirement should change only what it actually needs.


Existing Payment Provider Must Perform the Refund

The business already uses:

External Payment Provider

for payment execution.

The refund must therefore go through the existing Payment integration boundary.

We are not:

manually changing database state

to simulate a refund.

The money actually needs to be returned through the provider.

This immediately tells us:

refund is an external side-effecting workflow

just like payment.


But Provider Refund Semantics Are Not Yet Known

This is an important discovery.

Our existing course defined provider behavior for:

payment execution

but it did not define:

refund API

refund idempotency behavior

refund reference format

refund timeout semantics

refund lookup/reconciliation

We must not invent those details silently.

Therefore the change request contains a real technical unknown:

Before implementing provider-facing refund execution, we must understand the existing Payment Provider's refund capabilities and failure semantics.

That may require an investigation/spike before implementation is considered ready.


This Is a Legitimate Investigation

Earlier we avoided fake spikes such as:

Investigate whether PostgreSQL supports transactions.

That would be artificial.

But here we genuinely do not yet know:

Does provider expose full refund?

What identifier does refund require?

Does it have provider-side idempotency?

Can refund outcome become unknown after timeout?

Can we query a refund afterwards?

What provider reference identifies the refund?

These questions affect correctness.

Investigation is justified.


Refund Failure Is Not One Thing

Product says:

refund should succeed or report failure safely

Engineering must recognize multiple technical outcomes.

A provider call may result in:

confirmed refund success

confirmed rejection/failure

timeout

connection failure

malformed provider response

unknown outcome

The same lesson we learned from Payment applies again:

A timeout does not prove the external side effect did not happen.

This will strongly influence design.


We Must Not Mark an Order Refunded on Request Start

Bad workflow:

admin clicks refund
    ↓
Order marked REFUNDED
    ↓
provider call

If the provider rejects the refund:

local system says refunded

money was not returned

Clearly incorrect.

But the reverse ordering also has risk.


We Must Not Assume Provider Success and Database Success Are Atomic

Possible:

Provider refund succeeds
    ↓
application fails before local state update

Now:

money returned

but local system may still appear:

PAID

This is exactly the kind of external side-effect consistency problem we already encountered with Payment.

A local PostgreSQL transaction cannot make:

Payment Provider

part of:

COMMIT / ROLLBACK

Existing Payment Lessons Matter

When we originally designed Payment, we learned:

do not hold a database transaction open
over a remote financial call

and:

remote success
cannot be rolled back
by PostgreSQL

Those principles still apply.

A new requirement does not invalidate established failure reasoning.

Module 14 should reuse what the system already knows.


Refund Retry Safety Matters

Imagine:

refund request sent
    ↓
provider processes refund
    ↓
response is lost

If we blindly call refund again:

could money be refunded twice?

The answer depends on provider semantics.

Therefore a safe refund workflow needs:

operation identity

duplicate-processing protection

unknown-outcome handling

But we should not choose the exact mechanism until provider capabilities are confirmed.


Existing Order History Must Remain Valid

We already have historical Orders in production.

A schema/domain change cannot assume:

all existing rows were created
with refund fields

Any migration must account for:

existing UNPAID Orders

existing PAID Orders

existing CANCELLED Orders

without corrupting them.


Existing Orders Must Still Be Readable

Suppose we add new refund-related persistence.

After deployment:

GET /api/v1/orders/{orderId}

must still work for Orders created:

before refund support existed

We cannot require historical data that never existed.

This is the core difference from greenfield modeling.


Existing API Clients Matter

Customers already consume:

Order responses

The current status contract contains:

UNPAID

PAID

CANCELLED

If we decide later to introduce:

REFUNDED

that is an API compatibility change.

Existing clients may contain code such as:

switch(status) {
    UNPAID ...
    PAID ...
    CANCELLED ...
}

A new enum value may affect them.

Therefore:

add REFUNDED

cannot be treated as a trivial Java enum edit.

We must assess API compatibility deliberately.


Do We Definitely Need REFUNDED OrderStatus?

Not yet decided.

Possible designs include:

Option A
Order.status gains REFUNDED

or:

Option B
Order lifecycle remains focused on Order state,
while Payment/Refund state records the financial outcome

or some combination.

We will evaluate these in the design lesson.

Do not decide architecture while still interpreting the requirement.


Customer Must Be Able to See Refund Outcome

Product explicitly requires:

Customer and Support can see
that the payment was refunded.

Therefore the change affects some customer-facing read behavior.

We need eventually to determine:

Does Order response expose a refund state?

Does Order status itself change?

Does Payment information become visible?

What fields are needed?

Those are API design questions.

The requirement only says:

refund must be visible

not how.


Administrator Needs a Refund Operation

We also know we need a command surface.

Conceptually:

administrator
    ↓
request full refund
    ↓
backend

But we should not yet assume the endpoint.

Possibilities might include:

POST /api/v1/orders/{orderId}/refund

or another resource-oriented representation.

Exact API shape belongs to later design.

The requirement is:

administrator can initiate
full refund for eligible Order

Refund Is Not a Generic Payment CRUD Operation

Avoid jumping to:

/api/v1/refunds

POST /payments

PATCH /payment

without understanding resource/workflow semantics.

Our existing API favors explicit business operations such as:

/orders/{orderId}/pay

/orders/{orderId}/cancel

The new endpoint should eventually fit established conventions unless a good reason exists not to.


Existing Order Ownership Still Matters

Customer Order reads already enforce:

Customer sees only own Orders

Refund does not change that.

Administrator refund authority and Customer read ownership are separate security rules.

We must preserve both.


Historical Price Still Matters

Refund amount should be based on:

what was actually paid / historical Order amount

not:

current Product prices

Suppose:

Order O1:
unitPriceCents = 5000

Later Product price becomes:

7000

Refunding O1 must not suddenly return:

7000

because current catalog price changed.

Our historical pricing model becomes useful again.


But Order Total Alone May Not Be Enough

Payment consistency matters.

Ideally the refund corresponds to:

the successful Payment

not merely:

recalculate something from current Product state

The exact provider/reference relationship will be assessed once we inspect the existing Payment persistence and provider contract.

Again:

understand before changing

One Successful Full Refund Only

For this course scenario, Product confirms:

A successfully refunded Order cannot be refunded again.

So:

PAID
→ full refund succeeds
→ no second full refund

Retry safety still matters because:

same refund operation

may need to be retried after an uncertain provider outcome.

But a separate new attempt must not intentionally refund the same payment twice.


What Happens After a Confirmed Refund?

At product level we know:

the Order must visibly reflect
that its payment was refunded

We have not yet decided whether that means:

Order.status = REFUNDED

or:

Payment/Refund state = REFUNDED

That is a design decision.

Do not confuse:

required observable behavior

with:

implementation representation

Failed Refund

If the provider gives a confirmed failure:

money was not refunded

Therefore the Order must not be represented as successfully refunded.

The system should make the failure visible to the administrator through a safe API response.

Exact error codes depend on final design/provider semantics.


Unknown Refund Outcome

This is more dangerous.

Suppose:

request sent to provider

provider may have processed it

connection times out

We cannot safely conclude:

refund failed

and blindly retry.

Nor can we safely conclude:

refund succeeded

without confirmation.

Therefore:

unknown refund outcome

is a real state the design may need to represent or recover from.

This is a technical impact we already know before choosing implementation.


We Need Provider Capability Investigation

The provider investigation should answer:

1. How is a full refund initiated?

2. Which successful payment identifier is required?

3. Does the provider accept an idempotency key
   or merchant refund reference?

4. What does a confirmed successful response look like?

5. What does a confirmed rejected response look like?

6. What happens on duplicate refund requests?

7. Can refund status be queried later?

8. Can timeout leave outcome unknown?

9. Does the provider expose a stable Refund ID?

10. Are there provider states between
    requested and completed?

Implementation should remain blocked until the essential answers are known.


This Does Not Mean We Stop All Analysis

Even without provider details, we already know which system areas may be affected.

We can begin an impact map.


Preliminary Impact Map

Domain

Potentially affected:

Order lifecycle

financial state representation

Questions:

Does REFUNDED belong to OrderStatus?

Is refund financial state separate from Order state?

What constitutes refund eligibility?

Application

New workflow required:

RefundOrderUseCase

or equivalent application operation.

Responsibilities likely include:

load Order

verify eligibility

coordinate durable refund attempt state

call provider outside DB transaction

apply confirmed outcome safely

Exact design comes later.


Payment Integration

Definitely affected.

Current external provider boundary supports:

payment

The new requirement requires:

refund

We must determine whether to:

extend existing PaymentService boundary

or introduce another provider-neutral capability.

Not decided yet.


Persistence

Almost certainly affected.

Why?

We need durable evidence of:

refund operation

provider result

relationship to Payment/Order

especially under:

timeout

restart

retry

local update failure

But the exact schema is a design decision.


API

Affected in at least two directions:

administrator command

and:

customer/support visibility

Compatibility with existing Order responses must be assessed.


Security

Affected.

Need:

administrator authority

for refund execution.

Customer ownership remains required for Customer reads.


Testing

Affected extensively.

We will need tests for:

eligible paid Order

unpaid Order

cancelled Order

already refunded Order

provider success

provider rejection

provider timeout

unknown outcome

duplicate/refund retry

authorization

local persistence failure after provider success

Exact scenarios will depend on final design.


Observability

Likely affected.

Financial operations need useful signals such as:

refund requested

refund succeeded

refund confirmed failed

refund outcome unknown

refund reconciliation

But exact metric/log vocabulary comes after state semantics are defined.


Inventory

For the confirmed scope:

Inventory workflow does not change

because refunds do not automatically represent returned stock.

This is an important impact conclusion.

Not every adjacent capability must change.


Product

Also currently:

no Product Domain change required

Refund amount must use historical Order/payment meaning.

Current Product price or active status should not control refund eligibility.

This preserves the historical boundary we intentionally designed earlier.


Product Deactivation Must Not Block Refund

Suppose:

Customer buys Product P1

Order becomes PAID

Admin later deactivates P1

Support then needs to refund the Order

Should Product active state block refund?

No.

The refund concerns:

existing historical paid Order

not whether P1 is currently orderable.

This mirrors our earlier rule that Product deactivation does not rewrite existing Order history.


Current Product Price Must Not Change Refund Amount

Likewise:

Product price today

has no authority over:

historical paid Order

Refund logic must not load current Product price and calculate from it.

The relevant financial truth comes from the existing Order/payment history.


Existing Paid Orders Need to Become Eligible

The feature is not only for Orders created after deployment.

A major production question is:

Can a paid Order that existed before refund support be refunded after the feature launches?

Product says:

Yes.

That has major migration implications.

We cannot design a feature that only works for:

new Orders

if Support needs to refund historical paid Orders.


Historical Compatibility Becomes a Hard Requirement

Therefore whatever refund persistence we introduce must allow:

existing PAID Order
+
existing successful Payment information

to enter the new refund workflow.

We cannot require new data that older successfully paid Orders could never possess unless we can derive or migrate it safely.

This will be a central design question.


Existing Cancelled and Unpaid Orders Remain Unchanged

Historical:

UNPAID

Orders remain unpaid.

Historical:

CANCELLED

Orders remain cancelled.

We do not run a broad migration that changes old Order lifecycle state merely because refunds were added.


API Backward Compatibility

Existing clients may not immediately understand new refund information.

We will need to assess:

Can we add an optional field safely?

Will we introduce a new OrderStatus value?

Do clients treat unknown enum values safely?

Does OpenAPI change?

Does frontend require coordinated release?

This is why:

existing API clients

matter in Module 14.


Database Compatibility

Existing deployment also means:

old application version

and:

new schema

may briefly coexist during rollout depending on deployment strategy.

A good migration should preferably be:

additive

where possible.

We should avoid immediately:

dropping columns

rewriting all historical rows

making old application versions unable to start

without a deployment reason.

Exact migration comes later.


Definition of Done Still Applies

This production change is not Done merely when:

provider returns refund success

Our existing Definition of Done still requires, where relevant:

agreed scope implemented

acceptance criteria satisfied

failure behavior handled

tests added

existing tests pass

build succeeds

migration included

API documentation updated

technical documentation updated

PR reviewed

CI passes

Production changes do not get a lower quality bar because they arrive later.


Refine the Product Requirement

We can now rewrite the initial request into clearer behavior.

Production Change Request — Full Order Refunds

Goal

Authorized administrators can issue a full financial refund for an eligible paid Order through the existing Payment Provider.

Required Behavior

Only successfully paid Orders
are eligible for refund.

Refund amount represents
the full successful Order/payment amount.

A successful refund becomes
durable system state.

The Customer and Support can see
that the payment was refunded.

The same successful payment
must not be refunded twice.

Provider failure must not
incorrectly mark the Order refunded.

Unknown provider outcome must be
handled safely rather than blindly retried.

Existing historical paid Orders
must be eligible where required
Payment information exists.

Authorization Requirement

Refund initiation requires
administrator authority.

No customer self-service refund endpoint is part of this change.


Inventory Requirement

Refund does not automatically
restore Inventory.

Returns/restocking remain separate future concerns.


Scope

Included:

full refund

paid Orders

administrator initiation

existing Payment Provider

durable refund outcome

safe provider failure handling

safe retry/duplicate protection

historical paid Orders

customer/support visibility

Explicit Non-Goals

Still out of scope:

partial refunds

item-level refunds

returns

restocking

shipping

fulfilment

refund to a different payment method

store credit

coupons

discount changes

multiple Payment Providers

automatic refund on cancellation

Customer self-service refund

This prevents the production request from expanding into an entire commerce platform.


Open Technical Questions

Before implementation we still need answers to:

1. How should refund state be represented?

2. Does OrderStatus change?

3. What durable refund-attempt model is needed?

4. What Payment Provider refund capabilities exist?

5. What identifies the original provider Payment?

6. How does provider idempotency work?

7. How do we recover unknown outcomes?

8. What API exposes refund initiation?

9. How is refund status exposed to Customers?

10. How do we preserve compatibility
    with existing API clients?

11. What migration supports historical paid Orders?

12. What concurrency rules prevent
    two administrators refunding simultaneously?

Those are design questions, not reasons to expand the product requirement further.


We Have Not Designed the Solution Yet

At this stage, do not create:

REFUNDED enum

refunds table

RefundService

POST /refund

provider DTOs

yet.

We first needed a bounded, explicit requirement.

That is now complete.


Existing System Context

Our production baseline before this change is:

Order statuses:
UNPAID
PAID
CANCELLED
Payment:
external provider
durable PaymentAttempt coordination
unknown-outcome recovery
Cancellation:
UNPAID only
restores Inventory
Create Order:
idempotent through Customer-scoped
Idempotency-Key
Architecture:
modular monolith
Handler → UseCase → Repository
Persistence:
PostgreSQL + Flyway

The refund feature must fit this system.

We are not designing from a blank page.


Preliminary Risk Register

Even before detailed design, the requirement exposes several risks.

Risk 1 — Double Refund

two administrators

or retry

or timeout
    ↓
provider receives refund twice

We must prevent unintended duplicate financial effects.


Risk 2 — Provider Success, Local Failure

provider returns/succeeds with refund
    ↓
database update fails

Money has moved externally while local state may remain stale.

This is a major consistency risk.


Risk 3 — Unknown Outcome

refund call sent
    ↓
timeout

We may not know whether the provider refunded.

Blind retry may be dangerous.


Risk 4 — Concurrent Refund Requests

Two authorized users could issue:

refund O1

at nearly the same time.

Application/database coordination must ensure one logical refund workflow wins.


Risk 5 — Existing API Compatibility

If we change:

OrderStatus

existing clients may not recognize the new value.

The API evolution needs deliberate review.


Risk 6 — Historical Orders

Older paid Orders may lack data introduced by new refund persistence.

The feature must not silently make historical Orders impossible to refund if Product requires them to remain eligible.


Risk 7 — Incorrect Inventory Restoration

A developer might assume:

refund
=
cancellation

and restore Inventory.

That would violate the new requirement because return/restocking is not part of this feature.


What Has Not Changed

Even after the product request, these remain true:

one modular monolith

PostgreSQL transactional persistence

Handler → UseCase → Repository

external Payment Provider boundary

Customer ownership rules

administrator authorization

historical unitPriceCents

money stored as long cents

UUID resource identities

RFC 7807 API errors

Testcontainers for PostgreSQL behavior

A change request should change only what the new requirement demands.


Product Requirement vs Technical Design

We now have:

Product requirement:
support safe full refunds

We do not yet have:

Technical design:
how to represent and execute refunds

That distinction matters.

We will next examine the existing code and architecture boundaries and ask:

Which responsibilities actually change?

Only after that should we decide the implementation shape.


Engineering Principle

The first principle:

A production change request must be interpreted in the context of the system that already exists. Existing data, API clients, tests, production behavior, and external integrations are part of the requirements now.

The second:

A feature that was correctly excluded by YAGNI can later become a legitimate requirement. Good earlier boundaries should make that evolution manageable without pretending the old system was designed for every future feature.

The third:

Separate product semantics from technical representation. "A paid Order can be fully refunded" is a requirement; REFUNDED, a refunds table, and a particular endpoint are design decisions that still need evaluation.

And:

When new financial behavior touches an external provider, uncertain outcomes, retries, and duplicate side effects must be considered before implementation—not after production teaches the same lesson again.


Summary

In this lesson, we established the Module 14 production change request:

Authorized administrators must be able to issue a full refund for an eligible paid Order through the existing Payment Provider, and the successful refund must become visible durable system state.

We clarified that:

  • Refunds were intentionally outside v1 and are now a real new requirement.
  • This is system evolution, not correction of an original scope mistake.
  • Full refunds are supported; partial refunds are not.
  • Refunds are administrator-initiated.
  • Customer self-service refund is out of scope.
  • Only successfully paid Orders are eligible.
  • Refund and cancellation are different operations.
  • Refund does not automatically restore Inventory.
  • Returns and restocking remain out of scope.
  • Shipping and fulfilment remain out of scope.
  • The existing Payment Provider must perform the financial refund.
  • Provider refund semantics are currently a genuine technical unknown.
  • We must investigate provider refund/idempotency/reconciliation capabilities before provider-facing implementation is ready.
  • A provider timeout cannot automatically be treated as confirmed refund failure.
  • PostgreSQL cannot atomically roll back an external refund.
  • Duplicate refund protection is required.
  • Concurrent refund requests must be considered.
  • Existing historical paid Orders need to remain eligible.
  • Existing UNPAID and CANCELLED Orders remain unchanged.
  • Current Product active state must not determine refund eligibility.
  • Current Product price must not determine historical refund amount.
  • Existing Order history and Payment history are authoritative.
  • Customer and Support must be able to observe successful refund outcome.
  • How that outcome is represented remains a design question.
  • We have not yet decided whether OrderStatus gains REFUNDED.
  • Existing API clients make enum/API evolution a compatibility concern.
  • Persistence will likely change, but the schema is not yet designed.
  • Security must enforce administrator authority.
  • Inventory does not need a new refund mutation.
  • Product does not need new refund behavior.
  • The feature must preserve the established architecture rather than redesign the system from scratch.
  • Partial refunds, returns, restocking, shipping, fulfilment, store credit, and multiple providers remain non-goals.
  • The most important risks are double refund, provider-success/local-failure, unknown provider outcome, concurrent refunds, API compatibility, historical-data compatibility, and accidental Inventory restoration.

Next lesson:

Assessing the Impact on the Existing System

We will take the confirmed requirement and systematically inspect:

Order Domain
Payment workflow
PaymentAttempt model
API contracts
PostgreSQL schema
existing migrations
security
historical Orders
external provider boundary
tests
observability
deployment compatibility

and classify each area as:

must change

may change

must not change

before writing any refund implementation.