Skip to content
CAI
Software that uses CAICheck a score

Gramli/WeatherApi

68.2

Adequate · 21 September 2026

1.4k

lines of production code

C#

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This release establishes the foundational architecture for the Weather API, introducing a complete CQRS-based implementation for retrieving current and forecast weather data, as well as managing user favorites. The solution features a new Weatherbit HTTP client, an in-memory database context for favorites, and standardized response handling with global exception middleware. Additionally, the project has been upgraded to .NET 10.0 with centralized package management, supported by comprehensive unit, integration, and system tests.

Features

Add Weatherbit HTTP client for weather data retrieval

Introduced the internal WeatherbitHttpClient implementation, which provides methods to fetch current and 16-day weather forecasts by latitude and longitude. The client validates configuration options, constructs API requests with required headers, and deserializes JSON responses into DTOs.

src/Wheaterbit.Client · high confidence

Add Weatherbit client DTOs for current and forecast weather data

New data transfer objects are introduced in the Wheaterbit client to model weather API responses. This includes CurrentWeatherDataDto and CurrentWeatherDto for current conditions (temperature, city name, observation time, sunrise/sunset), and ForecastWeatherDto and ForecastTemperatureDto for forecast data (temperature and datetime). These DTOs enable the client to deserialize and process weather data from the Weatherbit API.

src/Wheaterbit.Client/Dtos · high confidence

Add Weatherbit client configuration and validation

Users can now register the Weatherbit HTTP client and its associated options via the new \AddWeatherbit\ extension method. This registration configures \WeatherbitOptions\ from the application's configuration, registers the \IWeatherbitHttpClient\ implementation, and adds a \Validot\-based validator to ensure that required configuration properties (such as \BaseUrl\, \XRapidAPIHost\, and \XRapidAPIKey\) are not empty or whitespace.

src/Wheaterbit.Client/Configuration · medium confidence

Add WeatherbitOptions configuration class

Introduced a new configuration class, WeatherbitOptions, which defines the settings for the Weatherbit client, including BaseUrl, XRapidAPIKey, and XRapidAPIHost properties.

src/Wheaterbit.Client/Options · high confidence

Add weather API endpoints for current, forecast, and favorite weather data

A new WeatherBuilder class was added to define the weather API endpoints. It exposes routes for retrieving current and forecast weather data by latitude and longitude, as well as managing user favorites (get, add, and delete). These endpoints use the CQRS pattern with request handlers and return DTOs, supporting cancellation and versioning.

src/Weather.API/EndpointBuilders · high confidence

Added .dockerignore, solution, and coverage report files

The src directory now includes a .dockerignore file to exclude unnecessary files from Docker builds, a new Weather.API.slnx solution file that organizes the project structure into folders for external clients, tests, and solution items, and a dotCover.Output.xml file containing detailed code coverage statistics for the application's components.

src · high confidence

Added AutoMapper profiles for weather data mapping

New AutoMapper profiles have been introduced to handle the mapping between external API responses and internal domain models. The WeatherbitClientProfile maps DTOs from the Weatherbit client library to the application's internal Dtos (including temperature, datetime, city name, and sunrise/sunset times), while the WeatherEntitiesProfile maps between FavoriteLocation entities and DTOs.

src/Weather.Infrastructure/Mapping · high confidence

Added WeatherService to fetch current and forecast weather data

A new WeatherService implementation was added to the infrastructure layer, providing methods to retrieve current weather and 16-day forecasts from the Weatherbit API. The service handles HTTP client interactions, validates the response data, and maps the results to domain DTOs.

src/Weather.Infrastructure/Services · medium confidence

Added validation for weather commands, queries, and DTOs

New validators have been introduced for the core domain, ensuring that requests and data transfer objects are properly validated before processing. Specifically, the system now validates AddFavoriteCommand, DeleteFavoriteCommand, GetCurrentWeatherQuery, and GetForecastWeatherQuery, as well as CurrentWeatherDto, ForecastWeatherDto, and LocationDto. The validation logic enforces constraints such as valid temperature ranges (-90 to 60), latitude (-90 to 90), and longitude (-180 to 180) via the GeneralPredicates class.

src/Weather.Core/Validation · high confidence

Adds extension methods for enumerables and FluentResults

New extension methods are introduced in the Weather.Domain.Extensions namespace to simplify common operations. EnumerableExtensions provides ForEach, ForEachAsync, HasAny, and JoinToMessage helpers for IEnumerable types. FluentResultExtensions adds ToErrorMessages and JoinToMessage helpers for IList\<IError\>, converting error collections into string representations. These utilities streamline iteration and error message formatting within the domain layer.

src/Weather.Domain/Extensions · high confidence

Initial Weather API project structure and configuration

The Weather.API project is introduced with a new entry point (Program.cs) that configures logging, dependency injection for core and infrastructure services, and OpenAPI/Scalar documentation. The setup includes an exception handling middleware, HTTPS redirection, and endpoint mapping. Configuration files (appsettings.json) define logging levels, allowed hosts, and external Weatherbit API settings, while a Dockerfile and container configuration extension support containerized development and deployment.

