data-vendor-contractual-usage-restriction-tracking · v2.0.0 · 2026-08-23 · sha256 6d79064972b5cdb3
data-vendor-contractual-usage-restriction-tracking v2.0.0A
Immutable. This exact content is served forever at /api/v1/blob/6d79064972b5cdb3.
--- name: data-vendor-contractual-usage-restriction-tracking description: Fail-closed pre-access gate enforcing market data vendor contract scope — licensed use cases, non-display entitlement, external redistribution, seat caps, and contract term — with an auditable reason recorded for every decision. domain: Data Management Global subdomain: Vendor Data Governance tags: - vendor-compliance - data-licensing - non-display-trading - bloomberg-bpipe - lseg-dacs - redistribution-audit - entitlement-tracking brokers_frameworks: - LSEG DACS (formerly Refinitiv DACS) - Bloomberg EMRS - Nasdaq Global Data Agreement - Python Dataclasses version: "2.0.0" author: algo-trading-skills-contributors license: Apache-2.0 --- ## When to Use Use this skill when an internal system — a research notebook, a risk engine, an execution algo, a client-facing portal — asks for vendor market data, and the firm must decide whether that specific purpose is inside the scope it actually licensed (Bloomberg B-PIPE, LSEG Real-Time / DACS, ICE Data Services, S&P Capital IQ). The gate exists because licensing breaches are discovered late and priced retroactively. Under the Nasdaq Global Data Agreement, any use of the Information not already provided for in the Nasdaq Requirements — expressly including derived information, retransmission, redistribution and index calculation — requires prior written approval and payment of the applicable fees (GDA s.4(c)). Nasdaq may audit a Distributor's records, reports and systems, normally no more than once in twelve months (s.7(a)). Where a Final Audit finds underreporting, the amounts plus interest are due within sixty days, and for a good-faith error the Distributor's liability reaches back **three years** (s.7(e)); underreporting of 10% or more of reported Reportable Units also makes the Distributor liable for Nasdaq's audit, legal and administrative costs (s.7(f)). Other venues and vendors impose their own audit clauses on comparable terms — read yours. ## When NOT to Use - **Not a fee calculator.** It counts contractual seats, not fee-liable units. Its seat counter cannot produce a vendor invoice or an exchange usage declaration — see the unit-of-count pitfall below. - **Not a replacement for the vendor's entitlement system.** Bloomberg EMRS and LSEG DACS enforce permissioning at the feed itself. This gate sits upstream of them and does not remove the need to configure them correctly. - **Not for venue-level entitlement or subscriber classification.** Professional vs non-professional status, per-venue licences and real-time vs delayed tiers belong to `market-data-entitlement-and-licensing-per-venue` and `real-time-vs-delayed-data-entitlement-handling`. - **Not a legal opinion.** It enforces the scope a compliance owner has encoded. Reading the contract and encoding it correctly is still a human job. ## Prerequisites - `VendorContractSpec`: `vendor_id`, `vendor_name`, `license_tier`, `allowed_use_cases`, `is_non_display_allowed`, `is_redistribution_allowed`, `max_concurrent_entitlements`, `current_active_entitlements` (default 0), `contract_expiration_date` (ISO-8601 `YYYY-MM-DD`, or `None` for "not tracked"). - `DataAccessRequest`: `request_id`, `vendor_id`, `requested_by_system`, `use_case_type`, `is_external_redistribution`, `requested_seats` (default 1). - A durable store for the returned `VendorUsageAuditReport` objects. The engine's in-memory buffer is bounded and is not the retained audit record. ## Workflow Checks run in this order and short-circuit on the first denial. The order is part of the contract: it determines which `status` an auditor sees for a request that breaches more than one restriction. 1. **Contract term gate** — if `as_of_date` is past `contract_expiration_date`, deny with `CONTRACT_EXPIRED`. Checked first because a lapsed term withdraws every other permission. A contract registered with `contract_expiration_date=None` is **not** gated on expiry; the engine logs a warning once per vendor so the omission is visible rather than silent. 2. **External redistribution gate** — deny with `REDISTRIBUTION_LICENSING_VIOLATION` when the request is external redistribution and the contract does not permit it. A request counts as redistribution if **either** `is_external_redistribution` is True **or** `use_case_type == "EXTERNAL_REDISTRIBUTION"`; the two signals can disagree, and this is the breach with the longest back-fee tail, so it fails closed on either one alone. 3. **Non-display gate** — if `use_case_type == "NON_DISPLAY_TRADING"` and `is_non_display_allowed` is False, deny with `NON_DISPLAY_LICENSING_VIOLATION`. Non-display means machine access without a natural person reading a display; it is fee-liable whether the engine runs on a desktop, in a datacenter or in the cloud. 4. **Licensed scope gate** — if the normalised `use_case_type` is not in `allowed_use_cases`, deny with `UNAUTHORIZED_USE_CASE_VIOLATION`. Unlisted means unlicensed: never widen the list to make a request pass. 5. **Concurrency headroom gate** — if `current_active_entitlements + requested_seats` would exceed `max_concurrent_entitlements`, deny with `CONCURRENCY_CAP_EXCEEDED`. A request landing exactly on the cap is approved. 6. **Reserve and record** — on approval the seats are reserved against the contract and a `VendorUsageAuditReport` is returned. Denials never mutate contract state. When the consuming system disconnects, call `release_entitlement(vendor_id, seats)`. > Full procedure: see `references/workflows.md`. > Standards reference: see `references/standards.md`. > Printable pre-flight checklist: see `assets/checklist.md`. ## Common Pitfalls - **Approving without ever releasing.** Every approval reserves seats permanently until `release_entitlement` returns them. A gate wired into connection setup but not into teardown drifts into denying compliant requests within hours, and the usual "fix" is to raise the cap above what the contract actually licensed. - **Reading the seat counter as a reportable unit count.** Nasdaq's non-display unit of count is the *greater* of (a) the number of Subscribers that can modify the application in real time or (b) the number of Devices (usually servers) that receive and benefit from the Information. A per-request seat counter will understate it. Derive declarations from your infrastructure inventory. - **Assuming "derived" means "unrestricted".** Derived Data is information that cannot be reverse-engineered back into Exchange Information or into a recognisable substitute for it. A client-facing chart of vendor quotes, a redistributed index recalculated from them, or a "summary" from which the underlying prices can be recovered is not derived data — it is redistribution, and GDA s.4(c) requires prior written approval and fees before it happens. - **Trusting one of two disagreeing signals.** A caller that sets `use_case_type="EXTERNAL_REDISTRIBUTION"` but leaves `is_external_redistribution` False is still redistributing. Gate on both. - **Placeholder expiry dates.** A hard-coded future `contract_expiration_date` authorises everything until the day it passes and then denies everything at once. Populate it from the executed contract or leave it `None` and track expiry elsewhere. - **Running desktop-terminal data through an algo.** A research desktop subscription does not carry non-display rights; pointing an automated strategy at it is a licensing breach regardless of how the bytes reached the process. ## Verification - Instantiate `VendorUsageRestrictionEngine`. Register a B-PIPE-style contract (`is_non_display_allowed=True`, `is_redistribution_allowed=False`, `max_concurrent_entitlements=10`, `current_active_entitlements=2`, `contract_expiration_date="2027-12-31"`). - Submit an internal HFT request (`use_case_type="NON_DISPLAY_TRADING"`, `is_external_redistribution=False`) $\implies$ `APPROVED`, `active_entitlements_remaining == 7`. - Submit a client-portal request with `is_external_redistribution=True` $\implies$ `REDISTRIBUTION_LICENSING_VIOLATION`, `is_approved` False, and the contract's `current_active_entitlements` unchanged. - Submit `use_case_type="EXTERNAL_REDISTRIBUTION"` with `is_external_redistribution=False` $\implies$ still `REDISTRIBUTION_LICENSING_VIOLATION`. - Evaluate with `as_of_date` past the expiry $\implies$ `CONTRACT_EXPIRED`. - Run `python scripts/test_vendor_usage_tracking.py`. ## Related Skills - `real-time-vs-delayed-data-entitlement-handling` - `market-data-entitlement-and-licensing-per-venue` - `market-data-cost-optimization-tiered-subscriptions`