mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 10:54:55 +08:00
fix(release):完善当前分发证明与质量门禁
This commit is contained in:
@@ -118,7 +118,7 @@ func (c *Client) callEnvelope(ctx context.Context, method string, params any) (*
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
defer func() { _ = conn.Close() }()
|
||||
|
||||
if deadline, ok := c.deadline(ctx); ok {
|
||||
_ = conn.SetDeadline(deadline)
|
||||
@@ -877,14 +877,29 @@ type ResourceManifestEntry struct {
|
||||
BLAKE3 string `json:"blake3,omitempty"`
|
||||
}
|
||||
|
||||
// ResourceManifestParams binds every page to one attested official release.
|
||||
type ResourceManifestParams struct {
|
||||
ReleaseID string `json:"release_id,omitempty"`
|
||||
ExpectedPublicationIdentity string `json:"expected_publication_identity,omitempty"`
|
||||
ExpectedManifestIdentity string `json:"expected_manifest_identity,omitempty"`
|
||||
Offset int `json:"offset"`
|
||||
Limit int `json:"limit"`
|
||||
}
|
||||
|
||||
type ResourceManifestPage struct {
|
||||
Available bool `json:"available"`
|
||||
ResourceRoot string `json:"resource_root,omitempty"`
|
||||
ManifestVersion int `json:"manifest_version,omitempty"`
|
||||
TotalEntries int `json:"total_entries,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Entries []ResourceManifestEntry `json:"entries,omitempty"`
|
||||
Available bool `json:"available"`
|
||||
Channel string `json:"channel,omitempty"`
|
||||
ReleaseID string `json:"release_id,omitempty"`
|
||||
ResourceRoot string `json:"resource_root,omitempty"`
|
||||
ManifestVersion int `json:"manifest_version,omitempty"`
|
||||
PublicationIdentity string `json:"publication_identity,omitempty"`
|
||||
MappingIdentity string `json:"mapping_identity,omitempty"`
|
||||
ManifestIdentity string `json:"manifest_identity,omitempty"`
|
||||
Generation uint64 `json:"generation,omitempty"`
|
||||
TotalEntries int `json:"total_entries,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Entries []ResourceManifestEntry `json:"entries,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) DaemonStatus(ctx context.Context) (*DaemonStatusReport, error) {
|
||||
@@ -953,9 +968,35 @@ func (c *Client) ResourceRepair(ctx context.Context) (*TaskAccepted, error) {
|
||||
return &out, err
|
||||
}
|
||||
|
||||
func (c *Client) ResourceManifest(ctx context.Context, offset int, limit int) (*ResourceManifestPage, error) {
|
||||
// DistributionAttestation is the Rust-owned current official health proof.
|
||||
type DistributionAttestation struct {
|
||||
Available bool `json:"available"`
|
||||
Channel string `json:"channel"`
|
||||
ReleaseID string `json:"release_id"`
|
||||
ResourceRoot string `json:"resource_root"`
|
||||
PublicationIdentity string `json:"publication_identity"`
|
||||
MappingIdentity string `json:"mapping_identity"`
|
||||
ManifestIdentity string `json:"manifest_identity"`
|
||||
EntryCount int `json:"entry_count"`
|
||||
IntegrityStatus string `json:"integrity_status"`
|
||||
Status string `json:"status"`
|
||||
StatusCode string `json:"status_code"`
|
||||
Ready bool `json:"ready"`
|
||||
VerificationGeneration uint64 `json:"verification_generation"`
|
||||
VerifiedAt *uint64 `json:"verified_at,omitempty"`
|
||||
MaxAgeSeconds uint64 `json:"max_age_seconds"`
|
||||
Diagnostics []string `json:"diagnostics,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) ReleaseAttestation(ctx context.Context) (*DistributionAttestation, error) {
|
||||
var out DistributionAttestation
|
||||
_, err := c.Call(ctx, "release.attestation", nil, &out)
|
||||
return &out, err
|
||||
}
|
||||
|
||||
func (c *Client) ResourceManifest(ctx context.Context, params ResourceManifestParams) (*ResourceManifestPage, error) {
|
||||
var out ResourceManifestPage
|
||||
_, err := c.Call(ctx, "resource.manifest", pageParam{Offset: offset, Limit: limit}, &out)
|
||||
_, err := c.Call(ctx, "resource.manifest", params, &out)
|
||||
return &out, err
|
||||
}
|
||||
|
||||
|
||||
@@ -249,6 +249,101 @@ func TestParseTextUnitsSendsQuery(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseAttestationMirrorsCurrentOfficialHealth(t *testing.T) {
|
||||
client := newTestClient(t, func(t *testing.T, req testRequest) testResponse {
|
||||
if req.Method != "release.attestation" {
|
||||
t.Fatalf("method = %s", req.Method)
|
||||
}
|
||||
return testResponse{
|
||||
Result: testEnvelope{
|
||||
OK: true,
|
||||
Status: "ok",
|
||||
Data: map[string]any{
|
||||
"available": true,
|
||||
"channel": "official",
|
||||
"release_id": "official-a",
|
||||
"resource_root": "/srv/official/versions/official-a",
|
||||
"publication_identity": "odp-v1-publication-a",
|
||||
"mapping_identity": "odm-v1-mapping-a",
|
||||
"manifest_identity": "manifest-a",
|
||||
"entry_count": 2,
|
||||
"integrity_status": "verified",
|
||||
"status": "ready",
|
||||
"status_code": "distribution.ready",
|
||||
"ready": true,
|
||||
"verification_generation": 7,
|
||||
"verified_at": 1234,
|
||||
"max_age_seconds": 900,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
report, err := client.ReleaseAttestation(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("ReleaseAttestation error: %v", err)
|
||||
}
|
||||
if !report.Ready || report.ReleaseID != "official-a" ||
|
||||
report.ManifestIdentity != "manifest-a" ||
|
||||
report.VerificationGeneration != 7 {
|
||||
t.Fatalf("report = %#v", report)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceManifestSendsAttestedGenerationParams(t *testing.T) {
|
||||
client := newTestClient(t, func(t *testing.T, req testRequest) testResponse {
|
||||
if req.Method != "resource.manifest" {
|
||||
t.Fatalf("method = %s", req.Method)
|
||||
}
|
||||
var params ResourceManifestParams
|
||||
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
|
||||
t.Fatalf("decode params: %v", err)
|
||||
}
|
||||
if params.ReleaseID != "official-a" ||
|
||||
params.ExpectedPublicationIdentity != "odp-v1-publication-a" ||
|
||||
params.ExpectedManifestIdentity != "manifest-a" ||
|
||||
params.Offset != 1 || params.Limit != 100 {
|
||||
t.Fatalf("params = %#v", params)
|
||||
}
|
||||
return testResponse{
|
||||
Result: testEnvelope{
|
||||
OK: true,
|
||||
Status: "ok",
|
||||
Data: map[string]any{
|
||||
"available": true,
|
||||
"channel": "official",
|
||||
"release_id": "official-a",
|
||||
"resource_root": "/srv/official/versions/official-a",
|
||||
"manifest_version": 1,
|
||||
"publication_identity": "odp-v1-publication-a",
|
||||
"mapping_identity": "odm-v1-mapping-a",
|
||||
"manifest_identity": "manifest-a",
|
||||
"generation": 7,
|
||||
"total_entries": 2,
|
||||
"offset": 1,
|
||||
"limit": 100,
|
||||
"entries": []any{},
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
page, err := client.ResourceManifest(context.Background(), ResourceManifestParams{
|
||||
ReleaseID: "official-a",
|
||||
ExpectedPublicationIdentity: "odp-v1-publication-a",
|
||||
ExpectedManifestIdentity: "manifest-a",
|
||||
Offset: 1,
|
||||
Limit: 100,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("ResourceManifest error: %v", err)
|
||||
}
|
||||
if page.ReleaseID != "official-a" || page.ManifestIdentity != "manifest-a" ||
|
||||
page.Generation != 7 {
|
||||
t.Fatalf("page = %#v", page)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnityFSPatchFieldSendsTaggedReplacement(t *testing.T) {
|
||||
client := newTestClient(t, func(t *testing.T, req testRequest) testResponse {
|
||||
if req.Method != "unityfs.patch_field" {
|
||||
|
||||
Reference in New Issue
Block a user