Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Generalize frequency rules from scalar package_id+campaign_id to arbitrary fcap_keys[]

Open
#104 7 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Quiet
Tech stack
go
Domain
backend, databases

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

claude-triaged

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:

  1. ExposureEntry: carry fcap_keys []string (or pre-hashed fcap_keys [][8]byte for binary log compactness) instead of separate PackageID / CampaignID fields. Or keep PackageID/CampaignID for backward compat and add fcap_keys as an additional field.
  2. FrequencyRule: attach to a fcap_key string rather than implicitly to a package or campaign.
  3. Engine: filter exposure entries by fcap_key membership in the entry's fcap_keys[], not by scalar match.
  4. Binary log format: exposure_binary.go currently 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.
  5. CheckFrequencyRulesMultiLog / CheckFrequencyRulesAggregated: drop the isCampaign bool parameter, take a single filterHash that 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 / CampaignID fields on ExposureEntry (deprecate but don't remove)
  • Add FcapKeys []string
  • During the transition, treat PackageID and CampaignID as implicit fcap_keys (pkg:<id> and campaign:<id>) so existing rules keep working
  • New rules attached via fcap_key directly

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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from adcontextprotocol/adcp-go

All issues in adcontextprotocol/adcp-go

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.