Generalize frequency rules from scalar package_id+campaign_id to arbitrary fcap_keys[]
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
Research direction
Start by reading the targeting package’s exposure data model and frequency rule checks, then inspect exposure_binary.go and the referenced identity match implementation document. Trace how binary logs encode and decode the current fixed hash slots, and review the linked preaggregation work in PR #103 for the indexes this change extends. Done means arbitrary fcap_keys can be checked and encoded while existing package and campaign callers remain compatible.
Written by the indexing model from the issue text.
Description
Background
The AdCP TMP spec (adcp#3359) defines frequency caps using an fcap_keys[] label model — tenant:dimension:value strings (e.g. buyer-acme:campaign:42, buyer-acme:advertiser:13, buyer-acme:creative:8) — with arbitrary buyer-chosen dimensions.
The current adcp-go/targeting/ impl predates this design and uses scalar fields:
ExposureEntry { ImpressionID, PackageID, CampaignID, SourceID, Timestamp }PackageIdentityConfig.FrequencyRules(per package)CampaignFreqConfig.FrequencyRules(per campaign)CheckFrequencyRulesMultiLog(logs, filterHash, isCampaign, ...)— boolean isCampaign flag picks between two scalar paths
This means today the impl supports exactly package-level and campaign-level caps; advertiser, creative, line-item, group, or any other dimension a buyer might want to cap on isn't expressible.
What needs to change
Generalize the data model so the dimension is arbitrary:
- ExposureEntry: carry
fcap_keys []string(or pre-hashedfcap_keys [][8]bytefor binary log compactness) instead of separatePackageID/CampaignIDfields. Or keep PackageID/CampaignID for backward compat and addfcap_keysas an additional field. - FrequencyRule: attach to a
fcap_keystring rather than implicitly to a package or campaign. - Engine: filter exposure entries by
fcap_keymembership in the entry'sfcap_keys[], not by scalar match. - Binary log format:
exposure_binary.gocurrently has fixed slots for ImpressionHash / PackageHash / CampaignHash / SourceHash. Either widen entries to variable-size (carry a count + N fcap_key hashes) or version-bump to a different layout. Backward compat plan: v1 = current, v2 = arbitrary fcap_keys, decoder handles both. - CheckFrequencyRulesMultiLog / CheckFrequencyRulesAggregated: drop the
isCampaign boolparameter, take a singlefilterHashthat matches against any fcap_key on the entry.
Backward compatibility
Existing callers using package_id and campaign_id should continue to work. Suggested approach:
- Keep
PackageID/CampaignIDfields onExposureEntry(deprecate but don't remove) - Add
FcapKeys []string - During the transition, treat
PackageIDandCampaignIDas implicit fcap_keys (pkg:<id>andcampaign:<id>) so existing rules keep working - New rules attached via
fcap_keydirectly
Why this matters
Without the generalization, buyers can only cap at package and campaign level. The whole point of the label model (per the spec) is that buyers choose dimensions — most DSPs need advertiser-level, creative-level, and flight-level caps. Today buyers running adcp-go's targeting/ package can't express those.
Out of scope for this issue
- The pre-aggregation optimization in #103 — that's orthogonal and should land first; the generalization extends the same data structures it indexes.
- Wire-spec changes — TMP itself doesn't carry fcap_keys on the wire; they're buyer-internal. No protocol coordination needed.
- Multi-tenant isolation rules (tenant prefix requirement) — those are buyer-side enforcement that lives in the SDK, not in
targeting/.
References
- AdCP spec PR: adcontextprotocol/adcp#3359
- fcap_keys label model section:
docs/trusted-match/identity-match-implementation.mdx#fcap_keys-label-model - Spec open question #1 explicitly tracks this work
- Related upstream perf PR (preaggregation): #103 — should land first; generalization builds on the same indexes.
- Dominant language
- Go
- Stars
- 4
- Forks
- 2
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 14
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from adcontextprotocol/adcp-go
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
adcontextprotocol/adcp-go#567 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
adcontextprotocol/adcp-go#562 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 22/100
adcontextprotocol/adcp-go#564 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 8/100
adcontextprotocol/adcp-go#556 ·
Maintainers usually reply within 1 day
-
claude-triaged cross-repo
Difficulty 5/5 Over a week Newbie friendliness 25/100
adcontextprotocol/adcp-go#548 · 2 comments ·
Maintainers usually reply within 1 day
All issues in adcontextprotocol/adcp-go
Similar issues
-
documentation hacktoberfest priority: low skill: good first issue status: ready for dev
Difficulty 2/5 Half a day Newbie friendliness 85/100
hyperledger-labs/fabric-smart-client#2142 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
numberly/vault-db-injector#107 ·
Maintainers usually reply within 1 day
-
area/import kind/bug
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 1 day
-
[DOC] Wrong sg_egress_ports range in the Terraform Databricks Guide for AWS Hub & Spoke with Network FirewallPossibly taken @akhil9tiet claimed this today. Opendocs
Difficulty 1/5 Under an hour Newbie friendliness 72/100
databricks/terraform-provider-databricks#6080 · 1 comment ·
Maintainers usually reply within 3 days
-
spqr-coordinator usage shows 'run --config', but 'run' is not a subcommand (unknown command "run")Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
pg-sharding/spqr#3092 · 1 comment ·
Maintainers usually reply within 1 day