Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
14252f9
Implement YARP API Gateway, migrate geoblocking, and cleanup ApiService
Apr 29, 2026
72d51f8
feat: implement rate limiting options and add unit tests for gateway …
Apr 29, 2026
b635cd2
ci: add backend CI pipeline with Postgres and Azurite integration tes…
Apr 30, 2026
8f1f3c3
chore: generate project lock files for centralized dependency management
Apr 30, 2026
9fd8556
feat: initialize ApiService project, add geographic restriction middl…
Apr 30, 2026
8877693
feat: implement main entry point with module registration and middlew…
Apr 30, 2026
8e08286
test: add unit tests for service defaults and scaffold initial projec…
Apr 30, 2026
c09ed48
feat: initialize API service project with geographic restriction midd…
Apr 30, 2026
5816499
feat: implement and test rate limiting and geographic restriction mid…
Apr 30, 2026
d4a8272
feat: add middleware to restrict access based on geographic location …
Apr 30, 2026
8f2e942
feat: add GeographicRestrictionMiddleware and configure gateway setti…
Apr 30, 2026
e7189c3
feat: implement API service and gateway bootstrapper with modular mid…
Apr 30, 2026
a5bc21b
feat: implement API service bootstrapper and base integration test cl…
Apr 30, 2026
04fb449
feat: implement structured request logging, security middleware, and …
Apr 30, 2026
06b0ef3
feat: implement geographic restriction middleware and add gateway res…
Apr 30, 2026
f34e6c6
feat: implement edge authentication guard and resilient forwarder cli…
Apr 30, 2026
3441ec1
feat: implement gateway authentication guard and resilient forwarder …
Apr 30, 2026
7f8d39c
test: implement unit tests for geographic restriction, rate limiting,…
Apr 30, 2026
f468f38
feat: add EdgeAuthGuard middleware and ResilientForwarderHttpClientFa…
Apr 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/setup-backend/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ runs:

- name: Restore dependencies
shell: bash
run: dotnet restore ${{ inputs.solution-path }}
run: dotnet restore ${{ inputs.solution-path }} --force-evaluate

- name: Install Tools
shell: bash
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
paths:
- 'src/Modules/**'
- 'src/Bootstrapper/**'
- 'src/Aspire/**'
- 'src/Shared/**'
- 'src/Contracts/**'
- 'tests/**'
Expand All @@ -20,6 +21,7 @@ on:
paths:
- 'src/Modules/**'
- 'src/Bootstrapper/**'
- 'src/Aspire/**'
- 'src/Shared/**'
- 'src/Contracts/**'
- 'tests/**'
Expand Down Expand Up @@ -181,6 +183,7 @@ jobs:
"src/Modules/Bookings/Tests/MeAjudaAi.Modules.Bookings.Tests.csproj"
"tests/MeAjudaAi.Shared.Tests/MeAjudaAi.Shared.Tests.csproj"
"tests/MeAjudaAi.ApiService.Tests/MeAjudaAi.ApiService.Tests.csproj"
"tests/MeAjudaAi.Gateway.Tests/MeAjudaAi.Gateway.Tests.csproj"
"tests/MeAjudaAi.Architecture.Tests/MeAjudaAi.Architecture.Tests.csproj"
)

