-
Notifications
You must be signed in to change notification settings - Fork 0
Image catalog: discover CCV image tags from OCI registries + add CodeCollection visibility #114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
bc2d684
3f02df7
ebfdba0
e132d97
01bc8d4
3e9a341
ff89b6d
2fd8dfe
fd4a8a5
eeb7089
c24a8da
57fa08d
cd5d9d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| """add image metadata to codecollection_versions and visibility to codecollections | ||
|
|
||
| Adds the columns needed to track versioned OCI image artifacts per ref so the | ||
| RunWhen platform (PAPI) can consume a built-image catalog directly from the | ||
| codecollection-registry instead of running its own corestate-operator. | ||
|
|
||
| Also adds a `visibility` column on `codecollections` so a CC can be tracked | ||
| for image consumption but kept out of the public registry website / MCP / | ||
| AI search (e.g. customer-private, internal, deprecated CCs). | ||
|
|
||
| Revision ID: 004 | ||
| Revises: 003 | ||
| Create Date: 2026-05-11 | ||
| """ | ||
| from alembic import op | ||
| import sqlalchemy as sa | ||
|
|
||
|
|
||
| # revision identifiers, used by Alembic. | ||
| revision = "004" | ||
| down_revision = "003" | ||
| branch_labels = None | ||
| depends_on = None | ||
|
|
||
|
|
||
| def upgrade() -> None: | ||
| # --- image metadata on codecollection_versions --- | ||
| op.execute( | ||
| """ | ||
| DO $$ | ||
| BEGIN | ||
| IF NOT EXISTS ( | ||
| SELECT 1 FROM information_schema.columns | ||
| WHERE table_name = 'codecollection_versions' | ||
| AND column_name = 'image_registry' | ||
| ) THEN | ||
| ALTER TABLE codecollection_versions | ||
| ADD COLUMN image_registry VARCHAR(500), | ||
| ADD COLUMN image_tag VARCHAR(200), | ||
| ADD COLUMN image_digest VARCHAR(80), | ||
| ADD COLUMN commit_hash VARCHAR(40), | ||
| ADD COLUMN rt_revision VARCHAR(40), | ||
| ADD COLUMN image_built_at TIMESTAMP; | ||
| END IF; | ||
| END $$; | ||
| """ | ||
| ) | ||
|
|
||
| # Index for PAPI's "latest ref for this CC" lookups. | ||
| op.execute( | ||
| """ | ||
| CREATE INDEX IF NOT EXISTS ix_ccv_collection_image_tag | ||
| ON codecollection_versions (codecollection_id, image_tag); | ||
| """ | ||
| ) | ||
|
|
||
| # --- visibility on codecollections --- | ||
| op.execute( | ||
| """ | ||
| DO $$ | ||
| BEGIN | ||
| IF NOT EXISTS ( | ||
| SELECT 1 FROM information_schema.columns | ||
| WHERE table_name = 'codecollections' | ||
| AND column_name = 'visibility' | ||
| ) THEN | ||
| ALTER TABLE codecollections | ||
| ADD COLUMN visibility VARCHAR(20) NOT NULL DEFAULT 'public'; | ||
| END IF; | ||
| END $$; | ||
| """ | ||
| ) | ||
| op.execute( | ||
| """ | ||
| CREATE INDEX IF NOT EXISTS ix_cc_visibility | ||
| ON codecollections (visibility); | ||
| """ | ||
| ) | ||
|
|
||
|
|
||
| def downgrade() -> None: | ||
| op.execute("DROP INDEX IF EXISTS ix_cc_visibility") | ||
| op.execute("ALTER TABLE codecollections DROP COLUMN IF EXISTS visibility") | ||
|
|
||
| op.execute("DROP INDEX IF EXISTS ix_ccv_collection_image_tag") | ||
| op.execute( | ||
| """ | ||
| ALTER TABLE codecollection_versions | ||
| DROP COLUMN IF EXISTS image_built_at, | ||
| DROP COLUMN IF EXISTS rt_revision, | ||
| DROP COLUMN IF EXISTS commit_hash, | ||
| DROP COLUMN IF EXISTS image_digest, | ||
| DROP COLUMN IF EXISTS image_tag, | ||
| DROP COLUMN IF EXISTS image_registry; | ||
| """ | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| """ | ||
| Visibility filter helpers. | ||
|
|
||
| A CodeCollection's `visibility` flag controls whether it appears on | ||
| public-audience surfaces: | ||
|
|
||
| - 'public' – default. Shown on the registry website, MCP, AI search, etc. | ||
| - 'hidden' – tracked for PAPI consumption but excluded from public lists. | ||
|
|
||
| This is a UX/discovery toggle, NOT a security boundary. Image-level | ||
| access control still lives in the OCI registry. | ||
|
|
||
| Centralizing the filter here keeps the rule consistent across endpoints — | ||
| if we ever add a third visibility tier (e.g. 'archived'), we change one | ||
| place rather than auditing every router. | ||
| """ | ||
| from __future__ import annotations | ||
|
|
||
| from sqlalchemy.orm import Query | ||
|
|
||
| from app.models import CodeCollection | ||
|
|
||
| PUBLIC_VISIBILITY = "public" | ||
| HIDDEN_VISIBILITY = "hidden" | ||
|
|
||
|
|
||
| def public_only(query: Query) -> Query: | ||
| """ | ||
| Apply `visibility = 'public'` to a SQLAlchemy query that selects from | ||
| or joins to `codecollections`. Use this on every public-audience | ||
| endpoint (anything PAPI / corestate would NOT call). | ||
| """ | ||
| return query.filter(CodeCollection.visibility == PUBLIC_VISIBILITY) | ||
|
|
||
|
|
||
| def is_public(cc: CodeCollection) -> bool: | ||
| """Predicate version for code paths that already have a loaded row.""" | ||
| return (cc.visibility or PUBLIC_VISIBILITY) == PUBLIC_VISIBILITY | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused exports in new visibility moduleLow Severity
Reviewed by Cursor Bugbot for commit 2fd8dfe. Configure here. |
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prod deploy scoped to nonprod infrastructure repository
Medium Severity
The
deploy-to-prodjob creates a GitHub App token scoped toinfra-flux-nonprod-sharedand dispatchesupdate-registry-prod-images.yamlagainst that same nonprod repo. If production infrastructure lives in a separateinfra-flux-prodrepo, this token won't have access. The old PAT likely had broader permissions, so switching to the narrowly-scoped App token may have inadvertently locked prod deploys to the nonprod repo.Reviewed by Cursor Bugbot for commit cd5d9d8. Configure here.