diff --git a/Thalos.Bff.slnx b/Thalos.Bff.slnx
new file mode 100644
index 0000000..e0195c7
--- /dev/null
+++ b/Thalos.Bff.slnx
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/api/identity-edge-api.md b/docs/api/identity-edge-api.md
new file mode 100644
index 0000000..c61beab
--- /dev/null
+++ b/docs/api/identity-edge-api.md
@@ -0,0 +1,16 @@
+# Identity Edge API
+
+## Active External Protocol
+
+- REST is the active external protocol for this BFF deployment.
+
+## Entrypoints
+
+- `POST /api/identity/token`
+- `POST /api/identity/session/refresh`
+
+## Boundary Notes
+
+- Endpoint handlers perform edge validation and permission checks.
+- Business orchestration remains in thalos-service.
+- Identity abstractions remain owned by Thalos repositories.
diff --git a/docs/architecture/thalos-bff-flow.puml b/docs/architecture/thalos-bff-flow.puml
new file mode 100644
index 0000000..ec2a6b0
--- /dev/null
+++ b/docs/architecture/thalos-bff-flow.puml
@@ -0,0 +1,27 @@
+@startuml
+skinparam packageStyle rectangle
+
+package "thalos-bff" {
+ class Program
+ interface IIssueTokenHandler
+ class IssueTokenHandler
+ interface IRefreshSessionHandler
+ class RefreshSessionHandler
+ interface IPermissionGuard
+ interface IThalosServiceClient
+
+ IssueTokenHandler ..|> IIssueTokenHandler
+ RefreshSessionHandler ..|> IRefreshSessionHandler
+ IssueTokenHandler --> IPermissionGuard
+ IssueTokenHandler --> IThalosServiceClient
+ RefreshSessionHandler --> IThalosServiceClient
+}
+
+package "Clients" as Clients
+package "thalos-service" as ThalosService
+
+Clients --> Program : REST
+Program --> IIssueTokenHandler
+Program --> IRefreshSessionHandler
+IThalosServiceClient ..> ThalosService : gRPC/internal
+@enduml
diff --git a/docs/security/permission-enforcement-map.md b/docs/security/permission-enforcement-map.md
new file mode 100644
index 0000000..e6592db
--- /dev/null
+++ b/docs/security/permission-enforcement-map.md
@@ -0,0 +1,11 @@
+# Permission Enforcement Map
+
+## Enforcement Points
+
+- `identity.token.issue` evaluated at token issuance handler.
+- Session refresh guarded by edge session validation policy.
+
+## Guardrail
+
+- Permission checks happen at BFF entrypoints before downstream calls.
+- Authorization decisions are explicit and traceable at edge boundaries.
diff --git a/src/Thalos.Bff.Application/Adapters/IThalosServiceClient.cs b/src/Thalos.Bff.Application/Adapters/IThalosServiceClient.cs
new file mode 100644
index 0000000..667d149
--- /dev/null
+++ b/src/Thalos.Bff.Application/Adapters/IThalosServiceClient.cs
@@ -0,0 +1,23 @@
+using Thalos.Bff.Contracts.Api;
+
+namespace Thalos.Bff.Application.Adapters;
+
+///
+/// Adapter boundary for downstream thalos-service calls.
+///
+public interface IThalosServiceClient
+{
+ ///
+ /// Requests token issuance from thalos-service.
+ ///
+ /// Token issuance request.
+ /// Token issuance response.
+ Task IssueTokenAsync(IssueTokenApiRequest request);
+
+ ///
+ /// Requests token refresh from thalos-service.
+ ///
+ /// Session refresh request.
+ /// Session refresh response.
+ Task RefreshSessionAsync(RefreshSessionApiRequest request);
+}
diff --git a/src/Thalos.Bff.Application/Handlers/IIssueTokenHandler.cs b/src/Thalos.Bff.Application/Handlers/IIssueTokenHandler.cs
new file mode 100644
index 0000000..557b5c7
--- /dev/null
+++ b/src/Thalos.Bff.Application/Handlers/IIssueTokenHandler.cs
@@ -0,0 +1,16 @@
+using Thalos.Bff.Contracts.Api;
+
+namespace Thalos.Bff.Application.Handlers;
+
+///
+/// Edge handler boundary for token issuance entrypoint.
+///
+public interface IIssueTokenHandler
+{
+ ///
+ /// Handles token issuance flow.
+ ///
+ /// Token issuance request.
+ /// Token issuance response.
+ Task HandleAsync(IssueTokenApiRequest request);
+}
diff --git a/src/Thalos.Bff.Application/Handlers/IRefreshSessionHandler.cs b/src/Thalos.Bff.Application/Handlers/IRefreshSessionHandler.cs
new file mode 100644
index 0000000..e0d75e4
--- /dev/null
+++ b/src/Thalos.Bff.Application/Handlers/IRefreshSessionHandler.cs
@@ -0,0 +1,16 @@
+using Thalos.Bff.Contracts.Api;
+
+namespace Thalos.Bff.Application.Handlers;
+
+///
+/// Edge handler boundary for session refresh entrypoint.
+///
+public interface IRefreshSessionHandler
+{
+ ///
+ /// Handles session refresh flow.
+ ///
+ /// Session refresh request.
+ /// Session refresh response.
+ Task HandleAsync(RefreshSessionApiRequest request);
+}
diff --git a/src/Thalos.Bff.Application/Handlers/IssueTokenHandler.cs b/src/Thalos.Bff.Application/Handlers/IssueTokenHandler.cs
new file mode 100644
index 0000000..2e3ec62
--- /dev/null
+++ b/src/Thalos.Bff.Application/Handlers/IssueTokenHandler.cs
@@ -0,0 +1,23 @@
+using Thalos.Bff.Application.Adapters;
+using Thalos.Bff.Application.Security;
+using Thalos.Bff.Contracts.Api;
+
+namespace Thalos.Bff.Application.Handlers;
+
+///
+/// Default edge handler for token issuance.
+///
+public sealed class IssueTokenHandler(IThalosServiceClient serviceClient, IPermissionGuard permissionGuard)
+ : IIssueTokenHandler
+{
+ ///
+ public Task HandleAsync(IssueTokenApiRequest request)
+ {
+ if (!permissionGuard.CanAccess("identity.token.issue"))
+ {
+ throw new UnauthorizedAccessException("Permission denied.");
+ }
+
+ return serviceClient.IssueTokenAsync(request);
+ }
+}
diff --git a/src/Thalos.Bff.Application/Handlers/RefreshSessionHandler.cs b/src/Thalos.Bff.Application/Handlers/RefreshSessionHandler.cs
new file mode 100644
index 0000000..0ffda49
--- /dev/null
+++ b/src/Thalos.Bff.Application/Handlers/RefreshSessionHandler.cs
@@ -0,0 +1,17 @@
+using Thalos.Bff.Application.Adapters;
+using Thalos.Bff.Contracts.Api;
+
+namespace Thalos.Bff.Application.Handlers;
+
+///
+/// Default edge handler for refresh session flow.
+///
+public sealed class RefreshSessionHandler(IThalosServiceClient serviceClient)
+ : IRefreshSessionHandler
+{
+ ///
+ public Task HandleAsync(RefreshSessionApiRequest request)
+ {
+ return serviceClient.RefreshSessionAsync(request);
+ }
+}
diff --git a/src/Thalos.Bff.Application/Security/IPermissionGuard.cs b/src/Thalos.Bff.Application/Security/IPermissionGuard.cs
new file mode 100644
index 0000000..ac2600d
--- /dev/null
+++ b/src/Thalos.Bff.Application/Security/IPermissionGuard.cs
@@ -0,0 +1,14 @@
+namespace Thalos.Bff.Application.Security;
+
+///
+/// Edge permission enforcement contract.
+///
+public interface IPermissionGuard
+{
+ ///
+ /// Evaluates whether a permission is satisfied for the current request context.
+ ///
+ /// Permission code to evaluate.
+ /// True when access is allowed.
+ bool CanAccess(string permissionCode);
+}
diff --git a/src/Thalos.Bff.Application/Thalos.Bff.Application.csproj b/src/Thalos.Bff.Application/Thalos.Bff.Application.csproj
new file mode 100644
index 0000000..99d234a
--- /dev/null
+++ b/src/Thalos.Bff.Application/Thalos.Bff.Application.csproj
@@ -0,0 +1,10 @@
+
+
+ net10.0
+ enable
+ enable
+
+
+
+
+
diff --git a/src/Thalos.Bff.Contracts/Api/IssueTokenApiRequest.cs b/src/Thalos.Bff.Contracts/Api/IssueTokenApiRequest.cs
new file mode 100644
index 0000000..a5b423d
--- /dev/null
+++ b/src/Thalos.Bff.Contracts/Api/IssueTokenApiRequest.cs
@@ -0,0 +1,8 @@
+namespace Thalos.Bff.Contracts.Api;
+
+///
+/// External API request for identity token issuance.
+///
+/// Identity subject identifier.
+/// Tenant identifier.
+public sealed record IssueTokenApiRequest(string SubjectId, string TenantId);
diff --git a/src/Thalos.Bff.Contracts/Api/IssueTokenApiResponse.cs b/src/Thalos.Bff.Contracts/Api/IssueTokenApiResponse.cs
new file mode 100644
index 0000000..44704b6
--- /dev/null
+++ b/src/Thalos.Bff.Contracts/Api/IssueTokenApiResponse.cs
@@ -0,0 +1,8 @@
+namespace Thalos.Bff.Contracts.Api;
+
+///
+/// External API response for identity token issuance.
+///
+/// Issued access token.
+/// Token expiration in seconds.
+public sealed record IssueTokenApiResponse(string AccessToken, int ExpiresInSeconds);
diff --git a/src/Thalos.Bff.Contracts/Api/RefreshSessionApiRequest.cs b/src/Thalos.Bff.Contracts/Api/RefreshSessionApiRequest.cs
new file mode 100644
index 0000000..c9c8e76
--- /dev/null
+++ b/src/Thalos.Bff.Contracts/Api/RefreshSessionApiRequest.cs
@@ -0,0 +1,7 @@
+namespace Thalos.Bff.Contracts.Api;
+
+///
+/// External API request for refresh token session flow.
+///
+/// Refresh token value.
+public sealed record RefreshSessionApiRequest(string RefreshToken);
diff --git a/src/Thalos.Bff.Contracts/Api/RefreshSessionApiResponse.cs b/src/Thalos.Bff.Contracts/Api/RefreshSessionApiResponse.cs
new file mode 100644
index 0000000..ebbace3
--- /dev/null
+++ b/src/Thalos.Bff.Contracts/Api/RefreshSessionApiResponse.cs
@@ -0,0 +1,8 @@
+namespace Thalos.Bff.Contracts.Api;
+
+///
+/// External API response for refresh token session flow.
+///
+/// Refreshed access token.
+/// New token expiration in seconds.
+public sealed record RefreshSessionApiResponse(string AccessToken, int ExpiresInSeconds);
diff --git a/src/Thalos.Bff.Contracts/Thalos.Bff.Contracts.csproj b/src/Thalos.Bff.Contracts/Thalos.Bff.Contracts.csproj
new file mode 100644
index 0000000..6c3a887
--- /dev/null
+++ b/src/Thalos.Bff.Contracts/Thalos.Bff.Contracts.csproj
@@ -0,0 +1,7 @@
+
+
+ net10.0
+ enable
+ enable
+
+
diff --git a/src/Thalos.Bff.Rest/Endpoints/EndpointConventions.cs b/src/Thalos.Bff.Rest/Endpoints/EndpointConventions.cs
new file mode 100644
index 0000000..19062a5
--- /dev/null
+++ b/src/Thalos.Bff.Rest/Endpoints/EndpointConventions.cs
@@ -0,0 +1,12 @@
+namespace Thalos.Bff.Rest.Endpoints;
+
+///
+/// Defines endpoint conventions for the identity edge API.
+///
+public static class EndpointConventions
+{
+ ///
+ /// Prefix used by identity edge API routes.
+ ///
+ public const string ApiPrefix = "/api/identity";
+}
diff --git a/src/Thalos.Bff.Rest/Program.cs b/src/Thalos.Bff.Rest/Program.cs
new file mode 100644
index 0000000..df15eb4
--- /dev/null
+++ b/src/Thalos.Bff.Rest/Program.cs
@@ -0,0 +1,18 @@
+using Thalos.Bff.Contracts.Api;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Stage 3 skeleton: single active external protocol for this deployment is REST.
+var app = builder.Build();
+
+app.MapPost("/api/identity/token", (IssueTokenApiRequest request) =>
+{
+ return Results.Ok(new IssueTokenApiResponse("", 0));
+});
+
+app.MapPost("/api/identity/session/refresh", (RefreshSessionApiRequest request) =>
+{
+ return Results.Ok(new RefreshSessionApiResponse("", 0));
+});
+
+app.Run();
diff --git a/src/Thalos.Bff.Rest/Thalos.Bff.Rest.csproj b/src/Thalos.Bff.Rest/Thalos.Bff.Rest.csproj
new file mode 100644
index 0000000..256722a
--- /dev/null
+++ b/src/Thalos.Bff.Rest/Thalos.Bff.Rest.csproj
@@ -0,0 +1,11 @@
+
+
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
diff --git a/tests/Thalos.Bff.Application.UnitTests/IssueTokenHandlerTests.cs b/tests/Thalos.Bff.Application.UnitTests/IssueTokenHandlerTests.cs
new file mode 100644
index 0000000..b5bf048
--- /dev/null
+++ b/tests/Thalos.Bff.Application.UnitTests/IssueTokenHandlerTests.cs
@@ -0,0 +1,38 @@
+using Thalos.Bff.Application.Adapters;
+using Thalos.Bff.Application.Handlers;
+using Thalos.Bff.Application.Security;
+using Thalos.Bff.Contracts.Api;
+
+namespace Thalos.Bff.Application.UnitTests;
+
+public class IssueTokenHandlerTests
+{
+ [Fact]
+ public async Task HandleAsync_WhenPermissionAllowed_DelegatesToServiceClient()
+ {
+ var handler = new IssueTokenHandler(new FakeThalosServiceClient(), new AllowPermissionGuard());
+
+ var response = await handler.HandleAsync(new IssueTokenApiRequest("user-1", "tenant-1"));
+
+ Assert.Equal("token-xyz", response.AccessToken);
+ Assert.Equal(1800, response.ExpiresInSeconds);
+ }
+
+ private sealed class FakeThalosServiceClient : IThalosServiceClient
+ {
+ public Task IssueTokenAsync(IssueTokenApiRequest request)
+ {
+ return Task.FromResult(new IssueTokenApiResponse("token-xyz", 1800));
+ }
+
+ public Task RefreshSessionAsync(RefreshSessionApiRequest request)
+ {
+ return Task.FromResult(new RefreshSessionApiResponse("token-refreshed", 1800));
+ }
+ }
+
+ private sealed class AllowPermissionGuard : IPermissionGuard
+ {
+ public bool CanAccess(string permissionCode) => true;
+ }
+}
diff --git a/tests/Thalos.Bff.Application.UnitTests/Thalos.Bff.Application.UnitTests.csproj b/tests/Thalos.Bff.Application.UnitTests/Thalos.Bff.Application.UnitTests.csproj
new file mode 100644
index 0000000..ecfabe1
--- /dev/null
+++ b/tests/Thalos.Bff.Application.UnitTests/Thalos.Bff.Application.UnitTests.csproj
@@ -0,0 +1,21 @@
+
+
+ net10.0
+ enable
+ enable
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+