Expand Down
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<PackageVersion Include="HtmlSanitizer" Version="9.0.892" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.7" />
<!-- .NET & Microsoft Core -->
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="10.0.7" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.4.0" />
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<!-- Pacotes Microsoft.Build - atualizados para 18.0.2 (CVE-2025-55247 resolvido) -->
Expand Down Expand Up @@ -177,7 +178,6 @@
<PackageVersion Include="Fluxor.Blazor.Web.ReduxDevTools" Version="6.9.0" />
<PackageVersion Include="Refit" Version="10.1.6" />
<PackageVersion Include="Refit.HttpClientFactory" Version="10.1.6" />
<!-- Testes Blazor -->
<PackageVersion Include="bUnit" Version="2.6.2" />
<PackageVersion Include="Yarp.ReverseProxy" Version="2.3.0" />
</ItemGroup>
</Project>
2 changes: 2 additions & 0 deletions MeAjudaAi.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
</Folder>
<Folder Name="/src/Bootstrapper/">
<Project Path="src/Bootstrapper/MeAjudaAi.ApiService/MeAjudaAi.ApiService.csproj" />
<Project Path="src/Bootstrapper/MeAjudaAi.Gateway/MeAjudaAi.Gateway.csproj" />
</Folder>
<Folder Name="/src/Client/">
<Project Path="src/Client/MeAjudaAi.Client.Contracts/MeAjudaAi.Client.Contracts.csproj" />
Expand Down Expand Up @@ -192,6 +193,7 @@
<Project Path="tests/MeAjudaAi.ApiService.Tests/MeAjudaAi.ApiService.Tests.csproj" />
<Project Path="tests/MeAjudaAi.Architecture.Tests/MeAjudaAi.Architecture.Tests.csproj" />
<Project Path="tests/MeAjudaAi.E2E.Tests/MeAjudaAi.E2E.Tests.csproj" />
<Project Path="tests/MeAjudaAi.Gateway.Tests/MeAjudaAi.Gateway.Tests.csproj" />
<Project Path="tests/MeAjudaAi.Integration.Tests/MeAjudaAi.Integration.Tests.csproj" />
<Project Path="tests/MeAjudaAi.Shared.Tests/MeAjudaAi.Shared.Tests.csproj" />
</Folder>
Expand Down
8 changes: 8 additions & 0 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ Este é o planejamento estratégico unificado da plataforma MeAjudaAi.
* **API Client Collections**: Adição de endpoints SSE para streaming de eventos (`/bookings/{id}/events`, `/providers/{id}/verification-events`), correções de paths em AllowedCitiesAdmin, padronização de variáveis (`{{bookingId}}`), remoção de tools/api-collections e referências a Postman nos docs.
* **Código e Testes**: Extração de constantes de mensagens SSE em BookingRealtimeEventsHandler, pré-compilação de Regex em BusinessMetricsMiddleware, expansão de casos de teste para headers de localização malformados.

## 🚀 Sprint 13.2: Edge Infrastructure & API Gateway (Planejado)

* **Implementação do YARP Gateway**: Criação do projeto `MeAjudaAi.Gateway` como ponto único de entrada para todos os frontends (Admin, Mobile, Web).
* **BFF (Backend for Frontend)**: Configuração de rotas segregadas e políticas de CORS/Rate Limiting específicas para cada perfil de acesso.
* **Security Hardening**: Centralização de validação de tokens JWT/Keycloak e sanitização de headers globais no Gateway.
* **Service Discovery**: Integração com .NET Aspire para roteamento dinâmico para o ApiService.
* **Resiliência**: Configuração de retentativas (Retries) e Circuit Breaker para endpoints críticos de integração.

---

## 🔮 Roadmaps Futuros (MVP Launch & Além)
Expand Down
1 change: 1 addition & 0 deletions src/Aspire/MeAjudaAi.AppHost/MeAjudaAi.AppHost.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<ProjectReference Include="..\..\Modules\SearchProviders\Infrastructure\MeAjudaAi.Modules.SearchProviders.Infrastructure.csproj" IsAspireProjectResource="false" />
<ProjectReference Include="..\..\Modules\ServiceCatalogs\Infrastructure\MeAjudaAi.Modules.ServiceCatalogs.Infrastructure.csproj" IsAspireProjectResource="false" />
<ProjectReference Include="..\..\Modules\Users\Infrastructure\MeAjudaAi.Modules.Users.Infrastructure.csproj" IsAspireProjectResource="false" />
<ProjectReference Include="..\..\Bootstrapper\MeAjudaAi.Gateway\MeAjudaAi.Gateway.csproj" />
</ItemGroup>

