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

Configure Feed

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

add attestation badge to tags

+18 -20
+3 -2
pkg/appview/db/models.go
··· 148 148 // TagWithPlatforms extends Tag with platform information 149 149 type TagWithPlatforms struct { 150 150 Tag 151 - Platforms []PlatformInfo 152 - IsMultiArch bool 151 + Platforms []PlatformInfo 152 + IsMultiArch bool 153 + HasAttestations bool // true if manifest list contains attestation references 153 154 } 154 155 155 156 // ManifestWithMetadata extends Manifest with tags and platform information
+12 -2
pkg/appview/db/queries.go
··· 596 596 // GetTagsWithPlatforms returns all tags for a repository with platform information 597 597 // Only multi-arch tags (manifest lists) have platform info in manifest_references 598 598 // Single-arch tags will have empty Platforms slice (platform is obvious for single-arch) 599 + // Attestation references (unknown/unknown platforms) are filtered out but tracked via HasAttestations 599 600 func GetTagsWithPlatforms(db *sql.DB, did, repository string) ([]TagWithPlatforms, error) { 600 601 rows, err := db.Query(` 601 602 SELECT ··· 609 610 COALESCE(mr.platform_os, '') as platform_os, 610 611 COALESCE(mr.platform_architecture, '') as platform_architecture, 611 612 COALESCE(mr.platform_variant, '') as platform_variant, 612 - COALESCE(mr.platform_os_version, '') as platform_os_version 613 + COALESCE(mr.platform_os_version, '') as platform_os_version, 614 + COALESCE(mr.is_attestation, 0) as is_attestation 613 615 FROM tags t 614 616 JOIN manifests m ON t.digest = m.digest AND t.did = m.did AND t.repository = m.repository 615 617 LEFT JOIN manifest_references mr ON m.id = mr.manifest_id ··· 629 631 for rows.Next() { 630 632 var t Tag 631 633 var mediaType, platformOS, platformArch, platformVariant, platformOSVersion string 634 + var isAttestation bool 632 635 633 636 if err := rows.Scan(&t.ID, &t.DID, &t.Repository, &t.Tag, &t.Digest, &t.CreatedAt, 634 - &mediaType, &platformOS, &platformArch, &platformVariant, &platformOSVersion); err != nil { 637 + &mediaType, &platformOS, &platformArch, &platformVariant, &platformOSVersion, &isAttestation); err != nil { 635 638 return nil, err 636 639 } 637 640 ··· 643 646 Platforms: []PlatformInfo{}, 644 647 } 645 648 tagOrder = append(tagOrder, tagKey) 649 + } 650 + 651 + // Track if manifest list has attestations 652 + if isAttestation { 653 + tagMap[tagKey].HasAttestations = true 654 + // Skip attestation references in platform display 655 + continue 646 656 } 647 657 648 658 // Add platform info if present (only for multi-arch manifest lists)
-7
pkg/appview/static/css/style.css
··· 1004 1004 margin: 1rem 0; 1005 1005 } 1006 1006 1007 - /* Load More Button */ 1008 - .load-more { 1009 - width: 100%; 1010 - margin-top: 1rem; 1011 - background: var(--secondary); 1012 - } 1013 - 1014 1007 /* Login Page */ 1015 1008 .login-page { 1016 1009 max-width: 450px;
+3
pkg/appview/templates/pages/repository.html
··· 130 130 {{ if .IsMultiArch }} 131 131 <span class="badge-multi">Multi-arch</span> 132 132 {{ end }} 133 + {{ if .HasAttestations }} 134 + <span class="badge-attestation"><i data-lucide="shield-check"></i> Attestations</span> 135 + {{ end }} 133 136 </div> 134 137 <div style="display: flex; gap: 1rem; align-items: center;"> 135 138 <time class="tag-timestamp" datetime="{{ .Tag.CreatedAt.Format "2006-01-02T15:04:05Z07:00" }}">
-9
pkg/appview/templates/partials/push-list.html
··· 44 44 </div> 45 45 {{ end }} 46 46 47 - {{ if .HasMore }} 48 - <button class="load-more" 49 - hx-get="/api/recent-pushes?offset={{ .NextOffset }}" 50 - hx-target="#push-list" 51 - hx-swap="beforeend"> 52 - Load More 53 - </button> 54 - {{ end }} 55 - 56 47 {{ if eq (len .Pushes) 0 }} 57 48 <div class="empty-state"> 58 49 <p>No pushes yet. Start using ATCR by pushing your first image!</p>