src/Weather.API · high confidence

Introduce JSON serialization configuration for date formatting

A new factory, JsonSerializerSettingsFactory, has been added to configure JSON serialization settings. Specifically, it sets the date format string to 'yyyy-MM-dd hh:mm' for the Wheaterbit client.

src/Wheaterbit.Client/Factories · high confidence

Introduce abstractions for Weatherbit client and JSON serialization

Added new interfaces to the Wheaterbit.Client.Abstractions namespace: IJsonSerializerSettingsFactory for managing Newtonsoft.Json settings, and IWeatherbitHttpClient which defines methods for retrieving current and 16-day weather forecasts using double-precision latitude and longitude parameters.

src/Wheaterbit.Client/Abstractions · high confidence

Introduce database context and favorite location entity

Added the Entity Framework Core context (WeatherContext) and the corresponding FavoriteLocationEntity, establishing the data access layer for storing favorite locations with latitude and longitude as double-precision values.

src/Weather.Infrastructure/Database/EFContext · medium confidence

Introduced new query classes for retrieving current and forecast weather data

Added GetCurrentWeatherQuery and GetForecastWeatherQuery classes in the Weather.Domain.Queries namespace. Each class accepts latitude and longitude (as doubles) to construct a LocationDto, enabling the domain layer to handle weather data retrieval requests with geographic coordinates.

src/Weather.Domain/Queries · high confidence

Introduction of structured logging event identifiers

A new LogEvents class has been added to the Weather.Domain.Logging namespace, defining static integer constants that serve as unique identifiers for various logging scenarios. These include general errors, and specific event codes for Favorite, Current, and Forecast weather operations, facilitating structured logging and traceability for these domain events.

src/Weather.Domain/Logging · high confidence

New database repositories for favorite locations

Added new repository classes to handle favorite location data access. WeatherCommandsRepository implements write operations (AddFavoriteLocation, DeleteFavoriteLocationSafeAsync) with error handling and cancellation support. WeatherQueriesRepository provides read operations (GetFavorites). Both inherit from a new RepositoryBase abstract class that encapsulates shared dependencies (EF context, AutoMapper).

src/Weather.Infrastructure/Database/Repositories · high confidence

Behavioural changes

Added commands for managing favorite locations

Users can now add and remove favorite locations. This change introduces new domain commands (AddFavoriteCommand and DeleteFavoriteCommand) and a FavoriteLocation business entity to support these operations.

src/Weather.Domain/Commands · medium confidence

Added global exception handling middleware

A new ExceptionMiddleware has been introduced to the API's request pipeline. This middleware catches unhandled exceptions during request processing and returns a standardized JSON error response, ensuring that unexpected server errors are logged and communicated to the client in a consistent format rather than causing a raw stack trace or HTTP 500 error.

src/Weather.API/Middlewares · high confidence

Added new DTOs for weather data and favorites

Introduced new data transfer objects in the domain layer to support weather and favorites functionality. This includes CurrentWeatherDto for displaying current conditions, ForecastWeatherDto and ForecastTemperatureDto for forecast data, LocationDto for geographic coordinates, and FavoriteCurrentWeatherDto and FavoritesWeatherDto to manage user-saved locations. These classes define the structure for serializing and transferring weather information between application components.

src/Weather.Domain/Dtos · high confidence

Centralized error message resources for Core, Domain, and Infrastructure layers

The project has reorganized its localized error messages by moving .resx files and their corresponding auto-generated .Designer.cs classes into dedicated Resources folders within the Weather.Core, Weather.Domain, and Weather.Infrastructure projects. This change consolidates the string resources for error handling in each layer, making it easier to manage and translate user-facing messages for database failures, external API issues, and validation errors.

src/Weather.Core/Resources, src/Weather.Domain/Resources, src/Weather.Infrastructure/Resources · high confidence

Implemented CQRS handlers for weather and favorites operations

Added new handlers for the Weather.Core layer to support the CQRS pattern. This includes handlers for adding and deleting favorite locations (AddFavoriteHandler, DeleteFavoriteHandler) and for retrieving current weather, forecast weather, and a list of favorite locations (GetCurrentWeatherHandler, GetForecastWeatherHandler, GetFavoritesHandler). Each handler integrates with the underlying weather service and repository, performing validation and logging as appropriate.

src/Weather.Core/Queries · high confidence

Introduce structured handler model and API extensions for request/response handling

Added a new handler model in the core layer that defines a standard response structure (DataResponse, HandlerResponse, and HandlerStatusCode enum) to represent success, validation errors, and internal errors. In the API layer, new extension methods were introduced to map these responses to appropriate HTTP status codes and JSON results, and to simplify route grouping by version. This change standardizes how handlers return data and errors across the application.

src/Weather.API/Extensions, src/Weather.Core/HandlerModel · high confidence

