services: add clan consent/visibility and oneok adapter stack
This commit is contained in:
80
services/clan-visibility-guard/app.py
Normal file
80
services/clan-visibility-guard/app.py
Normal file
@@ -0,0 +1,80 @@
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
LEVELS = ["public", "interclan", "incircle", "soulsafe", "sacred"]
|
||||
LEVEL_RANK = {k: i for i, k in enumerate(LEVELS)}
|
||||
SENSITIVE_KEYWORDS = [
|
||||
"child", "children", "minor", "health", "trauma", "violence", "abuse",
|
||||
"ребен", "дитин", "здоров", "травм", "насил",
|
||||
]
|
||||
|
||||
app = FastAPI(title="CLAN Visibility Guard", version="1.0.0")
|
||||
|
||||
|
||||
class VisibilityCheck(BaseModel):
|
||||
current_level: str
|
||||
requested_level: str
|
||||
|
||||
|
||||
class ClassifyRequest(BaseModel):
|
||||
text: str
|
||||
|
||||
|
||||
class RedactRequest(BaseModel):
|
||||
text: str
|
||||
target_level: str
|
||||
|
||||
|
||||
def _norm(level: str) -> str:
|
||||
v = (level or "").strip().lower()
|
||||
if v not in LEVEL_RANK:
|
||||
raise HTTPException(status_code=400, detail=f"invalid_visibility_level:{level}")
|
||||
return v
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health() -> Dict[str, Any]:
|
||||
return {"status": "ok", "service": "clan-visibility-guard"}
|
||||
|
||||
|
||||
@app.post("/visibility/check_downgrade")
|
||||
def check_downgrade(body: VisibilityCheck) -> Dict[str, Any]:
|
||||
cur = _norm(body.current_level)
|
||||
req = _norm(body.requested_level)
|
||||
allowed = LEVEL_RANK[req] >= LEVEL_RANK[cur]
|
||||
return {
|
||||
"allowed": allowed,
|
||||
"reason": "ok" if allowed else "downgrade_requires_consent",
|
||||
"current_level": cur,
|
||||
"requested_level": req,
|
||||
}
|
||||
|
||||
|
||||
@app.post("/visibility/classify")
|
||||
def classify(body: ClassifyRequest) -> Dict[str, Any]:
|
||||
t = (body.text or "").lower()
|
||||
flags: List[str] = [k for k in SENSITIVE_KEYWORDS if k in t]
|
||||
recommended = "soulsafe" if flags else "incircle"
|
||||
if any(x in t for x in ["sacred", "сакрал", "духовн"]):
|
||||
recommended = "sacred"
|
||||
return {
|
||||
"recommended_level": recommended,
|
||||
"sensitivity_flags": flags,
|
||||
}
|
||||
|
||||
|
||||
@app.post("/visibility/redact_for_level")
|
||||
def redact_for_level(body: RedactRequest) -> Dict[str, Any]:
|
||||
target = _norm(body.target_level)
|
||||
txt = body.text or ""
|
||||
redacted = txt
|
||||
if target in {"public", "interclan", "incircle"}:
|
||||
for token in ["ребен", "дитин", "здоров", "травм", "насил", "health", "trauma", "violence", "abuse"]:
|
||||
redacted = redacted.replace(token, "[sensitive]")
|
||||
return {
|
||||
"target_level": target,
|
||||
"redacted_text": redacted,
|
||||
"changed": redacted != txt,
|
||||
}
|
||||
Reference in New Issue
Block a user