Initial commit: SWP.Core enterprise framework with multi-tenant architecture, configuration management, security, telemetry and comprehensive test suite

This commit is contained in:
Janus C. H. Knudsen 2025-08-02 22:16:39 +02:00
commit 5275a75502
87 changed files with 6140 additions and 0 deletions

View file

@ -0,0 +1,7 @@
namespace SWP.Core.CommandQueries;
public abstract class Command : ICommand
{
public required Guid CorrelationId { get; set; }
public Guid TransactionId { get; set; }
}

View file

@ -0,0 +1,42 @@
namespace SWP.Core.CommandQueries;
/// <summary>
/// Represents a response to a command request
/// This class includes details such as a unique request ID, correlation ID, command name,
/// transaction ID, creation timestamp, and a URL to check the status of the command.
/// </summary>
/// <param name="correlationId">A unique identifier used to track the request across services.</param>
/// <param name="commandName">The name of the command being executed.</param>
/// <param name="transactionId">An optional unique identifier for the transaction associated with the command.</param>
public class CommandResponse(Guid correlationId, string commandName, Guid? transactionId)
{
/// <summary>
/// A unique identifier for the request. This is automatically generated using Guid.CreateVersion7().
/// </summary>
public Guid RequestId { get; } = Guid.CreateVersion7();
/// <summary>
/// A unique identifier used to track the request across services. This is provided when creating the response.
/// </summary>
public Guid CorrelationId { get; } = correlationId;
/// <summary>
/// The name of the command being executed.
/// </summary>
public string CommandName { get; } = commandName;
/// <summary>
/// An optional unique identifier for the transaction associated with the command.
/// </summary>
public Guid? TransactionId { get; } = transactionId;
/// <summary>
/// The timestamp when the command response was created. This is automatically set to the current UTC time.
/// </summary>
public DateTime CreatedAt { get; } = DateTime.UtcNow;
/// <summary>
/// A URL where the client can check the status of the command. This is typically used in asynchronous operations.
/// </summary>
public string StatusUrl { get; } = "statusUrl";
}

View file

@ -0,0 +1,7 @@
namespace SWP.Core.CommandQueries;
public interface ICommand
{
Guid CorrelationId { get; set; }
Guid TransactionId { get; set; }
}

View file

@ -0,0 +1,56 @@
namespace SWP.Core.CommandQueries;
/// <summary>
/// Represents a standardized error response according to RFC 9457 (Problem Details for HTTP APIs).
/// This class provides a consistent way to communicate errors in HTTP APIs, including details about the error type,
/// status code, and additional context. It also supports extensions for custom error information.
///
/// RFC 9457 Documentation: https://www.rfc-editor.org/rfc/rfc9457.html
/// </summary>
public class ProblemDetails
{
/// <summary>
/// A URI reference that identifies the problem type. This is typically a link to human-readable documentation about the error.
/// </summary>
public string Type { get; set; }
/// <summary>
/// A short, human-readable summary of the problem. It should not change between occurrences of the same error.
/// </summary>
public string Title { get; set; }
/// <summary>
/// The HTTP status code generated by the server for this occurrence of the problem. This allows the client to understand the general category of the error.
/// </summary>
public int? Status { get; set; }
/// <summary>
/// A human-readable explanation specific to this occurrence of the problem. It provides additional details about the error.
/// </summary>
public string Detail { get; set; }
/// <summary>
/// A URI reference that identifies the specific occurrence of the problem. This can be used to trace the error in logs or debugging tools.
/// </summary>
public string Instance { get; set; }
/// <summary>
/// A dictionary for additional, custom error information. This allows extending the problem details with application-specific fields.
/// </summary>
[Newtonsoft.Json.JsonExtensionData]
public Dictionary<string, object> Extensions { get; } = new();
/// <summary>
/// Adds a custom extension to the problem details.
/// </summary>
/// <param name="key">The key for the extension.</param>
/// <param name="value">The value of the extension.</param>
public void AddExtension(string key, object value) => Extensions.Add(key, value);
/// <summary>
/// Removes a custom extension from the problem details.
/// </summary>
/// <param name="key">The key of the extension to remove.</param>
public void RemoveExtension(string key) => Extensions.Remove(key);
}