Skip to content
Open
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c9fa4be
feat: implement CSVDiscoverer and catalog registry models
mnoserat Jan 30, 2026
45f8374
add missing validation for index.Entries
mnoserat Jan 30, 2026
35d5c82
add CsvConstants.cs and reslove all warnings
mnoserat Jan 30, 2026
6445bc3
change publisher to constant (the super hacker
mnoserat Jan 30, 2026
938263b
fix: configuration section is at wrong path
mnoserat Jan 30, 2026
bc8706f
fix: schema mismatch CsvCatalogRegistryIndex
mnoserat Jan 30, 2026
5853ab1
fix: Inconsistent FileCount type between CsvValidationCatalog and Csv…
mnoserat Jan 30, 2026
a272d46
feat(fix): configuration section is at wrong path
mnoserat Feb 20, 2026
58b2780
feat(fix): rephrase the AI authorship comment
mnoserat Feb 20, 2026
6d5d16e
feat(fix): Expand test coverage for CSVDiscoverer
mnoserat Feb 20, 2026
61a6156
feat(fix): SemaphoreSlim is not disposed
mnoserat Feb 28, 2026
03ef494
feat(fix): Double-checked locking pattern: consider using Volatile.Read
mnoserat Feb 28, 2026
ead2ac6
feat(fix): Minor documentation inaccuracy.
mnoserat Feb 28, 2026
5ba833a
feat(fix): Remove unused import
mnoserat Feb 28, 2026
8a41bed
feat(fix): Consider using a sentinel value for LastUpdatedAt default
mnoserat Feb 28, 2026
6e1f2cd
feat(fix): Language code should be uppercase
mnoserat Feb 28, 2026
1290c6f
feat(fix): TOCTOU race condition between File.Exists and File.ReadAll…
mnoserat Feb 28, 2026
bfda8d3
feat(fix): caching JsonSerializerOptions to avoid repeated allocation.
mnoserat Feb 28, 2026
5eb7fe8
feat(fix): Update CsvConstants.ResolverId to match issue #139 specifi…
mnoserat Feb 28, 2026
7f58082
feat(fix): match CsvCatalogRegistryEntry.cs with the actual JSON stru…
mnoserat Feb 28, 2026
b50f52c
feat(fix): adding explicit handling each valid game type
mnoserat Mar 3, 2026
317e23c
remove unused constant
mnoserat Mar 3, 2026
abf8c8f
Clarify IndexFilePath documentation semantics.
mnoserat Mar 3, 2026
2ca99cb
Switch expression now returns null for unknown GameType values inste…
mnoserat Mar 3, 2026
e896fdf
feat(fix): Language handling misses unified catalogs and emits non-ca…
mnoserat Mar 3, 2026
265ac94
feat(fix): Cancellation is swallowed and converted into a generic fai…
mnoserat Mar 3, 2026
3b55070
fix: Missing properties that exist in index.json
mnoserat Mar 3, 2026
e4d22fc
fix: CSVDiscovererTests.cs
mnoserat Mar 3, 2026
4d3363b
fix No validation for null or invalid entries. If index.Entries conta…
mnoserat Mar 3, 2026
7af0378
fix: IsActive flag is not checked when filtering entries.
mnoserat Mar 3, 2026
a78f88e
fix: remove unused config
mnoserat Mar 3, 2026
5d78c8c
fix: add null guard for _config in constructor
mnoserat Mar 3, 2026
5a5992f
fix: remove Unused using
mnoserat Mar 3, 2026
d1f34c8
Guard language collections before normalization to avoid discoverer-w…
mnoserat Mar 3, 2026
6884e87
Build manifest identity from canonical game type, not raw source casing.
mnoserat Mar 3, 2026
ba9f625
Merge remote-tracking branch 'upstream/development' into feature/CSV-…
mnoserat Mar 3, 2026
af1942f
fix: compile Failing
mnoserat Mar 3, 2026
8b00efd
fix: compile Failing wih exit code -1
mnoserat Mar 3, 2026
a725109
fix change branch url in index.json
mnoserat Mar 21, 2026
fdce2c6
refactor(csv-discovery): use index.json as single registry sourc
mnoserat Apr 24, 2026
9980a68
fix(csv-discovery): load index.json from remote source with default f…
mnoserat Apr 27, 2026
58d57e5
fix(csv-discovery): load CSV catalogs from unified source chain
mnoserat Apr 27, 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
62 changes: 62 additions & 0 deletions GenHub/GenHub.Core/Constants/CsvConstants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
namespace GenHub.Core.Constants;

/// <summary>
/// Constants specific to CSV catalog discovery and content pipeline.
/// </summary>
public static class CsvConstants
{
/// <summary>
/// Source name for the CSV catalog discoverer.
/// </summary>
public const string SourceName = "Csv Discoverer";

/// <summary>
/// Description for the CSV catalog discoverer.
/// </summary>
public const string Description = "Discovers base game manifests from verified CSV catalogs.";

/// <summary>
/// Resolver ID for CSV catalog content.
/// </summary>
public const string ResolverId = "CSVResolver";

/// <summary>
/// Metadata key for the CSV source URL.
/// </summary>
public const string CsvUrlMetadataKey = "csvUrl";

/// <summary>
/// Metadata key for the game type.
/// </summary>
public const string GameTypeMetadataKey = "gameType";

/// <summary>
/// Metadata key for the game version.
/// </summary>
public const string VersionMetadataKey = "version";

/// <summary>
/// Metadata key for the content language.
/// </summary>
public const string LanguageMetadataKey = "language";

/// <summary>
/// Metadata key for the expected file count.
/// </summary>
public const string FileCountMetadataKey = "fileCount";

/// <summary>
/// String representation for Generals game type in CSV catalogs.
/// </summary>
public const string GeneralsGameType = "Generals";

/// <summary>
/// String representation for Zero Hour game type in CSV catalogs.
/// </summary>
public const string ZeroHourGameType = "ZeroHour";

/// <summary>
/// Special language filter value to include all languages.
/// </summary>
public const string AllLanguagesFilter = "ALL";
}
7 changes: 7 additions & 0 deletions GenHub/GenHub.Core/Interfaces/Common/IAppConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using GenHub.Core.Models.Content;
using GenHub.Core.Models.Enums;
using Microsoft.Extensions.Logging;

Expand Down Expand Up @@ -81,4 +82,10 @@ public interface IAppConfiguration
/// <summary>Gets the maximum allowed download buffer size in bytes.</summary>
/// <returns>The maximum buffer size in bytes.</returns>
int GetMaxDownloadBufferSizeBytes();

/// <summary>
/// Gets the CSV catalog configuration.
/// </summary>
/// <returns>The CSV catalog configuration.</returns>
CsvCatalogConfiguration GetCsvCatalogConfiguration();
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GenHub.Core.Models.Common;
using GenHub.Core.Models.Content;
using GenHub.Core.Models.Enums;
using GenHub.Core.Models.Storage;

Expand Down Expand Up @@ -155,4 +156,10 @@ public interface IConfigurationProviderService
/// </summary>
/// <returns>The logs directory path.</returns>
string GetLogsPath();

/// <summary>
/// Gets the CSV catalog configuration.
/// </summary>
/// <returns>The CSV catalog configuration.</returns>
CsvCatalogConfiguration GetCsvCatalogConfiguration();
}
21 changes: 21 additions & 0 deletions GenHub/GenHub.Core/Models/Content/Checksum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Text.Json.Serialization;

