Project Configuration Feature

This feature provides project configuration management including git repository settings and encrypted authentication tokens.

Overview

Each project can have a configuration that includes:

  • Git Repositories: List of repository URLs to include in the project
  • File Exclusions: Patterns to exclude files from processing (e.g., *.log, node_modules/**)
  • Git Token: Encrypted authentication token for repository access

API Endpoints

GET /api/projects/{projectId}/config

Retrieves the project configuration.

Response:

{
  "projectId": 1,
  "gitRepositories": ["https://github.com/org/repo1", "https://github.com/org/repo2"],
  "fileExclusions": ["*.log", "node_modules/**", "bin/**"],
  "hasGitToken": true,
  "createdAt": "2026-02-03T12:00:00Z",
  "updatedAt": "2026-02-03T12:00:00Z"
}

Note: The git token itself is never returned - only whether one has been configured.

PUT /api/projects/{projectId}/config

Updates the project configuration.

Request:

{
  "projectId": 1,
  "gitRepositories": ["https://github.com/org/repo1"],
  "fileExclusions": ["*.log"],
  "gitToken": "ghp_xxxxxxxxxxxx"
}

Git Token Handling:

  • null or omitted: Leave the existing token unchanged
  • "" (empty string): Clear the token
  • Any other value: Encrypt and save the new token

Response:

{
  "success": true,
  "message": "Project configuration updated successfully.",
  "projectId": 1
}

Client L1 Cache Integration

The project configuration page in MILTON.Client/Pages/ProjectConfig.razor always fetches the configuration payload from GET /api/projects/{projectId}/config, but it only fetches the project list from GET /api/projects when the scoped ProjectStore cache is empty.

This means the configuration page reuses the same project-summary cache as Home.razor, ProjectLayout.razor, and ProjectDashboard.razor when it needs to resolve the current project’s title and metadata. The shared cache implementation lives in MILTON.Client/StateContainer/ProjectStore.cs and is registered in MILTON.Client/Program.cs.

Project creation in MILTON.Client/Pages/New-project.razor clears ProjectStore before redirecting, which ensures that a subsequent visit to the configuration page repopulates the list with the newly created project.

See Projects Feature for the project list endpoint contract and Client application for the broader cache lifecycle.

Security

Encryption

Git tokens and LLM API keys are encrypted at rest using Microsoft’s Data Protection API (DPAPI):

  1. Encryption keys are automatically managed and persisted to the database
  2. Each encrypted value includes a unique initialization vector handled by the framework
  3. Tokens are decrypted only when needed for git operations
  4. Uses the same encryption infrastructure as ASP.NET Core’s built-in protection mechanisms

No manual key configuration required. The DPAPI automatically:

  • Generates and manages encryption keys
  • Stores keys in the database via DataProtectionKey entity
  • Rotates keys periodically for security
  • Handles IV generation and padding automatically

This is the Microsoft-recommended approach for .NET applications and requires no additional configuration beyond the framework setup.

Using Git Credentials in Code

To use the decrypted git token for operations like cloning:

public class MyGitService
{
    private readonly IGitCredentialService _credentials;
 
    public MyGitService(IGitCredentialService credentials)
    {
        _credentials = credentials;
    }
 
    public async Task CloneRepositoryAsync(int projectId, CancellationToken ct)
    {
        // Get the decrypted token
        var token = await _credentials.GetGitTokenAsync(projectId, ct);
        
        // Get configured repositories
        var repos = await _credentials.GetRepositoriesAsync(projectId, ct);
        
        // Get file exclusions
        var exclusions = await _credentials.GetFileExclusionsAsync(projectId, ct);
        
        // Use token with git operations...
    }
}

Database Schema

The ProjectConfigs table stores:

ColumnTypeDescription
IdintPrimary key
ProjectIdintForeign key to Projects (unique)
GitRepositoriesjsonbJSON array of repository URLs
FileExclusionsjsonbJSON array of exclusion patterns
EncryptedGitTokenstringBase64 encrypted token
EncryptionIVstringBase64 IV for decryption
CreatedAtDateTimeCreation timestamp
UpdatedAtDateTimeLast update timestamp

Migration

After adding this feature, run the migration:

dotnet ef database update --project MILTON --startup-project MILTON