</Project>
24 changes: 17 additions & 7 deletions src/Aspire/MeAjudaAi.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ void AddSocialProviderEnv(string providerName, string clientIdKey, string client
.WaitFor(keycloakBootstrap)
.WithEnvironment("ASPNETCORE_ENVIRONMENT", EnvironmentHelpers.GetEnvironmentName(builder));

var gateway = builder.AddProject<Projects.MeAjudaAi_Gateway>("gateway")
.WithReference(apiService)
.WithExternalHttpEndpoints()
.WaitFor(apiService);
Comment thread
frigini marked this conversation as resolved.

// Admin Portal (Next.js 15 React)
var adminWebPath = Path.Combine(builder.AppHostDirectory, "..", "..", "..", "src", "Web", "MeAjudaAi.Web.Admin");
if (!Directory.Exists(adminWebPath))
Expand All @@ -220,8 +225,8 @@ void AddSocialProviderEnv(string providerName, string clientIdKey, string client
var adminPortal = builder.AddJavaScriptApp("admin-portal", adminWebPath)
.WithHttpEndpoint(port: 3002, env: "PORT")
.WithExternalHttpEndpoints()
.WithEnvironment("NEXT_PUBLIC_API_URL", apiService.GetEndpoint("http"))
.WaitFor(apiService)
.WithEnvironment("NEXT_PUBLIC_API_URL", gateway.GetEndpoint("http"))
.WaitFor(gateway)
.WaitFor(keycloak.Keycloak)
.WaitFor(keycloakBootstrap);

Expand All @@ -235,8 +240,8 @@ void AddSocialProviderEnv(string providerName, string clientIdKey, string client
var customerWeb = builder.AddJavaScriptApp("customer-web", customerWebPath)
.WithHttpEndpoint(port: 3000, env: "PORT")
.WithExternalHttpEndpoints()
.WithEnvironment("NEXT_PUBLIC_API_URL", apiService.GetEndpoint("http"))
.WaitFor(apiService)
.WithEnvironment("NEXT_PUBLIC_API_URL", gateway.GetEndpoint("http"))
.WaitFor(gateway)
.WaitFor(keycloakBootstrap);
// Nota: AddJavaScriptApp usa "dev" script por padrão em desenvolvimento
// e "build" script em produção. Ver package.json para scripts configurados.
Expand All @@ -251,8 +256,8 @@ void AddSocialProviderEnv(string providerName, string clientIdKey, string client
var providerWeb = builder.AddJavaScriptApp("provider-web", providerWebPath)
.WithHttpEndpoint(port: 3001, env: "PORT")
.WithExternalHttpEndpoints()
.WithEnvironment("NEXT_PUBLIC_API_URL", apiService.GetEndpoint("http"))
.WaitFor(apiService)
.WithEnvironment("NEXT_PUBLIC_API_URL", gateway.GetEndpoint("http"))
.WaitFor(gateway)
.WaitFor(keycloakBootstrap);

// Pass resolved endpoints to Keycloak options for bootstrap
Expand All @@ -275,7 +280,7 @@ private static void ConfigureProductionEnvironment(IDistributedApplicationBuilde

var keycloak = builder.AddMeAjudaAiKeycloakProduction();

builder.AddProject<Projects.MeAjudaAi_ApiService>("apiservice")
var apiService = builder.AddProject<Projects.MeAjudaAi_ApiService>("apiservice")
.WithReference(postgresql.MainDatabase, "DefaultConnection")
.WithReference(redis)
.WaitFor(postgresql.MainDatabase)
Expand All @@ -286,5 +291,10 @@ private static void ConfigureProductionEnvironment(IDistributedApplicationBuilde
.WaitFor(keycloak.Keycloak)
.WaitFor(keycloakBootstrap)
.WithEnvironment("ASPNETCORE_ENVIRONMENT", EnvironmentHelpers.GetEnvironmentName(builder));

var gateway = builder.AddProject<Projects.MeAjudaAi_Gateway>("gateway")
.WithReference(apiService)
.WithExternalHttpEndpoints()
.WaitFor(apiService);
}
}
3 changes: 0 additions & 3 deletions src/Aspire/MeAjudaAi.AppHost/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,5 @@
"EndpointUrls": "https://localhost:15889"
}
}
},
"FeatureManagement": {
"GeographicRestriction": false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ public static IEndpointRouteBuilder MapProviderRegistrationEndpoints(this IEndpo
"e a entidade Provider com Tier=Standard. Endpoint público, sem autenticação.")
.Produces<Response<ProviderDto>>(StatusCodes.Status201Created)
.Produces(StatusCodes.Status400BadRequest)
.AllowAnonymous()
.RequireRateLimiting(RateLimitPolicies.ProviderRegistration);
.AllowAnonymous();

return endpoints;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ public static IApplicationBuilder UseApiMiddlewares(this IApplicationBuilder app
// Cabeçalhos de segurança (no início do pipeline)
app.UseMiddleware<SecurityHeadersMiddleware>();

// Limitação de taxa (rate limiting)
app.UseMiddleware<RateLimitingMiddleware>();

return app;
}
}
Loading
Loading