fix: allow first-party store service subdomains and registry images
Unit Tests / test (push) Successful in 11m25s

Two manifest validation bugs blocked all store service installs:

1. service_store_manager.RESERVED_SUBDOMAINS included 'mail', which
   prevented the email service from using its required subdomain.
   Removed mail/calendar/files/webmail — they belong to official PIC
   store services and must be claimable by them.

2. manifest_validator required @sha256 digest pins on ALL images,
   including first-party git.pic.ngo/roof/* images that the PIC team
   builds and controls. service_store_manager._validate_manifest already
   only warned for first-party images; the secondary validator was
   stricter than intended, causing a hard reject on :latest tags.
   Aligned to warn-not-reject for first-party; malformed digests (when
   provided) are still a hard error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-30 03:09:41 -04:00
parent c493630bb5
commit f7bb2cc962
4 changed files with 39 additions and 21 deletions
+6 -6
View File
@@ -156,17 +156,17 @@ class TestValidateManifestImage(unittest.TestCase):
self.assertTrue(ok)
self.assertEqual(errs, [])
def test_image_tag_only_rejected(self):
# Digest pinning is required; tag-only images are rejected.
def test_image_tag_only_first_party_allowed(self):
# First-party images without a digest pin are allowed (warning only).
m = _valid_manifest(image='git.pic.ngo/roof/something:1.2.3')
ok, errs = ServiceStoreManager._validate_manifest(m)
self.assertFalse(ok)
self.assertTrue(ok)
def test_image_git_pic_ngo_roof_no_tag_rejected(self):
# No tag and no digest — rejected because digest pin is required.
def test_image_git_pic_ngo_roof_no_tag_allowed(self):
# No tag and no digest — Docker defaults to :latest; allowed for first-party.
m = _valid_manifest(image='git.pic.ngo/roof/myservice')
ok, errs = ServiceStoreManager._validate_manifest(m)
self.assertFalse(ok)
self.assertTrue(ok)
def test_image_wrong_registry_rejected(self):
m = _valid_manifest(image='ghcr.io/roof/myapp:latest')