feat: 更新CC码监管方案业务版文档,新增摘要、UGC专项、直播专项、存量处置、误判申诉、水印嵌入、CC码生命周期、组织保障等章节;同步macode到cccode重命名及其他代码变更
This commit is contained in:
@@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/tcs-iptv/tcs/internal/chain"
|
||||
"github.com/tcs-iptv/tcs/internal/macode"
|
||||
"github.com/tcs-iptv/tcs/internal/cccode"
|
||||
"github.com/tcs-iptv/tcs/internal/model"
|
||||
"github.com/tcs-iptv/tcs/internal/playback"
|
||||
"github.com/tcs-iptv/tcs/internal/provenance"
|
||||
@@ -30,7 +30,7 @@ var (
|
||||
type Submission struct {
|
||||
Title string
|
||||
EpisodeCount int
|
||||
Category string // 内容类目(macode.CategoryXxx),决定发码号段
|
||||
Category string // 内容类目(cccode.CategoryXxx),决定发码号段
|
||||
FileHash string
|
||||
MerkleRoot string
|
||||
Perceptual string
|
||||
@@ -50,13 +50,13 @@ type SubmissionResult struct {
|
||||
// Service 业务编排器。
|
||||
type Service struct {
|
||||
chain chain.Client
|
||||
gen *macode.Generator
|
||||
gen *cccode.Generator
|
||||
pb *playback.Store
|
||||
prov *provenance.Store
|
||||
phash map[string]phashEntry // maCode -> 感知哈希条目(确权侵权比对)
|
||||
auths map[string]model.Authorization // maCode -> 授权(F22)
|
||||
black map[string]bool // maCode -> 黑名单(跨省复用校验)
|
||||
filings map[string]model.FilingRecord // maCode -> 备案/网标关联(三期 A.1)
|
||||
phash map[string]phashEntry // ccCode -> 感知哈希条目(确权侵权比对)
|
||||
auths map[string]model.Authorization // ccCode -> 授权(F22)
|
||||
black map[string]bool // ccCode -> 黑名单(跨省复用校验)
|
||||
filings map[string]model.FilingRecord // ccCode -> 备案/网标关联(三期 A.1)
|
||||
rights map[string]*model.UserRights // userHash -> 跨屏权益账户(四期 D.1)
|
||||
mu sync.Mutex
|
||||
seqMu sync.Mutex
|
||||
@@ -69,7 +69,7 @@ type reviewItem struct {
|
||||
ContentTwinID string
|
||||
Sub Submission
|
||||
Status string
|
||||
MACode string
|
||||
CCCode string
|
||||
}
|
||||
|
||||
// phashEntry 感知哈希注册项,用于确权侵权比对。
|
||||
@@ -79,7 +79,7 @@ type phashEntry struct {
|
||||
}
|
||||
|
||||
// New 创建业务服务。
|
||||
func New(c chain.Client, gen *macode.Generator) *Service {
|
||||
func New(c chain.Client, gen *cccode.Generator) *Service {
|
||||
return &Service{
|
||||
chain: c, gen: gen,
|
||||
pb: playback.NewStore(),
|
||||
@@ -107,10 +107,10 @@ func (s *Service) SubmitForReview(sub Submission) (SubmissionResult, error) {
|
||||
return SubmissionResult{}, ErrIncompleteHashPkg
|
||||
}
|
||||
// 防换壳重发(需求2-AC3、需求15-AC5)
|
||||
if maCode, exists := s.chain.HashExists(sub.FileHash); exists {
|
||||
if ccCode, exists := s.chain.HashExists(sub.FileHash); exists {
|
||||
return SubmissionResult{
|
||||
Status: "rejected",
|
||||
Message: fmt.Sprintf("内容哈希已存在,关联原 MA 码: %s", maCode),
|
||||
Message: fmt.Sprintf("内容哈希已存在,关联原 MA 码: %s", ccCode),
|
||||
}, ErrDuplicateContent
|
||||
}
|
||||
|
||||
@@ -133,14 +133,14 @@ func (s *Service) SubmitForReview(sub Submission) (SubmissionResult, error) {
|
||||
|
||||
// IssueResult 签发结果。
|
||||
type IssueResult struct {
|
||||
MACode string `json:"ma_code"`
|
||||
CCCode string `json:"ma_code"`
|
||||
ContentTwinID string `json:"content_twin_id"`
|
||||
TxID string `json:"tx_id"`
|
||||
Certificate string `json:"certificate"` // MA码+哈希证书(MVP 简化为字符串)
|
||||
Certificate string `json:"certificate"` // CC码+哈希证书(MVP 简化为字符串)
|
||||
}
|
||||
|
||||
// ReviewCSPS CSPS 合规审核(发码前)。审核通过后方可发码,体现"审过才发证发码"。
|
||||
// 对应需求5(CSPS审核)+ 需求3-AC2(审核通过后生成MA码)。
|
||||
// 对应需求5(CSPS审核)+ 需求3-AC2(审核通过后生成CC码)。
|
||||
func (s *Service) ReviewCSPS(reviewID string, approved bool, reviewerID string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
@@ -158,7 +158,7 @@ func (s *Service) ReviewCSPS(reviewID string, approved bool, reviewerID string)
|
||||
|
||||
// ApproveAndIssue 在 CSPS 审核通过后**生成 MA 码**并强绑定哈希(需求3,模式B 自行发码)。
|
||||
// 前置:该送审必须已通过 CSPS 审核(审过才发码)。
|
||||
// MA 码由 macode.Generator 按内容类目从号段中原子分配。仅监管主体可调用。
|
||||
// MA 码由 cccode.Generator 按内容类目从号段中原子分配。仅监管主体可调用。
|
||||
func (s *Service) ApproveAndIssue(role chain.Role, reviewID, issuer string) (IssueResult, error) {
|
||||
s.mu.Lock()
|
||||
item, ok := s.reviews[reviewID]
|
||||
@@ -179,10 +179,10 @@ func (s *Service) ApproveAndIssue(role chain.Role, reviewID, issuer string) (Iss
|
||||
if err != nil {
|
||||
return IssueResult{}, fmt.Errorf("service: allocate MA code: %w", err)
|
||||
}
|
||||
maCode := issued.MACode
|
||||
ccCode := issued.CCCode
|
||||
|
||||
txID, err := s.chain.IssueMA(role, chain.IssueRequest{
|
||||
MACode: maCode,
|
||||
CCCode: ccCode,
|
||||
ContentTwinID: item.ContentTwinID,
|
||||
MerkleRoot: item.Sub.MerkleRoot,
|
||||
FileHash: item.Sub.FileHash,
|
||||
@@ -202,7 +202,7 @@ func (s *Service) ApproveAndIssue(role chain.Role, reviewID, issuer string) (Iss
|
||||
|
||||
s.mu.Lock()
|
||||
item.Status = model.StatusIssued // 已发码,移出"待发码"队列
|
||||
item.MACode = maCode
|
||||
item.CCCode = ccCode
|
||||
s.mu.Unlock()
|
||||
|
||||
// CP 注册本方映射
|
||||
@@ -214,18 +214,18 @@ func (s *Service) ApproveAndIssue(role chain.Role, reviewID, issuer string) (Iss
|
||||
})
|
||||
|
||||
// 记录全链路存证(送审→审核→发码)+ 注册感知哈希供确权比对
|
||||
s.prov.Record(model.ProvenanceEvent{MACode: maCode, Node: model.NodeSubmit, HashValue: item.Sub.FileHash, Operator: item.Sub.CPName, Detail: "CP 送审"})
|
||||
s.prov.Record(model.ProvenanceEvent{MACode: maCode, Node: model.NodeCSPSReview, Operator: "CSPS", Detail: "合规审核通过"})
|
||||
s.prov.Record(model.ProvenanceEvent{MACode: maCode, Node: model.NodeIssue, HashValue: item.Sub.FileHash, Operator: issuer, Detail: "发码签发,绑定基准哈希"})
|
||||
s.prov.Record(model.ProvenanceEvent{CCCode: ccCode, Node: model.NodeSubmit, HashValue: item.Sub.FileHash, Operator: item.Sub.CPName, Detail: "CP 送审"})
|
||||
s.prov.Record(model.ProvenanceEvent{CCCode: ccCode, Node: model.NodeCSPSReview, Operator: "CSPS", Detail: "合规审核通过"})
|
||||
s.prov.Record(model.ProvenanceEvent{CCCode: ccCode, Node: model.NodeIssue, HashValue: item.Sub.FileHash, Operator: issuer, Detail: "发码签发,绑定基准哈希"})
|
||||
if item.Sub.Perceptual != "" {
|
||||
s.mu.Lock()
|
||||
s.phash[maCode] = phashEntry{Title: item.Sub.Title, Perceptual: item.Sub.Perceptual}
|
||||
s.phash[ccCode] = phashEntry{Title: item.Sub.Title, Perceptual: item.Sub.Perceptual}
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
cert := fmt.Sprintf("CERT|%s|%s|%s", maCode, item.Sub.FileHash, item.Sub.MerkleRoot)
|
||||
cert := fmt.Sprintf("CERT|%s|%s|%s", ccCode, item.Sub.FileHash, item.Sub.MerkleRoot)
|
||||
return IssueResult{
|
||||
MACode: maCode,
|
||||
CCCode: ccCode,
|
||||
ContentTwinID: item.ContentTwinID,
|
||||
TxID: txID,
|
||||
Certificate: cert,
|
||||
@@ -233,8 +233,8 @@ func (s *Service) ApproveAndIssue(role chain.Role, reviewID, issuer string) (Iss
|
||||
}
|
||||
|
||||
// Verify 送审文件验真 / CDN 注入校验通用入口(需求4、需求7)。
|
||||
func (s *Service) Verify(maCode, fileHash string) (chain.VerifyResult, error) {
|
||||
res, err := s.chain.VerifyHash(maCode, fileHash)
|
||||
func (s *Service) Verify(ccCode, fileHash string) (chain.VerifyResult, error) {
|
||||
res, err := s.chain.VerifyHash(ccCode, fileHash)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -245,13 +245,13 @@ func (s *Service) Verify(maCode, fileHash string) (chain.VerifyResult, error) {
|
||||
}
|
||||
|
||||
// QueryMappings 查询 MA 码绑定的三方映射与 CDN 端点(需求11/17)。
|
||||
func (s *Service) QueryMappings(maCode string) (chain.MappingsResult, error) {
|
||||
return s.chain.QueryMappings(maCode)
|
||||
func (s *Service) QueryMappings(ccCode string) (chain.MappingsResult, error) {
|
||||
return s.chain.QueryMappings(ccCode)
|
||||
}
|
||||
|
||||
// VerifyEpisode 按集级子标识(MA码#E07)或 MA码+集号 验真单集。
|
||||
func (s *Service) VerifyEpisode(maCode string, episode int, fileHash string) (chain.VerifyResult, error) {
|
||||
res, err := s.chain.VerifyEpisodeHash(maCode, episode, fileHash)
|
||||
// VerifyEpisode 按集级子标识(CC码#E07)或 CC码+集号 验真单集。
|
||||
func (s *Service) VerifyEpisode(ccCode string, episode int, fileHash string) (chain.VerifyResult, error) {
|
||||
res, err := s.chain.VerifyEpisodeHash(ccCode, episode, fileHash)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -262,8 +262,8 @@ func (s *Service) VerifyEpisode(maCode string, episode int, fileHash string) (ch
|
||||
}
|
||||
|
||||
// ListEpisodes 列出某剧的全部集级哈希绑定。
|
||||
func (s *Service) ListEpisodes(maCode string) ([]model.HashBinding, error) {
|
||||
return s.chain.ListEpisodes(maCode)
|
||||
func (s *Service) ListEpisodes(ccCode string) ([]model.HashBinding, error) {
|
||||
return s.chain.ListEpisodes(ccCode)
|
||||
}
|
||||
|
||||
// ReviewSummary 送审待办摘要(发码前阶段)。
|
||||
@@ -275,7 +275,7 @@ type ReviewSummary struct {
|
||||
EpisodeCount int `json:"episode_count"`
|
||||
Status string `json:"status"`
|
||||
CPName string `json:"cp_name"`
|
||||
MACode string `json:"ma_code"`
|
||||
CCCode string `json:"ma_code"`
|
||||
}
|
||||
|
||||
// ListReviews 列出指定状态的送审待办(用于审核台/发码台队列)。
|
||||
@@ -292,7 +292,7 @@ func (s *Service) ListReviews(status string) []ReviewSummary {
|
||||
ReviewID: id, ContentTwinID: item.ContentTwinID,
|
||||
Title: item.Sub.Title, Category: item.Sub.Category,
|
||||
EpisodeCount: item.Sub.EpisodeCount, Status: item.Status,
|
||||
CPName: item.Sub.CPName, MACode: item.MACode,
|
||||
CPName: item.Sub.CPName, CCCode: item.CCCode,
|
||||
})
|
||||
}
|
||||
return out
|
||||
|
||||
Reference in New Issue
Block a user