A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
81
fork

Configure Feed

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

fix validation on dids with hyphens

+55 -14
+1 -1
pkg/appview/middleware/registry.go
··· 302 302 // Support hyphen-encoded DIDs in image paths (e.g., did-plc-abc123/repo:tag) 303 303 // OCI reference grammar doesn't allow colons in path components, so DIDs must 304 304 // be encoded with hyphens instead: did:plc:abc123 → did-plc-abc123 305 - if decoded, ok := token.DecodeDIDFromHyphens(identityStr); ok { 305 + if decoded, ok := auth.DecodeDIDFromHyphens(identityStr); ok { 306 306 identityStr = decoded 307 307 } 308 308
+19
pkg/auth/scope.go
··· 56 56 return access, nil 57 57 } 58 58 59 + // DecodeDIDFromHyphens converts a hyphen-encoded DID back to colon-separated form. 60 + // "did-plc-abc123" → "did:plc:abc123", "did-web-example.com" → "did:web:example.com" 61 + // Returns the decoded DID and true if the input matched, or ("", false) otherwise. 62 + func DecodeDIDFromHyphens(s string) (string, bool) { 63 + if strings.HasPrefix(s, "did-plc-") { 64 + return "did:plc:" + strings.TrimPrefix(s, "did-plc-"), true 65 + } 66 + if strings.HasPrefix(s, "did-web-") { 67 + return "did:web:" + strings.TrimPrefix(s, "did-web-"), true 68 + } 69 + return "", false 70 + } 71 + 59 72 // ValidateAccess checks if the requested access is allowed for the user 60 73 // For ATCR, users can only push to repositories under their own handle/DID 61 74 func ValidateAccess(userDID, userHandle string, access []AccessEntry) error { ··· 78 91 } 79 92 80 93 repoOwner := parts[0] 94 + 95 + // Decode hyphen-encoded DIDs (e.g., did-plc-abc123 → did:plc:abc123) 96 + // Image paths use hyphens because colons are parsed as transport separators 97 + if decoded, ok := DecodeDIDFromHyphens(repoOwner); ok { 98 + repoOwner = decoded 99 + } 81 100 82 101 // Check if user is trying to access their own repository 83 102 // They can use either their handle or DID
+34
pkg/auth/scope_test.go
··· 413 413 } 414 414 } 415 415 416 + func TestValidateAccess_HyphenEncodedDID(t *testing.T) { 417 + userDID := "did:plc:pddp4xt5lgnv2qsegbzzs4xg" 418 + userHandle := "evan.atcr.io" 419 + 420 + // Hyphen-encoded DID should match (this is how DIDs appear in image paths) 421 + access := []AccessEntry{ 422 + { 423 + Type: "repository", 424 + Name: "did-plc-pddp4xt5lgnv2qsegbzzs4xg/charts/loom", 425 + Actions: []string{"pull", "push"}, 426 + }, 427 + } 428 + 429 + err := ValidateAccess(userDID, userHandle, access) 430 + if err != nil { 431 + t.Errorf("Expected no error for hyphen-encoded DID, got: %v", err) 432 + } 433 + 434 + // did:web hyphen-encoded 435 + webDID := "did:web:example.com" 436 + accessWeb := []AccessEntry{ 437 + { 438 + Type: "repository", 439 + Name: "did-web-example.com/myapp", 440 + Actions: []string{"push"}, 441 + }, 442 + } 443 + 444 + err = ValidateAccess(webDID, "example.com", accessWeb) 445 + if err != nil { 446 + t.Errorf("Expected no error for hyphen-encoded did:web, got: %v", err) 447 + } 448 + } 449 + 416 450 func TestValidateAccess_MixedActionsAndOwnership(t *testing.T) { 417 451 userDID := "did:plc:alice123" 418 452 userHandle := "alice.bsky.social"
+1 -13
pkg/auth/token/handler.go
··· 284 284 // into username="did", password="plc:abc123:<real-password>". Reconstructed here. 285 285 func parseBasicAuthDID(username, password string) (string, string) { 286 286 // Case 1: Hyphen-encoded DID (e.g., did-plc-abc123 or did-web-example.com) 287 - if did, ok := DecodeDIDFromHyphens(username); ok { 287 + if did, ok := auth.DecodeDIDFromHyphens(username); ok { 288 288 return did, password 289 289 } 290 290 ··· 309 309 return username, password 310 310 } 311 311 312 - // DecodeDIDFromHyphens converts a hyphen-encoded DID back to colon-separated form. 313 - // "did-plc-abc123" → "did:plc:abc123", "did-web-example.com" → "did:web:example.com" 314 - // Returns the decoded DID and true if the input matched, or ("", false) otherwise. 315 - func DecodeDIDFromHyphens(s string) (string, bool) { 316 - if strings.HasPrefix(s, "did-plc-") { 317 - return "did:plc:" + strings.TrimPrefix(s, "did-plc-"), true 318 - } 319 - if strings.HasPrefix(s, "did-web-") { 320 - return "did:web:" + strings.TrimPrefix(s, "did-web-"), true 321 - } 322 - return "", false 323 - }