533db535f1
build / build (push) Successful in 1m12s
按已确认需求提供独立安全模型配置、真实探测、正式字典字段评估与原问题译中,持久批次支持只补空白、暂停恢复、有限重试、幂等和逐字段依据。覆盖固定规则、本地语言、组织关联与主表有效看板共用治理侧读模型,保留源生产和冻结历史。 验证:完整 make verify 退出0,702项Go与329项前端通过;默认118项外部/隔离集成明确跳过,另跑完整镜像及组织隔离PG竞态。12并发、输入漂移、过期租约、暂停/恢复及有限重试通过。用户授权的百炼 deepseek-v4.1-flash 完成真实后台与浏览器评估/翻译;552行、16列、11块看板及完整PNG、独立配置页测试/保存、重开恢复和零JS异常通过。仅非业务样本外发,自动处理关闭,原payload不变。 上线前治理库已做导出快照原生备份并真实恢复,60表行数与17个QA表内容哈希一致;不修改DobotAI生产或隧道。本提交时尚未部署,线上验收须独立完成。
66 lines
2.3 KiB
Go
66 lines
2.3 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"context"
|
|
"knowledge-governance/internal/dobotaiops"
|
|
"knowledge-governance/internal/qaopsquality"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
func masterNoStore(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if strings.HasPrefix(r.URL.Path, "/api/v1/qa-ops/master/") {
|
|
w.Header().Set("Cache-Control", "no-store")
|
|
w.Header().Set("Pragma", "no-cache")
|
|
}
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
// Master reads and reviews own their state; no source client is accepted as fallback.
|
|
type qaMasterStore interface {
|
|
ListMasterRecords(context.Context, dobotaiops.RecordQuery) (dobotaiops.RecordPage, error)
|
|
GetMasterRecord(context.Context, string, string) (dobotaiops.Record, error)
|
|
ReadMasterQualityScope(context.Context, dobotaiops.RecordQuery) (dobotaiops.QualityScope, error)
|
|
MasterQualityStore() *qaopsquality.Store
|
|
}
|
|
type qaMasterReader struct {
|
|
QAOpsReader
|
|
master qaMasterStore
|
|
}
|
|
|
|
func (s qaMasterReader) ListRecords(ctx context.Context, q dobotaiops.RecordQuery) (dobotaiops.RecordPage, error) {
|
|
return s.master.ListMasterRecords(ctx, q)
|
|
}
|
|
func (s qaMasterReader) GetRecord(ctx context.Context, tenant, id string) (dobotaiops.Record, error) {
|
|
return s.master.GetMasterRecord(ctx, tenant, id)
|
|
}
|
|
func (s qaMasterReader) ReadQualityScope(ctx context.Context, q dobotaiops.RecordQuery) (dobotaiops.QualityScope, error) {
|
|
return s.master.ReadMasterQualityScope(ctx, q)
|
|
}
|
|
func (s qaMasterReader) ReadStoredQuality(ctx context.Context, keys []dobotaiops.QualityKey) (map[string]qaopsquality.View, error) {
|
|
if reader, ok := s.master.(interface {
|
|
ReadMasterQualityViews(context.Context, []dobotaiops.QualityKey) (map[string]qaopsquality.View, error)
|
|
}); ok {
|
|
return reader.ReadMasterQualityViews(ctx, keys)
|
|
}
|
|
return s.master.MasterQualityStore().ReadViews(ctx, keys)
|
|
}
|
|
func withQAMaster(w http.ResponseWriter, r *http.Request, c Config, handler func(http.ResponseWriter, *http.Request, Config)) {
|
|
if !authorizeQAOps(w, r) {
|
|
return
|
|
}
|
|
master, ok := c.QAOps.(qaMasterStore)
|
|
if !ok {
|
|
qaOpsError(w, dobotaiops.ErrUnavailable)
|
|
return
|
|
}
|
|
c.QAOps = qaMasterReader{QAOpsReader: c.QAOps, master: master}
|
|
c.QAQuality = master.MasterQualityStore()
|
|
if master.MasterQualityStore() == nil {
|
|
c.QAQuality = nil
|
|
}
|
|
handler(w, r, c)
|
|
}
|