fix: restore system context for genome queries and support category format in v1 API

Two bugs fixed:
1. genome query RBAC: Someone removed sysCtx and changed back to user ctx after Saturday's fix, causing RBAC to block genome data access. Restored system context usage with dossier access check first.
2. query_entries category filter: API expected category names like 'genome' but MCP returns 'category004' format. Now supports both formats.

Fixes:
- api/api_genome.go: Restore system context for GenomeGetExtraction, GenomeGetTiers, GenomeGetVariants
- api/api_v1.go: Parse both 'category004' and 'genome' formats in v1Entries

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
James 2026-02-09 14:48:56 -05:00
parent c88c50bc12
commit ba668ed5fd
2 changed files with 22 additions and 9 deletions

View File

@ -40,7 +40,13 @@ func handleGenomeQuery(w http.ResponseWriter, r *http.Request) {
return
}
// RBAC enforced in lib layer - no checks here
// Check dossier access first
if !requireDossierAccess(w, ctx, dossierID) {
return
}
// Use system context for genome queries (dossier access already checked)
sysCtx := &lib.AccessContext{IsSystem: true}
category := r.URL.Query().Get("category")
search := r.URL.Query().Get("search")
@ -81,28 +87,28 @@ func handleGenomeQuery(w http.ResponseWriter, r *http.Request) {
}
}
// Find extraction entry (RBAC enforced in lib)
extraction, err := lib.GenomeGetExtraction(ctx, dossierID)
// Find extraction entry
extraction, err := lib.GenomeGetExtraction(sysCtx, dossierID)
if err != nil {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"error": "no genome data for this dossier"})
return
}
// Get tiers to query (RBAC enforced in lib)
// Get tiers to query
var tiers []lib.GenomeTier
tierCategories := make(map[string]string) // tierID -> category name
if category != "" {
// Specific category requested
tier, err := lib.GenomeGetTierByCategory(ctx, dossierID, extraction.EntryID, category)
tier, err := lib.GenomeGetTierByCategory(sysCtx, dossierID, extraction.EntryID, category)
if err == nil {
tiers = append(tiers, *tier)
tierCategories[tier.TierID] = tier.Category
}
} else {
// All tiers
tiers, _ = lib.GenomeGetTiers(ctx, dossierID, extraction.EntryID)
tiers, _ = lib.GenomeGetTiers(sysCtx, dossierID, extraction.EntryID)
for _, t := range tiers {
tierCategories[t.TierID] = t.Category
}
@ -120,8 +126,8 @@ func handleGenomeQuery(w http.ResponseWriter, r *http.Request) {
tierIDs[i] = t.TierID
}
// Query variants (RBAC enforced in lib)
variants, err := lib.GenomeGetVariants(ctx, dossierID, tierIDs)
// Query variants
variants, err := lib.GenomeGetVariants(sysCtx, dossierID, tierIDs)
if err != nil {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(GenomeResponse{Matches: []GenomeMatch{}, Returned: 0, Total: 0})

View File

@ -234,7 +234,14 @@ func v1Entries(w http.ResponseWriter, r *http.Request, dossierID string) {
parentID := q.Get("parent")
category := 0
if cat := q.Get("category"); cat != "" {
category = lib.CategoryFromString[cat]
// Support both "genome" and "category004" formats
if strings.HasPrefix(cat, "category") {
// Parse "category004" -> 4
fmt.Sscanf(cat, "category%d", &category)
} else {
// Parse name like "genome", "upload", etc.
category = lib.CategoryFromString[cat]
}
}
filter := &lib.EntryFilter{
DossierID: dossierID,