# LS2020: Module Names a Type Outside Another Module's Contracts

## Intent

LS2020 is a compiler check that reports a module naming another module's type outside its `Contracts/` folder, because a read past the public surface couples the caller to internals the owner may change. This page states what the rule reports, where the error sits, and how to read through the contracts the owner publishes.

## Reference

### What the Rule Enforces

LS2020 enforces [Reach Another Module Only Through Contracts](https://litespec.dev/4.0.0/backend/dotnet/architecture.md#reach-another-module-only-through-contracts) (`litespec/backend/dotnet/architecture#reach-another-module-only-through-contracts`). It runs in every layer except Test. Its category is `LiteSpec.Layers`. Severity and enablement follow the [Analyzers overview](https://litespec.dev/4.0.0/analyzers/README.md).

### What the Rule Reports

The rule reports a name that resolves to a type in another module declared outside that module's `Contracts/` folder. The diagnostic sits on the name, and its message names the type and the module that owns it.

### Failing Example

```csharp
namespace Claimwick.Reporting.UseCases.ReadExpenseTotals;

internal sealed class TotalsQueryHandler
{
    public void Handle() => Expense.FromRecord();
}
```

with `Expense` declared in the spending module outside its `Contracts/` folder.

### Passing Example

```csharp
namespace Claimwick.Reporting.UseCases.ReadExpenseTotals;

internal sealed class TotalsQueryHandler(IExpenseTotals totals)
{
}
```

with `IExpenseTotals` declared in the spending module `Contracts/Ports/` folder.

### How to Fix

Read the data through a port in the owner `Contracts/Ports/` folder, which returns contract results keyed by typed identifier, or answer with a query over data the module already holds. Load no foreign aggregate or repository.

## Notes

### What the Rule Ignores

The rule does not report a name in a Test file or in a file the layer rules cannot place. It does not report a type in the same module or in the owner `Contracts/` folder, or a name that resolves to no project source file. Under the `layer-projects` extension the rule does not run: project references hold the module boundary instead.
