# LS1012: Identifier Is Not a Strongly Typed Value

## Intent

LS1012 is a compiler check that reports an identifier in Domain, the project that holds business rules, that is not a strongly typed value, because a raw Guid lets one record's identity flow into another record's slot with no compiler complaint. This page states what the rule reports, where the warning sits, and how to wrap the value in a strongly typed identifier.

## Reference

### What the rule enforces

LS1012 enforces [Use strongly typed version 7 identifiers](https://litespec.dev/2.0.0/backend/dotnet/domain.md#use-strongly-typed-version-7-identifiers) (`litespec/backend/dotnet/domain#use-strongly-typed-version-7-identifiers`). It runs in Domain only. Its category is `LiteSpec.Domain`. It reports a warning and is enabled by default, as the [Analyzers overview](https://litespec.dev/2.0.0/analyzers/README.md) describes.

### What the rule reports

The rule reports a struct whose name ends in `Id` unless it is a `readonly record struct` that wraps exactly one `Guid` field and declares no implicit conversion. The rule also reports `AggregateRoot<Guid>`, where the raw `Guid` is used directly as the identity, and a malformed identity type used as the `AggregateRoot` type argument. The diagnostic sits on the identifier. In `AggregateRoot<Guid>` it sits on the base type.

### Failing example

```csharp
public record struct OrderId(Guid Value);
```

### Passing example

```csharp
public readonly record struct OrderId(Guid Value);
```

### How to fix

Declare the identifier as a `readonly record struct` that wraps one `Guid` with no implicit conversion, use it as the `AggregateRoot` type argument, and pass version 7 values in from the caller.

## Notes

### What the rule ignores

The rule does not report well-formed identifiers or explicit conversions. It does not run outside Domain.