Introduces core CQRS abstractions and validation handlers

The project now includes a set of new interfaces and base classes that support a Command Query Responsibility Segregation (CQRS) architecture. This includes generic request and validator interfaces (IRequestHandler, IRequestValidator), specific repository interfaces for weather commands and queries, and a weather service interface. Additionally, a ValidationStatusRequestHandler base class is provided to automatically validate requests before processing, standardizing how validation errors are handled across commands.

src/Weather.Core/Abstractions · high confidence

Register weather handlers and validators via DI

The application now explicitly registers all weather-related request handlers (for current weather, favorites, and forecast) and their corresponding DTO/command validators in the dependency injection container. This ensures that validation logic is applied to incoming requests and that the correct handler is invoked for each operation.

src/Weather.Core/Configuration · medium confidence

Register weather infrastructure services and dependencies

Users can now access weather data through the newly registered WeatherService, which is wired up via dependency injection. The infrastructure layer also configures the in-memory database context, repository implementations, AutoMapper profiles, and the external Weatherbit HTTP client, enabling the application to retrieve and process weather information.

src/Weather.Infrastructure/Configuration · high confidence

Test coverage

Added HTTP debug tests for weather endpoints; Added global using for xUnit in integration tests; Added global using statements for unit test projects; Added system tests for weather API endpoints; Added unit tests for GetCurrentWeatherHandler and GetFavoritesHandler; Added unit tests for WeatherService; Added unit tests for domain extension methods; Added unit tests for favorite management commands; Added unit tests for the WeatherCommandsRepository; Added unit tests for the Weatherbit HTTP client; Added unit tests for weather query handlers.

Dependencies

Upgrade to .NET 10.0 and centralize package versions

The project has been migrated to .NET 10.0, updating the target framework across all main and test projects. A central package management file (Directory.Packages.props) has been introduced to define specific versions for key dependencies, including FluentResults 4.0.0, xUnit 2.9.3, Moq 4.20.72, and AutoMapper 13.0.1, ensuring consistent dependency versions throughout the solution.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 66 → 68 (+2.5)
  • Rubric changed (rubric-2026.08.18 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 94 → 95 (+0.6)
  • Architecture 90 → 90 (+0.0)
  • Maturity 75 → 77 (+1.8)
  • Readiness 51 → 53 (+2.2)
  • Security 75 → 82 (+6.5)

Resolved (15)

  • Bounded contexts not declared
  • Coverage not measured — analyzer environment
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • No exposed public API
  • Secret: rapidapi-access-token (src/Weather.API/appsettings.json)
  • Secret: rapidapi-access-token (src/Weather.API/appsettings.json)
  • Secret: rapidapi-access-token (src/Weather.API/appsettings.json)
  • Secret: rapidapi-access-token (src/Weather.API/appsettings.json)
  • The 'Architecture' section is clipped, so the Clean Architecture Layers (Horizontal Diagram references) and Pros/Cons sections are not visible. (README.md)
  • The namespace and type names for the external 'Weatherbit' client are inconsistently spelled as 'Wheaterbit' (with an 'e' after 'W') in multiple locations, likely a typo for 'Weatherbit'.
  • dormant codebase — no living knowledge left to concentrate
  • redundant comment (src/Tests/SystemTests/Weather.API.SystemTests/WeatherSystemTests.cs)

New (19)

  • Documentation: no usage examples (README.md)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • Medium IaC: WD-DOCKER-0003 (src/Weather.API/Dockerfile)
  • Medium IaC: WD-DOCKER-0003 (src/Weather.API/Dockerfile)
  • Medium: security finding (details withheld)
  • Medium: security finding (details withheld)
  • Medium: security finding (details withheld)
  • Secret: rapidapi-access-token (src/Weather.API/appsettings.json)
  • Secret: rapidapi-access-token (src/Weather.API/appsettings.json)
  • Secret: rapidapi-access-token (src/Weather.API/appsettings.json)
  • Secret: rapidapi-access-token (src/Weather.API/appsettings.json)
  • The interface 'ICusomHttpMessageHandler' contains a typo in its name ('Cusom' instead of 'Custom'). This is inconsistent with the correctly spelled 'CustomHttpClientProxy' and 'CustomHttpMessageHandler' in the same module.
  • The namespace and type prefix 'Wheaterbit' is consistently misspelled (missing 'e' after 'Wheat') across the entire Wheaterbit client module, whereas the rest of the codebase uses the correct spelling 'Weather' (e.g., Weather.Core, Weather.Domain, Weather.API). This represents a distinct naming inconsistency between the two major client modules.
  • There is an inconsistency in the naming of resource containers for error messages. Two modules use 'ErrorMessages' while the Domain module uses 'ErrorLogMessages'. This suggests a semantic distinction or a naming drift that should be unified.
  • Workflow token permissions not restricted

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

Gramli/WeatherApi was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 06ce59beabca4864b65c86ad979f9c034ea2c05f — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-28e75b8e3254.