royaltyguard 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- royaltyguard-1.0.0/PKG-INFO +215 -0
- royaltyguard-1.0.0/README.md +186 -0
- royaltyguard-1.0.0/royaltyguard/__init__.py +70 -0
- royaltyguard-1.0.0/royaltyguard/advanced.py +414 -0
- royaltyguard-1.0.0/royaltyguard/detector.py +168 -0
- royaltyguard-1.0.0/royaltyguard/exceptions.py +17 -0
- royaltyguard-1.0.0/royaltyguard/models.py +119 -0
- royaltyguard-1.0.0/royaltyguard.egg-info/PKG-INFO +215 -0
- royaltyguard-1.0.0/royaltyguard.egg-info/SOURCES.txt +13 -0
- royaltyguard-1.0.0/royaltyguard.egg-info/dependency_links.txt +1 -0
- royaltyguard-1.0.0/royaltyguard.egg-info/requires.txt +1 -0
- royaltyguard-1.0.0/royaltyguard.egg-info/top_level.txt +1 -0
- royaltyguard-1.0.0/setup.cfg +4 -0
- royaltyguard-1.0.0/setup.py +38 -0
- royaltyguard-1.0.0/tests/test_royaltyguard.py +277 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: royaltyguard
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Creator royalty tracking and streaming fraud detection — detect bot streams, zero-rate payouts, duplicate claims for indie artists and labels
|
|
5
|
+
Home-page: https://github.com/royaltyguard-py/royaltyguard
|
|
6
|
+
Author:
|
|
7
|
+
Keywords: royalty tracking,streaming fraud detection,music royalties python,bot streams detection,spotify royalty audit,creator royalties,indie artist tools,royalty fraud,streaming manipulation detection,music rights management python
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Requires-Python: >=3.8
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: pydantic>=2.0
|
|
21
|
+
Dynamic: classifier
|
|
22
|
+
Dynamic: description
|
|
23
|
+
Dynamic: description-content-type
|
|
24
|
+
Dynamic: home-page
|
|
25
|
+
Dynamic: keywords
|
|
26
|
+
Dynamic: requires-dist
|
|
27
|
+
Dynamic: requires-python
|
|
28
|
+
Dynamic: summary
|
|
29
|
+
|
|
30
|
+
# royaltyguard
|
|
31
|
+
|
|
32
|
+
**Creator royalty tracking and streaming fraud detection** — detect bot streams, zero-rate payouts, duplicate claims, and royalty siphoning for indie artists, labels, and music platforms.
|
|
33
|
+
|
|
34
|
+
$2B/year is lost to streaming fraud. Indie creators have zero monitoring tools — enterprise solutions only. `royaltyguard` changes that.
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/royaltyguard/)
|
|
37
|
+
[](https://www.python.org/)
|
|
38
|
+
|
|
39
|
+
## The Problem
|
|
40
|
+
|
|
41
|
+
- $2B/year in streaming royalty fraud
|
|
42
|
+
- Bot streams inflate play counts, diluting the royalty pool for legitimate creators
|
|
43
|
+
- Zero-rate payout manipulation cheats creators on per-stream rates
|
|
44
|
+
- Indie artists have no affordable monitoring tool — only enterprise DSP solutions exist
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install royaltyguard
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from royaltyguard import AnomalyDetector, RoyaltyEntry, Platform
|
|
56
|
+
from datetime import datetime
|
|
57
|
+
|
|
58
|
+
detector = AnomalyDetector(
|
|
59
|
+
spike_multiplier=5.0,
|
|
60
|
+
min_rate_usd=0.003,
|
|
61
|
+
zero_rate_threshold=0.0005,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
entries = [
|
|
65
|
+
RoyaltyEntry(
|
|
66
|
+
entry_id="E001", creator_id="ARTIST-42", track_id="TRACK-99",
|
|
67
|
+
platform=Platform.SPOTIFY,
|
|
68
|
+
period_start=datetime(2025, 1, 1), period_end=datetime(2025, 1, 31),
|
|
69
|
+
streams=50000, royalty_amount=175.0,
|
|
70
|
+
),
|
|
71
|
+
RoyaltyEntry(
|
|
72
|
+
entry_id="E002", creator_id="ARTIST-42", track_id="TRACK-99",
|
|
73
|
+
platform=Platform.SPOTIFY,
|
|
74
|
+
period_start=datetime(2025, 2, 1), period_end=datetime(2025, 2, 28),
|
|
75
|
+
streams=2500000, # ← massive spike
|
|
76
|
+
royalty_amount=8750.0,
|
|
77
|
+
),
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
report = detector.analyze("ARTIST-42", entries)
|
|
81
|
+
|
|
82
|
+
print(f"Anomalies: {report.summary.anomalies_detected}")
|
|
83
|
+
print(f"Estimated fraud loss: ${report.summary.estimated_fraud_loss:.2f}")
|
|
84
|
+
print(report.recommendations)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Fraud Types Detected
|
|
88
|
+
|
|
89
|
+
| Fraud Type | Description |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `BOT_STREAMS` | Abnormal stream spike (5x+ standard deviation) |
|
|
92
|
+
| `ZERO_RATE_PAYOUTS` | Rate per stream below minimum threshold |
|
|
93
|
+
| `DUPLICATE_CLAIM` | Same track/platform reported twice in overlapping window |
|
|
94
|
+
| `ROYALTY_SIPHONING` | Systematic underpayment pattern |
|
|
95
|
+
| `STREAM_MANIPULATION` | Statistical manipulation of play counts |
|
|
96
|
+
|
|
97
|
+
## Platforms Supported
|
|
98
|
+
|
|
99
|
+
Spotify, Apple Music, YouTube Music, Amazon Music, Tidal, Deezer, SoundCloud, and custom platforms.
|
|
100
|
+
|
|
101
|
+
## Advanced Features
|
|
102
|
+
|
|
103
|
+
### Pipeline
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from royaltyguard import RoyaltyPipeline
|
|
107
|
+
|
|
108
|
+
pipeline = (
|
|
109
|
+
RoyaltyPipeline()
|
|
110
|
+
.filter(lambda e: e.streams > 1000, name="min_streams")
|
|
111
|
+
.map(lambda entries: sorted(entries, key=lambda e: -e.royalty_amount), name="sort_by_value")
|
|
112
|
+
.with_retry(count=2)
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
filtered = pipeline.run(entries)
|
|
116
|
+
print(pipeline.audit_log())
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Caching
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from royaltyguard import RoyaltyCache
|
|
123
|
+
|
|
124
|
+
cache = RoyaltyCache(max_size=512, ttl_seconds=1800)
|
|
125
|
+
|
|
126
|
+
@cache.memoize
|
|
127
|
+
def get_creator_report(creator_id):
|
|
128
|
+
return detector.analyze(creator_id, entries_map[creator_id])
|
|
129
|
+
|
|
130
|
+
cache.save("royalty_cache.pkl")
|
|
131
|
+
print(cache.stats())
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Validation
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from royaltyguard import RoyaltyValidator, RoyaltyRule
|
|
138
|
+
|
|
139
|
+
validator = RoyaltyValidator()
|
|
140
|
+
validator.add_rule(RoyaltyRule("min_streams", 100, "Ignore micro-plays"))
|
|
141
|
+
validator.add_rule(RoyaltyRule("allowed_platforms", ["spotify", "apple_music"]))
|
|
142
|
+
|
|
143
|
+
valid, errors = validator.validate(entry)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Batch Analysis
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from royaltyguard import batch_analyze, abatch_analyze
|
|
150
|
+
|
|
151
|
+
# Sync
|
|
152
|
+
reports = batch_analyze(
|
|
153
|
+
creator_ids=["ARTIST-1", "ARTIST-2"],
|
|
154
|
+
entries_map=entries_by_creator,
|
|
155
|
+
analyze_fn=detector.analyze,
|
|
156
|
+
max_workers=4,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Async
|
|
160
|
+
reports = await abatch_analyze(
|
|
161
|
+
creator_ids,
|
|
162
|
+
entries_map,
|
|
163
|
+
detector.analyze,
|
|
164
|
+
max_concurrency=8,
|
|
165
|
+
)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Export Reports
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
from royaltyguard import RoyaltyReportExporter
|
|
172
|
+
|
|
173
|
+
print(RoyaltyReportExporter.to_json(report))
|
|
174
|
+
print(RoyaltyReportExporter.to_csv(report))
|
|
175
|
+
print(RoyaltyReportExporter.to_markdown(report))
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Diff Between Periods
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from royaltyguard import diff_entries
|
|
182
|
+
|
|
183
|
+
diff = diff_entries(q1_entries, q2_entries)
|
|
184
|
+
print(diff.summary()) # {'added': 5, 'removed': 0, 'modified': 12}
|
|
185
|
+
print(diff.to_json())
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Drift Detection
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from royaltyguard import RoyaltyDriftDetector
|
|
192
|
+
|
|
193
|
+
detector_drift = RoyaltyDriftDetector(threshold=0.20)
|
|
194
|
+
for period_total in monthly_royalties:
|
|
195
|
+
detector_drift.record(period_total)
|
|
196
|
+
|
|
197
|
+
if detector_drift.is_drifted():
|
|
198
|
+
print("Royalty drift detected — investigate payout rates")
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Streaming
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from royaltyguard import stream_entries, entries_to_ndjson
|
|
205
|
+
|
|
206
|
+
for entry in stream_entries(all_entries):
|
|
207
|
+
process(entry)
|
|
208
|
+
|
|
209
|
+
for line in entries_to_ndjson(all_entries):
|
|
210
|
+
output.write(line)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
MIT
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# royaltyguard
|
|
2
|
+
|
|
3
|
+
**Creator royalty tracking and streaming fraud detection** — detect bot streams, zero-rate payouts, duplicate claims, and royalty siphoning for indie artists, labels, and music platforms.
|
|
4
|
+
|
|
5
|
+
$2B/year is lost to streaming fraud. Indie creators have zero monitoring tools — enterprise solutions only. `royaltyguard` changes that.
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/royaltyguard/)
|
|
8
|
+
[](https://www.python.org/)
|
|
9
|
+
|
|
10
|
+
## The Problem
|
|
11
|
+
|
|
12
|
+
- $2B/year in streaming royalty fraud
|
|
13
|
+
- Bot streams inflate play counts, diluting the royalty pool for legitimate creators
|
|
14
|
+
- Zero-rate payout manipulation cheats creators on per-stream rates
|
|
15
|
+
- Indie artists have no affordable monitoring tool — only enterprise DSP solutions exist
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install royaltyguard
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from royaltyguard import AnomalyDetector, RoyaltyEntry, Platform
|
|
27
|
+
from datetime import datetime
|
|
28
|
+
|
|
29
|
+
detector = AnomalyDetector(
|
|
30
|
+
spike_multiplier=5.0,
|
|
31
|
+
min_rate_usd=0.003,
|
|
32
|
+
zero_rate_threshold=0.0005,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
entries = [
|
|
36
|
+
RoyaltyEntry(
|
|
37
|
+
entry_id="E001", creator_id="ARTIST-42", track_id="TRACK-99",
|
|
38
|
+
platform=Platform.SPOTIFY,
|
|
39
|
+
period_start=datetime(2025, 1, 1), period_end=datetime(2025, 1, 31),
|
|
40
|
+
streams=50000, royalty_amount=175.0,
|
|
41
|
+
),
|
|
42
|
+
RoyaltyEntry(
|
|
43
|
+
entry_id="E002", creator_id="ARTIST-42", track_id="TRACK-99",
|
|
44
|
+
platform=Platform.SPOTIFY,
|
|
45
|
+
period_start=datetime(2025, 2, 1), period_end=datetime(2025, 2, 28),
|
|
46
|
+
streams=2500000, # ← massive spike
|
|
47
|
+
royalty_amount=8750.0,
|
|
48
|
+
),
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
report = detector.analyze("ARTIST-42", entries)
|
|
52
|
+
|
|
53
|
+
print(f"Anomalies: {report.summary.anomalies_detected}")
|
|
54
|
+
print(f"Estimated fraud loss: ${report.summary.estimated_fraud_loss:.2f}")
|
|
55
|
+
print(report.recommendations)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Fraud Types Detected
|
|
59
|
+
|
|
60
|
+
| Fraud Type | Description |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `BOT_STREAMS` | Abnormal stream spike (5x+ standard deviation) |
|
|
63
|
+
| `ZERO_RATE_PAYOUTS` | Rate per stream below minimum threshold |
|
|
64
|
+
| `DUPLICATE_CLAIM` | Same track/platform reported twice in overlapping window |
|
|
65
|
+
| `ROYALTY_SIPHONING` | Systematic underpayment pattern |
|
|
66
|
+
| `STREAM_MANIPULATION` | Statistical manipulation of play counts |
|
|
67
|
+
|
|
68
|
+
## Platforms Supported
|
|
69
|
+
|
|
70
|
+
Spotify, Apple Music, YouTube Music, Amazon Music, Tidal, Deezer, SoundCloud, and custom platforms.
|
|
71
|
+
|
|
72
|
+
## Advanced Features
|
|
73
|
+
|
|
74
|
+
### Pipeline
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from royaltyguard import RoyaltyPipeline
|
|
78
|
+
|
|
79
|
+
pipeline = (
|
|
80
|
+
RoyaltyPipeline()
|
|
81
|
+
.filter(lambda e: e.streams > 1000, name="min_streams")
|
|
82
|
+
.map(lambda entries: sorted(entries, key=lambda e: -e.royalty_amount), name="sort_by_value")
|
|
83
|
+
.with_retry(count=2)
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
filtered = pipeline.run(entries)
|
|
87
|
+
print(pipeline.audit_log())
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Caching
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from royaltyguard import RoyaltyCache
|
|
94
|
+
|
|
95
|
+
cache = RoyaltyCache(max_size=512, ttl_seconds=1800)
|
|
96
|
+
|
|
97
|
+
@cache.memoize
|
|
98
|
+
def get_creator_report(creator_id):
|
|
99
|
+
return detector.analyze(creator_id, entries_map[creator_id])
|
|
100
|
+
|
|
101
|
+
cache.save("royalty_cache.pkl")
|
|
102
|
+
print(cache.stats())
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Validation
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from royaltyguard import RoyaltyValidator, RoyaltyRule
|
|
109
|
+
|
|
110
|
+
validator = RoyaltyValidator()
|
|
111
|
+
validator.add_rule(RoyaltyRule("min_streams", 100, "Ignore micro-plays"))
|
|
112
|
+
validator.add_rule(RoyaltyRule("allowed_platforms", ["spotify", "apple_music"]))
|
|
113
|
+
|
|
114
|
+
valid, errors = validator.validate(entry)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Batch Analysis
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from royaltyguard import batch_analyze, abatch_analyze
|
|
121
|
+
|
|
122
|
+
# Sync
|
|
123
|
+
reports = batch_analyze(
|
|
124
|
+
creator_ids=["ARTIST-1", "ARTIST-2"],
|
|
125
|
+
entries_map=entries_by_creator,
|
|
126
|
+
analyze_fn=detector.analyze,
|
|
127
|
+
max_workers=4,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Async
|
|
131
|
+
reports = await abatch_analyze(
|
|
132
|
+
creator_ids,
|
|
133
|
+
entries_map,
|
|
134
|
+
detector.analyze,
|
|
135
|
+
max_concurrency=8,
|
|
136
|
+
)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Export Reports
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from royaltyguard import RoyaltyReportExporter
|
|
143
|
+
|
|
144
|
+
print(RoyaltyReportExporter.to_json(report))
|
|
145
|
+
print(RoyaltyReportExporter.to_csv(report))
|
|
146
|
+
print(RoyaltyReportExporter.to_markdown(report))
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Diff Between Periods
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from royaltyguard import diff_entries
|
|
153
|
+
|
|
154
|
+
diff = diff_entries(q1_entries, q2_entries)
|
|
155
|
+
print(diff.summary()) # {'added': 5, 'removed': 0, 'modified': 12}
|
|
156
|
+
print(diff.to_json())
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Drift Detection
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from royaltyguard import RoyaltyDriftDetector
|
|
163
|
+
|
|
164
|
+
detector_drift = RoyaltyDriftDetector(threshold=0.20)
|
|
165
|
+
for period_total in monthly_royalties:
|
|
166
|
+
detector_drift.record(period_total)
|
|
167
|
+
|
|
168
|
+
if detector_drift.is_drifted():
|
|
169
|
+
print("Royalty drift detected — investigate payout rates")
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Streaming
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from royaltyguard import stream_entries, entries_to_ndjson
|
|
176
|
+
|
|
177
|
+
for entry in stream_entries(all_entries):
|
|
178
|
+
process(entry)
|
|
179
|
+
|
|
180
|
+
for line in entries_to_ndjson(all_entries):
|
|
181
|
+
output.write(line)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""royaltyguard — Creator royalty tracking and streaming fraud detection."""
|
|
2
|
+
from royaltyguard.models import (
|
|
3
|
+
CreatorRoyaltySummary,
|
|
4
|
+
FraudType,
|
|
5
|
+
Platform,
|
|
6
|
+
RoyaltyEntry,
|
|
7
|
+
RoyaltyReport,
|
|
8
|
+
StreamAnomaly,
|
|
9
|
+
)
|
|
10
|
+
from royaltyguard.detector import AnomalyDetector
|
|
11
|
+
from royaltyguard.exceptions import (
|
|
12
|
+
DetectionError,
|
|
13
|
+
ReportError,
|
|
14
|
+
RoyaltyGuardError,
|
|
15
|
+
ValidationError,
|
|
16
|
+
)
|
|
17
|
+
from royaltyguard.advanced import (
|
|
18
|
+
AuditLog,
|
|
19
|
+
CancellationToken,
|
|
20
|
+
PIIScrubber,
|
|
21
|
+
RateLimiter,
|
|
22
|
+
RoyaltyCache,
|
|
23
|
+
RoyaltyDiff,
|
|
24
|
+
RoyaltyDriftDetector,
|
|
25
|
+
RoyaltyPipeline,
|
|
26
|
+
RoyaltyProfiler,
|
|
27
|
+
RoyaltyReportExporter,
|
|
28
|
+
RoyaltyRule,
|
|
29
|
+
RoyaltyValidator,
|
|
30
|
+
abatch_analyze,
|
|
31
|
+
batch_analyze,
|
|
32
|
+
diff_entries,
|
|
33
|
+
entries_to_ndjson,
|
|
34
|
+
stream_entries,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
__version__ = "1.0.0"
|
|
38
|
+
__all__ = [
|
|
39
|
+
# Core
|
|
40
|
+
"AnomalyDetector",
|
|
41
|
+
"RoyaltyEntry",
|
|
42
|
+
"RoyaltyReport",
|
|
43
|
+
"StreamAnomaly",
|
|
44
|
+
"CreatorRoyaltySummary",
|
|
45
|
+
"FraudType",
|
|
46
|
+
"Platform",
|
|
47
|
+
# Exceptions
|
|
48
|
+
"RoyaltyGuardError",
|
|
49
|
+
"DetectionError",
|
|
50
|
+
"ValidationError",
|
|
51
|
+
"ReportError",
|
|
52
|
+
# Advanced
|
|
53
|
+
"RoyaltyCache",
|
|
54
|
+
"RoyaltyPipeline",
|
|
55
|
+
"RoyaltyValidator",
|
|
56
|
+
"RoyaltyRule",
|
|
57
|
+
"RateLimiter",
|
|
58
|
+
"CancellationToken",
|
|
59
|
+
"batch_analyze",
|
|
60
|
+
"abatch_analyze",
|
|
61
|
+
"RoyaltyProfiler",
|
|
62
|
+
"RoyaltyDriftDetector",
|
|
63
|
+
"RoyaltyReportExporter",
|
|
64
|
+
"stream_entries",
|
|
65
|
+
"entries_to_ndjson",
|
|
66
|
+
"RoyaltyDiff",
|
|
67
|
+
"diff_entries",
|
|
68
|
+
"AuditLog",
|
|
69
|
+
"PIIScrubber",
|
|
70
|
+
]
|