# secret_options.dspy — AgentIO「插入敏感信息」选择窗的数据源(2026-09-17) # # 前端:AgentInput 的 opts.secret_dataurl 指向此处(bricks 通用框架不硬编码宿主路径, # 由 pipeline-core 的 agent/index.ui 注入)。 # 返回:{"success":true, "secrets":[{name,label,secret_type,prefix_hint,length_hint, # use_count,remark,status}, ...]} # # 安全铁律(与 secret_vault.list_secrets 同源): # - **绝不返回 encrypted_value 或明文**。只给元数据:名称/类型/前缀4字符/长度/使用次数。 # 前缀4字符够人类辨认是哪个凭据,拼不出可用值(GitHub PAT 前缀是公开固定值,零熵)。 # - 身份取自登录态(get_user/get_userorgid),**不接受前端传 user_id/org_id**—— # 否则任意用户改参数即可枚举他人凭据名称(元数据本身也是信息)。 # - 未登录返回 success:false,不返回空列表(区分「没登录」与「没数据」,便于前端提示)。 import json uid = await get_user() if not uid: return json.dumps({"success": False, "error": "未登录"}, ensure_ascii=False) org_id = (await get_userorgid()) or '' show_all = str((params_kw or {}).get('all', '') or '').strip() in ('1', 'true', 'True') from sqlor.dbpools import DBPools from pipeline_service import secret_vault async with DBPools().sqlorContext('pipeline') as sor: rows = await secret_vault.list_secrets(sor, org_id=org_id, user_id=uid, only_active=not show_all) await sor.sqlExe("COMMIT", {}) # 双保险:即使上游误带出密文字段,这里再剔一次(返回体是安全边界) _safe = [] for r in rows: item = {k: v for k, v in r.items() if k not in ('encrypted_value', 'fingerprint')} _safe.append(item) return json.dumps({"success": True, "secrets": _safe}, ensure_ascii=False, default=str)