wip: doctor/cli/docs/api to vector db consolidation; api hardening for descriptions, tenant, and scopes; migrations and conversions of all DALs to EF v10

This commit is contained in:
master
2026-02-23 15:30:50 +02:00
parent bd8fee6ed8
commit e746577380
1424 changed files with 81225 additions and 25251 deletions

View File

@@ -156,6 +156,8 @@ app.MapPost("/api/v1/packs", async (PackUploadRequest request, PackService servi
return Results.BadRequest(new { error = "upload_failed", message = ex.Message });
}
})
.WithName("UploadPack")
.WithDescription("Uploads a new policy pack as base64-encoded content with optional signature and provenance attachment. Returns 201 Created with the registered pack record and assigned pack ID. Requires the X-StellaOps-Tenant header or a tenantId body field.")
.Produces<PackResponse>(StatusCodes.Status201Created)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized);
@@ -192,6 +194,8 @@ app.MapGet("/api/v1/packs", async (string? tenant, bool? includeDeprecated, Pack
return Results.Ok(packs.Select(PackResponse.From));
})
.WithName("ListPacks")
.WithDescription("Returns the list of policy packs for the specified tenant, optionally excluding deprecated packs. When tenant allowlists are configured, a tenant query parameter or X-StellaOps-Tenant header is required.")
.Produces<IEnumerable<PackResponse>>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized);
@@ -217,6 +221,8 @@ app.MapGet("/api/v1/packs/{packId}", async (string packId, PackService service,
return Results.Ok(PackResponse.From(record));
})
.WithName("GetPack")
.WithDescription("Returns the metadata record for the specified pack ID including tenant, digest, provenance URI, and creation timestamp. Returns 403 if the caller's tenant allowlist does not include the pack's tenant. Returns 404 if the pack ID is not found.")
.Produces<PackResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
@@ -251,6 +257,8 @@ app.MapGet("/api/v1/packs/{packId}/content", async (string packId, PackService s
context.Response.Headers["X-Content-Digest"] = record.Digest;
return Results.File(content, "application/octet-stream", fileDownloadName: packId + ".bin");
})
.WithName("GetPackContent")
.WithDescription("Downloads the binary content of the specified pack as an octet-stream. The response includes an X-Content-Digest header with the stored digest for integrity verification. Returns 403 if the tenant does not match. Returns 404 if the pack or its content is not found.")
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
@@ -289,6 +297,8 @@ app.MapGet("/api/v1/packs/{packId}/provenance", async (string packId, PackServic
return Results.File(content, "application/json", fileDownloadName: packId + "-provenance.json");
})
.WithName("GetPackProvenance")
.WithDescription("Downloads the provenance document attached to the specified pack as a JSON file. The response includes an X-Provenance-Digest header when a digest is stored. Returns 404 if the pack or its provenance attachment is not found.")
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
@@ -329,6 +339,8 @@ app.MapGet("/api/v1/packs/{packId}/manifest", async (string packId, PackService
return Results.Ok(manifest);
})
.WithName("GetPackManifest")
.WithDescription("Returns a structured manifest for the specified pack including pack ID, tenant, content digest and size, provenance digest and size, creation timestamp, and attached metadata. Returns 403 if the tenant does not match. Returns 404 if the pack is not found.")
.Produces<PackManifestResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
@@ -373,6 +385,8 @@ app.MapPost("/api/v1/packs/{packId}/signature", async (string packId, RotateSign
return Results.BadRequest(new { error = "signature_rotation_failed", message = ex.Message });
}
})
.WithName("RotatePackSignature")
.WithDescription("Replaces the stored signature on a pack with a new signature, optionally using a caller-supplied public key PEM for verification instead of the server default. Returns the updated pack record on success. Returns 400 if the new signature is invalid or rotation fails.")
.Produces<PackResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
@@ -413,6 +427,8 @@ app.MapPost("/api/v1/packs/{packId}/attestations", async (string packId, Attesta
return Results.BadRequest(new { error = "attestation_failed", message = ex.Message });
}
})
.WithName("UploadPackAttestation")
.WithDescription("Attaches a typed attestation document to a pack as base64-encoded content. The type field identifies the attestation kind (e.g., sbom, scan-result). Returns 201 Created with the stored attestation record. Returns 400 if type or content is missing or the content is not valid base64.")
.Produces<AttestationResponse>(StatusCodes.Status201Created)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
@@ -440,6 +456,8 @@ app.MapGet("/api/v1/packs/{packId}/attestations", async (string packId, Attestat
return Results.Ok(records.Select(AttestationResponse.From));
})
.WithName("ListPackAttestations")
.WithDescription("Returns all attestation records stored for the specified pack. Returns 404 if no attestations exist for the pack. Returns 403 if the X-StellaOps-Tenant header does not match the tenant of the stored attestations.")
.Produces<IEnumerable<AttestationResponse>>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
@@ -473,6 +491,8 @@ app.MapGet("/api/v1/packs/{packId}/attestations/{type}", async (string packId, s
context.Response.Headers["X-Attestation-Digest"] = record.Digest;
return Results.File(content, "application/octet-stream", fileDownloadName: $"{packId}-{type}-attestation.bin");
})
.WithName("GetPackAttestationContent")
.WithDescription("Downloads the binary content of a specific attestation type for the specified pack. The response includes an X-Attestation-Digest header for integrity verification. Returns 403 if the tenant does not match. Returns 404 if the pack or the named attestation type is not found.")
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
@@ -500,6 +520,8 @@ app.MapGet("/api/v1/packs/{packId}/parity", async (string packId, ParityService
return Results.Ok(ParityResponse.From(parity));
})
.WithName("GetPackParity")
.WithDescription("Returns the parity status record for the specified pack, indicating whether the pack content is consistent across mirror sites. Returns 403 if the tenant does not match. Returns 404 if no parity record exists for the pack.")
.Produces<ParityResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
@@ -527,6 +549,8 @@ app.MapGet("/api/v1/packs/{packId}/lifecycle", async (string packId, LifecycleSe
return Results.Ok(LifecycleResponse.From(record));
})
.WithName("GetPackLifecycle")
.WithDescription("Returns the current lifecycle state record for the specified pack including state name, transition timestamp, and any associated notes. Returns 403 if the tenant does not match. Returns 404 if no lifecycle record exists for the pack.")
.Produces<LifecycleResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
@@ -566,6 +590,8 @@ app.MapPost("/api/v1/packs/{packId}/lifecycle", async (string packId, LifecycleR
return Results.BadRequest(new { error = "lifecycle_failed", message = ex.Message });
}
})
.WithName("SetPackLifecycleState")
.WithDescription("Transitions the specified pack to a new lifecycle state (e.g., active, deprecated, archived) with optional notes. Returns the updated lifecycle record. Returns 400 if the state value is missing or the transition is invalid.")
.Produces<LifecycleResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
@@ -606,6 +632,8 @@ app.MapPost("/api/v1/packs/{packId}/parity", async (string packId, ParityRequest
return Results.BadRequest(new { error = "parity_failed", message = ex.Message });
}
})
.WithName("SetPackParityStatus")
.WithDescription("Records the parity check result for the specified pack, marking it as verified, mismatch, or unknown with optional notes. Returns the updated parity record. Returns 400 if the status value is missing or the parity update fails.")
.Produces<ParityResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
@@ -634,6 +662,8 @@ app.MapPost("/api/v1/export/offline-seed", async (OfflineSeedRequest request, Ex
var archive = await exportService.ExportOfflineSeedAsync(tenant, request.IncludeContent, request.IncludeProvenance, cancellationToken).ConfigureAwait(false);
return Results.File(archive, "application/zip", fileDownloadName: "packs-offline-seed.zip");
})
.WithName("ExportOfflineSeed")
.WithDescription("Generates a ZIP archive containing all packs for the specified tenant, optionally including binary content and provenance documents, suitable for seeding an air-gapped PacksRegistry instance. When tenant allowlists are configured, a tenant ID is required.")
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
@@ -665,6 +695,8 @@ app.MapPost("/api/v1/mirrors", async (MirrorRequest request, MirrorService mirro
var record = await mirrorService.UpsertAsync(request.Id!, tenantHeader, new Uri(request.Upstream!), request.Enabled, request.Notes, cancellationToken).ConfigureAwait(false);
return Results.Created($"/api/v1/mirrors/{record.Id}", MirrorResponse.From(record));
})
.WithName("UpsertMirror")
.WithDescription("Creates or updates a mirror registration for the specified tenant, associating a mirror ID with an upstream URL and enabled state. Returns 201 Created with the stored mirror record. Returns 400 if required fields are missing.")
.Produces<MirrorResponse>(StatusCodes.Status201Created)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
@@ -687,6 +719,8 @@ app.MapGet("/api/v1/mirrors", async (string? tenant, MirrorService mirrorService
var mirrors = await mirrorService.ListAsync(effectiveTenant, cancellationToken).ConfigureAwait(false);
return Results.Ok(mirrors.Select(MirrorResponse.From));
})
.WithName("ListMirrors")
.WithDescription("Returns all mirror registrations for the specified tenant, or all mirrors if no tenant filter is applied. Returns 403 if the caller's tenant allowlist excludes the requested tenant.")
.Produces<IEnumerable<MirrorResponse>>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden);
@@ -712,6 +746,8 @@ app.MapPost("/api/v1/mirrors/{id}/sync", async (string id, MirrorSyncRequest req
return Results.Ok(MirrorResponse.From(updated));
})
.WithName("MarkMirrorSync")
.WithDescription("Records the outcome of a mirror synchronization attempt for the specified mirror ID, updating its sync status and optional notes. Returns the updated mirror record. Returns 404 if the mirror ID is not found.")
.Produces<MirrorResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
@@ -735,6 +771,8 @@ app.MapGet("/api/v1/compliance/summary", async (string? tenant, ComplianceServic
var summary = await complianceService.SummarizeAsync(effectiveTenant, cancellationToken).ConfigureAwait(false);
return Results.Ok(summary);
})
.WithName("GetPacksComplianceSummary")
.WithDescription("Returns a compliance summary for the specified tenant's pack collection including signed pack count, unsigned count, packs with attestations, deprecated packs, and mirror sync status breakdown. Returns 403 if the tenant is not allowed.")
.Produces<ComplianceSummary>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden);