Skip to content

The clean-architecture layout did not build with two of our own features - #254

Merged
omercelikdev merged 1 commit into
mainfrom
fix/clean-architecture-features
Sep 9, 2026
Merged

The clean-architecture layout did not build with two of our own features#254
omercelikdev merged 1 commit into
mainfrom
fix/clean-architecture-features

Conversation

@omercelikdev

Copy link
Copy Markdown
Collaborator

Found by qorpe/coexist on 2026-09-09, generating that layout as the first adopter to want it. Two independent breaks, one shape of cause: the template puts feature-conditional code in Domain and Application, but only the Api csproj carried the feature-conditional package references.

1 — IAuditLogged moves to Goldpath.Abstractions

Order.AuditTrail.cs lands in Domain and needs IAuditLogged, which lived in Goldpath.AuditTrail — a package that pulls ASP.NET Core, EF Core and Goldpath.Data. Referencing that from Domain inverts the dependency direction the layout exists to teach, so the reference is not the fix.

Its five siblings are already where it should have been:

marker package
IAuditedEntity, ISoftDeletable, IMultiTenant, IIntegrationEvent, GoldpathPersonalData Goldpath.Abstractions
IAuditLogged Goldpath.AuditTrailGoldpath.Abstractions

Both packages declare it in namespace Goldpath, so the move is source-compatible — adopters recompile and change nothing.

A TypeForwardedTo was written first and withdrawn: PublicApiAnalyzers cannot reconcile a forwarded type, reporting RS0016 (not part of the declared public API) and RS0017 (declared but could not be found) for the same symbol in the same build. On a pre-1.0 preview train, a recompile is cheaper honesty than a suppression that outlives its reason.

2 — the Application project gets the behaviours package it already uses

CreateOrder.cs carries [Mediant.Behaviors.Attributes.Idempotent] under UseIdempotency and lands in Application — and no template csproj referenced Mediant.Behaviors at all. In vertical-slice the file lands in Api and reaches it transitively through Goldpath.Idempotency. Central package management makes the fix two lines: the conditional reference and its PackageVersion.

Proven today. Generating --broker none --layout clean-architecture --features idempotency --features dataprotection --features locking from the fixed template builds clean where it failed:

error CS0234: The type or namespace name 'Behaviors' does not exist in the namespace 'Mediant'
  →  0 Warning(s)  0 Error(s)

The audittrail half cannot be proven the same way today: a generated app consumes the published Goldpath.Abstractions, so it needs the train.

How both were missed

The nightly matrix had two clean-architecture shapes and neither could reach these:

  • GmFourClean takes no features at all.
  • GmOneClean keeps the default broker, which supplies Mediant.Behaviors to Application by accident through Goldpath.Messaging.

GmCleanFeatures is the new shape: clean-architecture, deliberately broker-less, carrying the features whose code the layout moves.

It ships without audittrail, and that is a decision rather than an oversight — that flag would keep the shape red until the train publishing the move, and a nightly shape known to be red teaches the team to ignore a red nightly. The release checklist's next-train adoptions owns adding it, with the reason written down; docs/strategy/golden-manifests-v1.md carries the row (the docs-freshness gate refused the shape until it did).

Adopters

docs/upgrades/0.1.0-preview.9.md: recompile, nothing else. Adopters on vertical-slice do nothing at all. Anyone who hand-added Mediant.Behaviors to a clean-architecture Application project can delete it — a duplicate is harmless either way.

Verification

docs-freshness    23 packages, 13 CLI verbs, nightly shapes, scripts and templates documented
ledger-check      every issue referenced by a ledger has the state the ledger claims
skills-parity     16 files identical across 3 copies, 5 deliberate divergences
schema-honesty    every roadmap-only value annotated
template-pins     templates and adopter docs all on 0.1.0-preview.8
Goldpath.AuditTrail.Tests   9 passed
Goldpath.Cli.Tests        412 passed
dotnet build Goldpath.sln   0 warnings, 0 errors

Found by qorpe/coexist on 2026-09-09, generating that layout as the first
adopter to want it. Both breaks have the same shape: the template puts
feature-conditional CODE in Domain and Application, but only the Api
csproj carried the feature-conditional package references.

## IAuditLogged moves to Goldpath.Abstractions

Order.AuditTrail.cs lands in Domain and needs IAuditLogged, which lived in
Goldpath.AuditTrail — a package that pulls ASP.NET Core, EF Core and
Goldpath.Data. Referencing that from Domain inverts the dependency
direction the layout exists to teach, so the fix is not the reference.

Its five siblings — IAuditedEntity, ISoftDeletable, IMultiTenant,
IIntegrationEvent, GoldpathPersonalData — are all already in
Goldpath.Abstractions. The bare marker belongs there too, and both
packages declare it in namespace Goldpath, so the move is
source-compatible: adopters recompile and change nothing.

A TypeForwardedTo was written first and withdrawn. PublicApiAnalyzers
cannot reconcile a forwarded type: it reported RS0016 (not part of the
declared public API) and RS0017 (declared but could not be found) for the
same symbol in the same build. On a pre-1.0 preview train the recompile is
cheaper honesty than a suppression that outlives its reason.

## The Application project gets the behaviours package it already uses

CreateOrder.cs carries [Mediant.Behaviors.Attributes.Idempotent] under
UseIdempotency and lands in Application, and NO template csproj referenced
Mediant.Behaviors at all — in vertical-slice the file lands in Api and
reaches it transitively through Goldpath.Idempotency. Central package
management makes the fix two lines: the conditional reference and its
PackageVersion.

Proven: generating --broker none --layout clean-architecture with
idempotency, dataprotection and locking builds clean where it failed
before. The audittrail half cannot be proven the same way today — a
generated app consumes the PUBLISHED Abstractions, so it needs the train.

## How both were missed, and the shape that would have caught them

The nightly matrix had two clean shapes and neither could reach these.
GmFourClean takes no features at all. GmOneClean keeps the default broker,
which supplies Mediant.Behaviors to Application by accident through
Goldpath.Messaging.

GmCleanFeatures is the new shape: clean-architecture, deliberately
broker-less, carrying the features whose code the layout MOVES. It ships
WITHOUT audittrail, which is a decision rather than an oversight — that
flag would keep the shape red until the train publishing the move, and a
nightly shape known to be red teaches the team to ignore a red nightly.
The release checklist's next-train adoptions owns adding it, with the
reason, and the golden-manifests ledger carries the row.

docs/upgrades/0.1.0-preview.9.md says what an adopter does: recompile.

Five gates green. AuditTrail 9 tests, CLI 412 tests.
@omercelikdev
omercelikdev merged commit 03ae76e into main Sep 9, 2026
4 checks passed
@omercelikdev
omercelikdev deleted the fix/clean-architecture-features branch September 9, 2026 05:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant