Skip to content
Back to skills

Architecture 5

ASecurity

Service layer patterns, project responsibilities, dependency injection, and API contracts for RSSVibe. Use this skill when creating services, organizing code, or understanding project structure.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 27, 2026
developmentapidatabasefrontendbackend

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 27, 2026

npx -y skills add David-Li0406/meta-skill-evloving --skill architecture-5 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Architecture 5?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Architecture 5
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/david-li0406-architecture-5/badge)](https://www.skillsdirectory.com/skills/david-li0406-architecture-5)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: architecture
description: Service layer patterns, project responsibilities, dependency injection, and API contracts for RSSVibe. Use this skill when creating services, organizing code, or understanding project structure.
---

# Project Architecture

## Service Layer (`RSSVibe.Services`)

- MUST implement all business logic in the `RSSVibe.Services` project
- MUST define service interfaces (e.g., `IAuthService`, `IFeedService`) for dependency injection
- MUST use command/result patterns for service operations
- Services SHOULD be organized by domain area in folders (e.g., `Auth/`, `Feeds/`)
- MUST inject repositories, `UserManager`, and other infrastructure dependencies into services
- SHOULD use primary constructors for service classes
- Service implementations MUST be `internal sealed` (only interfaces and models are `public`)
- Each project MUST provide an `IServiceCollection` extension method to register its services

---

## Project Responsibilities

| Project | Responsibility |
|---------|---------------|
| `RSSVibe.Contracts` | API request/response DTOs, shared domain models |
| `RSSVibe.Services` | Business logic, validation, orchestration |
| `RSSVibe.Data` | Entity models, DbContext, configurations, migrations |
| `RSSVibe.ApiService` | Minimal API endpoints, routing, middleware |
| `RSSVibe.Web` | Blazor UI components and pages |

---

## Service Layer Patterns

```csharp
// Service interface (PUBLIC)
public interface IAuthService
{
    Task<RegisterUserResult> RegisterUserAsync(RegisterUserCommand command, CancellationToken ct);
}

// Service implementation with primary constructor (INTERNAL SEALED)
internal sealed class AuthService(
    UserManager<ApplicationUser> userManager,
    ILogger<AuthService> logger) : IAuthService
{
    public async Task<RegisterUserResult> RegisterUserAsync(
        RegisterUserCommand command,
        CancellationToken ct)
    {
        // Business logic here
    }
}

// Command model (PUBLIC - in same file as service or separate Commands/ folder)
public sealed record RegisterUserCommand(
    string Email,
    string Password,
    string DisplayName,
    bool MustChangePassword
);

// Result model (PUBLIC - in same file as service or separate Results/ folder)
public sealed record RegisterUserResult
{
    public bool Success { get; init; }
    public Guid UserId { get; init; }
    public string? Email { get; init; }
    public RegistrationError? Error { get; init; }
}
```

---

## Service Registration Pattern

**Each project MUST provide an extension method to register its services**

**Location**: `{ProjectName}/Extensions/ServiceCollectionExtensions.cs`

```csharp
// In RSSVibe.Services/Extensions/ServiceCollectionExtensions.cs
namespace RSSVibe.Services.Extensions;

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddRssVibeServices(this IServiceCollection services)
    {
        // Register all services from this project
        services.AddScoped<IAuthService, AuthService>();
        services.AddScoped<IFeedService, FeedService>();
        // ... other services

        return services;
    }
}

// In Program.cs (RSSVibe.ApiService)
builder.Services.AddRssVibeServices(); // Single call registers all services
```

**Benefits**:
- Encapsulates service registration logic within each project
- `Program.cs` remains clean with single method calls per project
- Internal implementations hidden from consuming projects
- Easy to maintain and test service registration

---

## Dependency Injection

- MUST use scoped lifetime for request-specific services
- MUST use singleton lifetime for stateless services
- MUST register services via extension methods (e.g., `AddRssVibeServices()`)
- Extension methods SHOULD be named `Add{ProjectName}` (e.g., `AddRssVibeServices`, `AddRssVibeDatabase`)
- Service implementations MUST be `internal sealed` to prevent external instantiation

---

## API Contracts

- MUST define all API request/response models in the `RSSVibe.Contracts` project
- API contracts are shared between frontend and backend services via project reference
- MUST use positional records for all contract models (immutability and clarity)
- MUST document contract changes in commit messages and ADRs when adding new endpoints or modifying existing ones
- Contracts include DTOs for API requests, responses, and domain models exposed to clients
- **Shared contracts** like `PagingDto` are placed in the root `RSSVibe.Contracts` namespace and reused across multiple feature areas (e.g., Feeds, FeedAnalyses, FeedItems) to ensure consistency

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…