From 1df7551e4145d744c2d7925236009f969652d042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Ren=C3=A9=20White=20Enciso?= Date: Sun, 22 Feb 2026 01:30:02 -0600 Subject: [PATCH] feat(stage3): scaffold task-001 baseline - WHY: establish Stage 3 task-001 execution baseline per repo intent - WHAT: add minimal solution/project skeleton and boundary docs - RULE: apply stage3 execution runtime and repository workflow directives --- Furniture.Bff.slnx | 10 +++++++ docs/api/external-api-surface.md | 15 +++++++++++ docs/architecture/protocol-adaptation.puml | 20 ++++++++++++++ docs/operations/tracing-and-headers.md | 16 +++++++++++ .../Adapters/IFurnitureServiceClient.cs | 16 +++++++++++ .../Furniture.Bff.Application.csproj | 10 +++++++ .../GetFurnitureAvailabilityHandler.cs | 17 ++++++++++++ .../IGetFurnitureAvailabilityHandler.cs | 16 +++++++++++ .../Api/GetFurnitureAvailabilityApiRequest.cs | 7 +++++ .../GetFurnitureAvailabilityApiResponse.cs | 8 ++++++ .../Furniture.Bff.Contracts.csproj | 7 +++++ .../Endpoints/EndpointConventions.cs | 12 +++++++++ .../Furniture.Bff.Rest.csproj | 11 ++++++++ src/Furniture.Bff.Rest/Program.cs | 13 +++++++++ ...Furniture.Bff.Application.UnitTests.csproj | 21 +++++++++++++++ .../GetFurnitureAvailabilityHandlerTests.cs | 27 +++++++++++++++++++ 16 files changed, 226 insertions(+) create mode 100644 Furniture.Bff.slnx create mode 100644 docs/api/external-api-surface.md create mode 100644 docs/architecture/protocol-adaptation.puml create mode 100644 docs/operations/tracing-and-headers.md create mode 100644 src/Furniture.Bff.Application/Adapters/IFurnitureServiceClient.cs create mode 100644 src/Furniture.Bff.Application/Furniture.Bff.Application.csproj create mode 100644 src/Furniture.Bff.Application/Handlers/GetFurnitureAvailabilityHandler.cs create mode 100644 src/Furniture.Bff.Application/Handlers/IGetFurnitureAvailabilityHandler.cs create mode 100644 src/Furniture.Bff.Contracts/Api/GetFurnitureAvailabilityApiRequest.cs create mode 100644 src/Furniture.Bff.Contracts/Api/GetFurnitureAvailabilityApiResponse.cs create mode 100644 src/Furniture.Bff.Contracts/Furniture.Bff.Contracts.csproj create mode 100644 src/Furniture.Bff.Rest/Endpoints/EndpointConventions.cs create mode 100644 src/Furniture.Bff.Rest/Furniture.Bff.Rest.csproj create mode 100644 src/Furniture.Bff.Rest/Program.cs create mode 100644 tests/Furniture.Bff.Application.UnitTests/Furniture.Bff.Application.UnitTests.csproj create mode 100644 tests/Furniture.Bff.Application.UnitTests/GetFurnitureAvailabilityHandlerTests.cs diff --git a/Furniture.Bff.slnx b/Furniture.Bff.slnx new file mode 100644 index 0000000..ecda2bd --- /dev/null +++ b/Furniture.Bff.slnx @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/docs/api/external-api-surface.md b/docs/api/external-api-surface.md new file mode 100644 index 0000000..b0b5433 --- /dev/null +++ b/docs/api/external-api-surface.md @@ -0,0 +1,15 @@ +# External API Surface + +## Active External Protocol + +- REST is the active external protocol for this BFF deployment. + +## Endpoint Baseline + +- `GET /api/furniture/{furnitureId}/availability` + +## Edge Responsibilities + +- Validate and normalize consumer request inputs. +- Map downstream service responses to consumer-facing shapes. +- Map downstream errors to consistent API error models. diff --git a/docs/architecture/protocol-adaptation.puml b/docs/architecture/protocol-adaptation.puml new file mode 100644 index 0000000..7d2790b --- /dev/null +++ b/docs/architecture/protocol-adaptation.puml @@ -0,0 +1,20 @@ +@startuml +skinparam packageStyle rectangle + +package "furniture-bff" { + class Program + interface IGetFurnitureAvailabilityHandler + class GetFurnitureAvailabilityHandler + interface IFurnitureServiceClient + + GetFurnitureAvailabilityHandler ..|> IGetFurnitureAvailabilityHandler + GetFurnitureAvailabilityHandler --> IFurnitureServiceClient +} + +package "Consumers" as Consumers +package "furniture-service" as FurnitureService + +Consumers --> Program : REST +Program --> IGetFurnitureAvailabilityHandler +IFurnitureServiceClient ..> FurnitureService : gRPC/internal +@enduml diff --git a/docs/operations/tracing-and-headers.md b/docs/operations/tracing-and-headers.md new file mode 100644 index 0000000..b159fa0 --- /dev/null +++ b/docs/operations/tracing-and-headers.md @@ -0,0 +1,16 @@ +# Tracing and Headers + +## Required Incoming Headers + +- `X-Correlation-Id` +- `X-Request-Id` + +## Forwarding Rules + +- Preserve correlation headers to downstream service calls. +- Add correlation headers if missing at the edge. + +## Observability Baseline + +- Log protocol, route, and correlation identifiers per request. +- Capture downstream call duration per request. diff --git a/src/Furniture.Bff.Application/Adapters/IFurnitureServiceClient.cs b/src/Furniture.Bff.Application/Adapters/IFurnitureServiceClient.cs new file mode 100644 index 0000000..1e118a1 --- /dev/null +++ b/src/Furniture.Bff.Application/Adapters/IFurnitureServiceClient.cs @@ -0,0 +1,16 @@ +using Furniture.Bff.Contracts.Api; + +namespace Furniture.Bff.Application.Adapters; + +/// +/// Service adapter boundary used by BFF handlers. +/// +public interface IFurnitureServiceClient +{ + /// + /// Retrieves furniture availability from downstream service. + /// + /// Furniture identifier. + /// Consumer-ready availability contract. + Task GetAvailabilityAsync(string furnitureId); +} diff --git a/src/Furniture.Bff.Application/Furniture.Bff.Application.csproj b/src/Furniture.Bff.Application/Furniture.Bff.Application.csproj new file mode 100644 index 0000000..c75bc4d --- /dev/null +++ b/src/Furniture.Bff.Application/Furniture.Bff.Application.csproj @@ -0,0 +1,10 @@ + + + net10.0 + enable + enable + + + + + diff --git a/src/Furniture.Bff.Application/Handlers/GetFurnitureAvailabilityHandler.cs b/src/Furniture.Bff.Application/Handlers/GetFurnitureAvailabilityHandler.cs new file mode 100644 index 0000000..7781661 --- /dev/null +++ b/src/Furniture.Bff.Application/Handlers/GetFurnitureAvailabilityHandler.cs @@ -0,0 +1,17 @@ +using Furniture.Bff.Application.Adapters; +using Furniture.Bff.Contracts.Api; + +namespace Furniture.Bff.Application.Handlers; + +/// +/// Default edge handler implementation for furniture availability. +/// +public sealed class GetFurnitureAvailabilityHandler(IFurnitureServiceClient serviceClient) + : IGetFurnitureAvailabilityHandler +{ + /// + public Task HandleAsync(GetFurnitureAvailabilityApiRequest request) + { + return serviceClient.GetAvailabilityAsync(request.FurnitureId); + } +} diff --git a/src/Furniture.Bff.Application/Handlers/IGetFurnitureAvailabilityHandler.cs b/src/Furniture.Bff.Application/Handlers/IGetFurnitureAvailabilityHandler.cs new file mode 100644 index 0000000..bcd5276 --- /dev/null +++ b/src/Furniture.Bff.Application/Handlers/IGetFurnitureAvailabilityHandler.cs @@ -0,0 +1,16 @@ +using Furniture.Bff.Contracts.Api; + +namespace Furniture.Bff.Application.Handlers; + +/// +/// Edge handler boundary for furniture availability endpoint. +/// +public interface IGetFurnitureAvailabilityHandler +{ + /// + /// Handles external request and returns API response. + /// + /// API request contract. + /// API response contract. + Task HandleAsync(GetFurnitureAvailabilityApiRequest request); +} diff --git a/src/Furniture.Bff.Contracts/Api/GetFurnitureAvailabilityApiRequest.cs b/src/Furniture.Bff.Contracts/Api/GetFurnitureAvailabilityApiRequest.cs new file mode 100644 index 0000000..42b9d38 --- /dev/null +++ b/src/Furniture.Bff.Contracts/Api/GetFurnitureAvailabilityApiRequest.cs @@ -0,0 +1,7 @@ +namespace Furniture.Bff.Contracts.Api; + +/// +/// External REST request contract for furniture availability. +/// +/// Furniture identifier provided by consumers. +public sealed record GetFurnitureAvailabilityApiRequest(string FurnitureId); diff --git a/src/Furniture.Bff.Contracts/Api/GetFurnitureAvailabilityApiResponse.cs b/src/Furniture.Bff.Contracts/Api/GetFurnitureAvailabilityApiResponse.cs new file mode 100644 index 0000000..c6068c8 --- /dev/null +++ b/src/Furniture.Bff.Contracts/Api/GetFurnitureAvailabilityApiResponse.cs @@ -0,0 +1,8 @@ +namespace Furniture.Bff.Contracts.Api; + +/// +/// External REST response contract for furniture availability. +/// +/// Requested furniture identifier. +/// Availability value for client display. +public sealed record GetFurnitureAvailabilityApiResponse(string FurnitureId, int QuantityAvailable); diff --git a/src/Furniture.Bff.Contracts/Furniture.Bff.Contracts.csproj b/src/Furniture.Bff.Contracts/Furniture.Bff.Contracts.csproj new file mode 100644 index 0000000..6c3a887 --- /dev/null +++ b/src/Furniture.Bff.Contracts/Furniture.Bff.Contracts.csproj @@ -0,0 +1,7 @@ + + + net10.0 + enable + enable + + diff --git a/src/Furniture.Bff.Rest/Endpoints/EndpointConventions.cs b/src/Furniture.Bff.Rest/Endpoints/EndpointConventions.cs new file mode 100644 index 0000000..d1cccb2 --- /dev/null +++ b/src/Furniture.Bff.Rest/Endpoints/EndpointConventions.cs @@ -0,0 +1,12 @@ +namespace Furniture.Bff.Rest.Endpoints; + +/// +/// Defines endpoint conventions for the furniture BFF REST surface. +/// +public static class EndpointConventions +{ + /// + /// Prefix used by public furniture API routes. + /// + public const string ApiPrefix = "/api/furniture"; +} diff --git a/src/Furniture.Bff.Rest/Furniture.Bff.Rest.csproj b/src/Furniture.Bff.Rest/Furniture.Bff.Rest.csproj new file mode 100644 index 0000000..2c53814 --- /dev/null +++ b/src/Furniture.Bff.Rest/Furniture.Bff.Rest.csproj @@ -0,0 +1,11 @@ + + + net10.0 + enable + enable + + + + + + diff --git a/src/Furniture.Bff.Rest/Program.cs b/src/Furniture.Bff.Rest/Program.cs new file mode 100644 index 0000000..aaac95c --- /dev/null +++ b/src/Furniture.Bff.Rest/Program.cs @@ -0,0 +1,13 @@ +using Furniture.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.MapGet("/api/furniture/{furnitureId}/availability", (string furnitureId) => +{ + return Results.Ok(new GetFurnitureAvailabilityApiResponse(furnitureId, 0)); +}); + +app.Run(); diff --git a/tests/Furniture.Bff.Application.UnitTests/Furniture.Bff.Application.UnitTests.csproj b/tests/Furniture.Bff.Application.UnitTests/Furniture.Bff.Application.UnitTests.csproj new file mode 100644 index 0000000..369c362 --- /dev/null +++ b/tests/Furniture.Bff.Application.UnitTests/Furniture.Bff.Application.UnitTests.csproj @@ -0,0 +1,21 @@ + + + net10.0 + enable + enable + false + + + + + + + + + + + + + + + diff --git a/tests/Furniture.Bff.Application.UnitTests/GetFurnitureAvailabilityHandlerTests.cs b/tests/Furniture.Bff.Application.UnitTests/GetFurnitureAvailabilityHandlerTests.cs new file mode 100644 index 0000000..8eabf74 --- /dev/null +++ b/tests/Furniture.Bff.Application.UnitTests/GetFurnitureAvailabilityHandlerTests.cs @@ -0,0 +1,27 @@ +using Furniture.Bff.Application.Adapters; +using Furniture.Bff.Application.Handlers; +using Furniture.Bff.Contracts.Api; + +namespace Furniture.Bff.Application.UnitTests; + +public class GetFurnitureAvailabilityHandlerTests +{ + [Fact] + public async Task HandleAsync_WhenCalled_DelegatesToServiceClient() + { + var handler = new GetFurnitureAvailabilityHandler(new FakeFurnitureServiceClient()); + + var response = await handler.HandleAsync(new GetFurnitureAvailabilityApiRequest("FUR-001")); + + Assert.Equal("FUR-001", response.FurnitureId); + Assert.Equal(3, response.QuantityAvailable); + } + + private sealed class FakeFurnitureServiceClient : IFurnitureServiceClient + { + public Task GetAvailabilityAsync(string furnitureId) + { + return Task.FromResult(new GetFurnitureAvailabilityApiResponse(furnitureId, 3)); + } + } +}