Initial curated Unraid-AppOps-Gateway source from 3bd6f6fee310125bfbb4d4650389a817f498724d
This commit is contained in:
commit
1dfbca08a1
528 files changed
+131054
No files matched your search
@@ -0,0 +1,139 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from sqlmodel import Session
|
||||
|
||||
from ..db.session import get_session
|
||||
from ..services.audit_logger import log_event
|
||||
from ..services.policy_engine import evaluate_policy
|
||||
from ..services.privatemuse_artifact_installer import (
|
||||
ArtifactInstallError,
|
||||
install,
|
||||
validate_request,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/api/privatemuse/artifacts")
|
||||
|
||||
|
||||
class ArtifactInstallRequest(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
artifact_type: str = Field(pattern="^(lora|checkpoint|unet|vae|clip|gguf)$")
|
||||
source_url: str = Field(min_length=9, max_length=2048)
|
||||
sha256: str = Field(pattern="^[0-9a-f]{64}$")
|
||||
filename: str = Field(min_length=13, max_length=192)
|
||||
source_id: str = Field(min_length=1, max_length=240)
|
||||
license: str = Field(min_length=1, max_length=240)
|
||||
reason: str = Field(min_length=1, max_length=1000)
|
||||
|
||||
|
||||
@router.post("/preflight")
|
||||
def preflight(
|
||||
payload: ArtifactInstallRequest,
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
action = "privatemuse.comfyui.install_artifact"
|
||||
target = "privatemuse/comfyui"
|
||||
decision = evaluate_policy(
|
||||
session,
|
||||
action=action,
|
||||
target=target,
|
||||
source="manual",
|
||||
)
|
||||
try:
|
||||
normalized = validate_request(payload.model_dump())
|
||||
except ArtifactInstallError as exc:
|
||||
raise HTTPException(422, str(exc)) from exc
|
||||
return {
|
||||
"ready": decision["decision"] != "blocked",
|
||||
"policy": decision,
|
||||
"artifact": {
|
||||
"artifact_type": normalized["artifact_type"],
|
||||
"filename": normalized["filename"],
|
||||
"sha256": normalized["sha256"],
|
||||
"source_id": normalized["source_id"],
|
||||
"source_host": normalized["source_url"].split("/")[2],
|
||||
"license": normalized["license"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@router.post("/install")
|
||||
def install_artifact(
|
||||
payload: ArtifactInstallRequest,
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
action = "privatemuse.comfyui.install_artifact"
|
||||
target = "privatemuse/comfyui"
|
||||
decision = evaluate_policy(
|
||||
session,
|
||||
action=action,
|
||||
target=target,
|
||||
source="manual",
|
||||
)
|
||||
if decision["decision"] != "allowed":
|
||||
raise HTTPException(
|
||||
409,
|
||||
"Artifact installation requires an explicitly allowed policy/approved execution context.",
|
||||
)
|
||||
model_root = Path(
|
||||
os.environ.get(
|
||||
"APPOPS_PRIVATEMUSE_COMFYUI_MODEL_ROOT",
|
||||
"/mnt/privatemuse-comfyui-models",
|
||||
)
|
||||
)
|
||||
receipt_root = Path(
|
||||
os.environ.get(
|
||||
"APPOPS_PRIVATEMUSE_ARTIFACT_RECEIPT_ROOT",
|
||||
"/data/privatemuse-artifact-receipts",
|
||||
)
|
||||
)
|
||||
try:
|
||||
result = install(
|
||||
payload.model_dump(),
|
||||
model_root=model_root,
|
||||
receipt_root=receipt_root,
|
||||
)
|
||||
except ArtifactInstallError as exc:
|
||||
log_event(
|
||||
session,
|
||||
source="action",
|
||||
identity="manual",
|
||||
action_id=action,
|
||||
target=target,
|
||||
risk="high",
|
||||
policy_decision="allowed",
|
||||
reason=payload.reason,
|
||||
result="failed",
|
||||
redacted_metadata={
|
||||
"filename": payload.filename,
|
||||
"sha256": payload.sha256,
|
||||
"source_id": payload.source_id,
|
||||
},
|
||||
)
|
||||
raise HTTPException(409, str(exc)) from exc
|
||||
audit = log_event(
|
||||
session,
|
||||
source="action",
|
||||
identity="manual",
|
||||
action_id=action,
|
||||
target=target,
|
||||
risk="high",
|
||||
policy_decision="allowed",
|
||||
reason=payload.reason,
|
||||
result="success",
|
||||
after_state={
|
||||
"status": result["status"],
|
||||
"sha256": result["sha256"],
|
||||
"bytes": result["bytes"],
|
||||
},
|
||||
redacted_metadata={
|
||||
"filename": payload.filename,
|
||||
"source_id": payload.source_id,
|
||||
"license": payload.license,
|
||||
},
|
||||
)
|
||||
return {**result, "auditId": audit.id}
|
||||
Reference in new issue
Block a user