namespace GenHub.Core.Models.Content;

/// <summary>
/// Represents checksum information for file integrity verification.
/// </summary>
public class Checksum
{
/// <summary>
/// Gets or sets the MD5 hash of the file.
/// </summary>
[JsonPropertyName("md5")]
public string Md5 { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the SHA-256 hash of the file.
/// </summary>
[JsonPropertyName("sha256")]
public string Sha256 { get; set; } = string.Empty;
}
22 changes: 22 additions & 0 deletions GenHub/GenHub.Core/Models/Content/CsvCatalogConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace GenHub.Core.Models.Content;

/// <summary>
/// Configuration for CSV Catalog discovery.
/// Binds to "CsvValidationCatalogs" and "GenHub:IndexFilePath" in configuration.
Comment thread
mnoserat marked this conversation as resolved.
Outdated
/// Refers to the <see cref="IndexFilePath"/> property.
/// </summary>
Comment thread
mnoserat marked this conversation as resolved.
public class CsvCatalogConfiguration
{
/// <summary>
/// Gets or sets the list of fallback validation catalogs defined in configuration.
/// Used when index.json cannot be reached.
/// </summary>
public List<CsvValidationCatalog> CsvValidationCatalogs { get; set; } = [];
Comment thread
mnoserat marked this conversation as resolved.
Outdated

/// <summary>
/// Gets or sets the path to the index.json file.
/// If a relative path is provided, it is resolved relative to the application's working directory;
/// absolute paths are used as given. The expected file is index.json.
/// </summary>
public string IndexFilePath { get; set; } = "docs/GameInstallationFilesRegistry/index.json";
Comment thread
mnoserat marked this conversation as resolved.
Outdated
Comment thread
mnoserat marked this conversation as resolved.
Outdated
}
76 changes: 76 additions & 0 deletions GenHub/GenHub.Core/Models/Content/CsvCatalogRegistryEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace GenHub.Core.Models.Content;

/// <summary>
/// Represents a single CSV catalog entry in the registry.
/// </summary>
public class CsvCatalogRegistryEntry
{
/// <summary>
/// Gets or sets the unique identifier for this registry entry.
/// </summary>
[JsonPropertyName("id")]
public string Id { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the URL to the CSV file.
/// </summary>
[JsonPropertyName("url")]
public string Url { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the game type (e.g., "Generals", "ZeroHour").
/// </summary>
[JsonPropertyName("gameType")]
public string GameType { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the game version (e.g., "1.08", "1.04").
/// </summary>
[JsonPropertyName("version")]
public string Version { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the list of supported languages in this CSV.
/// </summary>
[JsonPropertyName("languages")]
public List<string> SupportedLanguages { get; set; } = [];

/// <summary>
/// Gets or sets the optional file count in the CSV.
/// </summary>
[JsonPropertyName("fileCount")]
public int? FileCount { get; set; }

/// <summary>
/// Gets or sets the total size of the CSV file in bytes.
/// </summary>
[JsonPropertyName("totalSizeBytes")]
public long TotalSizeBytes { get; set; }

/// <summary>
/// Gets or sets the checksum information for integrity verification.
/// </summary>
[JsonPropertyName("checksum")]
public Checksum? Checksum { get; set; }

/// <summary>
/// Gets or sets when this registry entry was generated.
/// </summary>
[JsonPropertyName("generatedAt")]
public DateTime? GeneratedAt { get; set; }

/// <summary>
/// Gets or sets the version of the generator that created this entry.
/// </summary>
[JsonPropertyName("generatorVersion")]
public string GeneratorVersion { get; set; } = string.Empty;

/// <summary>
/// Gets or sets a value indicating whether this registry entry is active.
/// </summary>
[JsonPropertyName("isActive")]
public bool IsActive { get; set; }
}
Comment thread
mnoserat marked this conversation as resolved.
36 changes: 36 additions & 0 deletions GenHub/GenHub.Core/Models/Content/CsvCatalogRegistryIndex.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace GenHub.Core.Models.Content;

/// <summary>
/// Index of available CSV catalog registries.
/// Represents the structure of the docs/GameInstallationFilesRegistry/index.json file.
/// </summary>
public class CsvCatalogRegistryIndex
{
/// <summary>
/// Gets or sets the schema version.
/// </summary>
[JsonPropertyName("version")]
public string Version { get; set; } = string.Empty;

/// <summary>
/// Gets or sets when the index was last updated.
/// </summary>
[JsonPropertyName("lastUpdated")]
public DateTime? LastUpdatedAt { get; set; }

/// <summary>
/// Gets or sets the description of this registry index.
/// </summary>
[JsonPropertyName("description")]
public string Description { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the list of available catalog entries.
/// </summary>
[JsonPropertyName("registries")]
Comment thread
mnoserat marked this conversation as resolved.
public List<CsvCatalogRegistryEntry> Entries { get; set; } = [];
Comment thread
mnoserat marked this conversation as resolved.
}
35 changes: 35 additions & 0 deletions GenHub/GenHub.Core/Models/Content/CsvValidationCatalog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Collections.Generic;

namespace GenHub.Core.Models.Content;

/// <summary>
/// Represents a CSV catalog defined in appsettings.json.
/// Matches the structure of CsvCatalogRegistryEntry but optimized for config binding.
/// </summary>
public class CsvValidationCatalog
{
/// <summary>
/// Gets or sets the URL to the CSV file.
/// </summary>
public string Url { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the game type.
/// </summary>
public string GameType { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the version string.
/// </summary>
public string Version { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the supported languages.
/// </summary>
public List<string> SupportedLanguages { get; set; } = [];

/// <summary>
/// Gets or sets the file count.
/// </summary>
public int? FileCount { get; set; }
}
Loading
Loading