Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions cc-registry-v2/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ tasks:
desc: Start all services
cmds:
- echo "🚀 Starting all services..."
- docker-compose up -d --build
- source az.secret && docker-compose up -d --build

stop:
desc: Stop all services
Expand All @@ -27,7 +27,7 @@ tasks:
desc: Restart all services
cmds:
- echo "🔄 Restarting all services..."
- docker-compose restart
- source az.secret && docker-compose restart

# Monitoring commands
logs:
Expand Down Expand Up @@ -83,7 +83,7 @@ tasks:
desc: Start only backend services (db, redis, backend)
cmds:
- echo "🔧 Starting backend services..."
- docker-compose up -d database redis backend
- source az.secret && docker-compose up -d database redis backend

frontend:
desc: Start only frontend (requires backend)
Expand All @@ -95,14 +95,14 @@ tasks:
desc: Start worker services
cmds:
- echo "🔄 Starting worker services..."
- docker-compose up -d worker scheduler flower
- source az.secret && docker-compose up -d worker scheduler flower

# Development commands
dev:
desc: Start development environment (backend + frontend)
cmds:
- echo "💻 Starting development environment..."
- docker-compose up -d database redis backend frontend
- source az.secret && docker-compose up -d database redis backend frontend

dev:logs:
desc: Show logs for development services
Expand Down
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;
"""
)
8 changes: 8 additions & 0 deletions cc-registry-v2/backend/app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ class Settings(BaseSettings):
GITHUB_WEBHOOK_SECRET: str = "your_webhook_secret_here"
GITHUB_OWNER: str = "runwhen-contrib"
GITHUB_REPO: str = "codecollection-registry"

# GitHub App Authentication (preferred over GITHUB_TOKEN when configured)
GITHUB_APP_ID: Optional[str] = None
GITHUB_APP_PRIVATE_KEY: Optional[str] = None
GITHUB_APP_INSTALLATION_ID: Optional[int] = None

# Target repo for intake wizard issue creation
GITHUB_INTAKE_REPO: str = "runwhen-contrib/codecollection-registry"

# Security
SECRET_KEY: str = "your-secret-key-change-in-production"
Expand Down
38 changes: 38 additions & 0 deletions cc-registry-v2/backend/app/core/visibility.py
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
Loading