namespace Admin.NET.Plugin.AiDOP.Service.S8; /// S8 业务规则异常,由 Controller 捕获后返回 400。 public class S8BizException : Exception { public S8BizException(string message) : base(message) { } } /// /// S8-TENANT-FACTORY-P0-CLOSURE-1:目标资源在当前可信作用域内不存在(不存在,或属于其它租户 / 工厂)。 /// 由 Controller 捕获后统一返回 404——对越权 Id 与不存在 Id 给出同一响应, /// 不泄露「他租户存在该资源」。继承 , /// 使既有只捕获 S8BizException 的调用方仍能安全降级为 400,而不是 500。 /// public sealed class S8NotFoundException : S8BizException { public S8NotFoundException(string message = "记录不存在") : base(message) { } } /// /// S8-STEP6D-CFG-ALERT-LEGACY-WRITE-GUARD-CERT-1:该配置对象已转为历史兼容只读,写入口已退役。 /// 由 Controller 捕获后返回 410 Gone——语义是「该能力曾经存在、现已永久退役」, /// 区别于 400(入参不合法,改对了还能存)与 404(找不到,换个 Id 还能存)。 /// /// 继承 ,与 同理: /// 使既有只捕获 S8BizException 的调用方安全降级为 400,而不是 500。 /// ⚠️ Controller 的 catch 顺序必须把本类型排在 S8BizException 之前,否则会被基类先吞掉降级成 400。 /// /// 是**固定文案**,供 Controller 直接返回; /// 不要把 ex.Message 以外的内部信息(异常类型名 / 堆栈 / SQL)暴露给前端。 /// public sealed class S8WriteRetiredException : S8BizException { /// /// CFG_ALERT 的退役文案(默认值,保持既有调用方与测试引用不变): /// 说明只读原因 + 指出当前真正的运行时权威。 /// public const string UserMessage = "告警规则已转为历史兼容只读配置,当前运行时告警判定由监控规则管理。"; /// /// S8-STEP6E-CFG-WATCH-FIX-AND-SAFE-CERT-1:CFG_WATCH 通用整实体 PUT 的退役文案。 /// /// 与 CFG_ALERT 的语义不同——监控规则本身**仍是生产权威**,退役的只是那个会连带 /// 暴露 scheduler-owned 运行时列(lock_token / lock_until / paused_until / next_run_at / /// last_* / consecutive_failure_count)的整实体更新入口。正式配置修改仍走窄写入口。 /// 故文案必须引导用户去专用接口,而不能让人误以为「监控规则整体只读了」。 /// public const string WatchRuleUpdateMessage = "监控规则通用整实体更新接口已退役,请使用监控规则的专用配置接口。"; public S8WriteRetiredException() : base(UserMessage) { } /// 按写入口给出各自的固定文案;调用方只能传预定义常量,不得拼入内部实现细节。 public S8WriteRetiredException(string userMessage) : base(userMessage) { } }