chore(thalos-service): merge contract integration branch
This commit is contained in:
commit
b92ae237c7
@ -5,25 +5,32 @@ package "thalos-service" {
|
||||
package "Thalos.Service.Identity.Abstractions" {
|
||||
class IssueIdentityTokenRequest
|
||||
class IssueIdentityTokenResponse
|
||||
class EvaluateIdentityPolicyRequest
|
||||
class EvaluateIdentityPolicyResponse
|
||||
class IdentityPolicyContextRequest
|
||||
class IdentityPolicyContextResponse
|
||||
class ThalosIdentityPackageContract
|
||||
interface IdentityAbstractionBoundary
|
||||
}
|
||||
|
||||
package "Thalos.Service.Application" {
|
||||
interface IIssueIdentityTokenUseCase
|
||||
class IssueIdentityTokenUseCase
|
||||
interface IEvaluateIdentityPolicyUseCase
|
||||
class EvaluateIdentityPolicyUseCase
|
||||
interface IIdentityTokenReadPort
|
||||
interface IIdentityPolicyContextReadPort
|
||||
interface IIdentityCapabilityContractAdapter
|
||||
interface IIdentityPolicyGrpcContractAdapter
|
||||
}
|
||||
|
||||
package "Thalos.Service.Grpc" {
|
||||
class Program
|
||||
}
|
||||
|
||||
IssueIdentityTokenUseCase ..|> IIssueIdentityTokenUseCase
|
||||
IssueIdentityTokenUseCase --> IIdentityTokenReadPort
|
||||
IIssueIdentityTokenUseCase --> IssueIdentityTokenRequest
|
||||
IIssueIdentityTokenUseCase --> IssueIdentityTokenResponse
|
||||
}
|
||||
|
||||
package "thalos-dal" as ThalosDal
|
||||
|
||||
IIdentityPolicyContextReadPort ..> ThalosDal
|
||||
IIdentityTokenReadPort ..> ThalosDal
|
||||
@enduml
|
||||
|
||||
@ -3,10 +3,18 @@
|
||||
## Use-Case Boundaries
|
||||
|
||||
- `IIssueIdentityTokenUseCase`: orchestrates token issuance behavior.
|
||||
- `IEvaluateIdentityPolicyUseCase`: orchestrates policy evaluation behavior.
|
||||
- `IIdentityTokenReadPort`: DAL-facing identity token boundary.
|
||||
- `IIdentityPolicyContextReadPort`: DAL/integration-facing identity policy context boundary.
|
||||
|
||||
## Contract Integration
|
||||
|
||||
- Policy orchestration uses Thalos-owned transport-neutral identity contracts.
|
||||
- gRPC translation boundaries are isolated behind `IIdentityPolicyGrpcContractAdapter`.
|
||||
- Service contracts remain transport-neutral at the application boundary.
|
||||
|
||||
## Policy Baseline
|
||||
|
||||
- Token issuance policy is orchestrated in service use cases.
|
||||
- Data retrieval and persistence details remain in thalos-dal.
|
||||
- Token issuance and policy evaluation are orchestrated in service use cases.
|
||||
- Data retrieval and persistence details remain in thalos-dal and identity adapters.
|
||||
- Protocol adaptation remains outside use-case logic.
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
using Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
namespace Thalos.Service.Application.Adapters;
|
||||
|
||||
/// <summary>
|
||||
/// Defines adapter boundary for integrating identity contracts into policy use cases.
|
||||
/// </summary>
|
||||
public interface IIdentityCapabilityContractAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a transport-neutral context request for policy evaluation.
|
||||
/// </summary>
|
||||
/// <param name="identityRequest">Identity policy request.</param>
|
||||
/// <returns>Identity policy context request.</returns>
|
||||
IdentityPolicyContextRequest CreatePolicyContext(EvaluateIdentityPolicyRequest identityRequest);
|
||||
|
||||
/// <summary>
|
||||
/// Maps policy context response into identity policy response.
|
||||
/// </summary>
|
||||
/// <param name="identityRequest">Identity policy request.</param>
|
||||
/// <param name="contextResponse">Identity policy context response.</param>
|
||||
/// <returns>Identity policy response.</returns>
|
||||
EvaluateIdentityPolicyResponse MapPolicyResponse(
|
||||
EvaluateIdentityPolicyRequest identityRequest,
|
||||
IdentityPolicyContextResponse contextResponse);
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
using Thalos.Service.Application.Grpc;
|
||||
using Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
namespace Thalos.Service.Application.Adapters;
|
||||
|
||||
/// <summary>
|
||||
/// Defines adapter boundary for gRPC contract translation of identity policy flows.
|
||||
/// </summary>
|
||||
public interface IIdentityPolicyGrpcContractAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps transport-neutral request into gRPC contract shape.
|
||||
/// </summary>
|
||||
/// <param name="request">Identity policy request.</param>
|
||||
/// <returns>gRPC policy contract.</returns>
|
||||
EvaluateIdentityPolicyGrpcContract ToGrpc(EvaluateIdentityPolicyRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Maps gRPC contract into transport-neutral request.
|
||||
/// </summary>
|
||||
/// <param name="contract">gRPC policy contract.</param>
|
||||
/// <returns>Identity policy request.</returns>
|
||||
EvaluateIdentityPolicyRequest FromGrpc(EvaluateIdentityPolicyGrpcContract contract);
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Thalos.Service.Application.Grpc;
|
||||
|
||||
/// <summary>
|
||||
/// Defines minimal gRPC contract shape for identity policy adapter translation.
|
||||
/// </summary>
|
||||
/// <param name="SubjectId">Identity subject identifier.</param>
|
||||
/// <param name="TenantId">Tenant scope identifier.</param>
|
||||
/// <param name="PermissionCode">Permission code to evaluate.</param>
|
||||
public sealed record EvaluateIdentityPolicyGrpcContract(string SubjectId, string TenantId, string PermissionCode);
|
||||
@ -0,0 +1,16 @@
|
||||
using Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
namespace Thalos.Service.Application.Ports;
|
||||
|
||||
/// <summary>
|
||||
/// Defines DAL/integration read boundary for identity policy context contracts.
|
||||
/// </summary>
|
||||
public interface IIdentityPolicyContextReadPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads identity policy context for policy evaluation.
|
||||
/// </summary>
|
||||
/// <param name="request">Identity policy context request.</param>
|
||||
/// <returns>Identity policy context response.</returns>
|
||||
Task<IdentityPolicyContextResponse> ReadPolicyContextAsync(IdentityPolicyContextRequest request);
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
using Thalos.Service.Application.Adapters;
|
||||
using Thalos.Service.Application.Ports;
|
||||
using Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
namespace Thalos.Service.Application.UseCases;
|
||||
|
||||
/// <summary>
|
||||
/// Default orchestration implementation for identity policy evaluation.
|
||||
/// </summary>
|
||||
public sealed class EvaluateIdentityPolicyUseCase(
|
||||
IIdentityCapabilityContractAdapter contractAdapter,
|
||||
IIdentityPolicyContextReadPort policyContextReadPort)
|
||||
: IEvaluateIdentityPolicyUseCase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<EvaluateIdentityPolicyResponse> HandleAsync(EvaluateIdentityPolicyRequest request)
|
||||
{
|
||||
var policyContextRequest = contractAdapter.CreatePolicyContext(request);
|
||||
var policyContextResponse = await policyContextReadPort.ReadPolicyContextAsync(policyContextRequest);
|
||||
|
||||
return contractAdapter.MapPolicyResponse(request, policyContextResponse);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
using Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
namespace Thalos.Service.Application.UseCases;
|
||||
|
||||
/// <summary>
|
||||
/// Defines orchestration boundary for identity policy evaluation.
|
||||
/// </summary>
|
||||
public interface IEvaluateIdentityPolicyUseCase
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles identity policy evaluation.
|
||||
/// </summary>
|
||||
/// <param name="request">Identity policy request contract.</param>
|
||||
/// <returns>Identity policy response contract.</returns>
|
||||
Task<EvaluateIdentityPolicyResponse> HandleAsync(EvaluateIdentityPolicyRequest request);
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Transport-neutral request contract for identity policy evaluation.
|
||||
/// </summary>
|
||||
/// <param name="SubjectId">Identity subject identifier.</param>
|
||||
/// <param name="TenantId">Tenant scope identifier.</param>
|
||||
/// <param name="PermissionCode">Permission code to evaluate.</param>
|
||||
public sealed record EvaluateIdentityPolicyRequest(string SubjectId, string TenantId, string PermissionCode);
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Transport-neutral response contract for identity policy evaluation.
|
||||
/// </summary>
|
||||
/// <param name="SubjectId">Identity subject identifier.</param>
|
||||
/// <param name="PermissionCode">Permission code evaluated.</param>
|
||||
/// <param name="IsAllowed">Policy result.</param>
|
||||
public sealed record EvaluateIdentityPolicyResponse(string SubjectId, string PermissionCode, bool IsAllowed);
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Transport-neutral request contract for identity policy context retrieval.
|
||||
/// </summary>
|
||||
/// <param name="SubjectId">Identity subject identifier.</param>
|
||||
/// <param name="TenantId">Tenant scope identifier.</param>
|
||||
/// <param name="PermissionCode">Permission code to evaluate.</param>
|
||||
public sealed record IdentityPolicyContextRequest(string SubjectId, string TenantId, string PermissionCode);
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Transport-neutral response contract for identity policy context retrieval.
|
||||
/// </summary>
|
||||
/// <param name="SubjectId">Identity subject identifier.</param>
|
||||
/// <param name="PermissionCode">Permission code evaluated.</param>
|
||||
/// <param name="ContextSatisfied">Indicates whether context satisfies policy preconditions.</param>
|
||||
public sealed record IdentityPolicyContextResponse(string SubjectId, string PermissionCode, bool ContextSatisfied);
|
||||
@ -0,0 +1,15 @@
|
||||
using Core.Blueprint.Common.Contracts;
|
||||
|
||||
namespace Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Defines package descriptor metadata for Thalos identity abstractions.
|
||||
/// </summary>
|
||||
public sealed class ThalosIdentityPackageContract : IBlueprintPackageContract
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public BlueprintPackageDescriptor Descriptor { get; } = new(
|
||||
"Thalos.Service.Identity.Abstractions",
|
||||
PackageVersionPolicy.Minor,
|
||||
["Core.Blueprint.Common"]);
|
||||
}
|
||||
@ -4,4 +4,7 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\blueprint-platform\src\Core.Blueprint.Common\Core.Blueprint.Common.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
using Thalos.Service.Application.Adapters;
|
||||
using Thalos.Service.Application.Ports;
|
||||
using Thalos.Service.Application.UseCases;
|
||||
using Thalos.Service.Identity.Abstractions.Contracts;
|
||||
|
||||
namespace Thalos.Service.Application.UnitTests;
|
||||
|
||||
public class EvaluateIdentityPolicyUseCaseTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task HandleAsync_WhenCalled_UsesIdentityContractsAndReturnsMappedResponse()
|
||||
{
|
||||
var useCase = new EvaluateIdentityPolicyUseCase(
|
||||
new FakeIdentityCapabilityContractAdapter(),
|
||||
new FakeIdentityPolicyContextReadPort());
|
||||
|
||||
var response = await useCase.HandleAsync(new EvaluateIdentityPolicyRequest("subject-1", "tenant-1", "perm.read"));
|
||||
|
||||
Assert.Equal("subject-1", response.SubjectId);
|
||||
Assert.Equal("perm.read", response.PermissionCode);
|
||||
Assert.True(response.IsAllowed);
|
||||
}
|
||||
|
||||
private sealed class FakeIdentityCapabilityContractAdapter : IIdentityCapabilityContractAdapter
|
||||
{
|
||||
public IdentityPolicyContextRequest CreatePolicyContext(EvaluateIdentityPolicyRequest identityRequest)
|
||||
{
|
||||
return new IdentityPolicyContextRequest(identityRequest.SubjectId, identityRequest.TenantId, identityRequest.PermissionCode);
|
||||
}
|
||||
|
||||
public EvaluateIdentityPolicyResponse MapPolicyResponse(
|
||||
EvaluateIdentityPolicyRequest identityRequest,
|
||||
IdentityPolicyContextResponse contextResponse)
|
||||
{
|
||||
return new EvaluateIdentityPolicyResponse(
|
||||
identityRequest.SubjectId,
|
||||
identityRequest.PermissionCode,
|
||||
contextResponse.ContextSatisfied);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeIdentityPolicyContextReadPort : IIdentityPolicyContextReadPort
|
||||
{
|
||||
public Task<IdentityPolicyContextResponse> ReadPolicyContextAsync(IdentityPolicyContextRequest request)
|
||||
{
|
||||
return Task.FromResult(new IdentityPolicyContextResponse(request.SubjectId, request.PermissionCode, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user