A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cbor_gen crew

+370 -47
+32
gen/main.go
··· 1 + package main 2 + 3 + // CBOR Code Generator 4 + // 5 + // This generates optimized CBOR marshaling code for ATProto records. 6 + // 7 + // Usage: 8 + // go run gen/main.go 9 + // 10 + // This creates pkg/hold/pds/cbor_gen.go which should be committed to git. 11 + // Only re-run when you modify types in pkg/hold/pds/types.go 12 + 13 + import ( 14 + "fmt" 15 + "os" 16 + 17 + cbg "github.com/whyrusleeping/cbor-gen" 18 + 19 + "atcr.io/pkg/hold/pds" 20 + ) 21 + 22 + func main() { 23 + // Generate map-style encoders for CrewRecord 24 + if err := cbg.WriteMapEncodersToFile("pkg/hold/pds/cbor_gen.go", "pds", 25 + pds.CrewRecord{}, 26 + ); err != nil { 27 + fmt.Printf("Failed to generate CBOR encoders: %v\n", err) 28 + os.Exit(1) 29 + } 30 + 31 + fmt.Println("Generated CBOR encoders in pkg/hold/pds/cbor_gen.go") 32 + }
+3 -3
go.mod
··· 11 11 github.com/google/uuid v1.6.0 12 12 github.com/gorilla/mux v1.8.1 13 13 github.com/gorilla/websocket v1.5.3 14 + github.com/ipfs/go-cid v0.4.1 14 15 github.com/klauspost/compress v1.18.0 15 16 github.com/mattn/go-sqlite3 v1.14.32 16 17 github.com/opencontainers/go-digest v1.0.0 17 18 github.com/spf13/cobra v1.8.0 19 + github.com/whyrusleeping/cbor-gen v0.3.1 18 20 go.yaml.in/yaml/v4 v4.0.0-rc.2 19 21 golang.org/x/crypto v0.39.0 20 - github.com/ipfs/go-cid v0.4.1 22 + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 21 23 ) 22 24 23 25 require ( ··· 100 102 github.com/sirupsen/logrus v1.9.3 // indirect 101 103 github.com/spaolacci/murmur3 v1.1.0 // indirect 102 104 github.com/spf13/pflag v1.0.5 // indirect 103 - github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e // indirect 104 105 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect 105 106 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect 106 107 go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 // indirect ··· 133 134 golang.org/x/sys v0.33.0 // indirect 134 135 golang.org/x/text v0.26.0 // indirect 135 136 golang.org/x/time v0.6.0 // indirect 136 - golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect 137 137 google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect 138 138 google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect 139 139 google.golang.org/grpc v1.68.0 // indirect
+2 -2
go.sum
··· 370 370 github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= 371 371 github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= 372 372 github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= 373 - github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e h1:28X54ciEwwUxyHn9yrZfl5ojgF4CBNLWX7LR0rvBkf4= 374 - github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= 373 + github.com/whyrusleeping/cbor-gen v0.3.1 h1:82ioxmhEYut7LBVGhGq8xoRkXPLElVuh5mV67AFfdv0= 374 + github.com/whyrusleeping/cbor-gen v0.3.1/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= 375 375 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 376 376 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 377 377 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+1 -1
pkg/hold/authorization.go
··· 163 163 log.Printf("Warning: failed to resolve handle for DID %s: %v", did, err) 164 164 // Continue checking explicit DIDs even if handle resolution fails 165 165 handleResolved = true // Mark as attempted (don't retry) 166 - handle = "" // Empty handle won't match patterns 166 + handle = "" // Empty handle won't match patterns 167 167 } else { 168 168 handleResolved = true 169 169 }
+295
pkg/hold/pds/cbor_gen.go
··· 1 + // Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. 2 + 3 + package pds 4 + 5 + import ( 6 + "fmt" 7 + "io" 8 + "math" 9 + "sort" 10 + 11 + cid "github.com/ipfs/go-cid" 12 + cbg "github.com/whyrusleeping/cbor-gen" 13 + xerrors "golang.org/x/xerrors" 14 + ) 15 + 16 + var _ = xerrors.Errorf 17 + var _ = cid.Undef 18 + var _ = math.E 19 + var _ = sort.Sort 20 + 21 + func (t *CrewRecord) MarshalCBOR(w io.Writer) error { 22 + if t == nil { 23 + _, err := w.Write(cbg.CborNull) 24 + return err 25 + } 26 + 27 + cw := cbg.NewCborWriter(w) 28 + 29 + if _, err := cw.Write([]byte{165}); err != nil { 30 + return err 31 + } 32 + 33 + // t.Role (string) (string) 34 + if len("role") > 8192 { 35 + return xerrors.Errorf("Value in field \"role\" was too long") 36 + } 37 + 38 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("role"))); err != nil { 39 + return err 40 + } 41 + if _, err := cw.WriteString(string("role")); err != nil { 42 + return err 43 + } 44 + 45 + if len(t.Role) > 8192 { 46 + return xerrors.Errorf("Value in field t.Role was too long") 47 + } 48 + 49 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Role))); err != nil { 50 + return err 51 + } 52 + if _, err := cw.WriteString(string(t.Role)); err != nil { 53 + return err 54 + } 55 + 56 + // t.Type (string) (string) 57 + if len("$type") > 8192 { 58 + return xerrors.Errorf("Value in field \"$type\" was too long") 59 + } 60 + 61 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { 62 + return err 63 + } 64 + if _, err := cw.WriteString(string("$type")); err != nil { 65 + return err 66 + } 67 + 68 + if len(t.Type) > 8192 { 69 + return xerrors.Errorf("Value in field t.Type was too long") 70 + } 71 + 72 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Type))); err != nil { 73 + return err 74 + } 75 + if _, err := cw.WriteString(string(t.Type)); err != nil { 76 + return err 77 + } 78 + 79 + // t.Member (string) (string) 80 + if len("member") > 8192 { 81 + return xerrors.Errorf("Value in field \"member\" was too long") 82 + } 83 + 84 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("member"))); err != nil { 85 + return err 86 + } 87 + if _, err := cw.WriteString(string("member")); err != nil { 88 + return err 89 + } 90 + 91 + if len(t.Member) > 8192 { 92 + return xerrors.Errorf("Value in field t.Member was too long") 93 + } 94 + 95 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Member))); err != nil { 96 + return err 97 + } 98 + if _, err := cw.WriteString(string(t.Member)); err != nil { 99 + return err 100 + } 101 + 102 + // t.AddedAt (string) (string) 103 + if len("addedAt") > 8192 { 104 + return xerrors.Errorf("Value in field \"addedAt\" was too long") 105 + } 106 + 107 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("addedAt"))); err != nil { 108 + return err 109 + } 110 + if _, err := cw.WriteString(string("addedAt")); err != nil { 111 + return err 112 + } 113 + 114 + if len(t.AddedAt) > 8192 { 115 + return xerrors.Errorf("Value in field t.AddedAt was too long") 116 + } 117 + 118 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.AddedAt))); err != nil { 119 + return err 120 + } 121 + if _, err := cw.WriteString(string(t.AddedAt)); err != nil { 122 + return err 123 + } 124 + 125 + // t.Permissions ([]string) (slice) 126 + if len("permissions") > 8192 { 127 + return xerrors.Errorf("Value in field \"permissions\" was too long") 128 + } 129 + 130 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("permissions"))); err != nil { 131 + return err 132 + } 133 + if _, err := cw.WriteString(string("permissions")); err != nil { 134 + return err 135 + } 136 + 137 + if len(t.Permissions) > 8192 { 138 + return xerrors.Errorf("Slice value in field t.Permissions was too long") 139 + } 140 + 141 + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Permissions))); err != nil { 142 + return err 143 + } 144 + for _, v := range t.Permissions { 145 + if len(v) > 8192 { 146 + return xerrors.Errorf("Value in field v was too long") 147 + } 148 + 149 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(v))); err != nil { 150 + return err 151 + } 152 + if _, err := cw.WriteString(string(v)); err != nil { 153 + return err 154 + } 155 + 156 + } 157 + return nil 158 + } 159 + 160 + func (t *CrewRecord) UnmarshalCBOR(r io.Reader) (err error) { 161 + *t = CrewRecord{} 162 + 163 + cr := cbg.NewCborReader(r) 164 + 165 + maj, extra, err := cr.ReadHeader() 166 + if err != nil { 167 + return err 168 + } 169 + defer func() { 170 + if err == io.EOF { 171 + err = io.ErrUnexpectedEOF 172 + } 173 + }() 174 + 175 + if maj != cbg.MajMap { 176 + return fmt.Errorf("cbor input should be of type map") 177 + } 178 + 179 + if extra > cbg.MaxLength { 180 + return fmt.Errorf("CrewRecord: map struct too large (%d)", extra) 181 + } 182 + 183 + n := extra 184 + 185 + nameBuf := make([]byte, 11) 186 + for i := uint64(0); i < n; i++ { 187 + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192) 188 + if err != nil { 189 + return err 190 + } 191 + 192 + if !ok { 193 + // Field doesn't exist on this type, so ignore it 194 + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { 195 + return err 196 + } 197 + continue 198 + } 199 + 200 + switch string(nameBuf[:nameLen]) { 201 + // t.Role (string) (string) 202 + case "role": 203 + 204 + { 205 + sval, err := cbg.ReadStringWithMax(cr, 8192) 206 + if err != nil { 207 + return err 208 + } 209 + 210 + t.Role = string(sval) 211 + } 212 + // t.Type (string) (string) 213 + case "$type": 214 + 215 + { 216 + sval, err := cbg.ReadStringWithMax(cr, 8192) 217 + if err != nil { 218 + return err 219 + } 220 + 221 + t.Type = string(sval) 222 + } 223 + // t.Member (string) (string) 224 + case "member": 225 + 226 + { 227 + sval, err := cbg.ReadStringWithMax(cr, 8192) 228 + if err != nil { 229 + return err 230 + } 231 + 232 + t.Member = string(sval) 233 + } 234 + // t.AddedAt (string) (string) 235 + case "addedAt": 236 + 237 + { 238 + sval, err := cbg.ReadStringWithMax(cr, 8192) 239 + if err != nil { 240 + return err 241 + } 242 + 243 + t.AddedAt = string(sval) 244 + } 245 + // t.Permissions ([]string) (slice) 246 + case "permissions": 247 + 248 + maj, extra, err = cr.ReadHeader() 249 + if err != nil { 250 + return err 251 + } 252 + 253 + if extra > 8192 { 254 + return fmt.Errorf("t.Permissions: array too large (%d)", extra) 255 + } 256 + 257 + if maj != cbg.MajArray { 258 + return fmt.Errorf("expected cbor array") 259 + } 260 + 261 + if extra > 0 { 262 + t.Permissions = make([]string, extra) 263 + } 264 + 265 + for i := 0; i < int(extra); i++ { 266 + { 267 + var maj byte 268 + var extra uint64 269 + var err error 270 + _ = maj 271 + _ = extra 272 + _ = err 273 + 274 + { 275 + sval, err := cbg.ReadStringWithMax(cr, 8192) 276 + if err != nil { 277 + return err 278 + } 279 + 280 + t.Permissions[i] = string(sval) 281 + } 282 + 283 + } 284 + } 285 + 286 + default: 287 + // Field doesn't exist on this type, so ignore it 288 + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { 289 + return err 290 + } 291 + } 292 + } 293 + 294 + return nil 295 + }
+2 -26
pkg/hold/pds/crew.go
··· 3 3 import ( 4 4 "context" 5 5 "fmt" 6 - "io" 7 6 "time" 8 7 9 8 "github.com/ipfs/go-cid" 10 9 ) 11 10 12 - // CrewRecord represents a crew member in the hold 13 - type CrewRecord struct { 14 - Member string `json:"member" cborgen:"member"` // DID of the crew member 15 - Role string `json:"role" cborgen:"role"` // "admin" or "member" 16 - Permissions []string `json:"permissions" cborgen:"permissions"` // e.g., ["blob:read", "blob:write"] 17 - AddedAt time.Time `json:"addedAt" cborgen:"addedAt"` 18 - } 19 - 20 - // MarshalCBOR implements cbg.CBORMarshaler 21 - func (c *CrewRecord) MarshalCBOR(w io.Writer) error { 22 - // TODO: Implement proper CBOR marshaling 23 - return fmt.Errorf("CBOR marshaling not yet implemented") 24 - } 25 - 26 - // UnmarshalCBOR implements cbg.CBORUnmarshaler 27 - func (c *CrewRecord) UnmarshalCBOR(r io.Reader) error { 28 - // TODO: Implement proper CBOR unmarshaling 29 - return fmt.Errorf("CBOR unmarshaling not yet implemented") 30 - } 31 - 32 - const ( 33 - CrewCollection = "io.atcr.hold.crew" 34 - ) 35 - 36 11 // AddCrewMember adds a new crew member to the hold and commits to carstore 37 12 func (p *HoldPDS) AddCrewMember(ctx context.Context, memberDID, role string, permissions []string) (cid.Cid, error) { 38 13 crewRecord := &CrewRecord{ 14 + Type: CrewCollection, 39 15 Member: memberDID, 40 16 Role: role, 41 17 Permissions: permissions, 42 - AddedAt: time.Now(), 18 + AddedAt: time.Now().Format(time.RFC3339), 43 19 } 44 20 45 21 // Create record in repo (using memberDID as rkey for easy lookup)
+7 -8
pkg/hold/pds/did.go
··· 9 9 10 10 // DIDDocument represents a did:web document 11 11 type DIDDocument struct { 12 - Context []string `json:"@context"` 13 - ID string `json:"id"` 14 - AlsoKnownAs []string `json:"alsoKnownAs,omitempty"` 15 - VerificationMethod []VerificationMethod `json:"verificationMethod"` 16 - Authentication []string `json:"authentication,omitempty"` 17 - AssertionMethod []string `json:"assertionMethod,omitempty"` 18 - Service []Service `json:"service,omitempty"` 12 + Context []string `json:"@context"` 13 + ID string `json:"id"` 14 + AlsoKnownAs []string `json:"alsoKnownAs,omitempty"` 15 + VerificationMethod []VerificationMethod `json:"verificationMethod"` 16 + Authentication []string `json:"authentication,omitempty"` 17 + AssertionMethod []string `json:"assertionMethod,omitempty"` 18 + Service []Service `json:"service,omitempty"` 19 19 } 20 20 21 21 // VerificationMethod represents a public key in a DID document ··· 82 82 83 83 return doc, nil 84 84 } 85 - 86 85 87 86 // MarshalDIDDocument converts a DID document to JSON using the stored public URL 88 87 func (p *HoldPDS) MarshalDIDDocument() ([]byte, error) {
+9 -4
pkg/hold/pds/server.go
··· 101 101 // Bootstrap initializes the hold with the owner as the first crew member 102 102 func (p *HoldPDS) Bootstrap(ctx context.Context, ownerDID string) error { 103 103 if ownerDID == "" { 104 - // No owner specified, skip bootstrap 105 104 return nil 106 105 } 107 106 108 107 // Check if repo already has commits 109 - _, err := p.carstore.GetUserRepoHead(ctx, p.uid) 108 + head, err := p.carstore.GetUserRepoHead(ctx, p.uid) 110 109 if err == nil { 111 - // Repo already has commits, skip bootstrap 112 - return nil 110 + // Repo exists - check if we need to re-bootstrap due to key change 111 + // If the repo exists but is empty/invalid, we should re-bootstrap 112 + if head.String() == "" || head.String() == "b" { 113 + fmt.Printf("⚠️ Detected invalid repo state, re-bootstrapping...\n") 114 + } else { 115 + fmt.Printf("⏭️ Skipping PDS bootstrap: repo already initialized (head: %s)\n", head.String()[:16]) 116 + return nil 117 + } 113 118 } 114 119 115 120 // Add hold owner as first crew member with admin role
+16
pkg/hold/pds/types.go
··· 1 + package pds 2 + 3 + // ATProto record types for the hold service 4 + 5 + // CrewRecord represents a crew member in the hold 6 + type CrewRecord struct { 7 + Type string `cborgen:"$type"` 8 + Member string `cborgen:"member"` 9 + Role string `cborgen:"role"` 10 + Permissions []string `cborgen:"permissions"` 11 + AddedAt string `cborgen:"addedAt"` // RFC3339 timestamp 12 + } 13 + 14 + const ( 15 + CrewCollection = "io.atcr.hold.crew" 16 + )
+3 -3
pkg/hold/pds/xrpc.go
··· 11 11 12 12 // XRPCHandler handles XRPC requests for the embedded PDS 13 13 type XRPCHandler struct { 14 - pds *HoldPDS 15 - publicURL string 16 - blobStore BlobStore 14 + pds *HoldPDS 15 + publicURL string 16 + blobStore BlobStore 17 17 } 18 18 19 19 // BlobStore interface wraps the existing hold service storage operations