feat(release): front int PK with app-minted GUID EntryKey on the public addressing surface (P11 W5, 11.H)

This commit is contained in:
daniel-c-harvey
2026-06-16 17:11:55 -04:00
parent fe28573b68
commit f07d29cdcf
37 changed files with 627 additions and 160 deletions
+18 -15
View File
@@ -66,18 +66,20 @@ public class ReleaseController : ControllerBase
return Ok(result.Value);
}
// GET api/release/{id}/mix/waveform (unauthenticated)
// GET api/release/{entryKey}/mix/waveform (unauthenticated)
// Serves the high-res waveform datum for a Mix release as base64. Mirrors GET api/track/{id}/waveform
// but reads from the mix-waveforms vault. 404 when the release is not a Mix, carries no waveform key,
// or no datum is stored. Declared before the shorter "{id:long}" route for clarity.
[HttpGet("{id:long}/mix/waveform")]
public async Task<ActionResult> GetMixWaveform(long id, CancellationToken ct = default)
// or no datum is stored. Public read — addresses by the opaque EntryKey, not the int PK (§3e). The
// {entryKey} string segment cannot collide with the ApiKey-gated POST {id:long}/mix/waveform (different
// verb + constraint). Declared before the shorter "{entryKey}" route for clarity.
[HttpGet("{entryKey}/mix/waveform")]
public async Task<ActionResult> GetMixWaveform(string entryKey, CancellationToken ct = default)
{
var lookup = await _releaseService.GetByIdAsync(id, ct);
var lookup = await _releaseService.GetByEntryKeyAsync(entryKey, ct);
if (!lookup.Success)
{
var error = lookup.Messages.FirstOrDefault()?.Message ?? "Unknown error";
_logger.LogError("GetMixWaveform lookup failed for {ReleaseId}: {Error}", id, error);
_logger.LogError("GetMixWaveform lookup failed for {EntryKey}: {Error}", entryKey, error);
return StatusCode(500, "Failed to load release");
}
@@ -85,14 +87,14 @@ public class ReleaseController : ControllerBase
var waveformEntryKey = release?.MixMetadata?.WaveformEntryKey;
if (release is null || release.Medium != ReleaseMedium.Mix || string.IsNullOrEmpty(waveformEntryKey))
{
_logger.LogInformation("No mix waveform datum for release: {ReleaseId}", id);
_logger.LogInformation("No mix waveform datum for release: {EntryKey}", entryKey);
return NotFound();
}
var bytes = await _waveformProfileService.GetProfileAsync(waveformEntryKey, VaultConstants.MixWaveforms);
if (bytes is null)
{
_logger.LogInformation("Mix waveform key set but no datum stored for release: {ReleaseId}", id);
_logger.LogInformation("Mix waveform key set but no datum stored for release: {EntryKey}", entryKey);
return NotFound();
}
@@ -159,17 +161,18 @@ public class ReleaseController : ControllerBase
return StatusCode(500, error);
}
// GET api/release/{id} (unauthenticated)
// Single release with both metadata navs (nulls for non-matching media). Declared after the longer
// "{id:long}/mix/waveform" routes so the segmented routes resolve first.
[HttpGet("{id:long}")]
public async Task<ActionResult> GetReleaseById(long id, CancellationToken ct = default)
// GET api/release/{entryKey} (unauthenticated)
// Single release with both metadata navs (nulls for non-matching media). Public read — addresses by
// the opaque EntryKey, not the int PK (§3e). Declared after the longer "{entryKey}/mix/waveform"
// route so the segmented route resolves first.
[HttpGet("{entryKey}")]
public async Task<ActionResult> GetReleaseByEntryKey(string entryKey, CancellationToken ct = default)
{
var result = await _releaseService.GetByIdAsync(id, ct);
var result = await _releaseService.GetByEntryKeyAsync(entryKey, ct);
if (!result.Success)
{
var error = result.Messages.FirstOrDefault()?.Message ?? "Unknown error";
_logger.LogError("GetReleaseById failed for {ReleaseId}: {Error}", id, error);
_logger.LogError("GetReleaseByEntryKey failed for {EntryKey}: {Error}", entryKey, error);
return StatusCode(500, "Failed to load release");
}