fix(release): 完成分发证明代际绑定与质量门禁收口
bat-rust / Build and test Rust (push) Canceled after 0s
bat-rust / Build and test Go API (push) Canceled after 0s

This commit is contained in:
2026-09-15 21:13:52 +08:00
parent 13b0bd5b45
commit 99355effe4
29 changed files with 1137 additions and 189 deletions
+65 -13
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"os"
"path/filepath"
"time"
"bat-api/internal/backendrpc"
)
@@ -417,8 +418,17 @@ func DiscoverAndIndex(ctx context.Context, backend Backend, resourceRootOverride
}
out.Attestation = attestation
out.Distribution = rustAttestationHealth(attestation)
if !attestation.Available {
return emptyRPCResult(out, nil, "Rust current official distribution attestation is unavailable"), nil
if !attestation.Available ||
!attestation.Ready ||
attestation.Channel != "official" ||
attestation.IntegrityStatus != "verified" ||
attestation.VerificationGeneration == 0 ||
!attestationIsFresh(attestation) {
return emptyRPCResult(
out,
nil,
"Rust current official distribution attestation is unavailable or not ready",
), nil
}
// Catalog / resource discovery
@@ -604,6 +614,7 @@ func rustAttestationHealth(report *backendrpc.DistributionAttestation) Distribut
if report == nil {
return health
}
health.Available = report.Available
health.Ready = report.Ready
health.Channel = report.Channel
health.ReleaseID = report.ReleaseID
@@ -614,6 +625,7 @@ func rustAttestationHealth(report *backendrpc.DistributionAttestation) Distribut
health.EntryCount = report.EntryCount
health.VerificationGeneration = report.VerificationGeneration
health.VerifiedAt = report.VerifiedAt
health.MaxAgeSeconds = report.MaxAgeSeconds
health.Status = report.Status
health.StatusCode = report.StatusCode
health.IntegrityStatus = report.IntegrityStatus
@@ -639,6 +651,18 @@ func unavailableRustDistributionHealth() DistributionHealth {
}
}
func attestationIsFresh(attestation *backendrpc.DistributionAttestation) bool {
if attestation == nil || attestation.MaxAgeSeconds == 0 || attestation.VerifiedAt == nil {
return false
}
now := uint64(time.Now().Unix())
age := uint64(0)
if now > *attestation.VerifiedAt {
age = now - *attestation.VerifiedAt
}
return age <= attestation.MaxAgeSeconds
}
func snapshotWithDistributionHealth(snapshot *SnapshotSummary, health DistributionHealth) *SnapshotSummary {
if snapshot == nil {
return nil
@@ -729,18 +753,31 @@ func fetchAllManifestEntriesWithPageSize(
if pageSize <= 0 {
return nil, 0, "", fmt.Errorf("manifest page size must be positive")
}
if attestation == nil {
return nil, 0, "", fmt.Errorf("resource.manifest requires a Rust attestation")
}
if !attestation.Available ||
!attestation.Ready ||
attestation.Channel != "official" ||
attestation.IntegrityStatus != "verified" ||
attestation.VerificationGeneration == 0 ||
!attestationIsFresh(attestation) {
return nil, 0, "", fmt.Errorf("resource.manifest attestation is not ready")
}
offset := 0
var all []manifestEntry
var version int
var root, releaseID, publicationIdentity, mappingIdentity, manifestIdentity string
var version, limit int
var channel, root, releaseID, publicationIdentity, mappingIdentity, manifestIdentity string
var generation uint64
total := -1
for {
page, err := backend.ResourceManifest(ctx, backendrpc.ResourceManifestParams{
ReleaseID: attestation.ReleaseID,
ExpectedPublicationIdentity: attestation.PublicationIdentity,
ExpectedManifestIdentity: attestation.ManifestIdentity,
Offset: offset,
Limit: pageSize,
ReleaseID: attestation.ReleaseID,
ExpectedPublicationIdentity: attestation.PublicationIdentity,
ExpectedManifestIdentity: attestation.ManifestIdentity,
ExpectedVerificationGeneration: attestation.VerificationGeneration,
Offset: offset,
Limit: pageSize,
})
if err != nil {
return nil, 0, "", err
@@ -753,19 +790,25 @@ func fetchAllManifestEntriesWithPageSize(
}
if root == "" {
root = page.ResourceRoot
channel = page.Channel
releaseID = page.ReleaseID
publicationIdentity = page.PublicationIdentity
mappingIdentity = page.MappingIdentity
manifestIdentity = page.ManifestIdentity
generation = page.Generation
version = page.ManifestVersion
total = page.TotalEntries
limit = page.Limit
} else if page.ResourceRoot != root ||
page.Channel != channel ||
page.ReleaseID != releaseID ||
page.PublicationIdentity != publicationIdentity ||
page.MappingIdentity != mappingIdentity ||
page.ManifestIdentity != manifestIdentity ||
page.Generation != generation ||
page.ManifestVersion != version ||
page.TotalEntries != total {
page.TotalEntries != total ||
page.Limit != limit {
return nil, 0, "", fmt.Errorf("resource.manifest page identity or total changed")
}
if page.Offset != offset {
@@ -775,7 +818,7 @@ func fetchAllManifestEntriesWithPageSize(
page.Offset,
)
}
if page.Limit <= 0 || page.Limit > pageSize {
if page.Limit != pageSize {
return nil, 0, "", fmt.Errorf("resource.manifest page limit is unreasonable: %d", page.Limit)
}
if page.TotalEntries < 0 || len(page.Entries) > page.Limit {
@@ -784,12 +827,14 @@ func fetchAllManifestEntriesWithPageSize(
if total < 0 || offset > total || offset+len(page.Entries) > total {
return nil, 0, "", fmt.Errorf("resource.manifest page exceeds declared total")
}
if attestation != nil && (releaseID != attestation.ReleaseID ||
if channel != attestation.Channel ||
releaseID != attestation.ReleaseID ||
root != attestation.ResourceRoot ||
publicationIdentity != attestation.PublicationIdentity ||
mappingIdentity != attestation.MappingIdentity ||
manifestIdentity != attestation.ManifestIdentity ||
total != attestation.EntryCount) {
generation != attestation.VerificationGeneration ||
total != attestation.EntryCount {
return nil, 0, "", fmt.Errorf("resource.manifest page does not match attestation")
}
for _, e := range page.Entries {
@@ -812,5 +857,12 @@ func fetchAllManifestEntriesWithPageSize(
return nil, 0, "", fmt.Errorf("resource.manifest page has a gap before total")
}
}
if len(all) != total {
return nil, 0, "", fmt.Errorf(
"resource.manifest final entry count mismatch: entries=%d total=%d",
len(all),
total,
)
}
return all, version, root, nil
}