diff --git a/conformance/compexamples_test.go b/conformance/compexamples_test.go new file mode 100644 index 00000000..0c2e0c08 --- /dev/null +++ b/conformance/compexamples_test.go @@ -0,0 +1,368 @@ +package conformance + +import ( + "encoding/json" + "os" + "path/filepath" + "reflect" + "sort" + "strconv" + "strings" + "testing" + + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + + compv1 "github.com/RAMP-Protocol/protocol/gen/go/comp/v1" +) + +// compExamplesDir holds the canonical CoMP V1 worked examples vendored verbatim +// from the published standard (CoMP-1.0.md, "Implementation Guidance" section, +// finalized 2026-04-28). Each example in the spec wraps its payload in a single +// envelope key ("aisystem" or "package"); the vendored files contain the INNER +// object only, because that inner object is the actual CoMP root type the proto +// models (comp.v1.AISystem / comp.v1.Package). The envelope key is encoded in +// the filename suffix (.aisystem.json / .package.json) so the test can pick the +// correct generated root type per file. +const compExamplesDir = "testdata/comp_v1_examples" + +// TestCompV1ExamplesRoundTrip is an adversarial conformance gate for the +// re-baselined comp.proto. For every canonical CoMP V1 example it: +// +// 1. Unmarshals the spec payload into the generated comp.v1 root type using +// DEFAULT protojson options — i.e. DiscardUnknown is false, so unknown-field +// rejection is ON. Any field present in the standard's example but ABSENT +// from our proto surfaces here as an unmarshal error, proving a missing +// field rather than silently dropping it. +// 2. Re-marshals the message and compares it (JSON-normalized, semantically) +// against the original payload, catching any dropped or mutated value that a +// successful-but-lossy unmarshal could hide. +// +// A green run is executable proof that comp.proto can losslessly carry every +// documented CoMP V1 example. A red run names the exact example and field. +func TestCompV1ExamplesRoundTrip(t *testing.T) { + files := jsonFilesIn(t, compExamplesDir) + + // Sanity floor: the standard ships 8 examples, each with a request + // (AISystem) and a response (Package) payload — 16 vendored files. If the + // testdata set is ever truncated, fail loudly rather than pass vacuously. + if len(files) < 16 { + t.Fatalf("expected at least 16 vendored CoMP V1 example payloads, found %d in %s", len(files), compExamplesDir) + } + + for _, name := range files { + name := name + t.Run(name, func(t *testing.T) { + roundTripExample(t, compExamplesDir, name) + }) + } +} + +// jsonFilesIn returns the sorted *.json file names directly under dir. +func jsonFilesIn(t *testing.T, dir string) []string { + t.Helper() + entries, err := os.ReadDir(dir) + if err != nil { + t.Fatalf("reading %s: %v", dir, err) + } + var files []string + for _, e := range entries { + if e.IsDir() || !strings.HasSuffix(e.Name(), ".json") { + continue + } + files = append(files, e.Name()) + } + sort.Strings(files) + return files +} + +// roundTripExample runs the adversarial conformance round-trip for one example +// payload and returns its raw bytes. The two load-bearing properties: +// +// - Unmarshal uses DEFAULT protojson options — DiscardUnknown is false, so any +// field present in the payload but ABSENT from our proto is a hard error +// (a missing field surfaces here rather than being silently dropped). +// - Re-marshal uses enum-as-number (CoMP's integer List codes) with +// EmitDefaultValues so an explicitly-set zero is not elided, then +// assertJSONSemanticEqual proves every payload value survived the round-trip. +func roundTripExample(t *testing.T, dir, name string) []byte { + t.Helper() + raw, err := os.ReadFile(filepath.Join(dir, name)) + if err != nil { + t.Fatalf("reading %s: %v", name, err) + } + + msg := rootTypeFor(t, name) + + if err := protojson.Unmarshal(raw, msg); err != nil { + t.Fatalf("protojson.Unmarshal of %s into %T FAILED (a typed field in the payload is absent or mistyped in comp.proto): %v", + name, msg, err) + } + + out, err := protojson.MarshalOptions{ + UseEnumNumbers: true, + EmitDefaultValues: true, + }.Marshal(msg) + if err != nil { + t.Fatalf("protojson.Marshal of %T (%s): %v", msg, name, err) + } + + assertJSONSemanticEqual(t, name, raw, out) + return raw +} + +// syntheticExamplesDir holds RAMP-authored conformance fixtures that are NOT +// part of the verbatim IAB CoMP V1 worked-example set. The published examples +// leave the Scope commercial block (ause/pricetype/pricetier/unitprice/cur/ +// country/licensedur) and the per-asset language/update fields unpopulated, so +// those proto fields would round-trip green even if renamed, retyped, or +// renumbered. These fixtures exercise that surface so such drift fails the gate. +// They are kept in a separate directory (with their own README) so the verbatim +// IAB set stays a clean, blob-pinned mirror. See testdata/comp_v1_synthetic. +const syntheticExamplesDir = "testdata/comp_v1_synthetic" + +// requiredSyntheticCoverage declares, per synthetic fixture, the spec-value JSON +// paths the fixture MUST populate. It is an anti-vacuity floor: if a future edit +// drops one of these fields, the coverage the fixture exists to provide silently +// disappears — so presence is asserted explicitly rather than assumed. +var requiredSyntheticCoverage = map[string][]string{ + "commercial_terms.package.json": { + "packager", + "reporturl", + "scope.ause", + "scope.pricetype", + "scope.pricetier", + "scope.unitprice", + "scope.cur", + "scope.country", + "scope.licensedur", + "scope.text[0].update", + "scope.text[0].language", + }, + // Request side: the verbatim examples under-populate AISystemUse, so pin the + // fields that would otherwise round-trip green if renamed/retyped, plus the + // google.protobuf.Struct ext field (field 15, exercised by no other fixture). + "full_request.aisystem.json": { + "ua", + "id", + "aisysuse.lid", + "aisysuse.aiauth", + "aisysuse.uri", + "aisysuse.scope", + "aisysuse.function", + "aisysuse.subfn", + "aisysuse.resdis", + "aisysuse.ext", + "ext", + }, + // Response side, non-text media: Video/Image/Audio and Retrieval, plus ext + // at the package, scope, asset, and retrieval levels. + "media_assets.package.json": { + "scope.ctype", + "scope.ext", + "scope.video[0].dur", + "scope.video[0].clip", + "scope.video[0].transcript", + "scope.video[0].update", + "scope.video[0].language", + "scope.video[0].ext", + "scope.image[0].update", + "scope.image[0].language", + "scope.audio[0].dur", + "scope.audio[0].transcript", + "scope.audio[0].update", + "scope.audio[0].language", + "scope.audio[0].ext", + "retrieval.auth", + "retrieval.endpoint", + "retrieval.type", + "retrieval.ext", + "ext", + }, +} + +// TestCompV1SyntheticCoverageRoundTrip round-trips the RAMP-authored fixtures +// with the same adversarial properties as the verbatim set, then asserts each +// fixture still populates the proto fields it was authored to cover. +func TestCompV1SyntheticCoverageRoundTrip(t *testing.T) { + files := jsonFilesIn(t, syntheticExamplesDir) + if len(files) == 0 { + t.Fatalf("no RAMP-authored synthetic fixtures found in %s", syntheticExamplesDir) + } + + for _, name := range files { + name := name + t.Run(name, func(t *testing.T) { + raw := roundTripExample(t, syntheticExamplesDir, name) + + paths, ok := requiredSyntheticCoverage[name] + if !ok { + t.Fatalf("synthetic fixture %s has no entry in requiredSyntheticCoverage; "+ + "declare the proto fields it covers or remove the file", name) + } + + var tree any + if err := json.Unmarshal(raw, &tree); err != nil { + t.Fatalf("%s: not valid JSON: %v", name, err) + } + for _, p := range paths { + if _, ok := lookupJSONPath(tree, p); !ok { + t.Errorf("%s: required coverage path %q is absent — the proto field this "+ + "fixture exists to exercise is no longer present", name, p) + } + } + }) + } +} + +// rootTypeFor returns a fresh generated root message based on the filename +// envelope suffix. +func rootTypeFor(t *testing.T, name string) proto.Message { + t.Helper() + switch { + case strings.HasSuffix(name, ".aisystem.json"): + return &compv1.AISystem{} + case strings.HasSuffix(name, ".package.json"): + return &compv1.Package{} + default: + t.Fatalf("cannot determine root type for %q: name must end in .aisystem.json or .package.json", name) + return nil + } +} + +// assertJSONSemanticEqual compares the original spec payload to the re-marshaled +// proto output as normalized JSON values. It is order- and whitespace- +// insensitive but value-exact: a dropped field, a changed number, or a string +// mutation fails the comparison and reports the diverging key path. +func assertJSONSemanticEqual(t *testing.T, name string, original, roundtripped []byte) { + t.Helper() + + var want, got any + if err := json.Unmarshal(original, &want); err != nil { + t.Fatalf("%s: original payload is not valid JSON: %v", name, err) + } + if err := json.Unmarshal(roundtripped, &got); err != nil { + t.Fatalf("%s: round-tripped payload is not valid JSON: %v", name, err) + } + + // Directional, value-exact containment: every key/value present in the spec + // example MUST appear, byte-for-byte equal, in the proto round-trip output. + // The proto output is permitted to carry ADDITIONAL keys (proto3 emits all + // scalar defaults under EmitDefaultValues, and the spec examples omit + // default-valued optional fields); those extras are not a conformance fault. + // A MISSING spec key or a CHANGED value IS a fault and is reported with its + // path. This catches the "unmarshal succeeded but silently dropped/mutated a + // value" failure mode that a successful Unmarshal alone cannot. + if path, w, g, ok := firstMissingOrChanged("", want, got); ok { + t.Fatalf("%s: round-trip lost or changed a spec value at %q: spec has %#v, proto round-trip produced %#v", + name, path, w, g) + } +} + +// firstMissingOrChanged walks the spec tree (want) and asserts each value is +// present and equal in the proto round-trip tree (got). Extra keys in got are +// ignored. Returns the first diverging path. +func firstMissingOrChanged(path string, want, got any) (string, any, any, bool) { + switch w := want.(type) { + case map[string]any: + g, ok := got.(map[string]any) + if !ok { + return path, want, got, true + } + keys := make([]string, 0, len(w)) + for k := range w { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + gv, gok := g[k] + if !gok { + return joinPath(path, k), w[k], nil, true + } + if p, a, b, ok := firstMissingOrChanged(joinPath(path, k), w[k], gv); ok { + return p, a, b, true + } + } + return "", nil, nil, false + case []any: + g, ok := got.([]any) + if !ok || len(w) != len(g) { + return path, want, got, true + } + for i := range w { + if p, a, b, ok := firstMissingOrChanged(indexPath(path, i), w[i], g[i]); ok { + return p, a, b, true + } + } + return "", nil, nil, false + default: + if !numericEqual(want, got) && !reflect.DeepEqual(want, got) { + return path, want, got, true + } + return "", nil, nil, false + } +} + +// numericEqual compares two decoded-JSON scalars treating all JSON numbers as +// float64 (which is how encoding/json decodes them on both sides). +func numericEqual(a, b any) bool { + af, aok := a.(float64) + bf, bok := b.(float64) + if aok && bok { + return af == bf + } + return false +} + +func joinPath(base, key string) string { + if base == "" { + return key + } + return base + "." + key +} + +func indexPath(base string, i int) string { + return base + "[" + strconv.Itoa(i) + "]" +} + +// lookupJSONPath resolves a dotted path with optional single [i] array indices +// (e.g. "scope.text[0].language") against a decoded-JSON tree and reports +// whether a value exists there. Used by the synthetic-coverage anti-vacuity +// check; it does not assert on the value, only its presence. +func lookupJSONPath(tree any, path string) (any, bool) { + cur := tree + for _, seg := range strings.Split(path, ".") { + key := seg + idx := -1 + if lb := strings.IndexByte(seg, '['); lb >= 0 { + rb := strings.IndexByte(seg, ']') + if rb < lb+1 { + return nil, false + } + n, err := strconv.Atoi(seg[lb+1 : rb]) + if err != nil { + return nil, false + } + key = seg[:lb] + idx = n + } + + m, ok := cur.(map[string]any) + if !ok { + return nil, false + } + v, ok := m[key] + if !ok { + return nil, false + } + if idx >= 0 { + arr, ok := v.([]any) + if !ok || idx >= len(arr) { + return nil, false + } + v = arr[idx] + } + cur = v + } + return cur, true +} diff --git a/conformance/testdata/comp_v1_examples/README.md b/conformance/testdata/comp_v1_examples/README.md new file mode 100644 index 00000000..76df7e08 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/README.md @@ -0,0 +1,52 @@ +# CoMP V1 worked examples — vendored testdata + +These JSON files are the worked examples from the IAB Tech Lab **Content +Monetization Protocols (CoMP) V1** specification, vendored verbatim for the +`TestCompV1ExamplesRoundTrip` conformance gate (`../../compexamples_test.go`). + +## Source of truth (immutable pin) + +- Repository: `https://github.com/IABTechLab/CoMP` +- File: `CoMP-1.0.md` +- Branch: `main` +- Spec-file content (git blob SHA): `aa8c796be7a9bcfa1189a1cf6c1ec50aa67a0f5f` +- `main` commit at vendoring time: `880238e0100b3d0d67d5afd7357a18fc21a97be5` +- Raw URL (commit-pinned, reproducible): + `https://raw.githubusercontent.com/IABTechLab/CoMP/880238e0100b3d0d67d5afd7357a18fc21a97be5/CoMP-1.0.md` + +The pin is the **blob SHA** of the spec file, which is content-addressed and +therefore immutable regardless of future branch movement. To re-derive these +examples, fetch the URL above and confirm `git hash-object` of the result equals +`aa8c796be7a9bcfa1189a1cf6c1ec50aa67a0f5f`. + +## Provenance discrepancy — release tag does NOT carry the spec + +The CoMP repository carries a release tag `1.0-202604` +(commit `819a242bdad6e1644cfbdc0a8a49dfcfa201375c`). That tag was proposed as the +immutable provenance pin, but **it does not contain the CoMP V1 specification**: +the tree at `819a242` holds only a boilerplate `README.md`. `main` is 6 commits +*ahead* of the tag, and the entire specification — every object table, the +consolidated `Lists` section, and all 8 worked examples — was added to `main` in +those 6 commits, AFTER the tag was cut. The final content commit on `main` +("CoMP 1.0 Public Comment Changes") is what introduced `package.reporturl`, the +asset `cattax` / `cat` / `language` fields, and the integer-coded Lists — exactly +the surface the re-baselined `comp.proto` mirrors. + +Conclusion: the proto was (correctly) baselined against `main`, not against the +`1.0-202604` tag. The examples here are therefore pinned to the `main` blob SHA +above. If IAB later re-tags so that the release tag actually contains +`CoMP-1.0.md`, this pin should be revisited and the tag's content diffed against +blob `aa8c796be7a9bcfa1189a1cf6c1ec50aa67a0f5f`. + +## File layout + +The spec wraps each example payload in a single envelope key — `"aisystem"` for +requests, `"package"` for responses. The vendored files contain the **inner +object only**, because that inner object is the actual CoMP root type modeled by +the proto (`comp.v1.AISystem` / `comp.v1.Package`). The envelope is encoded in +the filename suffix so the test can select the correct generated root type: + +- `*.aisystem.json` → `comp.v1.AISystem` (the AI System request side) +- `*.package.json` → `comp.v1.Package` (the Content Owner / Marketplace response side) + +8 examples × {request, response} = 16 payloads. diff --git a/conformance/testdata/comp_v1_examples/ex1_unauthorized_request.aisystem.json b/conformance/testdata/comp_v1_examples/ex1_unauthorized_request.aisystem.json new file mode 100644 index 00000000..67b73be7 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex1_unauthorized_request.aisystem.json @@ -0,0 +1,16 @@ +{ + "name": "open-learner-ai.org", + "ua": "OpenLearnerBot/2.1", + "id": "TL-REG-445566", + "aisysuse": { + "lid": "PENDING_REVIEW", + "aiauth": 0, + "uri": [ + "https://primary-publisher.com" + ], + "scope": 0, + "function": [2], + "subfn": [0], + "resdis": 0 + } +} diff --git a/conformance/testdata/comp_v1_examples/ex1_unauthorized_response.package.json b/conformance/testdata/comp_v1_examples/ex1_unauthorized_response.package.json new file mode 100644 index 00000000..d37001cd --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex1_unauthorized_response.package.json @@ -0,0 +1,22 @@ +{ + "id": "PKG-REF-99-PENDING", + "title": "Full Corpus Access - Licensing Required", + "seller": "primary-publisher.com", + "licenseurl": "https://primary-publisher.com/licensing/ai-terms", + "reporturl": "https://primary-publisher.com/reporting/ai-usage", + "citation": 1, + "scope": { + "scope": 0, + "max": 1, + "ctype": [ + 4 + ] + }, + "retrieval": { + "auth": 0, + "endpoint": "https://api.primary-publisher.com/v1/unauthorized", + "type": [ + 2 + ] + } +} diff --git a/conformance/testdata/comp_v1_examples/ex2_authorized_request.aisystem.json b/conformance/testdata/comp_v1_examples/ex2_authorized_request.aisystem.json new file mode 100644 index 00000000..5bb75b2d --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex2_authorized_request.aisystem.json @@ -0,0 +1,16 @@ +{ + "name": "global-news-aggregator.com", + "ua": "GlobalNewsBot/5.0", + "id": "TL-REG-882211", + "aisysuse": { + "lid": "LIC-998-ALPHA-2026", + "aiauth": 1, + "uri": [ + "https://fin-times.com/markets/commodities" + ], + "scope": 1, + "function": [3], + "subfn": [1, 2], + "resdis": 1 + } +} diff --git a/conformance/testdata/comp_v1_examples/ex2_authorized_response.package.json b/conformance/testdata/comp_v1_examples/ex2_authorized_response.package.json new file mode 100644 index 00000000..18d798e0 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex2_authorized_response.package.json @@ -0,0 +1,41 @@ +{ + "id": "PKG-FIN-COMM-001", + "title": "Commodities Market Deep-Dive", + "seller": "fin-times.com", + "licenseurl": "https://fin-times.com/legal/terms/LIC-998", + "reporturl": "https://fin-times.com/reporting/ai-usage", + "citation": 1, + "scope": { + "scope": 1, + "max": 0, + "ctype": [ + 0 + ], + "text": [ + { + "title": "Gold Prices Surge Amid Volatility", + "cattax": 9, + "cat": [ + 272 + ], + "wordcount": [ + 1200 + ], + "pubdate": "2026-02-26T14:30:00Z", + "author": [ + "Alex Sterling" + ], + "sourcetype": 0, + "provenance": 1, + "provent": "c2pa.org" + } + ] + }, + "retrieval": { + "auth": 0, + "endpoint": "https://newsml.fin-times.com/v3/commodities", + "type": [ + 6 + ] + } +} diff --git a/conformance/testdata/comp_v1_examples/ex3_curated_request.aisystem.json b/conformance/testdata/comp_v1_examples/ex3_curated_request.aisystem.json new file mode 100644 index 00000000..60bdc86d --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex3_curated_request.aisystem.json @@ -0,0 +1,12 @@ +{ + "name": "vision-agent.ai", + "ua": "VisionAgentBot/1.2", + "aisysuse": { + "lid": "LIC-CURATED-777", + "aiauth": 2, + "scope": 5, + "function": [1], + "subfn": [4], + "resdis": 1 + } +} diff --git a/conformance/testdata/comp_v1_examples/ex3_curated_response.package.json b/conformance/testdata/comp_v1_examples/ex3_curated_response.package.json new file mode 100644 index 00000000..7417c83a --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex3_curated_response.package.json @@ -0,0 +1,60 @@ +{ + "id": "PKG-MEDIA-PREMIUM", + "title": "Verified Travel Selection 2026", + "seller": "premium-travel-pics.com", + "licenseurl": "https://premium-travel-pics.com/license", + "reporturl": "https://premium-travel-pics.com/reporting/ai-usage", + "citation": 1, + "scope": { + "scope": 5, + "ctype": [ + 1, + 2 + ], + "image": [ + { + "title": [ + "Grand Canyon Sunset" + ], + "cattax": 9, + "cat": [ + 653, 655, 660 + ], + "pubdate": "2026-01-10T18:00:00Z", + "published": 1, + "author": [ + "Jane Photographer" + ], + "sourcetype": 0, + "provenance": 1, + "provent": "c2pa.org" + } + ], + "video": [ + { + "title": [ + "Grand Canyon South Rim Walkthrough" + ], + "cattax": 9, + "cat": [ + 653, 655, 660 + ], + "dur": [ + 45 + ], + "clip": 1, + "transcript": 0, + "sourcetype": 0, + "provenance": 1, + "provent": "c2pa.org" + } + ] + }, + "retrieval": { + "auth": 1, + "endpoint": "https://media-api.premium-travel.com/v1/download", + "type": [ + 2 + ] + } +} diff --git a/conformance/testdata/comp_v1_examples/ex4_image_creation_request.aisystem.json b/conformance/testdata/comp_v1_examples/ex4_image_creation_request.aisystem.json new file mode 100644 index 00000000..3145db41 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex4_image_creation_request.aisystem.json @@ -0,0 +1,16 @@ +{ + "name": "creative-gen.ai", + "ua": "CreativeGenBot/2.0", + "id": "TL-REG-554433", + "aisysuse": { + "lid": "TOKEN-STYLE-99-ALPHA", + "aiauth": 2, + "uri": [ + "https://digital-archive-museum.org/collections/artist-style-ref" + ], + "scope": 4, + "function": [3], + "subfn": [5], + "resdis": 1 + } +} diff --git a/conformance/testdata/comp_v1_examples/ex4_image_creation_response.package.json b/conformance/testdata/comp_v1_examples/ex4_image_creation_response.package.json new file mode 100644 index 00000000..707bdee7 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex4_image_creation_response.package.json @@ -0,0 +1,57 @@ +{ + "id": "PKG-ARTIST-COLLECTION-02", + "title": "Impressionist Style Reference Set - Mixed Provenance", + "seller": "digital-archive-museum.org", + "licenseurl": "https://digital-archive-museum.org/licensing/style-transfer", + "reporturl": "https://digital-archive-museum.org/reporting/ai-usage", + "citation": 1, + "scope": { + "scope": 5, + "max": 1, + "ctype": [ + 2 + ], + "image": [ + { + "title": [ + "Starry Night Interpretation" + ], + "cattax": 9, + "cat": [ + 43 + ], + "pubdate": "2026-01-05T12:00:00Z", + "published": 1, + "author": [ + "Original Artist Name" + ], + "sourcetype": 0, + "provenance": 1, + "provent": "c2pa.org" + }, + { + "title": [ + "Abstract Study in Blue" + ], + "cattax": 9, + "cat": [ + 43 + ], + "pubdate": "2026-01-10T14:20:00Z", + "published": 1, + "author": [ + "Unknown Artist" + ], + "sourcetype": 0, + "provenance": 0 + } + ] + }, + "retrieval": { + "auth": 2, + "endpoint": "https://api.digital-archive-museum.org/v1/assets", + "type": [ + 2 + ] + } +} diff --git a/conformance/testdata/comp_v1_examples/ex5_podcast_full_request.aisystem.json b/conformance/testdata/comp_v1_examples/ex5_podcast_full_request.aisystem.json new file mode 100644 index 00000000..e2765b06 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex5_podcast_full_request.aisystem.json @@ -0,0 +1,16 @@ +{ + "name": "audio-intel.ai", + "ua": "AudioIntelBot/3.0", + "id": "TL-REG-223344", + "aisysuse": { + "lid": "LIC-POD-PRO-2026", + "aiauth": 2, + "uri": [ + "https://news-podcasts.com/daily-brief" + ], + "scope": 0, + "function": [2, 3], + "subfn": [0, 2], + "resdis": 0 + } +} diff --git a/conformance/testdata/comp_v1_examples/ex5_podcast_full_response.package.json b/conformance/testdata/comp_v1_examples/ex5_podcast_full_response.package.json new file mode 100644 index 00000000..a2c59eba --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex5_podcast_full_response.package.json @@ -0,0 +1,48 @@ +{ + "id": "PKG-DAILY-BRIEF-FULL", + "title": "Daily Brief Podcast Archive", + "seller": "news-podcasts.com", + "licenseurl": "https://news-podcasts.com/licensing", + "reporturl": "https://news-podcasts.com/reporting/ai-usage", + "citation": 1, + "scope": { + "scope": 0, + "max": 0, + "ctype": [ + 3 + ], + "audio": [ + { + "title": [ + "Global Markets Update - Feb 27" + ], + "cattax": 9, + "cat": [ + 392 + ], + "dur": [ + 1800 + ], + "wordcount": [ + 4500 + ], + "transcript": 1, + "pubdate": "2026-02-27T06:00:00Z", + "published": 1, + "author": [ + "Host Name", + "Guest Expert" + ], + "sourcetype": 0, + "provenance": 0 + } + ] + }, + "retrieval": { + "auth": 2, + "endpoint": "https://api.news-podcasts.com/v1/rss", + "type": [ + 1 + ] + } +} diff --git a/conformance/testdata/comp_v1_examples/ex6_podcast_daterange_request.aisystem.json b/conformance/testdata/comp_v1_examples/ex6_podcast_daterange_request.aisystem.json new file mode 100644 index 00000000..c01fe7af --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex6_podcast_daterange_request.aisystem.json @@ -0,0 +1,16 @@ +{ + "name": "current-events-agent.ai", + "ua": "CurrentEventsBot/1.5", + "id": "TL-REG-112233", + "aisysuse": { + "lid": "LIC-RAG-2026-X", + "aiauth": 2, + "uri": [ + "https://news-podcasts.com/daily-brief" + ], + "scope": 2, + "function": [3], + "subfn": [1], + "resdis": 1 + } +} diff --git a/conformance/testdata/comp_v1_examples/ex6_podcast_daterange_response.package.json b/conformance/testdata/comp_v1_examples/ex6_podcast_daterange_response.package.json new file mode 100644 index 00000000..171863c6 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex6_podcast_daterange_response.package.json @@ -0,0 +1,47 @@ +{ + "id": "PKG-POD-2026-Q1", + "title": "Daily Brief - 2026 Post-Jan Archive", + "seller": "news-podcasts.com", + "licenseurl": "https://news-podcasts.com/licensing/rag-terms", + "reporturl": "https://news-podcasts.com/reporting/ai-usage", + "citation": 1, + "scope": { + "scope": 2, + "max": 0, + "ctype": [ + 3 + ], + "audio": [ + { + "title": [ + "Economic Outlook: February 2026" + ], + "cattax": 9, + "cat": [ + 392 + ], + "dur": [ + 1500 + ], + "wordcount": [ + 3800 + ], + "transcript": 1, + "pubdate": "2026-02-15T08:00:00Z", + "published": 1, + "author": [ + "Casey Jordan" + ], + "sourcetype": 0, + "provenance": 0 + } + ] + }, + "retrieval": { + "auth": 2, + "endpoint": "https://api.news-podcasts.com/v1/feed", + "type": [ + 2 + ] + } +} diff --git a/conformance/testdata/comp_v1_examples/ex7_video_creation_request.aisystem.json b/conformance/testdata/comp_v1_examples/ex7_video_creation_request.aisystem.json new file mode 100644 index 00000000..48a3c406 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex7_video_creation_request.aisystem.json @@ -0,0 +1,16 @@ +{ + "name": "creative-gen.ai", + "ua": "CreativeGenBot/2.0", + "id": "TL-REG-554433", + "aisysuse": { + "lid": "LIC-TOPIC-SP-2026", + "aiauth": 2, + "uri": [ + "https://video-archive.com/steampunk-search" + ], + "scope": 4, + "function": [3], + "subfn": [1, 2], + "resdis": 1 + } +} diff --git a/conformance/testdata/comp_v1_examples/ex7_video_creation_response.package.json b/conformance/testdata/comp_v1_examples/ex7_video_creation_response.package.json new file mode 100644 index 00000000..49bf38fb --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex7_video_creation_response.package.json @@ -0,0 +1,65 @@ +{ + "id": "PKG-STEAMPUNK-001", + "title": "Steampunk Visual Archives", + "seller": "video-archive.com", + "licenseurl": "https://video-archive.com/legal/ai-terms", + "reporturl": "https://video-archive.com/reporting/ai-usage", + "citation": 1, + "scope": { + "scope": 4, + "max": 1, + "ctype": [ + 1 + ], + "video": [ + { + "title": [ + "History of Steampunk Aesthetics" + ], + "cattax": 9, + "cat": [ + 205 + ], + "dur": [ + 600 + ], + "clip": 0, + "transcript": 1, + "pubdate": "2026-01-20T10:00:00Z", + "author": [ + "Gearheart Media" + ], + "sourcetype": 0, + "provenance": 1, + "provent": "c2pa.org" + }, + { + "title": [ + "AI-Generated Steampunk Landscape" + ], + "cattax": 9, + "cat": [ + 205 + ], + "dur": [ + 60 + ], + "clip": 1, + "transcript": 0, + "pubdate": "2026-02-15T14:30:00Z", + "author": [ + "StyleBot-V1" + ], + "sourcetype": 1, + "provenance": 0 + } + ] + }, + "retrieval": { + "auth": 2, + "endpoint": "https://api.video-archive.com/v1/media", + "type": [ + 2 + ] + } +} diff --git a/conformance/testdata/comp_v1_examples/ex8_agent_actions_request.aisystem.json b/conformance/testdata/comp_v1_examples/ex8_agent_actions_request.aisystem.json new file mode 100644 index 00000000..dc6a86c1 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex8_agent_actions_request.aisystem.json @@ -0,0 +1,16 @@ +{ + "name": "concierge-bot.ai", + "ua": "ConciergeBot/1.0", + "id": "TL-REG-889900", + "aisysuse": { + "lid": "LIC-AGENT-ACT-2026", + "aiauth": 2, + "uri": [ + "https://bistro-reserve.com/api/availability" + ], + "scope": 5, + "function": [1], + "subfn": [3, 4], + "resdis": 1 + } +} diff --git a/conformance/testdata/comp_v1_examples/ex8_agent_actions_response.package.json b/conformance/testdata/comp_v1_examples/ex8_agent_actions_response.package.json new file mode 100644 index 00000000..eb7219d4 --- /dev/null +++ b/conformance/testdata/comp_v1_examples/ex8_agent_actions_response.package.json @@ -0,0 +1,34 @@ +{ + "id": "PKG-RESERVE-TOOL-01", + "title": "BistroReserve Agent Interface", + "seller": "bistro-reserve.com", + "licenseurl": "https://bistro-reserve.com/legal/agent-terms", + "reporturl": "https://bistro-reserve.com/reporting/ai-usage", + "citation": 0, + "scope": { + "scope": 5, + "max": 1, + "ctype": [ + 0 + ], + "text": [ + { + "title": "Real-time Table Availability", + "cattax": 9, + "cat": [ + 653 + ], + "published": 1, + "sourcetype": 0, + "provenance": 0 + } + ] + }, + "retrieval": { + "auth": 2, + "endpoint": "https://mcp.bistro-reserve.com/v1/connect", + "type": [ + 3 + ] + } +} diff --git a/conformance/testdata/comp_v1_synthetic/README.md b/conformance/testdata/comp_v1_synthetic/README.md new file mode 100644 index 00000000..eefb3b9c --- /dev/null +++ b/conformance/testdata/comp_v1_synthetic/README.md @@ -0,0 +1,48 @@ +# RAMP-authored CoMP V1 conformance fixtures — NOT verbatim spec examples + +These JSON files are **RAMP-authored**, not vendored from the IAB Tech Lab +specification. They exist solely to give `TestCompV1SyntheticCoverageRoundTrip` +(`../../compexamples_test.go`) coverage of proto fields the published worked +examples (in `../comp_v1_examples/`) leave unpopulated. + +Keep them strictly separate from `../comp_v1_examples/`: that directory is a +clean, blob-pinned 1:1 mirror of the spec's 8 worked examples and must stay +verbatim. Mixing synthetic payloads into it would break its provenance pin. + +## Why these exist + +Canonical CoMP V1 folds all commercial/licensing terms onto `Scope` +(`ause`, `pricetype`, `pricetier`, `unitprice`, `cur`, `country`, `licensedur`) +and adds per-asset `language` / `update`. None of the 16 verbatim spec examples +populate those fields, so the round-trip gate would stay green even if one of +them were renamed, retyped, or renumbered in `comp.proto`. These fixtures +exercise that surface so such drift fails the gate. + +The test holds each fixture to the **same adversarial round-trip** as the +verbatim set (unknown-field rejection on; value-exact containment) **and** an +anti-vacuity floor: `requiredSyntheticCoverage` in the test names the JSON paths +each fixture must populate, so the coverage cannot silently regress. + +## Fixtures + +- `commercial_terms.package.json` → `comp.v1.Package`. Exercises the full Scope + commercial block, `Package.packager`, `Package.reporturl`, and per-asset + `Text.update` / `Text.language`. +- `full_request.aisystem.json` → `comp.v1.AISystem`. Exercises the request side + the verbatim examples under-populate: `AISystemUse` `lid`/`aiauth`/`uri`/ + `scope`/`function`/`subfn`/`resdis`, plus the `ext` Struct at both levels. +- `media_assets.package.json` → `comp.v1.Package`. Exercises the non-text media + branches (`Video`/`Image`/`Audio`) and `Retrieval`, plus the `ext` Struct at + the package, scope, asset, and retrieval levels. + +Together these pin the proto fields the 16 blob-pinned IAB examples leave unset; +`requiredSyntheticCoverage` in the test is the authoritative list of what each +must populate. + +## Note on field values + +Values are illustrative and chosen only to round-trip losslessly through the +proto wire types — they do not assert membership in any external registry. In +particular `language` is typed `repeated int32` in `comp.proto` (a faithful +mirror of CoMP V1's integer-coded Lists), so the integers here demonstrate the +field carries and preserves values, not a specific ISO-639 mapping. diff --git a/conformance/testdata/comp_v1_synthetic/commercial_terms.package.json b/conformance/testdata/comp_v1_synthetic/commercial_terms.package.json new file mode 100644 index 00000000..71505adc --- /dev/null +++ b/conformance/testdata/comp_v1_synthetic/commercial_terms.package.json @@ -0,0 +1,59 @@ +{ + "id": "RAMP-SYNTH-COMMERCIAL-01", + "title": "RAMP synthetic fixture — Scope commercial terms coverage", + "seller": "publisher.example", + "packager": "marketplace.example", + "licenseurl": "https://publisher.example/licenses/commercial", + "citation": 1, + "reporturl": "https://publisher.example/usage", + "scope": { + "scope": 1, + "ause": 0, + "pricetype": 4, + "pricetier": 2, + "unitprice": 12.5, + "cur": "EUR", + "country": [ + 840, + 826, + 276 + ], + "licensedur": 365, + "max": 1, + "ctype": [ + 0 + ], + "text": [ + { + "title": "Quarterly Market Report", + "wordcount": [ + 5200 + ], + "pubdate": "2026-02-01T00:00:00Z", + "published": 1, + "update": "2026-03-15T09:30:00Z", + "author": [ + "Jane Analyst" + ], + "sourcetype": 0, + "provenance": 1, + "provent": "c2pa.org", + "cattax": 9, + "cat": [ + 432 + ], + "language": [ + 1, + 2 + ] + } + ] + }, + "retrieval": { + "auth": 1, + "endpoint": "https://api.publisher.example/v1/packages", + "type": [ + 2 + ] + } +} diff --git a/conformance/testdata/comp_v1_synthetic/full_request.aisystem.json b/conformance/testdata/comp_v1_synthetic/full_request.aisystem.json new file mode 100644 index 00000000..aa49464b --- /dev/null +++ b/conformance/testdata/comp_v1_synthetic/full_request.aisystem.json @@ -0,0 +1,29 @@ +{ + "name": "agent.example", + "ua": "ExampleBot/1.0", + "id": "agent-registry-id-123", + "aisysuse": { + "lid": "lid-abc", + "aiauth": 2, + "uri": [ + "https://publisher.example/article/1", + "https://publisher.example/article/2" + ], + "scope": 4, + "function": [ + 3, + 4 + ], + "subfn": [ + 1, + 2 + ], + "resdis": 1, + "ext": { + "vendor.purpose": "grounding" + } + }, + "ext": { + "vendor.trace": "t-1" + } +} diff --git a/conformance/testdata/comp_v1_synthetic/media_assets.package.json b/conformance/testdata/comp_v1_synthetic/media_assets.package.json new file mode 100644 index 00000000..0669e07e --- /dev/null +++ b/conformance/testdata/comp_v1_synthetic/media_assets.package.json @@ -0,0 +1,120 @@ +{ + "id": "RAMP-SYNTH-MEDIA-01", + "title": "RAMP synthetic fixture — media assets, retrieval, and ext coverage", + "seller": "publisher.example", + "scope": { + "scope": 0, + "ctype": [ + 1, + 2, + 3 + ], + "video": [ + { + "title": [ + "Documentary Clip" + ], + "dur": [ + 120 + ], + "clip": 1, + "wordcount": [ + 340 + ], + "transcript": 1, + "pubdate": "2026-01-02T00:00:00Z", + "published": 0, + "update": "2026-02-02T00:00:00Z", + "author": [ + "Studio Example" + ], + "sourcetype": 2, + "provenance": 1, + "provent": "c2pa.org", + "cattax": 9, + "cat": [ + 386 + ], + "language": [ + 1 + ], + "ext": { + "vendor.shotlist": "v1" + } + } + ], + "image": [ + { + "title": [ + "Cover Image" + ], + "pubdate": "2026-01-03T00:00:00Z", + "published": 0, + "update": "2026-02-03T00:00:00Z", + "author": [ + "Photographer Example" + ], + "sourcetype": 0, + "provenance": 0, + "cattax": 9, + "cat": [ + 43 + ], + "language": [ + 1 + ] + } + ], + "audio": [ + { + "title": [ + "Podcast Episode 12" + ], + "dur": [ + 1800 + ], + "wordcount": [ + 4200 + ], + "transcript": 1, + "pubdate": "2026-01-04T00:00:00Z", + "published": 0, + "update": "2026-02-04T00:00:00Z", + "author": [ + "Host Example" + ], + "sourcetype": 0, + "provenance": 0, + "cattax": 9, + "cat": [ + 261 + ], + "language": [ + 1, + 2 + ], + "ext": { + "vendor.show": "s12" + } + } + ], + "ext": { + "vendor.scopenote": "mixed-media" + } + }, + "retrieval": { + "auth": 3, + "endpoint": "https://api.publisher.example/v1/media", + "type": [ + 2, + 3, + 5 + ], + "ext": { + "vendor.region": "eu" + } + }, + "ext": { + "vendor.packagenote": "synthetic" + } +} diff --git a/gen/go/comp/v1/comp.pb.go b/gen/go/comp/v1/comp.pb.go index 0eb3d578..25b155b2 100644 --- a/gen/go/comp/v1/comp.pb.go +++ b/gen/go/comp/v1/comp.pb.go @@ -1,14 +1,18 @@ -// CoMP v1.0 — IAB Tech Lab Content Monetization Protocol +// CoMP V1 — IAB Tech Lab Content Monetization Protocols (finalized 2026-04-28). // -// 1:1 mapping from the official CoMP WG specification. -// Source: https://github.com/IABTechLab/CoMP/blob/dev/CoMP-1.0.md +// 1:1 mapping from the canonical CoMP V1 specification. +// Source (immutable pin): https://github.com/IABTechLab/CoMP/blob/880238e0100b3d0d67d5afd7357a18fc21a97be5/CoMP-1.0.md +// Spec-file content blob SHA (content-addressed): aa8c796be7a9bcfa1189a1cf6c1ec50aa67a0f5f +// NOTE: the 1.0-202604 release tag does NOT contain the spec; main carries it. // // Enum alignment: proto3 enum values map directly to CoMP integer values // (first real CoMP value = 0). No UNSPECIFIED sentinels — proto3 default // zero is a valid CoMP value, not a sentinel. // // This file preserves CoMP field names, enum values, and semantics exactly. -// RAMP extensions live in ramp/v1/ramp.proto, never here. +// Canonical V1 has no separate License object: all commercial/licensing terms +// live on Scope (ause, pricetype, pricetier, unitprice, cur, country, +// licensedur). RAMP extensions live in ramp/v1/ramp.proto, never here. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: @@ -158,7 +162,14 @@ func (ScopeType) EnumDescriptor() ([]byte, []int) { } // Function — What the AI system will use the content for. -// CoMP §aisystemuse.function +// CoMP §aisystemuse.function — Function Definitions: +// +// 0 all — All functions (no restriction on use). +// 1 ai-all — All AI functions (training, input, indexing). +// 2 ai-train — Use as AI/ML training data. +// 3 ai-input — Use as runtime input/grounding (e.g. RAG, agent view). +// 4 ai-index — Use to build a search/retrieval index. +// 5 search — Use for traditional search indexing. type Function int32 const ( @@ -218,7 +229,14 @@ func (Function) EnumDescriptor() ([]byte, []int) { } // SubFunction — Specific sub-function for content use. -// CoMP §aisystemuse.subfn +// CoMP §aisystemuse.subfn — SubFunction Definitions: +// +// 0 training — Model training. +// 1 rag — Retrieval-augmented generation. +// 2 grounding — Grounding/citation at inference time. +// 3 agent-view — Agent reads content on a user's behalf. +// 4 agent-actions — Agent acts on content on a user's behalf. +// 5 other — Any other sub-function. type SubFunction int32 const ( @@ -277,69 +295,129 @@ func (SubFunction) EnumDescriptor() ([]byte, []int) { return file_comp_v1_comp_proto_rawDescGZIP(), []int{3} } -// LicenseUse — Permitted use categories under a license. -// CoMP §license.use -type LicenseUse int32 +// AllowedUse — Kind of use allowed for a package. +// CoMP §scope.ause — List: Allowed Use +type AllowedUse int32 const ( - LicenseUse_LICENSE_USE_TRAINING_DISPLAY LicenseUse = 0 - LicenseUse_LICENSE_USE_RAG_DISPLAY_UNRESTRICTED LicenseUse = 1 - LicenseUse_LICENSE_USE_RAG_DISPLAY_MAX_WORDS LicenseUse = 2 - LicenseUse_LICENSE_USE_RAG_DISPLAY_ATTRIBUTION LicenseUse = 3 - LicenseUse_LICENSE_USE_RAG_NO_DISPLAY LicenseUse = 4 - LicenseUse_LICENSE_USE_AGENT_VIEW LicenseUse = 5 - LicenseUse_LICENSE_USE_AGENT_ACTIONS LicenseUse = 6 + AllowedUse_ALLOWED_USE_COMMERCIAL AllowedUse = 0 // CoMP 0 + AllowedUse_ALLOWED_USE_NON_COMMERCIAL AllowedUse = 1 // CoMP 1 + AllowedUse_ALLOWED_USE_EDUCATIONAL AllowedUse = 2 // CoMP 2 + AllowedUse_ALLOWED_USE_GOVERNMENT AllowedUse = 3 // CoMP 3 + AllowedUse_ALLOWED_USE_PERSONAL AllowedUse = 4 // CoMP 4 + AllowedUse_ALLOWED_USE_BYO_LICENSE AllowedUse = 5 // CoMP 5 (refer to terms in licenseurl) + AllowedUse_ALLOWED_USE_OTHER AllowedUse = 6 // CoMP 6 ) -// Enum value maps for LicenseUse. +// Enum value maps for AllowedUse. var ( - LicenseUse_name = map[int32]string{ - 0: "LICENSE_USE_TRAINING_DISPLAY", - 1: "LICENSE_USE_RAG_DISPLAY_UNRESTRICTED", - 2: "LICENSE_USE_RAG_DISPLAY_MAX_WORDS", - 3: "LICENSE_USE_RAG_DISPLAY_ATTRIBUTION", - 4: "LICENSE_USE_RAG_NO_DISPLAY", - 5: "LICENSE_USE_AGENT_VIEW", - 6: "LICENSE_USE_AGENT_ACTIONS", - } - LicenseUse_value = map[string]int32{ - "LICENSE_USE_TRAINING_DISPLAY": 0, - "LICENSE_USE_RAG_DISPLAY_UNRESTRICTED": 1, - "LICENSE_USE_RAG_DISPLAY_MAX_WORDS": 2, - "LICENSE_USE_RAG_DISPLAY_ATTRIBUTION": 3, - "LICENSE_USE_RAG_NO_DISPLAY": 4, - "LICENSE_USE_AGENT_VIEW": 5, - "LICENSE_USE_AGENT_ACTIONS": 6, + AllowedUse_name = map[int32]string{ + 0: "ALLOWED_USE_COMMERCIAL", + 1: "ALLOWED_USE_NON_COMMERCIAL", + 2: "ALLOWED_USE_EDUCATIONAL", + 3: "ALLOWED_USE_GOVERNMENT", + 4: "ALLOWED_USE_PERSONAL", + 5: "ALLOWED_USE_BYO_LICENSE", + 6: "ALLOWED_USE_OTHER", + } + AllowedUse_value = map[string]int32{ + "ALLOWED_USE_COMMERCIAL": 0, + "ALLOWED_USE_NON_COMMERCIAL": 1, + "ALLOWED_USE_EDUCATIONAL": 2, + "ALLOWED_USE_GOVERNMENT": 3, + "ALLOWED_USE_PERSONAL": 4, + "ALLOWED_USE_BYO_LICENSE": 5, + "ALLOWED_USE_OTHER": 6, } ) -func (x LicenseUse) Enum() *LicenseUse { - p := new(LicenseUse) +func (x AllowedUse) Enum() *AllowedUse { + p := new(AllowedUse) *p = x return p } -func (x LicenseUse) String() string { +func (x AllowedUse) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } -func (LicenseUse) Descriptor() protoreflect.EnumDescriptor { +func (AllowedUse) Descriptor() protoreflect.EnumDescriptor { return file_comp_v1_comp_proto_enumTypes[4].Descriptor() } -func (LicenseUse) Type() protoreflect.EnumType { +func (AllowedUse) Type() protoreflect.EnumType { return &file_comp_v1_comp_proto_enumTypes[4] } -func (x LicenseUse) Number() protoreflect.EnumNumber { +func (x AllowedUse) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } -// Deprecated: Use LicenseUse.Descriptor instead. -func (LicenseUse) EnumDescriptor() ([]byte, []int) { +// Deprecated: Use AllowedUse.Descriptor instead. +func (AllowedUse) EnumDescriptor() ([]byte, []int) { return file_comp_v1_comp_proto_rawDescGZIP(), []int{4} } +// PriceType — How a package is priced. +// CoMP §scope.pricetype — List: Price Type +type PriceType int32 + +const ( + PriceType_PRICE_TYPE_PER_USE PriceType = 0 // CoMP 0 + PriceType_PRICE_TYPE_PER_QUERY PriceType = 1 // CoMP 1 + PriceType_PRICE_TYPE_PER_TOKEN PriceType = 2 // CoMP 2 + PriceType_PRICE_TYPE_FLAT PriceType = 3 // CoMP 3 + PriceType_PRICE_TYPE_TIERED PriceType = 4 // CoMP 4 (Tiered Rate) + PriceType_PRICE_TYPE_OTHER PriceType = 5 // CoMP 5 +) + +// Enum value maps for PriceType. +var ( + PriceType_name = map[int32]string{ + 0: "PRICE_TYPE_PER_USE", + 1: "PRICE_TYPE_PER_QUERY", + 2: "PRICE_TYPE_PER_TOKEN", + 3: "PRICE_TYPE_FLAT", + 4: "PRICE_TYPE_TIERED", + 5: "PRICE_TYPE_OTHER", + } + PriceType_value = map[string]int32{ + "PRICE_TYPE_PER_USE": 0, + "PRICE_TYPE_PER_QUERY": 1, + "PRICE_TYPE_PER_TOKEN": 2, + "PRICE_TYPE_FLAT": 3, + "PRICE_TYPE_TIERED": 4, + "PRICE_TYPE_OTHER": 5, + } +) + +func (x PriceType) Enum() *PriceType { + p := new(PriceType) + *p = x + return p +} + +func (x PriceType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PriceType) Descriptor() protoreflect.EnumDescriptor { + return file_comp_v1_comp_proto_enumTypes[5].Descriptor() +} + +func (PriceType) Type() protoreflect.EnumType { + return &file_comp_v1_comp_proto_enumTypes[5] +} + +func (x PriceType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PriceType.Descriptor instead. +func (PriceType) EnumDescriptor() ([]byte, []int) { + return file_comp_v1_comp_proto_rawDescGZIP(), []int{5} +} + // ContentType — Type of content in the package. // CoMP §scope.ctype type ContentType int32 @@ -384,11 +462,11 @@ func (x ContentType) String() string { } func (ContentType) Descriptor() protoreflect.EnumDescriptor { - return file_comp_v1_comp_proto_enumTypes[5].Descriptor() + return file_comp_v1_comp_proto_enumTypes[6].Descriptor() } func (ContentType) Type() protoreflect.EnumType { - return &file_comp_v1_comp_proto_enumTypes[5] + return &file_comp_v1_comp_proto_enumTypes[6] } func (x ContentType) Number() protoreflect.EnumNumber { @@ -397,18 +475,19 @@ func (x ContentType) Number() protoreflect.EnumNumber { // Deprecated: Use ContentType.Descriptor instead. func (ContentType) EnumDescriptor() ([]byte, []int) { - return file_comp_v1_comp_proto_rawDescGZIP(), []int{5} + return file_comp_v1_comp_proto_rawDescGZIP(), []int{6} } // RetrievalAuth — Authorization method for content access. -// CoMP §retrieval.auth +// CoMP §retrieval.auth — List: Authorization Type type RetrievalAuth int32 const ( RetrievalAuth_RETRIEVAL_AUTH_NONE RetrievalAuth = 0 // CoMP 0 - RetrievalAuth_RETRIEVAL_AUTH_API_KEY RetrievalAuth = 1 // CoMP 1 - RetrievalAuth_RETRIEVAL_AUTH_OAUTH2 RetrievalAuth = 2 // CoMP 2 - RetrievalAuth_RETRIEVAL_AUTH_SSL RetrievalAuth = 3 // CoMP 3 + RetrievalAuth_RETRIEVAL_AUTH_API_KEY RetrievalAuth = 1 // CoMP 1 (api_key) + RetrievalAuth_RETRIEVAL_AUTH_OAUTH2 RetrievalAuth = 2 // CoMP 2 (oauth2) + RetrievalAuth_RETRIEVAL_AUTH_SSL RetrievalAuth = 3 // CoMP 3 (SSL) + RetrievalAuth_RETRIEVAL_AUTH_OTHER RetrievalAuth = 4 // CoMP 4 (Other) ) // Enum value maps for RetrievalAuth. @@ -418,12 +497,14 @@ var ( 1: "RETRIEVAL_AUTH_API_KEY", 2: "RETRIEVAL_AUTH_OAUTH2", 3: "RETRIEVAL_AUTH_SSL", + 4: "RETRIEVAL_AUTH_OTHER", } RetrievalAuth_value = map[string]int32{ "RETRIEVAL_AUTH_NONE": 0, "RETRIEVAL_AUTH_API_KEY": 1, "RETRIEVAL_AUTH_OAUTH2": 2, "RETRIEVAL_AUTH_SSL": 3, + "RETRIEVAL_AUTH_OTHER": 4, } ) @@ -438,11 +519,11 @@ func (x RetrievalAuth) String() string { } func (RetrievalAuth) Descriptor() protoreflect.EnumDescriptor { - return file_comp_v1_comp_proto_enumTypes[6].Descriptor() + return file_comp_v1_comp_proto_enumTypes[7].Descriptor() } func (RetrievalAuth) Type() protoreflect.EnumType { - return &file_comp_v1_comp_proto_enumTypes[6] + return &file_comp_v1_comp_proto_enumTypes[7] } func (x RetrievalAuth) Number() protoreflect.EnumNumber { @@ -451,7 +532,7 @@ func (x RetrievalAuth) Number() protoreflect.EnumNumber { // Deprecated: Use RetrievalAuth.Descriptor instead. func (RetrievalAuth) EnumDescriptor() ([]byte, []int) { - return file_comp_v1_comp_proto_rawDescGZIP(), []int{6} + return file_comp_v1_comp_proto_rawDescGZIP(), []int{7} } // RetrievalType — Endpoint type for content retrieval. @@ -504,11 +585,11 @@ func (x RetrievalType) String() string { } func (RetrievalType) Descriptor() protoreflect.EnumDescriptor { - return file_comp_v1_comp_proto_enumTypes[7].Descriptor() + return file_comp_v1_comp_proto_enumTypes[8].Descriptor() } func (RetrievalType) Type() protoreflect.EnumType { - return &file_comp_v1_comp_proto_enumTypes[7] + return &file_comp_v1_comp_proto_enumTypes[8] } func (x RetrievalType) Number() protoreflect.EnumNumber { @@ -517,7 +598,7 @@ func (x RetrievalType) Number() protoreflect.EnumNumber { // Deprecated: Use RetrievalType.Descriptor instead. func (RetrievalType) EnumDescriptor() ([]byte, []int) { - return file_comp_v1_comp_proto_rawDescGZIP(), []int{7} + return file_comp_v1_comp_proto_rawDescGZIP(), []int{8} } // AISystem — Information about the AI System making the request. @@ -719,7 +800,7 @@ func (x *AISystemUse) GetExt() *structpb.Struct { // CoMP §package.json type Package struct { state protoimpl.MessageState `protogen:"open.v1"` - // Unique package identifier defined by the Content Owner or Exchange. + // Unique package identifier defined by the Content Owner or Marketplace. Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // Title of the package. Title *string `protobuf:"bytes,2,opt,name=title,proto3,oneof" json:"title,omitempty"` @@ -727,16 +808,20 @@ type Package struct { Seller *string `protobuf:"bytes,3,opt,name=seller,proto3,oneof" json:"seller,omitempty"` // Canonical domain of the packager, if different than the seller. Packager *string `protobuf:"bytes,4,opt,name=packager,proto3,oneof" json:"packager,omitempty"` - // URL for the license terms. + // URL for AI system to find the License(s) required to access content. + // SSRF/fetch sink: a consumer that dereferences this URL must apply the + // countermeasures specified for core License.uri (threat model T-LIC-1). Licenseurl *string `protobuf:"bytes,5,opt,name=licenseurl,proto3,oneof" json:"licenseurl,omitempty"` // Whether citation of the Content Owner is required. 0=no, 1=yes. Citation *int32 `protobuf:"varint,6,opt,name=citation,proto3,oneof" json:"citation,omitempty"` + // URL for AI system to send usage reporting to the Content Owner or + // Marketplace. POST/exfil sink: apply the SSRF countermeasures specified + // for core License.uri (threat model T-LIC-1) before dereferencing. + Reporturl *string `protobuf:"bytes,7,opt,name=reporturl,proto3,oneof" json:"reporturl,omitempty"` // Scope of content in this package. - Scope *Scope `protobuf:"bytes,7,opt,name=scope,proto3,oneof" json:"scope,omitempty"` + Scope *Scope `protobuf:"bytes,8,opt,name=scope,proto3,oneof" json:"scope,omitempty"` // How to retrieve the content. - Retrieval *Retrieval `protobuf:"bytes,8,opt,name=retrieval,proto3,oneof" json:"retrieval,omitempty"` - // Licensing terms for this package. - License []*License `protobuf:"bytes,9,rep,name=license,proto3" json:"license,omitempty"` + Retrieval *Retrieval `protobuf:"bytes,9,opt,name=retrieval,proto3,oneof" json:"retrieval,omitempty"` Ext *structpb.Struct `protobuf:"bytes,15,opt,name=ext,proto3" json:"ext,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -814,6 +899,13 @@ func (x *Package) GetCitation() int32 { return 0 } +func (x *Package) GetReporturl() string { + if x != nil && x.Reporturl != nil { + return *x.Reporturl + } + return "" +} + func (x *Package) GetScope() *Scope { if x != nil { return x.Scope @@ -828,13 +920,6 @@ func (x *Package) GetRetrieval() *Retrieval { return nil } -func (x *Package) GetLicense() []*License { - if x != nil { - return x.License - } - return nil -} - func (x *Package) GetExt() *structpb.Struct { if x != nil { return x.Ext @@ -842,39 +927,61 @@ func (x *Package) GetExt() *structpb.Struct { return nil } -// License — Licensing terms for a content package. -// CoMP §license.json -type License struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id *string `protobuf:"bytes,1,opt,name=id,proto3,oneof" json:"id,omitempty"` - Turl *string `protobuf:"bytes,2,opt,name=turl,proto3,oneof" json:"turl,omitempty"` - Use []LicenseUse `protobuf:"varint,3,rep,packed,name=use,proto3,enum=comp.v1.LicenseUse" json:"use,omitempty"` - Country []string `protobuf:"bytes,4,rep,name=country,proto3" json:"country,omitempty"` - Maxword *int32 `protobuf:"varint,5,opt,name=maxword,proto3,oneof" json:"maxword,omitempty"` - Citation *int32 `protobuf:"varint,6,opt,name=citation,proto3,oneof" json:"citation,omitempty"` // 0=required, 1=not required - Price *float64 `protobuf:"fixed64,7,opt,name=price,proto3,oneof" json:"price,omitempty"` - Revshare *float64 `protobuf:"fixed64,8,opt,name=revshare,proto3,oneof" json:"revshare,omitempty"` - Cur *string `protobuf:"bytes,9,opt,name=cur,proto3,oneof" json:"cur,omitempty"` - Dur *int32 `protobuf:"varint,10,opt,name=dur,proto3,oneof" json:"dur,omitempty"` - Ext *structpb.Struct `protobuf:"bytes,15,opt,name=ext,proto3" json:"ext,omitempty"` +// Scope — What content is included in the package, plus its commercial terms. +// CoMP §scope.json — canonical V1 folds licensing/pricing into Scope. +type Scope struct { + state protoimpl.MessageState `protogen:"open.v1"` + // How much of the Content Owner's corpus is available in this package. + Scope *ScopeType `protobuf:"varint,1,opt,name=scope,proto3,enum=comp.v1.ScopeType,oneof" json:"scope,omitempty"` + // Kind of use that is allowed for this package. + Ause *AllowedUse `protobuf:"varint,2,opt,name=ause,proto3,enum=comp.v1.AllowedUse,oneof" json:"ause,omitempty"` + // How the package is priced. + Pricetype *PriceType `protobuf:"varint,3,opt,name=pricetype,proto3,enum=comp.v1.PriceType,oneof" json:"pricetype,omitempty"` + // Tier identifier if pricing is tiered (pricetype = 4). + Pricetier *int32 `protobuf:"varint,4,opt,name=pricetier,proto3,oneof" json:"pricetier,omitempty"` + // Content Owner set unit price at the given basis. Typed `double` to mirror + // the CoMP spec; downstream billing must convert to a decimal / minor-units + // representation — do not settle money directly off this float. + Unitprice *float64 `protobuf:"fixed64,5,opt,name=unitprice,proto3,oneof" json:"unitprice,omitempty"` + // Bid currency using ISO-4217 alpha codes. Default "USD". + Cur *string `protobuf:"bytes,6,opt,name=cur,proto3,oneof" json:"cur,omitempty"` + // Country code(s) where this package may be used, expressed by + // ISO-3166-1 numeric codes. + Country []int32 `protobuf:"varint,7,rep,packed,name=country,proto3" json:"country,omitempty"` + // Number of days the license is active, once the content package has been + // delivered to the AI System. + Licensedur *int32 `protobuf:"varint,8,opt,name=licensedur,proto3,oneof" json:"licensedur,omitempty"` + // Upper limit on crawl. 0=unlimited, 1=has maximum. + Max *int32 `protobuf:"varint,9,opt,name=max,proto3,oneof" json:"max,omitempty"` + // Content type(s) included. + Ctype []ContentType `protobuf:"varint,10,rep,packed,name=ctype,proto3,enum=comp.v1.ContentType" json:"ctype,omitempty"` + // Text assets. + Text []*Text `protobuf:"bytes,11,rep,name=text,proto3" json:"text,omitempty"` + // Video assets. + Video []*Video `protobuf:"bytes,12,rep,name=video,proto3" json:"video,omitempty"` + // Image assets. + Image []*Image `protobuf:"bytes,13,rep,name=image,proto3" json:"image,omitempty"` + // Audio assets. + Audio []*Audio `protobuf:"bytes,14,rep,name=audio,proto3" json:"audio,omitempty"` + Ext *structpb.Struct `protobuf:"bytes,15,opt,name=ext,proto3" json:"ext,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *License) Reset() { - *x = License{} +func (x *Scope) Reset() { + *x = Scope{} mi := &file_comp_v1_comp_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *License) String() string { +func (x *Scope) String() string { return protoimpl.X.MessageStringOf(x) } -func (*License) ProtoMessage() {} +func (*Scope) ProtoMessage() {} -func (x *License) ProtoReflect() protoreflect.Message { +func (x *Scope) ProtoReflect() protoreflect.Message { mi := &file_comp_v1_comp_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -886,145 +993,65 @@ func (x *License) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use License.ProtoReflect.Descriptor instead. -func (*License) Descriptor() ([]byte, []int) { +// Deprecated: Use Scope.ProtoReflect.Descriptor instead. +func (*Scope) Descriptor() ([]byte, []int) { return file_comp_v1_comp_proto_rawDescGZIP(), []int{3} } -func (x *License) GetId() string { - if x != nil && x.Id != nil { - return *x.Id - } - return "" -} - -func (x *License) GetTurl() string { - if x != nil && x.Turl != nil { - return *x.Turl - } - return "" -} - -func (x *License) GetUse() []LicenseUse { - if x != nil { - return x.Use - } - return nil -} - -func (x *License) GetCountry() []string { - if x != nil { - return x.Country +func (x *Scope) GetScope() ScopeType { + if x != nil && x.Scope != nil { + return *x.Scope } - return nil + return ScopeType_SCOPE_TYPE_FULL_CORPUS } -func (x *License) GetMaxword() int32 { - if x != nil && x.Maxword != nil { - return *x.Maxword +func (x *Scope) GetAuse() AllowedUse { + if x != nil && x.Ause != nil { + return *x.Ause } - return 0 + return AllowedUse_ALLOWED_USE_COMMERCIAL } -func (x *License) GetCitation() int32 { - if x != nil && x.Citation != nil { - return *x.Citation +func (x *Scope) GetPricetype() PriceType { + if x != nil && x.Pricetype != nil { + return *x.Pricetype } - return 0 + return PriceType_PRICE_TYPE_PER_USE } -func (x *License) GetPrice() float64 { - if x != nil && x.Price != nil { - return *x.Price +func (x *Scope) GetPricetier() int32 { + if x != nil && x.Pricetier != nil { + return *x.Pricetier } return 0 } -func (x *License) GetRevshare() float64 { - if x != nil && x.Revshare != nil { - return *x.Revshare +func (x *Scope) GetUnitprice() float64 { + if x != nil && x.Unitprice != nil { + return *x.Unitprice } return 0 } -func (x *License) GetCur() string { +func (x *Scope) GetCur() string { if x != nil && x.Cur != nil { return *x.Cur } return "" } -func (x *License) GetDur() int32 { - if x != nil && x.Dur != nil { - return *x.Dur - } - return 0 -} - -func (x *License) GetExt() *structpb.Struct { +func (x *Scope) GetCountry() []int32 { if x != nil { - return x.Ext + return x.Country } return nil } -// Scope — What content is included in the package. -// CoMP §scope.json -type Scope struct { - state protoimpl.MessageState `protogen:"open.v1"` - Scope *ScopeType `protobuf:"varint,1,opt,name=scope,proto3,enum=comp.v1.ScopeType,oneof" json:"scope,omitempty"` - // Upper limit on crawl. 0=unlimited, 1=has maximum. - Max *int32 `protobuf:"varint,2,opt,name=max,proto3,oneof" json:"max,omitempty"` - // Content type(s) included. - Ctype []ContentType `protobuf:"varint,3,rep,packed,name=ctype,proto3,enum=comp.v1.ContentType" json:"ctype,omitempty"` - // Text assets. - Text []*Text `protobuf:"bytes,4,rep,name=text,proto3" json:"text,omitempty"` - // Video assets. - Video []*Video `protobuf:"bytes,5,rep,name=video,proto3" json:"video,omitempty"` - // Image assets. - Image []*Image `protobuf:"bytes,6,rep,name=image,proto3" json:"image,omitempty"` - // Audio assets. - Audio []*Audio `protobuf:"bytes,7,rep,name=audio,proto3" json:"audio,omitempty"` - Ext *structpb.Struct `protobuf:"bytes,15,opt,name=ext,proto3" json:"ext,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Scope) Reset() { - *x = Scope{} - mi := &file_comp_v1_comp_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Scope) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Scope) ProtoMessage() {} - -func (x *Scope) ProtoReflect() protoreflect.Message { - mi := &file_comp_v1_comp_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Scope.ProtoReflect.Descriptor instead. -func (*Scope) Descriptor() ([]byte, []int) { - return file_comp_v1_comp_proto_rawDescGZIP(), []int{4} -} - -func (x *Scope) GetScope() ScopeType { - if x != nil && x.Scope != nil { - return *x.Scope +func (x *Scope) GetLicensedur() int32 { + if x != nil && x.Licensedur != nil { + return *x.Licensedur } - return ScopeType_SCOPE_TYPE_FULL_CORPUS + return 0 } func (x *Scope) GetMax() int32 { @@ -1081,11 +1108,11 @@ func (x *Scope) GetExt() *structpb.Struct { type Text struct { state protoimpl.MessageState `protogen:"open.v1"` Title *string `protobuf:"bytes,1,opt,name=title,proto3,oneof" json:"title,omitempty"` - // Word count(s) of main body. + // Count of whitespace-delimited words in main body. Wordcount []int32 `protobuf:"varint,2,rep,packed,name=wordcount,proto3" json:"wordcount,omitempty"` // Original publication date (ISO 8601). Pubdate *string `protobuf:"bytes,3,opt,name=pubdate,proto3,oneof" json:"pubdate,omitempty"` - // Publication status. 0=not specified, 1=published, 2=unpublished/archival. + // Denotes if the content is publicly available. Default 1 for Text. Published *int32 `protobuf:"varint,4,opt,name=published,proto3,oneof" json:"published,omitempty"` // Most recent substantive update (ISO 8601). Update *string `protobuf:"bytes,5,opt,name=update,proto3,oneof" json:"update,omitempty"` @@ -1096,11 +1123,16 @@ type Text struct { // Provenance available. 0=no, 1=yes. Provenance *int32 `protobuf:"varint,8,opt,name=provenance,proto3,oneof" json:"provenance,omitempty"` // Canonical domain of the provenance entity (e.g. c2pa.org). + // Required if provenance = 1. Provent *string `protobuf:"bytes,9,opt,name=provent,proto3,oneof" json:"provent,omitempty"` - // Authority score (0.0–1.0). Publisher/verifier-assessed domain authority. - Authority *float64 `protobuf:"fixed64,10,opt,name=authority,proto3,oneof" json:"authority,omitempty"` - // Originality score (0.0–1.0). Degree of original vs. syndicated content. - Originality *float64 `protobuf:"fixed64,11,opt,name=originality,proto3,oneof" json:"originality,omitempty"` + // IAB category taxonomy in use. Default 9 (IAB Content Category Taxonomy 3.1). + Cattax *int32 `protobuf:"varint,10,opt,name=cattax,proto3,oneof" json:"cattax,omitempty"` + // IAB Tech Lab content category codes (per cattax). + Cat []int32 `protobuf:"varint,11,rep,packed,name=cat,proto3" json:"cat,omitempty"` + // Content language. CoMP declares this `int` (array) though its prose says + // ISO-639-1 (alpha-2) — an upstream inconsistency; the proto follows the + // declared `int` type. + Language []int32 `protobuf:"varint,12,rep,packed,name=language,proto3" json:"language,omitempty"` Ext *structpb.Struct `protobuf:"bytes,15,opt,name=ext,proto3" json:"ext,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1108,7 +1140,7 @@ type Text struct { func (x *Text) Reset() { *x = Text{} - mi := &file_comp_v1_comp_proto_msgTypes[5] + mi := &file_comp_v1_comp_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1120,7 +1152,7 @@ func (x *Text) String() string { func (*Text) ProtoMessage() {} func (x *Text) ProtoReflect() protoreflect.Message { - mi := &file_comp_v1_comp_proto_msgTypes[5] + mi := &file_comp_v1_comp_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1133,7 +1165,7 @@ func (x *Text) ProtoReflect() protoreflect.Message { // Deprecated: Use Text.ProtoReflect.Descriptor instead. func (*Text) Descriptor() ([]byte, []int) { - return file_comp_v1_comp_proto_rawDescGZIP(), []int{5} + return file_comp_v1_comp_proto_rawDescGZIP(), []int{4} } func (x *Text) GetTitle() string { @@ -1199,18 +1231,25 @@ func (x *Text) GetProvent() string { return "" } -func (x *Text) GetAuthority() float64 { - if x != nil && x.Authority != nil { - return *x.Authority +func (x *Text) GetCattax() int32 { + if x != nil && x.Cattax != nil { + return *x.Cattax } return 0 } -func (x *Text) GetOriginality() float64 { - if x != nil && x.Originality != nil { - return *x.Originality +func (x *Text) GetCat() []int32 { + if x != nil { + return x.Cat } - return 0 + return nil +} + +func (x *Text) GetLanguage() []int32 { + if x != nil { + return x.Language + } + return nil } func (x *Text) GetExt() *structpb.Struct { @@ -1230,14 +1269,23 @@ type Video struct { Wordcount []int32 `protobuf:"varint,4,rep,packed,name=wordcount,proto3" json:"wordcount,omitempty"` Transcript *int32 `protobuf:"varint,5,opt,name=transcript,proto3,oneof" json:"transcript,omitempty"` // 0=no, 1=yes. Pubdate *string `protobuf:"bytes,6,opt,name=pubdate,proto3,oneof" json:"pubdate,omitempty"` - Published *int32 `protobuf:"varint,7,opt,name=published,proto3,oneof" json:"published,omitempty"` - Update *string `protobuf:"bytes,8,opt,name=update,proto3,oneof" json:"update,omitempty"` - Author []string `protobuf:"bytes,9,rep,name=author,proto3" json:"author,omitempty"` - Sourcetype *int32 `protobuf:"varint,10,opt,name=sourcetype,proto3,oneof" json:"sourcetype,omitempty"` - Provenance *int32 `protobuf:"varint,11,opt,name=provenance,proto3,oneof" json:"provenance,omitempty"` - Provent *string `protobuf:"bytes,12,opt,name=provent,proto3,oneof" json:"provent,omitempty"` - // C2PA content credentials manifest URI. - C2Pa *string `protobuf:"bytes,13,opt,name=c2pa,proto3,oneof" json:"c2pa,omitempty"` + // Denotes if the content is publicly available. Default 0 for Video. + Published *int32 `protobuf:"varint,7,opt,name=published,proto3,oneof" json:"published,omitempty"` + Update *string `protobuf:"bytes,8,opt,name=update,proto3,oneof" json:"update,omitempty"` + Author []string `protobuf:"bytes,9,rep,name=author,proto3" json:"author,omitempty"` + Sourcetype *int32 `protobuf:"varint,10,opt,name=sourcetype,proto3,oneof" json:"sourcetype,omitempty"` + Provenance *int32 `protobuf:"varint,11,opt,name=provenance,proto3,oneof" json:"provenance,omitempty"` + Provent *string `protobuf:"bytes,12,opt,name=provent,proto3,oneof" json:"provent,omitempty"` + // IAB category taxonomy in use. Default 9 (IAB Content Category Taxonomy 3.1). + Cattax *int32 `protobuf:"varint,13,opt,name=cattax,proto3,oneof" json:"cattax,omitempty"` + // IAB Tech Lab content category codes (per cattax). + Cat []int32 `protobuf:"varint,14,rep,packed,name=cat,proto3" json:"cat,omitempty"` + // Content language. CoMP declares this `int` (array) though its prose says + // ISO-639-1 (alpha-2) — an upstream inconsistency; the proto follows the + // declared `int` type. + // Tag 16 sits above ext (15) only here: cattax/cat consumed 13/14, and ext is + // kept at 15 for cross-message uniformity rather than the usual terminal slot. + Language []int32 `protobuf:"varint,16,rep,packed,name=language,proto3" json:"language,omitempty"` Ext *structpb.Struct `protobuf:"bytes,15,opt,name=ext,proto3" json:"ext,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1245,7 +1293,7 @@ type Video struct { func (x *Video) Reset() { *x = Video{} - mi := &file_comp_v1_comp_proto_msgTypes[6] + mi := &file_comp_v1_comp_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1257,7 +1305,7 @@ func (x *Video) String() string { func (*Video) ProtoMessage() {} func (x *Video) ProtoReflect() protoreflect.Message { - mi := &file_comp_v1_comp_proto_msgTypes[6] + mi := &file_comp_v1_comp_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1270,7 +1318,7 @@ func (x *Video) ProtoReflect() protoreflect.Message { // Deprecated: Use Video.ProtoReflect.Descriptor instead. func (*Video) Descriptor() ([]byte, []int) { - return file_comp_v1_comp_proto_rawDescGZIP(), []int{6} + return file_comp_v1_comp_proto_rawDescGZIP(), []int{5} } func (x *Video) GetTitle() []string { @@ -1357,11 +1405,25 @@ func (x *Video) GetProvent() string { return "" } -func (x *Video) GetC2Pa() string { - if x != nil && x.C2Pa != nil { - return *x.C2Pa +func (x *Video) GetCattax() int32 { + if x != nil && x.Cattax != nil { + return *x.Cattax } - return "" + return 0 +} + +func (x *Video) GetCat() []int32 { + if x != nil { + return x.Cat + } + return nil +} + +func (x *Video) GetLanguage() []int32 { + if x != nil { + return x.Language + } + return nil } func (x *Video) GetExt() *structpb.Struct { @@ -1374,21 +1436,24 @@ func (x *Video) GetExt() *structpb.Struct { // Image — An image asset. // CoMP §image.json type Image struct { - state protoimpl.MessageState `protogen:"open.v1"` - Title []string `protobuf:"bytes,1,rep,name=title,proto3" json:"title,omitempty"` - Pubdate *string `protobuf:"bytes,2,opt,name=pubdate,proto3,oneof" json:"pubdate,omitempty"` - Published *int32 `protobuf:"varint,3,opt,name=published,proto3,oneof" json:"published,omitempty"` - Update *string `protobuf:"bytes,4,opt,name=update,proto3,oneof" json:"update,omitempty"` - Author []string `protobuf:"bytes,5,rep,name=author,proto3" json:"author,omitempty"` - Sourcetype *int32 `protobuf:"varint,6,opt,name=sourcetype,proto3,oneof" json:"sourcetype,omitempty"` - Provenance *int32 `protobuf:"varint,7,opt,name=provenance,proto3,oneof" json:"provenance,omitempty"` - Provent *string `protobuf:"bytes,8,opt,name=provent,proto3,oneof" json:"provent,omitempty"` - // Alt text for the image. - Alt *string `protobuf:"bytes,9,opt,name=alt,proto3,oneof" json:"alt,omitempty"` - // Caption for the image. - Caption *string `protobuf:"bytes,10,opt,name=caption,proto3,oneof" json:"caption,omitempty"` - // C2PA content credentials manifest URI. - C2Pa *string `protobuf:"bytes,11,opt,name=c2pa,proto3,oneof" json:"c2pa,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Title []string `protobuf:"bytes,1,rep,name=title,proto3" json:"title,omitempty"` + Pubdate *string `protobuf:"bytes,2,opt,name=pubdate,proto3,oneof" json:"pubdate,omitempty"` + // Denotes if the content is publicly available. Default 0 for Image. + Published *int32 `protobuf:"varint,3,opt,name=published,proto3,oneof" json:"published,omitempty"` + Update *string `protobuf:"bytes,4,opt,name=update,proto3,oneof" json:"update,omitempty"` + Author []string `protobuf:"bytes,5,rep,name=author,proto3" json:"author,omitempty"` + Sourcetype *int32 `protobuf:"varint,6,opt,name=sourcetype,proto3,oneof" json:"sourcetype,omitempty"` + Provenance *int32 `protobuf:"varint,7,opt,name=provenance,proto3,oneof" json:"provenance,omitempty"` + Provent *string `protobuf:"bytes,8,opt,name=provent,proto3,oneof" json:"provent,omitempty"` + // IAB category taxonomy in use. Default 9 (IAB Content Category Taxonomy 3.1). + Cattax *int32 `protobuf:"varint,9,opt,name=cattax,proto3,oneof" json:"cattax,omitempty"` + // IAB Tech Lab content category codes (per cattax). + Cat []int32 `protobuf:"varint,10,rep,packed,name=cat,proto3" json:"cat,omitempty"` + // Content language. CoMP declares this `int` (array) though its prose says + // ISO-639-1 (alpha-2) — an upstream inconsistency; the proto follows the + // declared `int` type. + Language []int32 `protobuf:"varint,11,rep,packed,name=language,proto3" json:"language,omitempty"` Ext *structpb.Struct `protobuf:"bytes,15,opt,name=ext,proto3" json:"ext,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1396,7 +1461,7 @@ type Image struct { func (x *Image) Reset() { *x = Image{} - mi := &file_comp_v1_comp_proto_msgTypes[7] + mi := &file_comp_v1_comp_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1408,7 +1473,7 @@ func (x *Image) String() string { func (*Image) ProtoMessage() {} func (x *Image) ProtoReflect() protoreflect.Message { - mi := &file_comp_v1_comp_proto_msgTypes[7] + mi := &file_comp_v1_comp_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1421,7 +1486,7 @@ func (x *Image) ProtoReflect() protoreflect.Message { // Deprecated: Use Image.ProtoReflect.Descriptor instead. func (*Image) Descriptor() ([]byte, []int) { - return file_comp_v1_comp_proto_rawDescGZIP(), []int{7} + return file_comp_v1_comp_proto_rawDescGZIP(), []int{6} } func (x *Image) GetTitle() []string { @@ -1480,25 +1545,25 @@ func (x *Image) GetProvent() string { return "" } -func (x *Image) GetAlt() string { - if x != nil && x.Alt != nil { - return *x.Alt +func (x *Image) GetCattax() int32 { + if x != nil && x.Cattax != nil { + return *x.Cattax } - return "" + return 0 } -func (x *Image) GetCaption() string { - if x != nil && x.Caption != nil { - return *x.Caption +func (x *Image) GetCat() []int32 { + if x != nil { + return x.Cat } - return "" + return nil } -func (x *Image) GetC2Pa() string { - if x != nil && x.C2Pa != nil { - return *x.C2Pa +func (x *Image) GetLanguage() []int32 { + if x != nil { + return x.Language } - return "" + return nil } func (x *Image) GetExt() *structpb.Struct { @@ -1517,14 +1582,21 @@ type Audio struct { Wordcount []int32 `protobuf:"varint,3,rep,packed,name=wordcount,proto3" json:"wordcount,omitempty"` Transcript *int32 `protobuf:"varint,4,opt,name=transcript,proto3,oneof" json:"transcript,omitempty"` Pubdate *string `protobuf:"bytes,5,opt,name=pubdate,proto3,oneof" json:"pubdate,omitempty"` - Published *int32 `protobuf:"varint,6,opt,name=published,proto3,oneof" json:"published,omitempty"` - Update *string `protobuf:"bytes,7,opt,name=update,proto3,oneof" json:"update,omitempty"` - Author []string `protobuf:"bytes,8,rep,name=author,proto3" json:"author,omitempty"` - Sourcetype *int32 `protobuf:"varint,9,opt,name=sourcetype,proto3,oneof" json:"sourcetype,omitempty"` - Provenance *int32 `protobuf:"varint,10,opt,name=provenance,proto3,oneof" json:"provenance,omitempty"` - Provent *string `protobuf:"bytes,11,opt,name=provent,proto3,oneof" json:"provent,omitempty"` - // C2PA content credentials manifest URI. - C2Pa *string `protobuf:"bytes,12,opt,name=c2pa,proto3,oneof" json:"c2pa,omitempty"` + // Denotes if the content is publicly available. Default 0 for Audio. + Published *int32 `protobuf:"varint,6,opt,name=published,proto3,oneof" json:"published,omitempty"` + Update *string `protobuf:"bytes,7,opt,name=update,proto3,oneof" json:"update,omitempty"` + Author []string `protobuf:"bytes,8,rep,name=author,proto3" json:"author,omitempty"` + Sourcetype *int32 `protobuf:"varint,9,opt,name=sourcetype,proto3,oneof" json:"sourcetype,omitempty"` + Provenance *int32 `protobuf:"varint,10,opt,name=provenance,proto3,oneof" json:"provenance,omitempty"` + Provent *string `protobuf:"bytes,11,opt,name=provent,proto3,oneof" json:"provent,omitempty"` + // IAB category taxonomy in use. Default 9 (IAB Content Category Taxonomy 3.1). + Cattax *int32 `protobuf:"varint,12,opt,name=cattax,proto3,oneof" json:"cattax,omitempty"` + // IAB Tech Lab content category codes (per cattax). + Cat []int32 `protobuf:"varint,13,rep,packed,name=cat,proto3" json:"cat,omitempty"` + // Content language. CoMP declares this `int` (array) though its prose says + // ISO-639-1 (alpha-2) — an upstream inconsistency; the proto follows the + // declared `int` type. + Language []int32 `protobuf:"varint,14,rep,packed,name=language,proto3" json:"language,omitempty"` Ext *structpb.Struct `protobuf:"bytes,15,opt,name=ext,proto3" json:"ext,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1532,7 +1604,7 @@ type Audio struct { func (x *Audio) Reset() { *x = Audio{} - mi := &file_comp_v1_comp_proto_msgTypes[8] + mi := &file_comp_v1_comp_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1544,7 +1616,7 @@ func (x *Audio) String() string { func (*Audio) ProtoMessage() {} func (x *Audio) ProtoReflect() protoreflect.Message { - mi := &file_comp_v1_comp_proto_msgTypes[8] + mi := &file_comp_v1_comp_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1557,7 +1629,7 @@ func (x *Audio) ProtoReflect() protoreflect.Message { // Deprecated: Use Audio.ProtoReflect.Descriptor instead. func (*Audio) Descriptor() ([]byte, []int) { - return file_comp_v1_comp_proto_rawDescGZIP(), []int{8} + return file_comp_v1_comp_proto_rawDescGZIP(), []int{7} } func (x *Audio) GetTitle() []string { @@ -1637,11 +1709,25 @@ func (x *Audio) GetProvent() string { return "" } -func (x *Audio) GetC2Pa() string { - if x != nil && x.C2Pa != nil { - return *x.C2Pa +func (x *Audio) GetCattax() int32 { + if x != nil && x.Cattax != nil { + return *x.Cattax } - return "" + return 0 +} + +func (x *Audio) GetCat() []int32 { + if x != nil { + return x.Cat + } + return nil +} + +func (x *Audio) GetLanguage() []int32 { + if x != nil { + return x.Language + } + return nil } func (x *Audio) GetExt() *structpb.Struct { @@ -1657,12 +1743,11 @@ type Retrieval struct { state protoimpl.MessageState `protogen:"open.v1"` // Authorization type. Auth *RetrievalAuth `protobuf:"varint,1,opt,name=auth,proto3,enum=comp.v1.RetrievalAuth,oneof" json:"auth,omitempty"` - // Entry point / feed URI. + // Entry point / feed URI. SSRF/fetch sink: apply the countermeasures + // specified for core License.uri (threat model T-LIC-1) before fetching. Endpoint *string `protobuf:"bytes,2,opt,name=endpoint,proto3,oneof" json:"endpoint,omitempty"` // Endpoint type(s). - Type []RetrievalType `protobuf:"varint,3,rep,packed,name=type,proto3,enum=comp.v1.RetrievalType" json:"type,omitempty"` - // Rate limit (requests per minute) for this retrieval endpoint. - Ratelmt *int32 `protobuf:"varint,4,opt,name=ratelmt,proto3,oneof" json:"ratelmt,omitempty"` + Type []RetrievalType `protobuf:"varint,3,rep,packed,name=type,proto3,enum=comp.v1.RetrievalType" json:"type,omitempty"` Ext *structpb.Struct `protobuf:"bytes,15,opt,name=ext,proto3" json:"ext,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1670,7 +1755,7 @@ type Retrieval struct { func (x *Retrieval) Reset() { *x = Retrieval{} - mi := &file_comp_v1_comp_proto_msgTypes[9] + mi := &file_comp_v1_comp_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1682,7 +1767,7 @@ func (x *Retrieval) String() string { func (*Retrieval) ProtoMessage() {} func (x *Retrieval) ProtoReflect() protoreflect.Message { - mi := &file_comp_v1_comp_proto_msgTypes[9] + mi := &file_comp_v1_comp_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1695,7 +1780,7 @@ func (x *Retrieval) ProtoReflect() protoreflect.Message { // Deprecated: Use Retrieval.ProtoReflect.Descriptor instead. func (*Retrieval) Descriptor() ([]byte, []int) { - return file_comp_v1_comp_proto_rawDescGZIP(), []int{9} + return file_comp_v1_comp_proto_rawDescGZIP(), []int{8} } func (x *Retrieval) GetAuth() RetrievalAuth { @@ -1719,13 +1804,6 @@ func (x *Retrieval) GetType() []RetrievalType { return nil } -func (x *Retrieval) GetRatelmt() int32 { - if x != nil && x.Ratelmt != nil { - return *x.Ratelmt - } - return 0 -} - func (x *Retrieval) GetExt() *structpb.Struct { if x != nil { return x.Ext @@ -1756,7 +1834,7 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\x06resdis\x18\a \x01(\x05H\x01R\x06resdis\x88\x01\x01\x12)\n" + "\x03ext\x18\x0f \x01(\v2\x17.google.protobuf.StructR\x03extB\b\n" + "\x06_scopeB\t\n" + - "\a_resdis\"\xc7\x03\n" + + "\a_resdis\"\xcc\x03\n" + "\aPackage\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x19\n" + "\x05title\x18\x02 \x01(\tH\x00R\x05title\x88\x01\x01\x12\x1b\n" + @@ -1765,52 +1843,51 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\n" + "licenseurl\x18\x05 \x01(\tH\x03R\n" + "licenseurl\x88\x01\x01\x12\x1f\n" + - "\bcitation\x18\x06 \x01(\x05H\x04R\bcitation\x88\x01\x01\x12)\n" + - "\x05scope\x18\a \x01(\v2\x0e.comp.v1.ScopeH\x05R\x05scope\x88\x01\x01\x125\n" + - "\tretrieval\x18\b \x01(\v2\x12.comp.v1.RetrievalH\x06R\tretrieval\x88\x01\x01\x12*\n" + - "\alicense\x18\t \x03(\v2\x10.comp.v1.LicenseR\alicense\x12)\n" + + "\bcitation\x18\x06 \x01(\x05H\x04R\bcitation\x88\x01\x01\x12!\n" + + "\treporturl\x18\a \x01(\tH\x05R\treporturl\x88\x01\x01\x12)\n" + + "\x05scope\x18\b \x01(\v2\x0e.comp.v1.ScopeH\x06R\x05scope\x88\x01\x01\x125\n" + + "\tretrieval\x18\t \x01(\v2\x12.comp.v1.RetrievalH\aR\tretrieval\x88\x01\x01\x12)\n" + "\x03ext\x18\x0f \x01(\v2\x17.google.protobuf.StructR\x03extB\b\n" + "\x06_titleB\t\n" + "\a_sellerB\v\n" + "\t_packagerB\r\n" + "\v_licenseurlB\v\n" + - "\t_citationB\b\n" + - "\x06_scopeB\f\n" + + "\t_citationB\f\n" + "\n" + - "_retrieval\"\x9d\x03\n" + - "\aLicense\x12\x13\n" + - "\x02id\x18\x01 \x01(\tH\x00R\x02id\x88\x01\x01\x12\x17\n" + - "\x04turl\x18\x02 \x01(\tH\x01R\x04turl\x88\x01\x01\x12%\n" + - "\x03use\x18\x03 \x03(\x0e2\x13.comp.v1.LicenseUseR\x03use\x12\x18\n" + - "\acountry\x18\x04 \x03(\tR\acountry\x12\x1d\n" + - "\amaxword\x18\x05 \x01(\x05H\x02R\amaxword\x88\x01\x01\x12\x1f\n" + - "\bcitation\x18\x06 \x01(\x05H\x03R\bcitation\x88\x01\x01\x12\x19\n" + - "\x05price\x18\a \x01(\x01H\x04R\x05price\x88\x01\x01\x12\x1f\n" + - "\brevshare\x18\b \x01(\x01H\x05R\brevshare\x88\x01\x01\x12\x15\n" + - "\x03cur\x18\t \x01(\tH\x06R\x03cur\x88\x01\x01\x12\x15\n" + - "\x03dur\x18\n" + - " \x01(\x05H\aR\x03dur\x88\x01\x01\x12)\n" + - "\x03ext\x18\x0f \x01(\v2\x17.google.protobuf.StructR\x03extB\x05\n" + - "\x03_idB\a\n" + - "\x05_turlB\n" + + "_reporturlB\b\n" + + "\x06_scopeB\f\n" + "\n" + - "\b_maxwordB\v\n" + - "\t_citationB\b\n" + - "\x06_priceB\v\n" + - "\t_revshareB\x06\n" + - "\x04_curB\x06\n" + - "\x04_dur\"\xcb\x02\n" + + "_retrieval\"\x96\x05\n" + "\x05Scope\x12-\n" + - "\x05scope\x18\x01 \x01(\x0e2\x12.comp.v1.ScopeTypeH\x00R\x05scope\x88\x01\x01\x12\x15\n" + - "\x03max\x18\x02 \x01(\x05H\x01R\x03max\x88\x01\x01\x12*\n" + - "\x05ctype\x18\x03 \x03(\x0e2\x14.comp.v1.ContentTypeR\x05ctype\x12!\n" + - "\x04text\x18\x04 \x03(\v2\r.comp.v1.TextR\x04text\x12$\n" + - "\x05video\x18\x05 \x03(\v2\x0e.comp.v1.VideoR\x05video\x12$\n" + - "\x05image\x18\x06 \x03(\v2\x0e.comp.v1.ImageR\x05image\x12$\n" + - "\x05audio\x18\a \x03(\v2\x0e.comp.v1.AudioR\x05audio\x12)\n" + + "\x05scope\x18\x01 \x01(\x0e2\x12.comp.v1.ScopeTypeH\x00R\x05scope\x88\x01\x01\x12,\n" + + "\x04ause\x18\x02 \x01(\x0e2\x13.comp.v1.AllowedUseH\x01R\x04ause\x88\x01\x01\x125\n" + + "\tpricetype\x18\x03 \x01(\x0e2\x12.comp.v1.PriceTypeH\x02R\tpricetype\x88\x01\x01\x12!\n" + + "\tpricetier\x18\x04 \x01(\x05H\x03R\tpricetier\x88\x01\x01\x12!\n" + + "\tunitprice\x18\x05 \x01(\x01H\x04R\tunitprice\x88\x01\x01\x12\x15\n" + + "\x03cur\x18\x06 \x01(\tH\x05R\x03cur\x88\x01\x01\x12\x18\n" + + "\acountry\x18\a \x03(\x05R\acountry\x12#\n" + + "\n" + + "licensedur\x18\b \x01(\x05H\x06R\n" + + "licensedur\x88\x01\x01\x12\x15\n" + + "\x03max\x18\t \x01(\x05H\aR\x03max\x88\x01\x01\x12*\n" + + "\x05ctype\x18\n" + + " \x03(\x0e2\x14.comp.v1.ContentTypeR\x05ctype\x12!\n" + + "\x04text\x18\v \x03(\v2\r.comp.v1.TextR\x04text\x12$\n" + + "\x05video\x18\f \x03(\v2\x0e.comp.v1.VideoR\x05video\x12$\n" + + "\x05image\x18\r \x03(\v2\x0e.comp.v1.ImageR\x05image\x12$\n" + + "\x05audio\x18\x0e \x03(\v2\x0e.comp.v1.AudioR\x05audio\x12)\n" + "\x03ext\x18\x0f \x01(\v2\x17.google.protobuf.StructR\x03extB\b\n" + - "\x06_scopeB\x06\n" + - "\x04_max\"\x8b\x04\n" + + "\x06_scopeB\a\n" + + "\x05_auseB\f\n" + + "\n" + + "_pricetypeB\f\n" + + "\n" + + "_pricetierB\f\n" + + "\n" + + "_unitpriceB\x06\n" + + "\x04_curB\r\n" + + "\v_licensedurB\x06\n" + + "\x04_max\"\xf9\x03\n" + "\x04Text\x12\x19\n" + "\x05title\x18\x01 \x01(\tH\x00R\x05title\x88\x01\x01\x12\x1c\n" + "\twordcount\x18\x02 \x03(\x05R\twordcount\x12\x1d\n" + @@ -1824,10 +1901,11 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\n" + "provenance\x18\b \x01(\x05H\x05R\n" + "provenance\x88\x01\x01\x12\x1d\n" + - "\aprovent\x18\t \x01(\tH\x06R\aprovent\x88\x01\x01\x12!\n" + - "\tauthority\x18\n" + - " \x01(\x01H\aR\tauthority\x88\x01\x01\x12%\n" + - "\voriginality\x18\v \x01(\x01H\bR\voriginality\x88\x01\x01\x12)\n" + + "\aprovent\x18\t \x01(\tH\x06R\aprovent\x88\x01\x01\x12\x1b\n" + + "\x06cattax\x18\n" + + " \x01(\x05H\aR\x06cattax\x88\x01\x01\x12\x10\n" + + "\x03cat\x18\v \x03(\x05R\x03cat\x12\x1a\n" + + "\blanguage\x18\f \x03(\x05R\blanguage\x12)\n" + "\x03ext\x18\x0f \x01(\v2\x17.google.protobuf.StructR\x03extB\b\n" + "\x06_titleB\n" + "\n" + @@ -1838,10 +1916,8 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\v_sourcetypeB\r\n" + "\v_provenanceB\n" + "\n" + - "\b_proventB\f\n" + - "\n" + - "_authorityB\x0e\n" + - "\f_originality\"\x9f\x04\n" + + "\b_proventB\t\n" + + "\a_cattax\"\xd3\x04\n" + "\x05Video\x12\x14\n" + "\x05title\x18\x01 \x03(\tR\x05title\x12\x10\n" + "\x03dur\x18\x02 \x03(\x05R\x03dur\x12\x17\n" + @@ -1861,8 +1937,10 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\n" + "provenance\x18\v \x01(\x05H\x06R\n" + "provenance\x88\x01\x01\x12\x1d\n" + - "\aprovent\x18\f \x01(\tH\aR\aprovent\x88\x01\x01\x12\x17\n" + - "\x04c2pa\x18\r \x01(\tH\bR\x04c2pa\x88\x01\x01\x12)\n" + + "\aprovent\x18\f \x01(\tH\aR\aprovent\x88\x01\x01\x12\x1b\n" + + "\x06cattax\x18\r \x01(\x05H\bR\x06cattax\x88\x01\x01\x12\x10\n" + + "\x03cat\x18\x0e \x03(\x05R\x03cat\x12\x1a\n" + + "\blanguage\x18\x10 \x03(\x05R\blanguage\x12)\n" + "\x03ext\x18\x0f \x01(\v2\x17.google.protobuf.StructR\x03extB\a\n" + "\x05_clipB\r\n" + "\v_transcriptB\n" + @@ -1874,8 +1952,8 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\v_sourcetypeB\r\n" + "\v_provenanceB\n" + "\n" + - "\b_proventB\a\n" + - "\x05_c2pa\"\xe3\x03\n" + + "\b_proventB\t\n" + + "\a_cattax\"\xcd\x03\n" + "\x05Image\x12\x14\n" + "\x05title\x18\x01 \x03(\tR\x05title\x12\x1d\n" + "\apubdate\x18\x02 \x01(\tH\x00R\apubdate\x88\x01\x01\x12!\n" + @@ -1888,11 +1966,11 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\n" + "provenance\x18\a \x01(\x05H\x04R\n" + "provenance\x88\x01\x01\x12\x1d\n" + - "\aprovent\x18\b \x01(\tH\x05R\aprovent\x88\x01\x01\x12\x15\n" + - "\x03alt\x18\t \x01(\tH\x06R\x03alt\x88\x01\x01\x12\x1d\n" + - "\acaption\x18\n" + - " \x01(\tH\aR\acaption\x88\x01\x01\x12\x17\n" + - "\x04c2pa\x18\v \x01(\tH\bR\x04c2pa\x88\x01\x01\x12)\n" + + "\aprovent\x18\b \x01(\tH\x05R\aprovent\x88\x01\x01\x12\x1b\n" + + "\x06cattax\x18\t \x01(\x05H\x06R\x06cattax\x88\x01\x01\x12\x10\n" + + "\x03cat\x18\n" + + " \x03(\x05R\x03cat\x12\x1a\n" + + "\blanguage\x18\v \x03(\x05R\blanguage\x12)\n" + "\x03ext\x18\x0f \x01(\v2\x17.google.protobuf.StructR\x03extB\n" + "\n" + "\b_pubdateB\f\n" + @@ -1902,11 +1980,8 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\v_sourcetypeB\r\n" + "\v_provenanceB\n" + "\n" + - "\b_proventB\x06\n" + - "\x04_altB\n" + - "\n" + - "\b_captionB\a\n" + - "\x05_c2pa\"\xfd\x03\n" + + "\b_proventB\t\n" + + "\a_cattax\"\xb1\x04\n" + "\x05Audio\x12\x14\n" + "\x05title\x18\x01 \x03(\tR\x05title\x12\x10\n" + "\x03dur\x18\x02 \x03(\x05R\x03dur\x12\x1c\n" + @@ -1925,8 +2000,10 @@ const file_comp_v1_comp_proto_rawDesc = "" + "provenance\x18\n" + " \x01(\x05H\x05R\n" + "provenance\x88\x01\x01\x12\x1d\n" + - "\aprovent\x18\v \x01(\tH\x06R\aprovent\x88\x01\x01\x12\x17\n" + - "\x04c2pa\x18\f \x01(\tH\aR\x04c2pa\x88\x01\x01\x12)\n" + + "\aprovent\x18\v \x01(\tH\x06R\aprovent\x88\x01\x01\x12\x1b\n" + + "\x06cattax\x18\f \x01(\x05H\aR\x06cattax\x88\x01\x01\x12\x10\n" + + "\x03cat\x18\r \x03(\x05R\x03cat\x12\x1a\n" + + "\blanguage\x18\x0e \x03(\x05R\blanguage\x12)\n" + "\x03ext\x18\x0f \x01(\v2\x17.google.protobuf.StructR\x03extB\r\n" + "\v_transcriptB\n" + "\n" + @@ -1937,18 +2014,15 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\v_sourcetypeB\r\n" + "\v_provenanceB\n" + "\n" + - "\b_proventB\a\n" + - "\x05_c2pa\"\xf5\x01\n" + + "\b_proventB\t\n" + + "\a_cattax\"\xca\x01\n" + "\tRetrieval\x12/\n" + "\x04auth\x18\x01 \x01(\x0e2\x16.comp.v1.RetrievalAuthH\x00R\x04auth\x88\x01\x01\x12\x1f\n" + "\bendpoint\x18\x02 \x01(\tH\x01R\bendpoint\x88\x01\x01\x12*\n" + - "\x04type\x18\x03 \x03(\x0e2\x16.comp.v1.RetrievalTypeR\x04type\x12\x1d\n" + - "\aratelmt\x18\x04 \x01(\x05H\x02R\aratelmt\x88\x01\x01\x12)\n" + + "\x04type\x18\x03 \x03(\x0e2\x16.comp.v1.RetrievalTypeR\x04type\x12)\n" + "\x03ext\x18\x0f \x01(\v2\x17.google.protobuf.StructR\x03extB\a\n" + "\x05_authB\v\n" + - "\t_endpointB\n" + - "\n" + - "\b_ratelmt*\x9c\x01\n" + + "\t_endpoint*\x9c\x01\n" + "\n" + "AuthMethod\x12\x1a\n" + "\x16AUTH_METHOD_USER_AGENT\x10\x00\x12\x12\n" + @@ -1978,28 +2052,36 @@ const file_comp_v1_comp_proto_rawDesc = "" + "\x16SUB_FUNCTION_GROUNDING\x10\x02\x12\x1b\n" + "\x17SUB_FUNCTION_AGENT_VIEW\x10\x03\x12\x1e\n" + "\x1aSUB_FUNCTION_AGENT_ACTIONS\x10\x04\x12\x16\n" + - "\x12SUB_FUNCTION_OTHER\x10\x05*\x83\x02\n" + + "\x12SUB_FUNCTION_OTHER\x10\x05*\xcf\x01\n" + "\n" + - "LicenseUse\x12 \n" + - "\x1cLICENSE_USE_TRAINING_DISPLAY\x10\x00\x12(\n" + - "$LICENSE_USE_RAG_DISPLAY_UNRESTRICTED\x10\x01\x12%\n" + - "!LICENSE_USE_RAG_DISPLAY_MAX_WORDS\x10\x02\x12'\n" + - "#LICENSE_USE_RAG_DISPLAY_ATTRIBUTION\x10\x03\x12\x1e\n" + - "\x1aLICENSE_USE_RAG_NO_DISPLAY\x10\x04\x12\x1a\n" + - "\x16LICENSE_USE_AGENT_VIEW\x10\x05\x12\x1d\n" + - "\x19LICENSE_USE_AGENT_ACTIONS\x10\x06*\x9a\x01\n" + + "AllowedUse\x12\x1a\n" + + "\x16ALLOWED_USE_COMMERCIAL\x10\x00\x12\x1e\n" + + "\x1aALLOWED_USE_NON_COMMERCIAL\x10\x01\x12\x1b\n" + + "\x17ALLOWED_USE_EDUCATIONAL\x10\x02\x12\x1a\n" + + "\x16ALLOWED_USE_GOVERNMENT\x10\x03\x12\x18\n" + + "\x14ALLOWED_USE_PERSONAL\x10\x04\x12\x1b\n" + + "\x17ALLOWED_USE_BYO_LICENSE\x10\x05\x12\x15\n" + + "\x11ALLOWED_USE_OTHER\x10\x06*\x99\x01\n" + + "\tPriceType\x12\x16\n" + + "\x12PRICE_TYPE_PER_USE\x10\x00\x12\x18\n" + + "\x14PRICE_TYPE_PER_QUERY\x10\x01\x12\x18\n" + + "\x14PRICE_TYPE_PER_TOKEN\x10\x02\x12\x13\n" + + "\x0fPRICE_TYPE_FLAT\x10\x03\x12\x15\n" + + "\x11PRICE_TYPE_TIERED\x10\x04\x12\x14\n" + + "\x10PRICE_TYPE_OTHER\x10\x05*\x9a\x01\n" + "\vContentType\x12\x15\n" + "\x11CONTENT_TYPE_TEXT\x10\x00\x12\x16\n" + "\x12CONTENT_TYPE_VIDEO\x10\x01\x12\x16\n" + "\x12CONTENT_TYPE_IMAGE\x10\x02\x12\x16\n" + "\x12CONTENT_TYPE_AUDIO\x10\x03\x12\x14\n" + "\x10CONTENT_TYPE_ALL\x10\x04\x12\x16\n" + - "\x12CONTENT_TYPE_OTHER\x10\x05*w\n" + + "\x12CONTENT_TYPE_OTHER\x10\x05*\x91\x01\n" + "\rRetrievalAuth\x12\x17\n" + "\x13RETRIEVAL_AUTH_NONE\x10\x00\x12\x1a\n" + "\x16RETRIEVAL_AUTH_API_KEY\x10\x01\x12\x19\n" + "\x15RETRIEVAL_AUTH_OAUTH2\x10\x02\x12\x16\n" + - "\x12RETRIEVAL_AUTH_SSL\x10\x03*\xd7\x01\n" + + "\x12RETRIEVAL_AUTH_SSL\x10\x03\x12\x18\n" + + "\x14RETRIEVAL_AUTH_OTHER\x10\x04*\xd7\x01\n" + "\rRetrievalType\x12\x17\n" + "\x13RETRIEVAL_TYPE_HTML\x10\x00\x12\x16\n" + "\x12RETRIEVAL_TYPE_RSS\x10\x01\x12\x16\n" + @@ -2023,21 +2105,21 @@ func file_comp_v1_comp_proto_rawDescGZIP() []byte { return file_comp_v1_comp_proto_rawDescData } -var file_comp_v1_comp_proto_enumTypes = make([]protoimpl.EnumInfo, 8) -var file_comp_v1_comp_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_comp_v1_comp_proto_enumTypes = make([]protoimpl.EnumInfo, 9) +var file_comp_v1_comp_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_comp_v1_comp_proto_goTypes = []any{ (AuthMethod)(0), // 0: comp.v1.AuthMethod (ScopeType)(0), // 1: comp.v1.ScopeType (Function)(0), // 2: comp.v1.Function (SubFunction)(0), // 3: comp.v1.SubFunction - (LicenseUse)(0), // 4: comp.v1.LicenseUse - (ContentType)(0), // 5: comp.v1.ContentType - (RetrievalAuth)(0), // 6: comp.v1.RetrievalAuth - (RetrievalType)(0), // 7: comp.v1.RetrievalType - (*AISystem)(nil), // 8: comp.v1.AISystem - (*AISystemUse)(nil), // 9: comp.v1.AISystemUse - (*Package)(nil), // 10: comp.v1.Package - (*License)(nil), // 11: comp.v1.License + (AllowedUse)(0), // 4: comp.v1.AllowedUse + (PriceType)(0), // 5: comp.v1.PriceType + (ContentType)(0), // 6: comp.v1.ContentType + (RetrievalAuth)(0), // 7: comp.v1.RetrievalAuth + (RetrievalType)(0), // 8: comp.v1.RetrievalType + (*AISystem)(nil), // 9: comp.v1.AISystem + (*AISystemUse)(nil), // 10: comp.v1.AISystemUse + (*Package)(nil), // 11: comp.v1.Package (*Scope)(nil), // 12: comp.v1.Scope (*Text)(nil), // 13: comp.v1.Text (*Video)(nil), // 14: comp.v1.Video @@ -2047,7 +2129,7 @@ var file_comp_v1_comp_proto_goTypes = []any{ (*structpb.Struct)(nil), // 18: google.protobuf.Struct } var file_comp_v1_comp_proto_depIdxs = []int32{ - 9, // 0: comp.v1.AISystem.aisysuse:type_name -> comp.v1.AISystemUse + 10, // 0: comp.v1.AISystem.aisysuse:type_name -> comp.v1.AISystemUse 18, // 1: comp.v1.AISystem.ext:type_name -> google.protobuf.Struct 0, // 2: comp.v1.AISystemUse.aiauth:type_name -> comp.v1.AuthMethod 1, // 3: comp.v1.AISystemUse.scope:type_name -> comp.v1.ScopeType @@ -2056,29 +2138,28 @@ var file_comp_v1_comp_proto_depIdxs = []int32{ 18, // 6: comp.v1.AISystemUse.ext:type_name -> google.protobuf.Struct 12, // 7: comp.v1.Package.scope:type_name -> comp.v1.Scope 17, // 8: comp.v1.Package.retrieval:type_name -> comp.v1.Retrieval - 11, // 9: comp.v1.Package.license:type_name -> comp.v1.License - 18, // 10: comp.v1.Package.ext:type_name -> google.protobuf.Struct - 4, // 11: comp.v1.License.use:type_name -> comp.v1.LicenseUse - 18, // 12: comp.v1.License.ext:type_name -> google.protobuf.Struct - 1, // 13: comp.v1.Scope.scope:type_name -> comp.v1.ScopeType - 5, // 14: comp.v1.Scope.ctype:type_name -> comp.v1.ContentType - 13, // 15: comp.v1.Scope.text:type_name -> comp.v1.Text - 14, // 16: comp.v1.Scope.video:type_name -> comp.v1.Video - 15, // 17: comp.v1.Scope.image:type_name -> comp.v1.Image - 16, // 18: comp.v1.Scope.audio:type_name -> comp.v1.Audio - 18, // 19: comp.v1.Scope.ext:type_name -> google.protobuf.Struct - 18, // 20: comp.v1.Text.ext:type_name -> google.protobuf.Struct - 18, // 21: comp.v1.Video.ext:type_name -> google.protobuf.Struct - 18, // 22: comp.v1.Image.ext:type_name -> google.protobuf.Struct - 18, // 23: comp.v1.Audio.ext:type_name -> google.protobuf.Struct - 6, // 24: comp.v1.Retrieval.auth:type_name -> comp.v1.RetrievalAuth - 7, // 25: comp.v1.Retrieval.type:type_name -> comp.v1.RetrievalType - 18, // 26: comp.v1.Retrieval.ext:type_name -> google.protobuf.Struct - 27, // [27:27] is the sub-list for method output_type - 27, // [27:27] is the sub-list for method input_type - 27, // [27:27] is the sub-list for extension type_name - 27, // [27:27] is the sub-list for extension extendee - 0, // [0:27] is the sub-list for field type_name + 18, // 9: comp.v1.Package.ext:type_name -> google.protobuf.Struct + 1, // 10: comp.v1.Scope.scope:type_name -> comp.v1.ScopeType + 4, // 11: comp.v1.Scope.ause:type_name -> comp.v1.AllowedUse + 5, // 12: comp.v1.Scope.pricetype:type_name -> comp.v1.PriceType + 6, // 13: comp.v1.Scope.ctype:type_name -> comp.v1.ContentType + 13, // 14: comp.v1.Scope.text:type_name -> comp.v1.Text + 14, // 15: comp.v1.Scope.video:type_name -> comp.v1.Video + 15, // 16: comp.v1.Scope.image:type_name -> comp.v1.Image + 16, // 17: comp.v1.Scope.audio:type_name -> comp.v1.Audio + 18, // 18: comp.v1.Scope.ext:type_name -> google.protobuf.Struct + 18, // 19: comp.v1.Text.ext:type_name -> google.protobuf.Struct + 18, // 20: comp.v1.Video.ext:type_name -> google.protobuf.Struct + 18, // 21: comp.v1.Image.ext:type_name -> google.protobuf.Struct + 18, // 22: comp.v1.Audio.ext:type_name -> google.protobuf.Struct + 7, // 23: comp.v1.Retrieval.auth:type_name -> comp.v1.RetrievalAuth + 8, // 24: comp.v1.Retrieval.type:type_name -> comp.v1.RetrievalType + 18, // 25: comp.v1.Retrieval.ext:type_name -> google.protobuf.Struct + 26, // [26:26] is the sub-list for method output_type + 26, // [26:26] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_comp_v1_comp_proto_init() } @@ -2095,14 +2176,13 @@ func file_comp_v1_comp_proto_init() { file_comp_v1_comp_proto_msgTypes[6].OneofWrappers = []any{} file_comp_v1_comp_proto_msgTypes[7].OneofWrappers = []any{} file_comp_v1_comp_proto_msgTypes[8].OneofWrappers = []any{} - file_comp_v1_comp_proto_msgTypes[9].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_comp_v1_comp_proto_rawDesc), len(file_comp_v1_comp_proto_rawDesc)), - NumEnums: 8, - NumMessages: 10, + NumEnums: 9, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/gen/ts/comp/v1/comp_pb.ts b/gen/ts/comp/v1/comp_pb.ts index 68eb2f9e..2052874b 100644 --- a/gen/ts/comp/v1/comp_pb.ts +++ b/gen/ts/comp/v1/comp_pb.ts @@ -1,14 +1,18 @@ -// CoMP v1.0 — IAB Tech Lab Content Monetization Protocol +// CoMP V1 — IAB Tech Lab Content Monetization Protocols (finalized 2026-04-28). // -// 1:1 mapping from the official CoMP WG specification. -// Source: https://github.com/IABTechLab/CoMP/blob/dev/CoMP-1.0.md +// 1:1 mapping from the canonical CoMP V1 specification. +// Source (immutable pin): https://github.com/IABTechLab/CoMP/blob/880238e0100b3d0d67d5afd7357a18fc21a97be5/CoMP-1.0.md +// Spec-file content blob SHA (content-addressed): aa8c796be7a9bcfa1189a1cf6c1ec50aa67a0f5f +// NOTE: the 1.0-202604 release tag does NOT contain the spec; main carries it. // // Enum alignment: proto3 enum values map directly to CoMP integer values // (first real CoMP value = 0). No UNSPECIFIED sentinels — proto3 default // zero is a valid CoMP value, not a sentinel. // // This file preserves CoMP field names, enum values, and semantics exactly. -// RAMP extensions live in ramp/v1/ramp.proto, never here. +// Canonical V1 has no separate License object: all commercial/licensing terms +// live on Scope (ause, pricetype, pricetier, unitprice, cur, country, +// licensedur). RAMP extensions live in ramp/v1/ramp.proto, never here. // @generated by protoc-gen-es v2.12.0 with parameter "target=ts" // @generated from file comp/v1/comp.proto (package comp.v1, syntax proto3) @@ -23,7 +27,7 @@ import type { JsonObject, Message } from "@bufbuild/protobuf"; * Describes the file comp/v1/comp.proto. */ export const file_comp_v1_comp: GenFile = /*@__PURE__*/ - fileDesc("ChJjb21wL3YxL2NvbXAucHJvdG8SB2NvbXAudjEilgEKCEFJU3lzdGVtEgwKBG5hbWUYASABKAkSDwoCdWEYAiABKAlIAIgBARIPCgJpZBgDIAEoCUgBiAEBEiYKCGFpc3lzdXNlGAQgASgLMhQuY29tcC52MS5BSVN5c3RlbVVzZRIkCgNleHQYDyABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0QgUKA191YUIFCgNfaWQijgIKC0FJU3lzdGVtVXNlEgsKA2xpZBgBIAEoCRIjCgZhaWF1dGgYAiABKA4yEy5jb21wLnYxLkF1dGhNZXRob2QSCwoDdXJpGAMgAygJEiYKBXNjb3BlGAQgASgOMhIuY29tcC52MS5TY29wZVR5cGVIAIgBARIjCghmdW5jdGlvbhgFIAMoDjIRLmNvbXAudjEuRnVuY3Rpb24SIwoFc3ViZm4YBiADKA4yFC5jb21wLnYxLlN1YkZ1bmN0aW9uEhMKBnJlc2RpcxgHIAEoBUgBiAEBEiQKA2V4dBgPIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RCCAoGX3Njb3BlQgkKB19yZXNkaXMi9AIKB1BhY2thZ2USCgoCaWQYASABKAkSEgoFdGl0bGUYAiABKAlIAIgBARITCgZzZWxsZXIYAyABKAlIAYgBARIVCghwYWNrYWdlchgEIAEoCUgCiAEBEhcKCmxpY2Vuc2V1cmwYBSABKAlIA4gBARIVCghjaXRhdGlvbhgGIAEoBUgEiAEBEiIKBXNjb3BlGAcgASgLMg4uY29tcC52MS5TY29wZUgFiAEBEioKCXJldHJpZXZhbBgIIAEoCzISLmNvbXAudjEuUmV0cmlldmFsSAaIAQESIQoHbGljZW5zZRgJIAMoCzIQLmNvbXAudjEuTGljZW5zZRIkCgNleHQYDyABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0QggKBl90aXRsZUIJCgdfc2VsbGVyQgsKCV9wYWNrYWdlckINCgtfbGljZW5zZXVybEILCglfY2l0YXRpb25CCAoGX3Njb3BlQgwKCl9yZXRyaWV2YWwi0gIKB0xpY2Vuc2USDwoCaWQYASABKAlIAIgBARIRCgR0dXJsGAIgASgJSAGIAQESIAoDdXNlGAMgAygOMhMuY29tcC52MS5MaWNlbnNlVXNlEg8KB2NvdW50cnkYBCADKAkSFAoHbWF4d29yZBgFIAEoBUgCiAEBEhUKCGNpdGF0aW9uGAYgASgFSAOIAQESEgoFcHJpY2UYByABKAFIBIgBARIVCghyZXZzaGFyZRgIIAEoAUgFiAEBEhAKA2N1chgJIAEoCUgGiAEBEhAKA2R1chgKIAEoBUgHiAEBEiQKA2V4dBgPIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RCBQoDX2lkQgcKBV90dXJsQgoKCF9tYXh3b3JkQgsKCV9jaXRhdGlvbkIICgZfcHJpY2VCCwoJX3JldnNoYXJlQgYKBF9jdXJCBgoEX2R1ciKYAgoFU2NvcGUSJgoFc2NvcGUYASABKA4yEi5jb21wLnYxLlNjb3BlVHlwZUgAiAEBEhAKA21heBgCIAEoBUgBiAEBEiMKBWN0eXBlGAMgAygOMhQuY29tcC52MS5Db250ZW50VHlwZRIbCgR0ZXh0GAQgAygLMg0uY29tcC52MS5UZXh0Eh0KBXZpZGVvGAUgAygLMg4uY29tcC52MS5WaWRlbxIdCgVpbWFnZRgGIAMoCzIOLmNvbXAudjEuSW1hZ2USHQoFYXVkaW8YByADKAsyDi5jb21wLnYxLkF1ZGlvEiQKA2V4dBgPIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RCCAoGX3Njb3BlQgYKBF9tYXgilwMKBFRleHQSEgoFdGl0bGUYASABKAlIAIgBARIRCgl3b3JkY291bnQYAiADKAUSFAoHcHViZGF0ZRgDIAEoCUgBiAEBEhYKCXB1Ymxpc2hlZBgEIAEoBUgCiAEBEhMKBnVwZGF0ZRgFIAEoCUgDiAEBEg4KBmF1dGhvchgGIAMoCRIXCgpzb3VyY2V0eXBlGAcgASgFSASIAQESFwoKcHJvdmVuYW5jZRgIIAEoBUgFiAEBEhQKB3Byb3ZlbnQYCSABKAlIBogBARIWCglhdXRob3JpdHkYCiABKAFIB4gBARIYCgtvcmlnaW5hbGl0eRgLIAEoAUgIiAEBEiQKA2V4dBgPIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RCCAoGX3RpdGxlQgoKCF9wdWJkYXRlQgwKCl9wdWJsaXNoZWRCCQoHX3VwZGF0ZUINCgtfc291cmNldHlwZUINCgtfcHJvdmVuYW5jZUIKCghfcHJvdmVudEIMCgpfYXV0aG9yaXR5Qg4KDF9vcmlnaW5hbGl0eSKmAwoFVmlkZW8SDQoFdGl0bGUYASADKAkSCwoDZHVyGAIgAygFEhEKBGNsaXAYAyABKAVIAIgBARIRCgl3b3JkY291bnQYBCADKAUSFwoKdHJhbnNjcmlwdBgFIAEoBUgBiAEBEhQKB3B1YmRhdGUYBiABKAlIAogBARIWCglwdWJsaXNoZWQYByABKAVIA4gBARITCgZ1cGRhdGUYCCABKAlIBIgBARIOCgZhdXRob3IYCSADKAkSFwoKc291cmNldHlwZRgKIAEoBUgFiAEBEhcKCnByb3ZlbmFuY2UYCyABKAVIBogBARIUCgdwcm92ZW50GAwgASgJSAeIAQESEQoEYzJwYRgNIAEoCUgIiAEBEiQKA2V4dBgPIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RCBwoFX2NsaXBCDQoLX3RyYW5zY3JpcHRCCgoIX3B1YmRhdGVCDAoKX3B1Ymxpc2hlZEIJCgdfdXBkYXRlQg0KC19zb3VyY2V0eXBlQg0KC19wcm92ZW5hbmNlQgoKCF9wcm92ZW50QgcKBV9jMnBhIv4CCgVJbWFnZRINCgV0aXRsZRgBIAMoCRIUCgdwdWJkYXRlGAIgASgJSACIAQESFgoJcHVibGlzaGVkGAMgASgFSAGIAQESEwoGdXBkYXRlGAQgASgJSAKIAQESDgoGYXV0aG9yGAUgAygJEhcKCnNvdXJjZXR5cGUYBiABKAVIA4gBARIXCgpwcm92ZW5hbmNlGAcgASgFSASIAQESFAoHcHJvdmVudBgIIAEoCUgFiAEBEhAKA2FsdBgJIAEoCUgGiAEBEhQKB2NhcHRpb24YCiABKAlIB4gBARIRCgRjMnBhGAsgASgJSAiIAQESJAoDZXh0GA8gASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEIKCghfcHViZGF0ZUIMCgpfcHVibGlzaGVkQgkKB191cGRhdGVCDQoLX3NvdXJjZXR5cGVCDQoLX3Byb3ZlbmFuY2VCCgoIX3Byb3ZlbnRCBgoEX2FsdEIKCghfY2FwdGlvbkIHCgVfYzJwYSKKAwoFQXVkaW8SDQoFdGl0bGUYASADKAkSCwoDZHVyGAIgAygFEhEKCXdvcmRjb3VudBgDIAMoBRIXCgp0cmFuc2NyaXB0GAQgASgFSACIAQESFAoHcHViZGF0ZRgFIAEoCUgBiAEBEhYKCXB1Ymxpc2hlZBgGIAEoBUgCiAEBEhMKBnVwZGF0ZRgHIAEoCUgDiAEBEg4KBmF1dGhvchgIIAMoCRIXCgpzb3VyY2V0eXBlGAkgASgFSASIAQESFwoKcHJvdmVuYW5jZRgKIAEoBUgFiAEBEhQKB3Byb3ZlbnQYCyABKAlIBogBARIRCgRjMnBhGAwgASgJSAeIAQESJAoDZXh0GA8gASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEINCgtfdHJhbnNjcmlwdEIKCghfcHViZGF0ZUIMCgpfcHVibGlzaGVkQgkKB191cGRhdGVCDQoLX3NvdXJjZXR5cGVCDQoLX3Byb3ZlbmFuY2VCCgoIX3Byb3ZlbnRCBwoFX2MycGEi0QEKCVJldHJpZXZhbBIpCgRhdXRoGAEgASgOMhYuY29tcC52MS5SZXRyaWV2YWxBdXRoSACIAQESFQoIZW5kcG9pbnQYAiABKAlIAYgBARIkCgR0eXBlGAMgAygOMhYuY29tcC52MS5SZXRyaWV2YWxUeXBlEhQKB3JhdGVsbXQYBCABKAVIAogBARIkCgNleHQYDyABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0QgcKBV9hdXRoQgsKCV9lbmRwb2ludEIKCghfcmF0ZWxtdCqcAQoKQXV0aE1ldGhvZBIaChZBVVRIX01FVEhPRF9VU0VSX0FHRU5UEAASEgoOQVVUSF9NRVRIT0RfSVAQARIVChFBVVRIX01FVEhPRF9UT0tFThACEhYKEkFVVEhfTUVUSE9EX1dFQkJPVBADEhgKFEFVVEhfTUVUSE9EX0FHRU5UX0lEEAQSFQoRQVVUSF9NRVRIT0RfT1RIRVIQBSq0AQoJU2NvcGVUeXBlEhoKFlNDT1BFX1RZUEVfRlVMTF9DT1JQVVMQABIWChJTQ09QRV9UWVBFX1NFQ1RJT04QARIZChVTQ09QRV9UWVBFX0RBVEVfUkFOR0UQAhIUChBTQ09QRV9UWVBFX0dFTlJFEAMSFAoQU0NPUEVfVFlQRV9UT1BJQxAEEhYKElNDT1BFX1RZUEVfQ1VSQVRFRBAFEhQKEFNDT1BFX1RZUEVfT1RIRVIQBiqLAQoIRnVuY3Rpb24SEAoMRlVOQ1RJT05fQUxMEAASEwoPRlVOQ1RJT05fQUlfQUxMEAESFQoRRlVOQ1RJT05fQUlfVFJBSU4QAhIVChFGVU5DVElPTl9BSV9JTlBVVBADEhUKEUZVTkNUSU9OX0FJX0lOREVYEAQSEwoPRlVOQ1RJT05fU0VBUkNIEAUqrwEKC1N1YkZ1bmN0aW9uEhkKFVNVQl9GVU5DVElPTl9UUkFJTklORxAAEhQKEFNVQl9GVU5DVElPTl9SQUcQARIaChZTVUJfRlVOQ1RJT05fR1JPVU5ESU5HEAISGwoXU1VCX0ZVTkNUSU9OX0FHRU5UX1ZJRVcQAxIeChpTVUJfRlVOQ1RJT05fQUdFTlRfQUNUSU9OUxAEEhYKElNVQl9GVU5DVElPTl9PVEhFUhAFKoMCCgpMaWNlbnNlVXNlEiAKHExJQ0VOU0VfVVNFX1RSQUlOSU5HX0RJU1BMQVkQABIoCiRMSUNFTlNFX1VTRV9SQUdfRElTUExBWV9VTlJFU1RSSUNURUQQARIlCiFMSUNFTlNFX1VTRV9SQUdfRElTUExBWV9NQVhfV09SRFMQAhInCiNMSUNFTlNFX1VTRV9SQUdfRElTUExBWV9BVFRSSUJVVElPThADEh4KGkxJQ0VOU0VfVVNFX1JBR19OT19ESVNQTEFZEAQSGgoWTElDRU5TRV9VU0VfQUdFTlRfVklFVxAFEh0KGUxJQ0VOU0VfVVNFX0FHRU5UX0FDVElPTlMQBiqaAQoLQ29udGVudFR5cGUSFQoRQ09OVEVOVF9UWVBFX1RFWFQQABIWChJDT05URU5UX1RZUEVfVklERU8QARIWChJDT05URU5UX1RZUEVfSU1BR0UQAhIWChJDT05URU5UX1RZUEVfQVVESU8QAxIUChBDT05URU5UX1RZUEVfQUxMEAQSFgoSQ09OVEVOVF9UWVBFX09USEVSEAUqdwoNUmV0cmlldmFsQXV0aBIXChNSRVRSSUVWQUxfQVVUSF9OT05FEAASGgoWUkVUUklFVkFMX0FVVEhfQVBJX0tFWRABEhkKFVJFVFJJRVZBTF9BVVRIX09BVVRIMhACEhYKElJFVFJJRVZBTF9BVVRIX1NTTBADKtcBCg1SZXRyaWV2YWxUeXBlEhcKE1JFVFJJRVZBTF9UWVBFX0hUTUwQABIWChJSRVRSSUVWQUxfVFlQRV9SU1MQARIWChJSRVRSSUVWQUxfVFlQRV9BUEkQAhIWChJSRVRSSUVWQUxfVFlQRV9NQ1AQAxIYChRSRVRSSUVWQUxfVFlQRV9OTFdFQhAEEhYKElJFVFJJRVZBTF9UWVBFX1hNTBAFEhkKFVJFVFJJRVZBTF9UWVBFX05FV1NNTBAGEhgKFFJFVFJJRVZBTF9UWVBFX09USEVSEAdCjgEKC2NvbS5jb21wLnYxQglDb21wUHJvdG9QAVo3Z2l0aHViLmNvbS9SQU1QLVByb3RvY29sL3Byb3RvY29sL2dlbi9nby9jb21wL3YxO2NvbXB2MaICA0NYWKoCB0NvbXAuVjHKAgdDb21wXFYx4gITQ29tcFxWMVxHUEJNZXRhZGF0YeoCCENvbXA6OlYxYgZwcm90bzM", [file_google_protobuf_struct]); + fileDesc("ChJjb21wL3YxL2NvbXAucHJvdG8SB2NvbXAudjEilgEKCEFJU3lzdGVtEgwKBG5hbWUYASABKAkSDwoCdWEYAiABKAlIAIgBARIPCgJpZBgDIAEoCUgBiAEBEiYKCGFpc3lzdXNlGAQgASgLMhQuY29tcC52MS5BSVN5c3RlbVVzZRIkCgNleHQYDyABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0QgUKA191YUIFCgNfaWQijgIKC0FJU3lzdGVtVXNlEgsKA2xpZBgBIAEoCRIjCgZhaWF1dGgYAiABKA4yEy5jb21wLnYxLkF1dGhNZXRob2QSCwoDdXJpGAMgAygJEiYKBXNjb3BlGAQgASgOMhIuY29tcC52MS5TY29wZVR5cGVIAIgBARIjCghmdW5jdGlvbhgFIAMoDjIRLmNvbXAudjEuRnVuY3Rpb24SIwoFc3ViZm4YBiADKA4yFC5jb21wLnYxLlN1YkZ1bmN0aW9uEhMKBnJlc2RpcxgHIAEoBUgBiAEBEiQKA2V4dBgPIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RCCAoGX3Njb3BlQgkKB19yZXNkaXMi9wIKB1BhY2thZ2USCgoCaWQYASABKAkSEgoFdGl0bGUYAiABKAlIAIgBARITCgZzZWxsZXIYAyABKAlIAYgBARIVCghwYWNrYWdlchgEIAEoCUgCiAEBEhcKCmxpY2Vuc2V1cmwYBSABKAlIA4gBARIVCghjaXRhdGlvbhgGIAEoBUgEiAEBEhYKCXJlcG9ydHVybBgHIAEoCUgFiAEBEiIKBXNjb3BlGAggASgLMg4uY29tcC52MS5TY29wZUgGiAEBEioKCXJldHJpZXZhbBgJIAEoCzISLmNvbXAudjEuUmV0cmlldmFsSAeIAQESJAoDZXh0GA8gASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEIICgZfdGl0bGVCCQoHX3NlbGxlckILCglfcGFja2FnZXJCDQoLX2xpY2Vuc2V1cmxCCwoJX2NpdGF0aW9uQgwKCl9yZXBvcnR1cmxCCAoGX3Njb3BlQgwKCl9yZXRyaWV2YWwiogQKBVNjb3BlEiYKBXNjb3BlGAEgASgOMhIuY29tcC52MS5TY29wZVR5cGVIAIgBARImCgRhdXNlGAIgASgOMhMuY29tcC52MS5BbGxvd2VkVXNlSAGIAQESKgoJcHJpY2V0eXBlGAMgASgOMhIuY29tcC52MS5QcmljZVR5cGVIAogBARIWCglwcmljZXRpZXIYBCABKAVIA4gBARIWCgl1bml0cHJpY2UYBSABKAFIBIgBARIQCgNjdXIYBiABKAlIBYgBARIPCgdjb3VudHJ5GAcgAygFEhcKCmxpY2Vuc2VkdXIYCCABKAVIBogBARIQCgNtYXgYCSABKAVIB4gBARIjCgVjdHlwZRgKIAMoDjIULmNvbXAudjEuQ29udGVudFR5cGUSGwoEdGV4dBgLIAMoCzINLmNvbXAudjEuVGV4dBIdCgV2aWRlbxgMIAMoCzIOLmNvbXAudjEuVmlkZW8SHQoFaW1hZ2UYDSADKAsyDi5jb21wLnYxLkltYWdlEh0KBWF1ZGlvGA4gAygLMg4uY29tcC52MS5BdWRpbxIkCgNleHQYDyABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0QggKBl9zY29wZUIHCgVfYXVzZUIMCgpfcHJpY2V0eXBlQgwKCl9wcmljZXRpZXJCDAoKX3VuaXRwcmljZUIGCgRfY3VyQg0KC19saWNlbnNlZHVyQgYKBF9tYXgihgMKBFRleHQSEgoFdGl0bGUYASABKAlIAIgBARIRCgl3b3JkY291bnQYAiADKAUSFAoHcHViZGF0ZRgDIAEoCUgBiAEBEhYKCXB1Ymxpc2hlZBgEIAEoBUgCiAEBEhMKBnVwZGF0ZRgFIAEoCUgDiAEBEg4KBmF1dGhvchgGIAMoCRIXCgpzb3VyY2V0eXBlGAcgASgFSASIAQESFwoKcHJvdmVuYW5jZRgIIAEoBUgFiAEBEhQKB3Byb3ZlbnQYCSABKAlIBogBARITCgZjYXR0YXgYCiABKAVIB4gBARILCgNjYXQYCyADKAUSEAoIbGFuZ3VhZ2UYDCADKAUSJAoDZXh0GA8gASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEIICgZfdGl0bGVCCgoIX3B1YmRhdGVCDAoKX3B1Ymxpc2hlZEIJCgdfdXBkYXRlQg0KC19zb3VyY2V0eXBlQg0KC19wcm92ZW5hbmNlQgoKCF9wcm92ZW50QgkKB19jYXR0YXgiyQMKBVZpZGVvEg0KBXRpdGxlGAEgAygJEgsKA2R1chgCIAMoBRIRCgRjbGlwGAMgASgFSACIAQESEQoJd29yZGNvdW50GAQgAygFEhcKCnRyYW5zY3JpcHQYBSABKAVIAYgBARIUCgdwdWJkYXRlGAYgASgJSAKIAQESFgoJcHVibGlzaGVkGAcgASgFSAOIAQESEwoGdXBkYXRlGAggASgJSASIAQESDgoGYXV0aG9yGAkgAygJEhcKCnNvdXJjZXR5cGUYCiABKAVIBYgBARIXCgpwcm92ZW5hbmNlGAsgASgFSAaIAQESFAoHcHJvdmVudBgMIAEoCUgHiAEBEhMKBmNhdHRheBgNIAEoBUgIiAEBEgsKA2NhdBgOIAMoBRIQCghsYW5ndWFnZRgQIAMoBRIkCgNleHQYDyABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0QgcKBV9jbGlwQg0KC190cmFuc2NyaXB0QgoKCF9wdWJkYXRlQgwKCl9wdWJsaXNoZWRCCQoHX3VwZGF0ZUINCgtfc291cmNldHlwZUINCgtfcHJvdmVuYW5jZUIKCghfcHJvdmVudEIJCgdfY2F0dGF4IuUCCgVJbWFnZRINCgV0aXRsZRgBIAMoCRIUCgdwdWJkYXRlGAIgASgJSACIAQESFgoJcHVibGlzaGVkGAMgASgFSAGIAQESEwoGdXBkYXRlGAQgASgJSAKIAQESDgoGYXV0aG9yGAUgAygJEhcKCnNvdXJjZXR5cGUYBiABKAVIA4gBARIXCgpwcm92ZW5hbmNlGAcgASgFSASIAQESFAoHcHJvdmVudBgIIAEoCUgFiAEBEhMKBmNhdHRheBgJIAEoBUgGiAEBEgsKA2NhdBgKIAMoBRIQCghsYW5ndWFnZRgLIAMoBRIkCgNleHQYDyABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0QgoKCF9wdWJkYXRlQgwKCl9wdWJsaXNoZWRCCQoHX3VwZGF0ZUINCgtfc291cmNldHlwZUINCgtfcHJvdmVuYW5jZUIKCghfcHJvdmVudEIJCgdfY2F0dGF4Iq0DCgVBdWRpbxINCgV0aXRsZRgBIAMoCRILCgNkdXIYAiADKAUSEQoJd29yZGNvdW50GAMgAygFEhcKCnRyYW5zY3JpcHQYBCABKAVIAIgBARIUCgdwdWJkYXRlGAUgASgJSAGIAQESFgoJcHVibGlzaGVkGAYgASgFSAKIAQESEwoGdXBkYXRlGAcgASgJSAOIAQESDgoGYXV0aG9yGAggAygJEhcKCnNvdXJjZXR5cGUYCSABKAVIBIgBARIXCgpwcm92ZW5hbmNlGAogASgFSAWIAQESFAoHcHJvdmVudBgLIAEoCUgGiAEBEhMKBmNhdHRheBgMIAEoBUgHiAEBEgsKA2NhdBgNIAMoBRIQCghsYW5ndWFnZRgOIAMoBRIkCgNleHQYDyABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0Qg0KC190cmFuc2NyaXB0QgoKCF9wdWJkYXRlQgwKCl9wdWJsaXNoZWRCCQoHX3VwZGF0ZUINCgtfc291cmNldHlwZUINCgtfcHJvdmVuYW5jZUIKCghfcHJvdmVudEIJCgdfY2F0dGF4Iq8BCglSZXRyaWV2YWwSKQoEYXV0aBgBIAEoDjIWLmNvbXAudjEuUmV0cmlldmFsQXV0aEgAiAEBEhUKCGVuZHBvaW50GAIgASgJSAGIAQESJAoEdHlwZRgDIAMoDjIWLmNvbXAudjEuUmV0cmlldmFsVHlwZRIkCgNleHQYDyABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0QgcKBV9hdXRoQgsKCV9lbmRwb2ludCqcAQoKQXV0aE1ldGhvZBIaChZBVVRIX01FVEhPRF9VU0VSX0FHRU5UEAASEgoOQVVUSF9NRVRIT0RfSVAQARIVChFBVVRIX01FVEhPRF9UT0tFThACEhYKEkFVVEhfTUVUSE9EX1dFQkJPVBADEhgKFEFVVEhfTUVUSE9EX0FHRU5UX0lEEAQSFQoRQVVUSF9NRVRIT0RfT1RIRVIQBSq0AQoJU2NvcGVUeXBlEhoKFlNDT1BFX1RZUEVfRlVMTF9DT1JQVVMQABIWChJTQ09QRV9UWVBFX1NFQ1RJT04QARIZChVTQ09QRV9UWVBFX0RBVEVfUkFOR0UQAhIUChBTQ09QRV9UWVBFX0dFTlJFEAMSFAoQU0NPUEVfVFlQRV9UT1BJQxAEEhYKElNDT1BFX1RZUEVfQ1VSQVRFRBAFEhQKEFNDT1BFX1RZUEVfT1RIRVIQBiqLAQoIRnVuY3Rpb24SEAoMRlVOQ1RJT05fQUxMEAASEwoPRlVOQ1RJT05fQUlfQUxMEAESFQoRRlVOQ1RJT05fQUlfVFJBSU4QAhIVChFGVU5DVElPTl9BSV9JTlBVVBADEhUKEUZVTkNUSU9OX0FJX0lOREVYEAQSEwoPRlVOQ1RJT05fU0VBUkNIEAUqrwEKC1N1YkZ1bmN0aW9uEhkKFVNVQl9GVU5DVElPTl9UUkFJTklORxAAEhQKEFNVQl9GVU5DVElPTl9SQUcQARIaChZTVUJfRlVOQ1RJT05fR1JPVU5ESU5HEAISGwoXU1VCX0ZVTkNUSU9OX0FHRU5UX1ZJRVcQAxIeChpTVUJfRlVOQ1RJT05fQUdFTlRfQUNUSU9OUxAEEhYKElNVQl9GVU5DVElPTl9PVEhFUhAFKs8BCgpBbGxvd2VkVXNlEhoKFkFMTE9XRURfVVNFX0NPTU1FUkNJQUwQABIeChpBTExPV0VEX1VTRV9OT05fQ09NTUVSQ0lBTBABEhsKF0FMTE9XRURfVVNFX0VEVUNBVElPTkFMEAISGgoWQUxMT1dFRF9VU0VfR09WRVJOTUVOVBADEhgKFEFMTE9XRURfVVNFX1BFUlNPTkFMEAQSGwoXQUxMT1dFRF9VU0VfQllPX0xJQ0VOU0UQBRIVChFBTExPV0VEX1VTRV9PVEhFUhAGKpkBCglQcmljZVR5cGUSFgoSUFJJQ0VfVFlQRV9QRVJfVVNFEAASGAoUUFJJQ0VfVFlQRV9QRVJfUVVFUlkQARIYChRQUklDRV9UWVBFX1BFUl9UT0tFThACEhMKD1BSSUNFX1RZUEVfRkxBVBADEhUKEVBSSUNFX1RZUEVfVElFUkVEEAQSFAoQUFJJQ0VfVFlQRV9PVEhFUhAFKpoBCgtDb250ZW50VHlwZRIVChFDT05URU5UX1RZUEVfVEVYVBAAEhYKEkNPTlRFTlRfVFlQRV9WSURFTxABEhYKEkNPTlRFTlRfVFlQRV9JTUFHRRACEhYKEkNPTlRFTlRfVFlQRV9BVURJTxADEhQKEENPTlRFTlRfVFlQRV9BTEwQBBIWChJDT05URU5UX1RZUEVfT1RIRVIQBSqRAQoNUmV0cmlldmFsQXV0aBIXChNSRVRSSUVWQUxfQVVUSF9OT05FEAASGgoWUkVUUklFVkFMX0FVVEhfQVBJX0tFWRABEhkKFVJFVFJJRVZBTF9BVVRIX09BVVRIMhACEhYKElJFVFJJRVZBTF9BVVRIX1NTTBADEhgKFFJFVFJJRVZBTF9BVVRIX09USEVSEAQq1wEKDVJldHJpZXZhbFR5cGUSFwoTUkVUUklFVkFMX1RZUEVfSFRNTBAAEhYKElJFVFJJRVZBTF9UWVBFX1JTUxABEhYKElJFVFJJRVZBTF9UWVBFX0FQSRACEhYKElJFVFJJRVZBTF9UWVBFX01DUBADEhgKFFJFVFJJRVZBTF9UWVBFX05MV0VCEAQSFgoSUkVUUklFVkFMX1RZUEVfWE1MEAUSGQoVUkVUUklFVkFMX1RZUEVfTkVXU01MEAYSGAoUUkVUUklFVkFMX1RZUEVfT1RIRVIQB0KOAQoLY29tLmNvbXAudjFCCUNvbXBQcm90b1ABWjdnaXRodWIuY29tL1JBTVAtUHJvdG9jb2wvcHJvdG9jb2wvZ2VuL2dvL2NvbXAvdjE7Y29tcHYxogIDQ1hYqgIHQ29tcC5WMcoCB0NvbXBcVjHiAhNDb21wXFYxXEdQQk1ldGFkYXRh6gIIQ29tcDo6VjFiBnByb3RvMw", [file_google_protobuf_struct]); /** * AISystem — Information about the AI System making the request. @@ -155,7 +159,7 @@ export const AISystemUseSchema: GenMessage = /*@__PURE__*/ */ export type Package = Message<"comp.v1.Package"> & { /** - * Unique package identifier defined by the Content Owner or Exchange. + * Unique package identifier defined by the Content Owner or Marketplace. * * @generated from field: string id = 1; */ @@ -183,7 +187,9 @@ export type Package = Message<"comp.v1.Package"> & { packager?: string | undefined; /** - * URL for the license terms. + * URL for AI system to find the License(s) required to access content. + * SSRF/fetch sink: a consumer that dereferences this URL must apply the + * countermeasures specified for core License.uri (threat model T-LIC-1). * * @generated from field: optional string licenseurl = 5; */ @@ -197,25 +203,27 @@ export type Package = Message<"comp.v1.Package"> & { citation?: number | undefined; /** - * Scope of content in this package. + * URL for AI system to send usage reporting to the Content Owner or + * Marketplace. POST/exfil sink: apply the SSRF countermeasures specified + * for core License.uri (threat model T-LIC-1) before dereferencing. * - * @generated from field: optional comp.v1.Scope scope = 7; + * @generated from field: optional string reporturl = 7; */ - scope?: Scope | undefined; + reporturl?: string | undefined; /** - * How to retrieve the content. + * Scope of content in this package. * - * @generated from field: optional comp.v1.Retrieval retrieval = 8; + * @generated from field: optional comp.v1.Scope scope = 8; */ - retrieval?: Retrieval | undefined; + scope?: Scope | undefined; /** - * Licensing terms for this package. + * How to retrieve the content. * - * @generated from field: repeated comp.v1.License license = 9; + * @generated from field: optional comp.v1.Retrieval retrieval = 9; */ - license: License[]; + retrieval?: Retrieval | undefined; /** * @generated from field: google.protobuf.Struct ext = 15; @@ -231,128 +239,111 @@ export const PackageSchema: GenMessage = /*@__PURE__*/ messageDesc(file_comp_v1_comp, 2); /** - * License — Licensing terms for a content package. - * CoMP §license.json + * Scope — What content is included in the package, plus its commercial terms. + * CoMP §scope.json — canonical V1 folds licensing/pricing into Scope. * - * @generated from message comp.v1.License + * @generated from message comp.v1.Scope */ -export type License = Message<"comp.v1.License"> & { - /** - * @generated from field: optional string id = 1; - */ - id?: string | undefined; - - /** - * @generated from field: optional string turl = 2; - */ - turl?: string | undefined; - - /** - * @generated from field: repeated comp.v1.LicenseUse use = 3; - */ - use: LicenseUse[]; - +export type Scope = Message<"comp.v1.Scope"> & { /** - * @generated from field: repeated string country = 4; + * How much of the Content Owner's corpus is available in this package. + * + * @generated from field: optional comp.v1.ScopeType scope = 1; */ - country: string[]; + scope?: ScopeType | undefined; /** - * @generated from field: optional int32 maxword = 5; + * Kind of use that is allowed for this package. + * + * @generated from field: optional comp.v1.AllowedUse ause = 2; */ - maxword?: number | undefined; + ause?: AllowedUse | undefined; /** - * 0=required, 1=not required + * How the package is priced. * - * @generated from field: optional int32 citation = 6; + * @generated from field: optional comp.v1.PriceType pricetype = 3; */ - citation?: number | undefined; + pricetype?: PriceType | undefined; /** - * @generated from field: optional double price = 7; + * Tier identifier if pricing is tiered (pricetype = 4). + * + * @generated from field: optional int32 pricetier = 4; */ - price?: number | undefined; + pricetier?: number | undefined; /** - * @generated from field: optional double revshare = 8; + * Content Owner set unit price at the given basis. Typed `double` to mirror + * the CoMP spec; downstream billing must convert to a decimal / minor-units + * representation — do not settle money directly off this float. + * + * @generated from field: optional double unitprice = 5; */ - revshare?: number | undefined; + unitprice?: number | undefined; /** - * @generated from field: optional string cur = 9; + * Bid currency using ISO-4217 alpha codes. Default "USD". + * + * @generated from field: optional string cur = 6; */ cur?: string | undefined; /** - * @generated from field: optional int32 dur = 10; + * Country code(s) where this package may be used, expressed by + * ISO-3166-1 numeric codes. + * + * @generated from field: repeated int32 country = 7; */ - dur?: number | undefined; + country: number[]; /** - * @generated from field: google.protobuf.Struct ext = 15; - */ - ext?: JsonObject | undefined; -}; - -/** - * Describes the message comp.v1.License. - * Use `create(LicenseSchema)` to create a new message. - */ -export const LicenseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_comp_v1_comp, 3); - -/** - * Scope — What content is included in the package. - * CoMP §scope.json - * - * @generated from message comp.v1.Scope - */ -export type Scope = Message<"comp.v1.Scope"> & { - /** - * @generated from field: optional comp.v1.ScopeType scope = 1; + * Number of days the license is active, once the content package has been + * delivered to the AI System. + * + * @generated from field: optional int32 licensedur = 8; */ - scope?: ScopeType | undefined; + licensedur?: number | undefined; /** * Upper limit on crawl. 0=unlimited, 1=has maximum. * - * @generated from field: optional int32 max = 2; + * @generated from field: optional int32 max = 9; */ max?: number | undefined; /** * Content type(s) included. * - * @generated from field: repeated comp.v1.ContentType ctype = 3; + * @generated from field: repeated comp.v1.ContentType ctype = 10; */ ctype: ContentType[]; /** * Text assets. * - * @generated from field: repeated comp.v1.Text text = 4; + * @generated from field: repeated comp.v1.Text text = 11; */ text: Text[]; /** * Video assets. * - * @generated from field: repeated comp.v1.Video video = 5; + * @generated from field: repeated comp.v1.Video video = 12; */ video: Video[]; /** * Image assets. * - * @generated from field: repeated comp.v1.Image image = 6; + * @generated from field: repeated comp.v1.Image image = 13; */ image: Image[]; /** * Audio assets. * - * @generated from field: repeated comp.v1.Audio audio = 7; + * @generated from field: repeated comp.v1.Audio audio = 14; */ audio: Audio[]; @@ -367,7 +358,7 @@ export type Scope = Message<"comp.v1.Scope"> & { * Use `create(ScopeSchema)` to create a new message. */ export const ScopeSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_comp_v1_comp, 4); + messageDesc(file_comp_v1_comp, 3); /** * Text — A text-based asset. @@ -382,7 +373,7 @@ export type Text = Message<"comp.v1.Text"> & { title?: string | undefined; /** - * Word count(s) of main body. + * Count of whitespace-delimited words in main body. * * @generated from field: repeated int32 wordcount = 2; */ @@ -396,7 +387,7 @@ export type Text = Message<"comp.v1.Text"> & { pubdate?: string | undefined; /** - * Publication status. 0=not specified, 1=published, 2=unpublished/archival. + * Denotes if the content is publicly available. Default 1 for Text. * * @generated from field: optional int32 published = 4; */ @@ -432,24 +423,34 @@ export type Text = Message<"comp.v1.Text"> & { /** * Canonical domain of the provenance entity (e.g. c2pa.org). + * Required if provenance = 1. * * @generated from field: optional string provent = 9; */ provent?: string | undefined; /** - * Authority score (0.0–1.0). Publisher/verifier-assessed domain authority. + * IAB category taxonomy in use. Default 9 (IAB Content Category Taxonomy 3.1). * - * @generated from field: optional double authority = 10; + * @generated from field: optional int32 cattax = 10; */ - authority?: number | undefined; + cattax?: number | undefined; /** - * Originality score (0.0–1.0). Degree of original vs. syndicated content. + * IAB Tech Lab content category codes (per cattax). * - * @generated from field: optional double originality = 11; + * @generated from field: repeated int32 cat = 11; */ - originality?: number | undefined; + cat: number[]; + + /** + * Content language. CoMP declares this `int` (array) though its prose says + * ISO-639-1 (alpha-2) — an upstream inconsistency; the proto follows the + * declared `int` type. + * + * @generated from field: repeated int32 language = 12; + */ + language: number[]; /** * @generated from field: google.protobuf.Struct ext = 15; @@ -462,7 +463,7 @@ export type Text = Message<"comp.v1.Text"> & { * Use `create(TextSchema)` to create a new message. */ export const TextSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_comp_v1_comp, 5); + messageDesc(file_comp_v1_comp, 4); /** * Video — A video asset. @@ -508,6 +509,8 @@ export type Video = Message<"comp.v1.Video"> & { pubdate?: string | undefined; /** + * Denotes if the content is publicly available. Default 0 for Video. + * * @generated from field: optional int32 published = 7; */ published?: number | undefined; @@ -538,11 +541,29 @@ export type Video = Message<"comp.v1.Video"> & { provent?: string | undefined; /** - * C2PA content credentials manifest URI. + * IAB category taxonomy in use. Default 9 (IAB Content Category Taxonomy 3.1). * - * @generated from field: optional string c2pa = 13; + * @generated from field: optional int32 cattax = 13; */ - c2pa?: string | undefined; + cattax?: number | undefined; + + /** + * IAB Tech Lab content category codes (per cattax). + * + * @generated from field: repeated int32 cat = 14; + */ + cat: number[]; + + /** + * Content language. CoMP declares this `int` (array) though its prose says + * ISO-639-1 (alpha-2) — an upstream inconsistency; the proto follows the + * declared `int` type. + * Tag 16 sits above ext (15) only here: cattax/cat consumed 13/14, and ext is + * kept at 15 for cross-message uniformity rather than the usual terminal slot. + * + * @generated from field: repeated int32 language = 16; + */ + language: number[]; /** * @generated from field: google.protobuf.Struct ext = 15; @@ -555,7 +576,7 @@ export type Video = Message<"comp.v1.Video"> & { * Use `create(VideoSchema)` to create a new message. */ export const VideoSchema: GenMessage