Step 12 - completed
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""Plugin review workflow.
|
||||
"""Plugin review workflow backed by PostgreSQL.
|
||||
|
||||
Manages the approval queue for newly submitted plugins and enforces a
|
||||
security checklist before any plugin is made visible in the marketplace.
|
||||
@@ -11,10 +11,12 @@ Module-level singleton::
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import time
|
||||
from typing import Any, Literal
|
||||
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.marketplace.plugin_registry import registry
|
||||
from app.models import PluginReview as PluginReviewModel
|
||||
from app.schemas import PluginManifest
|
||||
|
||||
# ── Security policy ───────────────────────────────────────────────────
|
||||
@@ -72,20 +74,16 @@ def validate_manifest(manifest: PluginManifest) -> None:
|
||||
class ReviewQueue:
|
||||
"""Approval queue for pending plugin submissions.
|
||||
|
||||
Delegates status changes to the shared ``PluginRegistry`` singleton so
|
||||
there is a single source of truth for plugin state.
|
||||
Delegates status changes to the shared ``PluginRegistry`` singleton.
|
||||
Review records are persisted in the ``plugin_reviews`` table.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
# Completed reviews — Step 12 stores in plugin_reviews table
|
||||
self._reviews: list[dict[str, Any]] = []
|
||||
|
||||
async def get_pending(self) -> list[dict[str, Any]]:
|
||||
async def get_pending(self, db: AsyncSession) -> list[dict[str, Any]]:
|
||||
"""Return all plugins currently awaiting review.
|
||||
|
||||
Each item is ``{plugin_id, manifest, submitted_at}``.
|
||||
"""
|
||||
entries = registry._get_pending_entries()
|
||||
entries = await registry.get_pending_entries(db)
|
||||
return [
|
||||
{
|
||||
"plugin_id": e["manifest"].id,
|
||||
@@ -97,6 +95,7 @@ class ReviewQueue:
|
||||
|
||||
async def submit_review(
|
||||
self,
|
||||
db: AsyncSession,
|
||||
plugin_id: str,
|
||||
reviewer_id: str,
|
||||
decision: Literal["approved", "rejected"],
|
||||
@@ -108,19 +107,18 @@ class ReviewQueue:
|
||||
``KeyError`` if *plugin_id* is not found in the registry.
|
||||
"""
|
||||
if decision == "approved":
|
||||
await registry.approve_plugin(plugin_id)
|
||||
await registry.approve_plugin(db, plugin_id)
|
||||
else:
|
||||
await registry.reject_plugin(plugin_id, reason=notes)
|
||||
await registry.reject_plugin(db, plugin_id, reason=notes)
|
||||
|
||||
self._reviews.append(
|
||||
{
|
||||
"plugin_id": plugin_id,
|
||||
"reviewer_id": reviewer_id,
|
||||
"decision": decision,
|
||||
"notes": notes,
|
||||
"reviewed_at": int(time.time()),
|
||||
}
|
||||
review = PluginReviewModel(
|
||||
plugin_id=plugin_id,
|
||||
reviewer_id=reviewer_id,
|
||||
decision=decision,
|
||||
notes=notes,
|
||||
)
|
||||
db.add(review)
|
||||
await db.commit()
|
||||
|
||||
|
||||
# Module-level singleton
|
||||
|
||||
Reference in New Issue
Block a user