Skip to content

Commit 8da5815

Browse files
authored
[Feat] Added Mux API Analyzer (#4128)
* added mux analyzer * updated mux analyzer print function and mux detector * updated mux analyzer test expected output
1 parent f7b6d7d commit 8da5815

File tree

13 files changed

+940
-0
lines changed

13 files changed

+940
-0
lines changed

pkg/analyzer/analyzers/analyzers.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ const (
9898
AnalyzerTypeFastly
9999
AnalyzerTypeMonday
100100
AnalyzerTypeNgrok
101+
AnalyzerTypeMux
101102
// Add new items here with AnalyzerType prefix
102103
)
103104

@@ -141,6 +142,7 @@ var analyzerTypeStrings = map[AnalyzerType]string{
141142
AnalyzerTypeFastly: "Fastly",
142143
AnalyzerTypeMonday: "Monday",
143144
AnalyzerTypeNgrok: "Ngrok",
145+
AnalyzerTypeMux: "Mux",
144146
// Add new mappings here
145147
}
146148

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"AnalyzerType":38,"Bindings":[{"Resource":{"Name":"wV300mH02AsW9XmwfieoMlmLNXConYCREXQHbb7kWAUbw","FullyQualifiedName":"asset/SnmkoMLmA2smTuCHU18H00MOL028LeVQHX3uEQCwD7BMI/track/wV300mH02AsW9XmwfieoMlmLNXConYCREXQHbb7kWAUbw","Type":"track","Metadata":{"duration":16.750067,"languageCode":"","maxChannels":0,"maxFrameRate":29.97,"maxHeight":1080,"maxWidth":1920,"name":"","primary":false,"status":"","textSource":"","textType":"","type":"video"},"Parent":{"Name":"SnmkoMLmA2smTuCHU18H00MOL028LeVQHX3uEQCwD7BMI","FullyQualifiedName":"asset/SnmkoMLmA2smTuCHU18H00MOL028LeVQHX3uEQCwD7BMI","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746529086","duration":16.750067,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"6gYp01Q1DQu02Y1BFChIGYlEReYtMyZWYC601VcrSLK02KA","FullyQualifiedName":"asset/SnmkoMLmA2smTuCHU18H00MOL028LeVQHX3uEQCwD7BMI/playback_id/6gYp01Q1DQu02Y1BFChIGYlEReYtMyZWYC601VcrSLK02KA","Type":"playback_id","Metadata":{"policy":"public"},"Parent":{"Name":"SnmkoMLmA2smTuCHU18H00MOL028LeVQHX3uEQCwD7BMI","FullyQualifiedName":"asset/SnmkoMLmA2smTuCHU18H00MOL028LeVQHX3uEQCwD7BMI","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746529086","duration":16.750067,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"SnmkoMLmA2smTuCHU18H00MOL028LeVQHX3uEQCwD7BMI","FullyQualifiedName":"asset/SnmkoMLmA2smTuCHU18H00MOL028LeVQHX3uEQCwD7BMI","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746529086","duration":16.750067,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"EPWJi6t301mELwzilEDAnZS8T2Uqs8ULDbgZVeCOhLNA","FullyQualifiedName":"asset/a00U5GeBR6pAO3MkdZQBB00enwG1rLwx7UTsYPd0200sylo/track/EPWJi6t301mELwzilEDAnZS8T2Uqs8ULDbgZVeCOhLNA","Type":"track","Metadata":{"duration":16.750067,"languageCode":"","maxChannels":0,"maxFrameRate":29.97,"maxHeight":1080,"maxWidth":1920,"name":"","primary":false,"status":"","textSource":"","textType":"","type":"video"},"Parent":{"Name":"a00U5GeBR6pAO3MkdZQBB00enwG1rLwx7UTsYPd0200sylo","FullyQualifiedName":"asset/a00U5GeBR6pAO3MkdZQBB00enwG1rLwx7UTsYPd0200sylo","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746529083","duration":16.750067,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"X9gY7SmIrDIB5Y02gu8KnUnzuAOi005iOafaJuCQqqZbA","FullyQualifiedName":"asset/a00U5GeBR6pAO3MkdZQBB00enwG1rLwx7UTsYPd0200sylo/playback_id/X9gY7SmIrDIB5Y02gu8KnUnzuAOi005iOafaJuCQqqZbA","Type":"playback_id","Metadata":{"policy":"public"},"Parent":{"Name":"a00U5GeBR6pAO3MkdZQBB00enwG1rLwx7UTsYPd0200sylo","FullyQualifiedName":"asset/a00U5GeBR6pAO3MkdZQBB00enwG1rLwx7UTsYPd0200sylo","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746529083","duration":16.750067,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"a00U5GeBR6pAO3MkdZQBB00enwG1rLwx7UTsYPd0200sylo","FullyQualifiedName":"asset/a00U5GeBR6pAO3MkdZQBB00enwG1rLwx7UTsYPd0200sylo","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746529083","duration":16.750067,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"6nV01pBVrQLad3kjFoEUd023Uxfgl8x8DOK546dqA5xD00","FullyQualifiedName":"asset/QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw/track/6nV01pBVrQLad3kjFoEUd023Uxfgl8x8DOK546dqA5xD00","Type":"track","Metadata":{"duration":25.45,"languageCode":"","maxChannels":2,"maxFrameRate":0,"maxHeight":0,"maxWidth":0,"name":"","primary":true,"status":"","textSource":"","textType":"","type":"audio"},"Parent":{"Name":"QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","FullyQualifiedName":"asset/QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513418","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"OXOWt16AiGYvtAwuFFfA00hKAHNW02ERja00bvPEWmHLys","FullyQualifiedName":"asset/QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw/track/OXOWt16AiGYvtAwuFFfA00hKAHNW02ERja00bvPEWmHLys","Type":"track","Metadata":{"duration":25.4254,"languageCode":"","maxChannels":0,"maxFrameRate":29.97,"maxHeight":1080,"maxWidth":1920,"name":"","primary":false,"status":"","textSource":"","textType":"","type":"video"},"Parent":{"Name":"QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","FullyQualifiedName":"asset/QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513418","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"gaJcYKWQ7P01r02XJwU02KAe5KofkQ01497weVghrWNrqlWNYAXHx7fqmQ","FullyQualifiedName":"asset/QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw/track/gaJcYKWQ7P01r02XJwU02KAe5KofkQ01497weVghrWNrqlWNYAXHx7fqmQ","Type":"track","Metadata":{"duration":0,"languageCode":"pt","maxChannels":0,"maxFrameRate":0,"maxHeight":0,"maxWidth":0,"name":"Portuguese","primary":false,"status":"ready","textSource":"generated_vod","textType":"subtitles","type":"text"},"Parent":{"Name":"QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","FullyQualifiedName":"asset/QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513418","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"hQKQ8U1RkGTN3700ynnDCa00y4q2sCflbKf2Nw01T8OcTc","FullyQualifiedName":"asset/QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw/playback_id/hQKQ8U1RkGTN3700ynnDCa00y4q2sCflbKf2Nw01T8OcTc","Type":"playback_id","Metadata":{"policy":"signed"},"Parent":{"Name":"QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","FullyQualifiedName":"asset/QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513418","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","FullyQualifiedName":"asset/QLnXn72rbNKLLvfzVJU2t01atuGSbyYMLsU026jza8YOw","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513418","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"ZJ9HiAaXUO02Da3W7Yj3y5Ct902SIafAbjMTvDhnfaOcs","FullyQualifiedName":"asset/Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8/track/ZJ9HiAaXUO02Da3W7Yj3y5Ct902SIafAbjMTvDhnfaOcs","Type":"track","Metadata":{"duration":25.4254,"languageCode":"","maxChannels":0,"maxFrameRate":29.97,"maxHeight":1080,"maxWidth":1920,"name":"","primary":false,"status":"","textSource":"","textType":"","type":"video"},"Parent":{"Name":"Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","FullyQualifiedName":"asset/Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513375","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"5Od27uOFUUNPgNhnqwxmc6YQH200q5SD17CRkc25eciM6YMb7c00JvDA","FullyQualifiedName":"asset/Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8/track/5Od27uOFUUNPgNhnqwxmc6YQH200q5SD17CRkc25eciM6YMb7c00JvDA","Type":"track","Metadata":{"duration":0,"languageCode":"it","maxChannels":0,"maxFrameRate":0,"maxHeight":0,"maxWidth":0,"name":"Italian","primary":false,"status":"ready","textSource":"generated_vod","textType":"subtitles","type":"text"},"Parent":{"Name":"Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","FullyQualifiedName":"asset/Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513375","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"xmgPZVZwnFlWC8Y2Q0046eAOxR88oPP01S5OqHYPLBM01jy601502OoGSwA","FullyQualifiedName":"asset/Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8/track/xmgPZVZwnFlWC8Y2Q0046eAOxR88oPP01S5OqHYPLBM01jy601502OoGSwA","Type":"track","Metadata":{"duration":0,"languageCode":"und","maxChannels":2,"maxFrameRate":0,"maxHeight":0,"maxWidth":0,"name":"Default","primary":true,"status":"ready","textSource":"","textType":"","type":"audio"},"Parent":{"Name":"Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","FullyQualifiedName":"asset/Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513375","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"GD1K9sPH4Vopr4ticPdOAO02vEIslfN2400cPQnA8YZfo","FullyQualifiedName":"asset/Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8/playback_id/GD1K9sPH4Vopr4ticPdOAO02vEIslfN2400cPQnA8YZfo","Type":"playback_id","Metadata":{"policy":"public"},"Parent":{"Name":"Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","FullyQualifiedName":"asset/Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513375","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null}},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","FullyQualifiedName":"asset/Wa5Qmq78b02p2kMCB3P7Lyn4tHjiSkEJT01HEZq8l4Oq8","Type":"asset","Metadata":{"aspectRatio":"16:9","createdAt":"1746513375","duration":25.492133,"mp4Support":"none","status":"ready","videoQuality":"basic"},"Parent":null},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"8f23e2ab-6780-4dc8-aa8d-8e27339188a6","FullyQualifiedName":"annotation/8f23e2ab-6780-4dc8-aa8d-8e27339188a6","Type":"annotation","Metadata":{"date":"2025-04-23T20:00:00Z","note":"This is a note2","subPropertyID":"123456"},"Parent":null},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"21d0aca6-9ea4-4d92-a8c5-254a7da2a455","FullyQualifiedName":"annotation/21d0aca6-9ea4-4d92-a8c5-254a7da2a455","Type":"annotation","Metadata":{"date":"2025-04-23T20:00:00Z","note":"This is a note","subPropertyID":"123456"},"Parent":null},"Permission":{"Value":"full_access","Parent":null}},{"Resource":{"Name":"NNqGrk9T7Bi4AkaWB38JoOEJiUb417f01P43agSLYXCg","FullyQualifiedName":"signing_key/NNqGrk9T7Bi4AkaWB38JoOEJiUb417f01P43agSLYXCg","Type":"signing_key","Metadata":{"createdAt":"1746615294"},"Parent":null},"Permission":{"Value":"read","Parent":null}},{"Resource":{"Name":"t4zt5HNbEPmJEDJLpLMXty4d39xMlMgB0292mlbY17sI","FullyQualifiedName":"signing_key/t4zt5HNbEPmJEDJLpLMXty4d39xMlMgB0292mlbY17sI","Type":"signing_key","Metadata":{"createdAt":"1746615296"},"Parent":null},"Permission":{"Value":"read","Parent":null}},{"Resource":{"Name":"dGQ8BK2joovz4WElQqK02I9ZXN1UeySO27Zn21Y8ATf8","FullyQualifiedName":"signing_key/dGQ8BK2joovz4WElQqK02I9ZXN1UeySO27Zn21Y8ATf8","Type":"signing_key","Metadata":{"createdAt":"1746615298"},"Parent":null},"Permission":{"Value":"read","Parent":null}},{"Resource":{"Name":"3FA1JvJkG8Ye4i4OpTRcEvFkuNVWkeTLN8BEkKWUko8","FullyQualifiedName":"signing_key/3FA1JvJkG8Ye4i4OpTRcEvFkuNVWkeTLN8BEkKWUko8","Type":"signing_key","Metadata":{"createdAt":"1746615300"},"Parent":null},"Permission":{"Value":"read","Parent":null}},{"Resource":{"Name":"7kH3cGnX4e5qavqA1Zd7GbxeQ7pDCX702LuXUhCOhdnY","FullyQualifiedName":"signing_key/7kH3cGnX4e5qavqA1Zd7GbxeQ7pDCX702LuXUhCOhdnY","Type":"signing_key","Metadata":{"createdAt":"1746615302"},"Parent":null},"Permission":{"Value":"read","Parent":null}},{"Resource":{"Name":"T6OmB00xJqpIoM3nbSTRbvHiOjrTGCA7HkKx02UtRRkgk","FullyQualifiedName":"signing_key/T6OmB00xJqpIoM3nbSTRbvHiOjrTGCA7HkKx02UtRRkgk","Type":"signing_key","Metadata":{"createdAt":"1746615304"},"Parent":null},"Permission":{"Value":"read","Parent":null}},{"Resource":{"Name":"ivN5HCZBsuhWUUBrlusVCB7aseh87N1sAji7XFM8LEs","FullyQualifiedName":"signing_key/ivN5HCZBsuhWUUBrlusVCB7aseh87N1sAji7XFM8LEs","Type":"signing_key","Metadata":{"createdAt":"1746615305"},"Parent":null},"Permission":{"Value":"read","Parent":null}},{"Resource":{"Name":"jUGFLfsJSqDev6NBjbnOLh4VX6WZJTIuHSFAgomgpkQ","FullyQualifiedName":"signing_key/jUGFLfsJSqDev6NBjbnOLh4VX6WZJTIuHSFAgomgpkQ","Type":"signing_key","Metadata":{"createdAt":"1746615307"},"Parent":null},"Permission":{"Value":"read","Parent":null}},{"Resource":{"Name":"xnM4650153BqZfmYf167G8Vo91X9Z43im024AwUksPP7o","FullyQualifiedName":"signing_key/xnM4650153BqZfmYf167G8Vo91X9Z43im024AwUksPP7o","Type":"signing_key","Metadata":{"createdAt":"1746615327"},"Parent":null},"Permission":{"Value":"read","Parent":null}}],"UnboundedResources":null,"Metadata":null}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package mux
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
)
7+
8+
type ResourceType string
9+
10+
const (
11+
ResourceTypeVideo ResourceType = "video"
12+
ResourceTypeData ResourceType = "data"
13+
ResourceTypeSystem ResourceType = "system"
14+
)
15+
16+
type permissionTestConfig struct {
17+
Tests []permissionTest `json:"tests"`
18+
}
19+
20+
type permissionTest struct {
21+
ResourceType ResourceType `json:"resource_type"`
22+
Permission string `json:"permission"`
23+
Endpoint string `json:"endpoint"`
24+
Method string `json:"method"`
25+
ValidStatusCode int `json:"valid_status_code"`
26+
}
27+
28+
func (test permissionTest) testPermission(client *http.Client, key string, secret string) (bool, error) {
29+
_, statusCode, err := makeAPIRequest(client, key, secret, test.Method, test.Endpoint)
30+
if err != nil {
31+
return false, err
32+
}
33+
34+
switch statusCode {
35+
case test.ValidStatusCode:
36+
return true, nil
37+
case http.StatusNotFound:
38+
return false, nil
39+
default:
40+
return false, fmt.Errorf("unexpected status code: %d", statusCode)
41+
}
42+
}
43+
44+
type secretInfo struct {
45+
Permissions map[ResourceType]Permission
46+
Assets []asset
47+
Annotations []annotation
48+
SigningKeys []signingKey
49+
}
50+
51+
func (info *secretInfo) addPermission(resourceType ResourceType, permission string) {
52+
if info.Permissions == nil {
53+
info.Permissions = map[ResourceType]Permission{}
54+
}
55+
if perm := info.Permissions[resourceType]; perm == FullAccess {
56+
return
57+
}
58+
59+
if permission == "read" {
60+
info.Permissions[resourceType] = Read
61+
} else if permission == "write" {
62+
info.Permissions[resourceType] = FullAccess
63+
}
64+
}
65+
66+
func (info *secretInfo) hasPermission(resourceType ResourceType, permission Permission) bool {
67+
perm, exists := info.Permissions[resourceType]
68+
if !exists {
69+
return false
70+
}
71+
return perm == permission || perm == FullAccess
72+
}
73+
74+
// Resource structs
75+
76+
type track struct {
77+
ID string `json:"id"`
78+
Name string `json:"name"`
79+
Type string `json:"type"`
80+
Duration float64 `json:"duration"`
81+
Status string `json:"status"`
82+
Primary bool `json:"primary"`
83+
84+
TextType string `json:"text_type"`
85+
TextSource string `json:"text_source"`
86+
LanguageCode string `json:"language_code"`
87+
88+
MaxWidth int `json:"max_width"`
89+
MaxHeight int `json:"max_height"`
90+
MaxFrameRate float64 `json:"max_frame_rate"`
91+
MaxChannels int `json:"max_channels"`
92+
}
93+
94+
type playbackID struct {
95+
ID string `json:"id"`
96+
Policy string `json:"policy"`
97+
}
98+
99+
type meta struct {
100+
Title string `json:"title"`
101+
ExternalID string `json:"external_id"`
102+
CreatorID string `json:"creator_id"`
103+
}
104+
105+
type asset struct {
106+
ID string `json:"id"`
107+
Duration float64 `json:"duration"`
108+
Status string `json:"status"`
109+
VideoQuality string `json:"video_quality"`
110+
MP4Support string `json:"mp4_support"`
111+
AspectRatio string `json:"aspect_ratio"`
112+
Tracks []track `json:"tracks"`
113+
PlaybackIDs []playbackID `json:"playback_ids"`
114+
Meta meta `json:"meta"`
115+
CreatedAt string `json:"created_at"`
116+
}
117+
118+
type annotation struct {
119+
SubPropertyID string `json:"sub_property_id"`
120+
Note string `json:"note"`
121+
ID string `json:"id"`
122+
Date string `json:"date"`
123+
}
124+
125+
type signingKey struct {
126+
ID string `json:"id"`
127+
CreatedAt string `json:"created_at"`
128+
}
129+
130+
// API response structs
131+
132+
type assetListResponse struct {
133+
Data []asset `json:"data"`
134+
}
135+
136+
type annotationListResponse struct {
137+
Data []annotation `json:"data"`
138+
}
139+
140+
type signingKeyListResponse struct {
141+
Data []signingKey `json:"data"`
142+
}

0 commit comments

Comments
 (0)