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.

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>