PMQ Suite
Public .NET libraries that I write and maintain. It is the part of my work anyone can read today, without a confidentiality agreement.
| Package | Downloads | What it solves |
|---|---|---|
| PMQ.Notifications | 1,864 | a violated business rule as data, not as an exception |
| PMQ.Mediator | 977 | a mediator with a behavior and validation pipeline |
| PMQ.ErrorHandling | 1,149 | standardized error responses in ASP.NET Core, RFC 9457 |
| PMQ.Identity | 685 | provider-agnostic authentication, OIDC or its own JWT |
| PMQ.Domain | 902 | DDD blocks: entity, aggregate, value object, event |
Where they came from
The same problems show up in every .NET service I write: how the business rule complains, how the use case is dispatched, how the error reaches the client, who the caller is.
I solved each of them a few times before writing these packages, and that is where they come from. Not from a cut of what already existed, but from an opinion formed about what works, written from scratch. They are better than my first versions, and the reason is simple: whoever has already gotten one implementation wrong can get more out of the next.
The thesis
They are not loose exercises. Together, they are the blocks of a Clean Architecture:
PMQ.Domain → the domain: entity, aggregate, value object, event
PMQ.Notifications → how the rule complains, without throwing an exception
PMQ.Mediator → how the use case is dispatched, with validation on the way
PMQ.ErrorHandling → how the error reaches the HTTP client
PMQ.Identity → who the caller is, regardless of who issues the token
How the pieces fit together
The fit is the thesis. The notification the domain accumulates is the same one the mediator’s pipeline checks before executing, and the same one the error handler converts into an HTTP response. That is how the weakness accepted in PMQ.Notifications, that nothing forces the caller to check, ended up solved structurally: the pipeline checks on everyone’s behalf.
Decisions I stand by
Generalize after the third case. An abstraction created in the expectation of reuse is almost always wrong. Only the third use reveals what is essential and what was an accident of the first. Each package here came from a problem I had already solved more than once.
Notification instead of exception. A violated business rule is a foreseen outcome, not a program failure. It is the decision that ties the suite together, and the package that implements it is the most downloaded one.
Industry standards where they exist. Error handling follows RFC 9457 instead of a format of its own. Inventing a format is a cost for whoever consumes it.
Why this matters in the portfolio
These packages are verifiable. The code is open, the history is public, and the download count does not depend on my word.