@@ -12,63 +12,119 @@ Unified repository server for distributing OpenShock desktop app modules and fir
1212- FlexLabs.EntityFrameworkCore.Upsert for upserts
1313- MiniValidation for config validation
1414- Semver NuGet package for semver parsing
15+ - OneOf for discriminated parser results
1516- TUnit for tests
1617- Scalar for API docs UI
1718- Docker (Alpine) with self-signed HTTPS cert generation
1819
1920## Project Structure
2021```
2122RepositoryServer/ # Main web API project
22- AuthenticationHandlers/ # Custom AdminToken auth handler
23- Config/ # ApiConfig, DbConfig, RepoConfig, MetricsConfig, FirmwareConfig
23+ AuthenticationHandlers/
24+ AdminTokenAuthentication.cs # AdminToken scheme (static header compare)
25+ GitHubOidcAuthentication.cs # JwtBearer + GitHub OIDC claim handling
26+ # auto-upserts repositories rows on first use
27+ Config/ # ApiConfig, DbConfig, RepoConfig, MetricsConfig,
28+ # FirmwareConfig, FirmwareCiCdConfig, FirmwareAdvisoryConfig, DiscordConfig
2429 Controllers/
2530 OpenShockControllerBase.cs # Shared base controller
26- V1/ # Desktop endpoints
27- RepoController.cs # GET /v1/ — desktop module manifest
28- AdminController.cs # /v1/admin/... — desktop module CRUD
29- V2/
30- Firmware/
31- LatestController.cs # GET /v2/firmware/latest/{channel}
32- VersionsController.cs # GET /v2/firmware/versions[/{version}]
33- BoardsController.cs # GET /v2/firmware/boards
34- ChipsController.cs # GET /v2/firmware/chips
35- AdminController.cs # /v2/firmware/admin/... CRUD
36- Errors/ # Static error factories (AuthResultError, ExceptionError)
31+ V1/ # Desktop module endpoints (V1)
32+ RepoController.cs # GET /v1/ — desktop module manifest
33+ AdminController.cs # /v1/admin/... — desktop module CRUD
34+ CiCdController.cs # PUT /v1/cicd/modules/{id}/versions/{v} — desktop zip upload
35+ V2/Firmware/ # Firmware V2 endpoints
36+ ManifestController.cs # GET /v2/firmware/manifest (bootstrap payload)
37+ LatestController.cs # GET /v2/firmware/latest/{channel}[/{boardId}?version=]
38+ VersionsController.cs # GET /v2/firmware/versions[/{version}[/{boardId}]]
39+ BoardsController.cs # GET /v2/firmware/boards
40+ ChipsController.cs # GET /v2/firmware/chips
41+ ReleasesController.cs # POST/PUT/DELETE /v2/firmware/releases/... (CI/CD ingestion)
42+ Admin/ # AdminToken-protected CRUD (split by concern)
43+ RepositoriesController.cs # GET, DELETE /v2/firmware/admin/repositories
44+ VersionsAdminController.cs # DELETE /v2/firmware/admin/versions/{v}
45+ BoardsAdminController.cs # PUT, PATCH, DELETE /v2/firmware/admin/boards/{id}
46+ # + USB attach/detach
47+ ChipsAdminController.cs # PUT, DELETE /v2/firmware/admin/chips/{id} + USB attach/detach
48+ ReleasesAdminController.cs # PUT /v2/firmware/admin/releases/{id}/changelog (fix)
49+ UsbDevicesController.cs # PUT/GET/DELETE /v2/firmware/admin/usb-devices
50+ UsbSerialFiltersController.cs # PUT/GET/DELETE /v2/firmware/admin/usb-serial-filters
51+ Enums/ # ReleaseChannel, FirmwareArtifactType, FirmwareChipArchitecture,
52+ # ReleaseNoteSectionType, ReleaseStatus, RepositoryProvider
53+ Errors/ # AuthResultError, ExceptionError
3754 ExceptionHandler/ # Global IExceptionHandler + RequestInfo logging
38- Migrations/ # EF Core migrations (Initial + AddFirmwareTables)
55+ Migrations/ # EF Core migrations
3956 Models/ # Desktop module DTOs
40- Models/Firmware/ # Firmware DTOs (response + admin request)
57+ Models/Firmware/ # Firmware DTOs
58+ FirmwareManifestResponse, FirmwareReleaseDto, FirmwareVersionSummary,
59+ FirmwareBoardDetailDto, FirmwareChipRefDto, FirmwareBoardReleaseResponseDto,
60+ FirmwareSourceDto, FirmwareAdvisoryDto, FirmwareUsbDeviceDto,
61+ FirmwareUsbSerialFilterDto (+ admin variant), RepositoryDto, VersionListResponse,
62+ InitReleaseRequest (+ response), FixChangelogRequest, Upsert* requests
4163 Problems/ # RFC 7807 problem details (OpenShockProblem base)
4264 RepoServerDb/ # EF Core entities + RepoServerContext
43- Utils/ # ByteArrayHexConverter, SemVersionConverter, etc.
44- Program.cs # App startup and middleware pipeline
65+ SourceRepository, FirmwareVersion, FirmwareRelease, FirmwareArtifact, FirmwareReleaseNote,
66+ FirmwareStagedArtifact, FirmwareStagedReleaseNote, FirmwareBoard, FirmwareChip,
67+ UsbDevice, UsbSerialFilter, FirmwareChipUsbDevice, FirmwareBoardUsbDevice
68+ Services/
69+ IStorageService (+ BunnyCdn / Local / S3 impls)
70+ IDiscordNotificationService + DiscordNotificationService (webhook, fire-and-forget)
71+ StagedReleaseCleanupService # BackgroundService, PeriodicTimer 5 min, two TTLs
72+ Utils/
73+ ChangelogParser # Markdown → FirmwareReleaseNoteDto[] (OneOf-based)
74+ SourceUrlBuilder # provider-aware commit/ref/run URL construction
75+ FirmwareResponseMapper # shared release/artifact response projections
76+ CacheControlAttribute # filter per spec §8
77+ FirmwareArtifactFileNames, ByteArrayHexConverter, SemVersionConverter
78+ Program.cs # App startup: schemes, DbContextPool, HttpClient,
79+ # HostedService, storage, migrations, etc.
4580
46- RepositoryServer.Tests/ # TUnit test project
81+ RepositoryServer.Tests/ # TUnit test project (references the main project)
82+ Utils/
83+ ChangelogParserTests
84+ SourceUrlBuilderTests
4785docker/
4886 RepositoryServer.Dockerfile
4987 entrypoint.sh # Cert gen + `dotnet OpenShock.RepositoryServer.dll`
5088 appsettings.Container.json
5189```
5290
5391## Namespace
54- ` OpenShock.RepositoryServer ` (renamed from ` OpenShock.Desktop.RepositoryServer ` )
92+ ` OpenShock.RepositoryServer `
5593
5694## Key Patterns
57- - ** Auth** : Custom ` AdminTokenAuthentication ` handler, ` AuthSchemas.AdminToken ` scheme
95+ - ** Auth** : Two schemes. ` AdminTokenAuthentication ` (header compare) for admin endpoints;
96+ JwtBearer + ` GitHubOidcAuthentication.Configure(...) ` for CI/CD endpoints. The OIDC hook
97+ validates a GitHub Actions OIDC JWT, then looks up (or inserts) a matching row in the
98+ ` repositories ` table and attaches ` AuthSchemas.CiCdClaims ` to the principal.
99+ No config allowlist — the DB is authoritative.
58100- ** Error Handling** : ` OpenShockProblem ` base class → ` ToObjectResult() ` for RFC 7807
59101- ** Config** : Bind root config to ` ApiConfig ` , validated with MiniValidator, registered as singleton
102+ - ** Background jobs** : ` StagedReleaseCleanupService ` (` BackgroundService ` with ` PeriodicTimer ` )
103+ periodically aborts expired staging/editing releases per ` FirmwareConfig.StagedReleaseTtl `
104+ and ` EditingReleaseTtl `
60105- ** DB Migrations** : ` MigrationOpenShockContext ` subclass for migration tooling, auto-applied on startup
61106- ** JSON** : CamelCase, custom ` SemVersionConverter ` + ` ByteArrayHexConverter `
62107- ** Upsert** : FlexLabs ` .Upsert().On().RunAsync() ` pattern
108+ - ** Caching** : ` CacheControlAttribute ` action filter — public max-age on 2xx, no-store on errors
63109- ** CORS** : Allow all origins/methods/headers
64110- ** Metrics** : Prometheus at ` /metrics ` , restricted to private networks
111+ - ** Notifications** : Fire-and-forget Discord webhooks via ` IDiscordNotificationService ` .
112+ Empty ` Discord.WebhookUrls ` → no-op.
65113
66114## Database
67- - PostgreSQL, connection in ` ApiConfig.Db.Conn `
115+ - PostgreSQL (15+ required for ` NULLS NOT DISTINCT ` on ` usb_serial_filters ` ), connection in ` ApiConfig.Db.Conn `
116+ - Shared table: ` repositories ` (PK: id, UNIQUE ` (provider, owner, repo) ` )
68117- Desktop tables: ` modules ` (PK: id), ` versions ` (composite PK: version+module, FK→modules CASCADE)
69- - Firmware tables: ` firmware_chips ` , ` firmware_boards ` , ` firmware_versions ` , ` firmware_artifacts ` , ` firmware_release_notes `
70- - Firmware enums: ` firmware_channel ` , ` firmware_artifact_type ` , ` firmware_release_note_type ` , ` firmware_chip_architecture `
118+ - Firmware tables: ` firmware_chips ` , ` firmware_boards ` , ` firmware_versions ` ,
119+ ` firmware_artifacts ` , ` firmware_release_notes ` , ` firmware_releases ` ,
120+ ` firmware_staged_artifacts ` , ` firmware_staged_release_notes `
121+ - USB catalog: ` usb_devices ` , ` usb_serial_filters ` , ` firmware_chip_usb_devices ` ,
122+ ` firmware_board_usb_devices `
123+ - Firmware enums: ` release_channel ` , ` firmware_artifact_type ` , ` firmware_release_note_type ` ,
124+ ` firmware_chip_architecture ` , ` release_status ` , ` repository_provider `
71125- URL convention for firmware artifacts: ` {CdnBaseUrl}/{version}/{boardId}/{artifactType}.bin `
126+ - Source-traceability URLs (commit / ref / run) are built server-side per provider
127+ (` Utils/SourceUrlBuilder ` ) and never stored
72128
73129## CI/CD
74130- ` ci-build.yml ` : Test + build Docker + promote image + deploy prod (on master)
0 commit comments