@xnetjs/abuse 0.0.1
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.
- package/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/adapters-B-9W_mn3.d.ts +190 -0
- package/dist/adapters-B63EWOI3.d.ts +196 -0
- package/dist/adapters-B92QvJK9.d.ts +190 -0
- package/dist/adapters-BE8Dk1m1.d.ts +193 -0
- package/dist/adapters-BPXuKMIo.d.ts +196 -0
- package/dist/adapters-BtDzNNjU.d.ts +190 -0
- package/dist/adapters-CBfkKocx.d.ts +196 -0
- package/dist/adapters-CD50ercr.d.ts +191 -0
- package/dist/adapters-CIj_ODTY.d.ts +190 -0
- package/dist/adapters-D2lWWuTk.d.ts +196 -0
- package/dist/adapters-Qu3BkEMk.d.ts +153 -0
- package/dist/adapters-hOtVE8hd.d.ts +153 -0
- package/dist/adapters-k10HxbtE.d.ts +190 -0
- package/dist/adapters.d.ts +1 -0
- package/dist/adapters.js +12 -0
- package/dist/chunk-4FW6LHWU.js +495 -0
- package/dist/chunk-O2ZULYP6.js +487 -0
- package/dist/chunk-O3JDSAJP.js +507 -0
- package/dist/chunk-O4S27KHE.js +390 -0
- package/dist/chunk-Y2RKXAMV.js +499 -0
- package/dist/index.d.ts +1408 -0
- package/dist/index.js +3201 -0
- package/package.json +42 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1408 @@
|
|
|
1
|
+
import { N as NormalizedAbuseFacts, A as AbuseLabel, a as AbuseFacts, b as AbuseDecision, D as DecisionExplanation, c as AbuseReasonCode, d as DecisionExplanationReason, e as AbuseSurface, f as AbuseQualitySignals, g as AbuseVisibility, h as AbuseReach, i as AbuseReviewQueue, j as AbuseResource, P as PolicyScope, k as AbuseDecisionOverride } from './adapters-CBfkKocx.js';
|
|
2
|
+
export { E as AbuseActorFacts, t as AbuseAdapterResult, F as AbuseAdmission, G as AbuseCryptoFacts, u as AbuseDecisionFunction, H as AbuseDecisionOverrideScope, v as AbuseFactAdapter, y as AbusePeerScoreBucket, I as AbuseResourceFacts, J as AbuseReviewDecision, K as AbuseSeverity, z as AbuseTelemetryReporter, L as PendingLabel, M as PendingSecurityEvent, R as RemoteAdmissionPipeline, w as RemoteAdmissionPipelineOptions, x as RemoteAdmissionResult, B as RemoteMutationRejectionTelemetry, C as RemoteMutationRejectionTelemetryInput, p as bucketAbusePeerScore, l as createAbuseDecisionAdapter, m as createAbuseFactAdapter, n as createRemoteAdmissionPipeline, q as createRemoteMutationRejectionTelemetry, o as decideWithAdapter, r as hashAbusePeerIdentifier, s as reportRemoteMutationRejection } from './adapters-CBfkKocx.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Pure abuse decision helpers.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare function normalizeAbuseFacts(facts: AbuseFacts): NormalizedAbuseFacts;
|
|
9
|
+
declare function decideTransport(facts?: Omit<AbuseFacts, 'surface'>): AbuseDecision;
|
|
10
|
+
declare function decideRemoteMutation(facts?: Omit<AbuseFacts, 'surface'>): AbuseDecision;
|
|
11
|
+
declare function decidePublicInteraction(facts?: Omit<AbuseFacts, 'surface'> & {
|
|
12
|
+
surface?: 'commentThread' | 'messageInbox';
|
|
13
|
+
}): AbuseDecision;
|
|
14
|
+
declare function decideReach(facts?: Omit<AbuseFacts, 'surface'> & {
|
|
15
|
+
surface?: 'searchIndex' | 'feed';
|
|
16
|
+
}): AbuseDecision;
|
|
17
|
+
declare function decideAbuse(input: AbuseFacts): AbuseDecision;
|
|
18
|
+
declare function activeLabels(facts: NormalizedAbuseFacts): readonly AbuseLabel[];
|
|
19
|
+
declare function weightedLabelScore(facts: NormalizedAbuseFacts, values: readonly string[]): number;
|
|
20
|
+
declare function qualityRiskScore(facts: NormalizedAbuseFacts): number;
|
|
21
|
+
declare function shouldThrottle(decision: AbuseDecision): boolean;
|
|
22
|
+
declare function isVisible(decision: AbuseDecision): boolean;
|
|
23
|
+
declare function isRejected(decision: AbuseDecision): boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Human-readable explanations for deterministic abuse decisions.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
declare function explainDecision(decision: AbuseDecision): DecisionExplanation;
|
|
30
|
+
declare function getReasonDetail(code: AbuseReasonCode): DecisionExplanationReason;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Reusable abuse decision fixtures for tests and adapters.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
declare const TRUSTED_SPAM_LABEL: AbuseLabel;
|
|
37
|
+
declare const WARNING_SLOP_LABEL: AbuseLabel;
|
|
38
|
+
declare function createBaseFacts(overrides?: Partial<AbuseFacts>): AbuseFacts;
|
|
39
|
+
declare const abuseFixtures: {
|
|
40
|
+
readonly validRemoteMutation: AbuseFacts;
|
|
41
|
+
readonly invalidSignatureRemoteMutation: AbuseFacts;
|
|
42
|
+
readonly oversizedRemoteMutation: AbuseFacts;
|
|
43
|
+
readonly firstContactComment: AbuseFacts;
|
|
44
|
+
readonly trustedSpamComment: AbuseFacts;
|
|
45
|
+
readonly lowQualitySearchCandidate: AbuseFacts;
|
|
46
|
+
readonly expiredSpamLabel: AbuseFacts;
|
|
47
|
+
readonly throttledPeer: AbuseFacts;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Model/provider provenance helpers for AI-generated moderation signals.
|
|
52
|
+
*/
|
|
53
|
+
type AISignalSourceType = 'local-ai' | 'cloud-ai';
|
|
54
|
+
type AISignalProvenanceInput = {
|
|
55
|
+
sourceType?: string;
|
|
56
|
+
modelProvider?: string;
|
|
57
|
+
modelName?: string;
|
|
58
|
+
modelVersion?: string;
|
|
59
|
+
adapterId?: string;
|
|
60
|
+
adapterVersion?: string;
|
|
61
|
+
policyId?: string;
|
|
62
|
+
};
|
|
63
|
+
type AISignalProvenance = {
|
|
64
|
+
sourceType: AISignalSourceType;
|
|
65
|
+
modelProvider: string;
|
|
66
|
+
modelName: string;
|
|
67
|
+
modelVersion?: string;
|
|
68
|
+
adapterId?: string;
|
|
69
|
+
adapterVersion?: string;
|
|
70
|
+
policyId?: string;
|
|
71
|
+
};
|
|
72
|
+
type AISignalProvenanceValidation = {
|
|
73
|
+
required: boolean;
|
|
74
|
+
valid: boolean;
|
|
75
|
+
errors: string[];
|
|
76
|
+
provenance: AISignalProvenance | null;
|
|
77
|
+
};
|
|
78
|
+
declare function isAISignalSourceType(sourceType: string | undefined): sourceType is AISignalSourceType;
|
|
79
|
+
declare function validateAISignalProvenance(input: AISignalProvenanceInput): AISignalProvenanceValidation;
|
|
80
|
+
declare function createAISignalProvenanceEvidenceRef(input: AISignalProvenanceInput): string | null;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Deterministic content fingerprints for duplicate and near-duplicate checks.
|
|
84
|
+
*/
|
|
85
|
+
type ContentFingerprintInput = string | {
|
|
86
|
+
title?: string;
|
|
87
|
+
body?: string;
|
|
88
|
+
};
|
|
89
|
+
type ContentFingerprintOptions = {
|
|
90
|
+
minTokenLength?: number;
|
|
91
|
+
shingleSize?: number;
|
|
92
|
+
maxShingles?: number;
|
|
93
|
+
};
|
|
94
|
+
type DuplicateContentOptions = ContentFingerprintOptions & {
|
|
95
|
+
nearDuplicateThreshold?: number;
|
|
96
|
+
weakDuplicateThreshold?: number;
|
|
97
|
+
};
|
|
98
|
+
type ContentFingerprint = {
|
|
99
|
+
kind: 'xnet.content-fingerprint.v1';
|
|
100
|
+
textHash: string;
|
|
101
|
+
simHash64: string;
|
|
102
|
+
tokenCount: number;
|
|
103
|
+
uniqueTokenCount: number;
|
|
104
|
+
shingleSize: number;
|
|
105
|
+
shingles: string[];
|
|
106
|
+
};
|
|
107
|
+
type DuplicateContentAssessment = {
|
|
108
|
+
duplicateScore: number;
|
|
109
|
+
matchType: 'none' | 'exact' | 'near' | 'weak';
|
|
110
|
+
exact: boolean;
|
|
111
|
+
matchedIndex: number | null;
|
|
112
|
+
matchedTextHash: string | null;
|
|
113
|
+
shingleJaccard: number;
|
|
114
|
+
simHashSimilarity: number;
|
|
115
|
+
reasons: string[];
|
|
116
|
+
};
|
|
117
|
+
declare function createContentFingerprint(input: ContentFingerprintInput, options?: ContentFingerprintOptions): ContentFingerprint;
|
|
118
|
+
declare function assessDuplicateContent(candidate: ContentFingerprintInput | ContentFingerprint, references: readonly (ContentFingerprintInput | ContentFingerprint)[], options?: DuplicateContentOptions): DuplicateContentAssessment;
|
|
119
|
+
declare function compareContentFingerprints(candidate: ContentFingerprint, reference: ContentFingerprint, options?: DuplicateContentOptions & {
|
|
120
|
+
matchedIndex?: number;
|
|
121
|
+
}): DuplicateContentAssessment;
|
|
122
|
+
declare function canonicalizeContentText(input: ContentFingerprintInput): string;
|
|
123
|
+
declare function tokenizeContent(canonicalText: string, options?: ContentFingerprintOptions): string[];
|
|
124
|
+
declare function compareSimHash64(left: string, right: string): number;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Budgeted cloud classifier adapters for optional moderation review.
|
|
128
|
+
*/
|
|
129
|
+
|
|
130
|
+
type CloudPrivacyMode = 'disabled' | 'metadata-only' | 'redacted-content' | 'raw-content';
|
|
131
|
+
type CloudClassificationSkipReason = 'cloud-disabled' | 'unsupported-surface' | 'provider-not-allowed' | 'privacy-policy-blocked' | 'over-budget';
|
|
132
|
+
type CloudClassifierInput = {
|
|
133
|
+
surface: AbuseSurface;
|
|
134
|
+
subjectId?: string;
|
|
135
|
+
title?: string;
|
|
136
|
+
body: string;
|
|
137
|
+
language?: string;
|
|
138
|
+
metadata?: Record<string, unknown>;
|
|
139
|
+
contentFingerprint?: ContentFingerprint;
|
|
140
|
+
};
|
|
141
|
+
type CloudClassifierPrivacyPolicy = {
|
|
142
|
+
mode: CloudPrivacyMode;
|
|
143
|
+
allowedProviders?: readonly string[];
|
|
144
|
+
allowedSurfaces?: readonly AbuseSurface[];
|
|
145
|
+
sendSubjectId?: boolean;
|
|
146
|
+
sendMetadata?: boolean;
|
|
147
|
+
sendContentFingerprint?: boolean;
|
|
148
|
+
maxInputChars?: number;
|
|
149
|
+
redactPatterns?: readonly RegExp[];
|
|
150
|
+
redactionReplacement?: string;
|
|
151
|
+
requireExplicitRawContentApproval?: boolean;
|
|
152
|
+
rawContentApproved?: boolean;
|
|
153
|
+
};
|
|
154
|
+
type CloudClassifierBudgetPolicy = {
|
|
155
|
+
remainingMicroUsd: number;
|
|
156
|
+
maxPerRequestMicroUsd: number;
|
|
157
|
+
minRemainingMicroUsd?: number;
|
|
158
|
+
};
|
|
159
|
+
type CloudClassifierRequest = {
|
|
160
|
+
provider: string;
|
|
161
|
+
model: string;
|
|
162
|
+
adapterId: string;
|
|
163
|
+
adapterVersion: string;
|
|
164
|
+
surface: AbuseSurface;
|
|
165
|
+
subjectId?: string;
|
|
166
|
+
title?: string;
|
|
167
|
+
body?: string;
|
|
168
|
+
language?: string;
|
|
169
|
+
metadata?: Record<string, unknown>;
|
|
170
|
+
contentFingerprint?: ContentFingerprint;
|
|
171
|
+
privacyMode: Exclude<CloudPrivacyMode, 'disabled'>;
|
|
172
|
+
estimatedCostMicroUsd: number;
|
|
173
|
+
};
|
|
174
|
+
type CloudClassifierProvenance = {
|
|
175
|
+
provider: 'cloud';
|
|
176
|
+
cloudProvider: string;
|
|
177
|
+
adapterId: string;
|
|
178
|
+
adapterVersion: string;
|
|
179
|
+
model: string;
|
|
180
|
+
policyId?: string;
|
|
181
|
+
privacyMode: Exclude<CloudPrivacyMode, 'disabled'>;
|
|
182
|
+
};
|
|
183
|
+
type CloudClassifierSignal = {
|
|
184
|
+
kind: 'label' | 'quality';
|
|
185
|
+
value: string;
|
|
186
|
+
confidence: number;
|
|
187
|
+
reason?: string;
|
|
188
|
+
evidenceRefs: string[];
|
|
189
|
+
provenance: CloudClassifierProvenance;
|
|
190
|
+
};
|
|
191
|
+
type CloudClassifierProviderSignal = Omit<CloudClassifierSignal, 'provenance'> & {
|
|
192
|
+
evidenceRefs?: readonly string[];
|
|
193
|
+
};
|
|
194
|
+
type CloudClassifierProviderResult = {
|
|
195
|
+
labels?: readonly AbuseLabel[];
|
|
196
|
+
quality?: Partial<AbuseQualitySignals>;
|
|
197
|
+
signals?: readonly CloudClassifierProviderSignal[];
|
|
198
|
+
chargedCostMicroUsd?: number;
|
|
199
|
+
errors?: readonly string[];
|
|
200
|
+
};
|
|
201
|
+
type CloudClassificationUsage = {
|
|
202
|
+
estimatedCostMicroUsd: number;
|
|
203
|
+
chargedCostMicroUsd: number;
|
|
204
|
+
remainingBudgetMicroUsd: number;
|
|
205
|
+
privacyMode: CloudPrivacyMode;
|
|
206
|
+
sentBodyChars: number;
|
|
207
|
+
};
|
|
208
|
+
type CloudClassificationResult = {
|
|
209
|
+
labels: AbuseLabel[];
|
|
210
|
+
quality: Partial<AbuseQualitySignals>;
|
|
211
|
+
signals: CloudClassifierSignal[];
|
|
212
|
+
provenance: CloudClassifierProvenance;
|
|
213
|
+
usage: CloudClassificationUsage;
|
|
214
|
+
skipped: CloudClassificationSkipReason | null;
|
|
215
|
+
elapsedMs?: number;
|
|
216
|
+
errors: string[];
|
|
217
|
+
};
|
|
218
|
+
type CloudClassifierAdapter = {
|
|
219
|
+
id: string;
|
|
220
|
+
version: string;
|
|
221
|
+
provider: string;
|
|
222
|
+
model: string;
|
|
223
|
+
policyId?: string;
|
|
224
|
+
defaultEstimatedCostMicroUsd: number;
|
|
225
|
+
supports?: (input: CloudClassifierInput) => boolean;
|
|
226
|
+
estimateCostMicroUsd?: (request: Omit<CloudClassifierRequest, 'estimatedCostMicroUsd'>) => number;
|
|
227
|
+
classify: (request: CloudClassifierRequest) => CloudClassifierProviderResult | Promise<CloudClassifierProviderResult>;
|
|
228
|
+
};
|
|
229
|
+
type CloudClassificationOptions = {
|
|
230
|
+
now?: number;
|
|
231
|
+
};
|
|
232
|
+
declare function classifyWithCloudAdapter(input: CloudClassifierInput, adapter: CloudClassifierAdapter, privacy: CloudClassifierPrivacyPolicy, budget: CloudClassifierBudgetPolicy, _options?: CloudClassificationOptions): Promise<CloudClassificationResult>;
|
|
233
|
+
declare function createCloudClassifierAdapter(adapter: CloudClassifierAdapter): CloudClassifierAdapter;
|
|
234
|
+
declare function createCloudClassifierRequestBase(input: CloudClassifierInput, adapter: CloudClassifierAdapter, privacy: CloudClassifierPrivacyPolicy): Omit<CloudClassifierRequest, 'estimatedCostMicroUsd'>;
|
|
235
|
+
declare function estimateCloudClassifierCost(adapter: CloudClassifierAdapter, request: Omit<CloudClassifierRequest, 'estimatedCostMicroUsd'>): number;
|
|
236
|
+
declare function getCloudClassificationSkipReason(input: CloudClassifierInput, adapter: CloudClassifierAdapter, privacy: CloudClassifierPrivacyPolicy, budget: CloudClassifierBudgetPolicy): CloudClassificationSkipReason | null;
|
|
237
|
+
declare function redactCloudClassifierText(text: string, patterns?: readonly RegExp[], replacement?: string): string;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Local classifier adapter interfaces for moderation and quality signals.
|
|
241
|
+
*/
|
|
242
|
+
|
|
243
|
+
type LocalClassifierInput = {
|
|
244
|
+
surface: AbuseSurface;
|
|
245
|
+
subjectId?: string;
|
|
246
|
+
title?: string;
|
|
247
|
+
body: string;
|
|
248
|
+
language?: string;
|
|
249
|
+
metadata?: Record<string, unknown>;
|
|
250
|
+
contentFingerprint?: ContentFingerprint;
|
|
251
|
+
};
|
|
252
|
+
type LocalClassifierOptions = {
|
|
253
|
+
now?: number;
|
|
254
|
+
maxInputChars?: number;
|
|
255
|
+
minConfidence?: number;
|
|
256
|
+
};
|
|
257
|
+
type LocalClassifierProvenance = {
|
|
258
|
+
provider: 'local';
|
|
259
|
+
adapterId: string;
|
|
260
|
+
adapterVersion: string;
|
|
261
|
+
model?: string;
|
|
262
|
+
policyId?: string;
|
|
263
|
+
};
|
|
264
|
+
type LocalClassifierSignal = {
|
|
265
|
+
kind: 'label' | 'quality';
|
|
266
|
+
value: string;
|
|
267
|
+
confidence: number;
|
|
268
|
+
reason?: string;
|
|
269
|
+
evidenceRefs: string[];
|
|
270
|
+
provenance: LocalClassifierProvenance;
|
|
271
|
+
};
|
|
272
|
+
type LocalClassificationResult = {
|
|
273
|
+
labels: AbuseLabel[];
|
|
274
|
+
quality: Partial<AbuseQualitySignals>;
|
|
275
|
+
signals: LocalClassifierSignal[];
|
|
276
|
+
provenance: LocalClassifierProvenance;
|
|
277
|
+
elapsedMs?: number;
|
|
278
|
+
errors: string[];
|
|
279
|
+
};
|
|
280
|
+
type LocalClassifierAdapter = {
|
|
281
|
+
id: string;
|
|
282
|
+
version: string;
|
|
283
|
+
model?: string;
|
|
284
|
+
supports?: (input: LocalClassifierInput) => boolean;
|
|
285
|
+
classify: (input: LocalClassifierInput, options?: LocalClassifierOptions) => LocalClassificationResult | Promise<LocalClassificationResult>;
|
|
286
|
+
};
|
|
287
|
+
type KeywordClassifierRule = {
|
|
288
|
+
label: string;
|
|
289
|
+
keywords: string[];
|
|
290
|
+
confidence: number;
|
|
291
|
+
sourceWeight?: number;
|
|
292
|
+
expiresInMs?: number;
|
|
293
|
+
};
|
|
294
|
+
type KeywordLocalClassifierOptions = {
|
|
295
|
+
id?: string;
|
|
296
|
+
version?: string;
|
|
297
|
+
model?: string;
|
|
298
|
+
sourceDid?: string;
|
|
299
|
+
rules: KeywordClassifierRule[];
|
|
300
|
+
};
|
|
301
|
+
declare function classifyWithLocalAdapters(input: LocalClassifierInput, adapters: readonly LocalClassifierAdapter[], options?: LocalClassifierOptions): Promise<LocalClassificationResult>;
|
|
302
|
+
declare function createKeywordLocalClassifier(options: KeywordLocalClassifierOptions): LocalClassifierAdapter;
|
|
303
|
+
declare function mergeLocalClassificationResults(results: readonly LocalClassificationResult[], options?: LocalClassifierOptions): LocalClassificationResult;
|
|
304
|
+
declare function createLocalClassificationResult(input: {
|
|
305
|
+
labels?: AbuseLabel[];
|
|
306
|
+
quality?: Partial<AbuseQualitySignals>;
|
|
307
|
+
signals?: LocalClassifierSignal[];
|
|
308
|
+
provenance: LocalClassifierProvenance;
|
|
309
|
+
elapsedMs?: number;
|
|
310
|
+
errors?: string[];
|
|
311
|
+
}): LocalClassificationResult;
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Local-first moderation classifier cascade.
|
|
315
|
+
*/
|
|
316
|
+
|
|
317
|
+
type CloudReviewSkipReason = CloudClassificationSkipReason | 'cloud-not-configured' | 'low-risk-local-signals';
|
|
318
|
+
type CloudReviewCallReason = 'local-label-risk' | 'local-quality-risk' | 'no-local-signals';
|
|
319
|
+
type CloudReviewCallPolicy = {
|
|
320
|
+
enabled?: boolean;
|
|
321
|
+
allowedSurfaces?: readonly AbuseSurface[];
|
|
322
|
+
minLocalLabelConfidence?: number;
|
|
323
|
+
minLocalQualityRisk?: number;
|
|
324
|
+
forceWhenNoLocalSignals?: boolean;
|
|
325
|
+
};
|
|
326
|
+
type ModerationCascadeCloudConfig = {
|
|
327
|
+
adapter: CloudClassifierAdapter;
|
|
328
|
+
privacy: CloudClassifierPrivacyPolicy;
|
|
329
|
+
budget: CloudClassifierBudgetPolicy;
|
|
330
|
+
callPolicy?: CloudReviewCallPolicy;
|
|
331
|
+
options?: CloudClassificationOptions;
|
|
332
|
+
};
|
|
333
|
+
type ModerationCascadeOptions = {
|
|
334
|
+
localAdapters?: readonly LocalClassifierAdapter[];
|
|
335
|
+
localOptions?: LocalClassifierOptions;
|
|
336
|
+
cloud?: ModerationCascadeCloudConfig;
|
|
337
|
+
};
|
|
338
|
+
type CloudReviewRouteDecision = {
|
|
339
|
+
callCloud: true;
|
|
340
|
+
reasons: readonly CloudReviewCallReason[];
|
|
341
|
+
skipped: null;
|
|
342
|
+
} | {
|
|
343
|
+
callCloud: false;
|
|
344
|
+
reasons: readonly CloudReviewCallReason[];
|
|
345
|
+
skipped: CloudReviewSkipReason;
|
|
346
|
+
};
|
|
347
|
+
type ModerationCascadeResult = {
|
|
348
|
+
labels: AbuseLabel[];
|
|
349
|
+
quality: Partial<AbuseQualitySignals>;
|
|
350
|
+
local: LocalClassificationResult;
|
|
351
|
+
cloud?: CloudClassificationResult;
|
|
352
|
+
cloudCalled: boolean;
|
|
353
|
+
cloudReasons: readonly CloudReviewCallReason[];
|
|
354
|
+
cloudSkippedReason: CloudReviewSkipReason | null;
|
|
355
|
+
errors: readonly string[];
|
|
356
|
+
};
|
|
357
|
+
declare function classifyWithModerationCascade(input: LocalClassifierInput, options?: ModerationCascadeOptions): Promise<ModerationCascadeResult>;
|
|
358
|
+
declare function decideCloudReviewRoute(input: LocalClassifierInput, local: LocalClassificationResult, policy?: CloudReviewCallPolicy): CloudReviewRouteDecision;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Signed hub policy and service offer documents.
|
|
362
|
+
*/
|
|
363
|
+
|
|
364
|
+
type HubPolicyServiceKind = 'sync-relay' | 'node-relay' | 'public-write' | 'crawl' | 'search-index' | 'federation-query' | 'labeler' | 'ai-review' | 'appeal';
|
|
365
|
+
type HubPolicySettlementMode = 'free' | 'paid' | 'sponsored' | 'reciprocal' | 'mixed';
|
|
366
|
+
type HubModerationMode = 'off' | 'local-deterministic' | 'labeler-assisted' | 'ai-assisted' | 'human-reviewed' | 'hybrid';
|
|
367
|
+
type HubPolicyAIReviewSettings = {
|
|
368
|
+
localModelsEnabled: boolean;
|
|
369
|
+
cloudModelsEnabled: boolean;
|
|
370
|
+
rawContentToCloudAllowed: boolean;
|
|
371
|
+
maxCloudReviewMicroUsdPerDay?: number;
|
|
372
|
+
defaultReviewQueue?: AbuseReviewQueue;
|
|
373
|
+
};
|
|
374
|
+
type HubPolicyLabelSettings = {
|
|
375
|
+
trustedLabelerDIDs: readonly string[];
|
|
376
|
+
subscribedPolicyListIds: readonly string[];
|
|
377
|
+
maxLabelsPerSubject?: number;
|
|
378
|
+
allowLabelNegation: boolean;
|
|
379
|
+
};
|
|
380
|
+
type HubPolicyModerationSettings = {
|
|
381
|
+
mode: HubModerationMode;
|
|
382
|
+
requireSignedWrites: boolean;
|
|
383
|
+
rejectUnsignedFederation: boolean;
|
|
384
|
+
quarantineFirstContact: boolean;
|
|
385
|
+
allowLocalOverride: boolean;
|
|
386
|
+
publishLabelExplanations: boolean;
|
|
387
|
+
defaultVisibility: AbuseVisibility;
|
|
388
|
+
defaultReach: AbuseReach;
|
|
389
|
+
aiReview: HubPolicyAIReviewSettings;
|
|
390
|
+
labels: HubPolicyLabelSettings;
|
|
391
|
+
};
|
|
392
|
+
type HubPolicyBudgetHint = {
|
|
393
|
+
name: string;
|
|
394
|
+
workType: 'public-write' | 'crawl' | 'search-index' | 'federation-query' | 'cloud-review' | 'moderation-review' | 'labeling';
|
|
395
|
+
scope: string;
|
|
396
|
+
unitsPerWindow: number;
|
|
397
|
+
windowMs: number;
|
|
398
|
+
};
|
|
399
|
+
type HubPolicyServiceOfferEntry = {
|
|
400
|
+
service: HubPolicyServiceKind;
|
|
401
|
+
enabled: boolean;
|
|
402
|
+
endpoint?: string;
|
|
403
|
+
authenticated: boolean;
|
|
404
|
+
settlement: HubPolicySettlementMode;
|
|
405
|
+
costMicroUsdPerUnit?: number;
|
|
406
|
+
reciprocalCreditRatio?: number;
|
|
407
|
+
sponsoredBy?: string;
|
|
408
|
+
};
|
|
409
|
+
type HubPolicyOperatorContact = {
|
|
410
|
+
displayName?: string;
|
|
411
|
+
homepageUrl?: string;
|
|
412
|
+
email?: string;
|
|
413
|
+
abuseReportUrl?: string;
|
|
414
|
+
securityContactUrl?: string;
|
|
415
|
+
jurisdiction?: string;
|
|
416
|
+
responseTimeHours?: number;
|
|
417
|
+
};
|
|
418
|
+
type HubPolicyAppealChannelKind = 'web-form' | 'email' | 'xnet-message' | 'external-ticket';
|
|
419
|
+
type HubPolicyAppealChannel = {
|
|
420
|
+
kind: HubPolicyAppealChannelKind;
|
|
421
|
+
authenticated: boolean;
|
|
422
|
+
url?: string;
|
|
423
|
+
email?: string;
|
|
424
|
+
recipientDID?: string;
|
|
425
|
+
languages?: readonly string[];
|
|
426
|
+
minResponseTimeHours?: number;
|
|
427
|
+
maxResponseTimeHours?: number;
|
|
428
|
+
};
|
|
429
|
+
type UnsignedHubPolicyServiceOffer = {
|
|
430
|
+
v: 1;
|
|
431
|
+
kind: 'xnet.hub.policy-service-offer';
|
|
432
|
+
id: string;
|
|
433
|
+
hubDID: string;
|
|
434
|
+
issuerDID: string;
|
|
435
|
+
title?: string;
|
|
436
|
+
createdAt: number;
|
|
437
|
+
updatedAt: number;
|
|
438
|
+
expiresAt?: number;
|
|
439
|
+
moderation: HubPolicyModerationSettings;
|
|
440
|
+
services: readonly HubPolicyServiceOfferEntry[];
|
|
441
|
+
budgetHints: readonly HubPolicyBudgetHint[];
|
|
442
|
+
policyRefs: readonly string[];
|
|
443
|
+
operatorContact?: HubPolicyOperatorContact;
|
|
444
|
+
appealChannels: readonly HubPolicyAppealChannel[];
|
|
445
|
+
};
|
|
446
|
+
type HubPolicyServiceOfferSignature = {
|
|
447
|
+
alg: 'Ed25519';
|
|
448
|
+
value: string;
|
|
449
|
+
};
|
|
450
|
+
type SignedHubPolicyServiceOffer = UnsignedHubPolicyServiceOffer & {
|
|
451
|
+
signature: HubPolicyServiceOfferSignature;
|
|
452
|
+
};
|
|
453
|
+
type HubPolicyServiceOfferVerificationResult = {
|
|
454
|
+
valid: boolean;
|
|
455
|
+
errors: readonly string[];
|
|
456
|
+
};
|
|
457
|
+
declare const createHubPolicyServiceOffer: (input: Omit<UnsignedHubPolicyServiceOffer, "v" | "kind" | "createdAt" | "updatedAt" | "moderation" | "budgetHints" | "policyRefs" | "operatorContact" | "appealChannels"> & {
|
|
458
|
+
createdAt?: number;
|
|
459
|
+
updatedAt?: number;
|
|
460
|
+
moderation?: Partial<HubPolicyModerationSettings> & {
|
|
461
|
+
aiReview?: Partial<HubPolicyAIReviewSettings>;
|
|
462
|
+
labels?: Partial<HubPolicyLabelSettings>;
|
|
463
|
+
};
|
|
464
|
+
budgetHints?: readonly HubPolicyBudgetHint[];
|
|
465
|
+
policyRefs?: readonly string[];
|
|
466
|
+
operatorContact?: HubPolicyOperatorContact;
|
|
467
|
+
appealChannels?: readonly HubPolicyAppealChannel[];
|
|
468
|
+
}) => UnsignedHubPolicyServiceOffer;
|
|
469
|
+
declare const canonicalizeHubPolicyServiceOffer: (offer: UnsignedHubPolicyServiceOffer) => string;
|
|
470
|
+
declare const hubPolicyServiceOfferSigningBytes: (offer: UnsignedHubPolicyServiceOffer) => Uint8Array;
|
|
471
|
+
declare const signHubPolicyServiceOffer: (offer: UnsignedHubPolicyServiceOffer, signingKey: Uint8Array) => SignedHubPolicyServiceOffer;
|
|
472
|
+
declare const unsignedHubPolicyServiceOffer: (offer: SignedHubPolicyServiceOffer | UnsignedHubPolicyServiceOffer) => UnsignedHubPolicyServiceOffer;
|
|
473
|
+
declare const isSignedHubPolicyServiceOffer: (offer: unknown) => offer is SignedHubPolicyServiceOffer;
|
|
474
|
+
declare const validateHubPolicyServiceOffer: (offer: UnsignedHubPolicyServiceOffer, now?: number) => HubPolicyServiceOfferVerificationResult;
|
|
475
|
+
declare const verifySignedHubPolicyServiceOffer: (offer: SignedHubPolicyServiceOffer, now?: number) => HubPolicyServiceOfferVerificationResult;
|
|
476
|
+
declare const activeHubPolicyServices: (offer: SignedHubPolicyServiceOffer | UnsignedHubPolicyServiceOffer) => readonly HubPolicyServiceOfferEntry[];
|
|
477
|
+
declare const publicAppealChannels: (offer: SignedHubPolicyServiceOffer | UnsignedHubPolicyServiceOffer) => readonly HubPolicyAppealChannel[];
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Public write budget accounting for local-first and federated surfaces.
|
|
481
|
+
*/
|
|
482
|
+
|
|
483
|
+
type PublicWriteBudgetScope = 'did' | 'hub' | 'workspace' | 'surface' | 'did-surface' | 'hub-surface' | 'workspace-surface';
|
|
484
|
+
type PublicWriteBudgetLimit = {
|
|
485
|
+
scope: PublicWriteBudgetScope;
|
|
486
|
+
unitsPerWindow: number;
|
|
487
|
+
windowMs: number;
|
|
488
|
+
};
|
|
489
|
+
type PublicWriteBudgetPolicy = {
|
|
490
|
+
limits: readonly PublicWriteBudgetLimit[];
|
|
491
|
+
defaultCostUnits?: number;
|
|
492
|
+
};
|
|
493
|
+
type PublicWriteBudgetInput = {
|
|
494
|
+
did?: string;
|
|
495
|
+
hubId?: string;
|
|
496
|
+
workspaceId?: string;
|
|
497
|
+
surface: AbuseSurface;
|
|
498
|
+
costUnits?: number;
|
|
499
|
+
now?: number;
|
|
500
|
+
};
|
|
501
|
+
type PublicWriteBudgetUsage = {
|
|
502
|
+
key: string;
|
|
503
|
+
scope: PublicWriteBudgetScope;
|
|
504
|
+
usedUnits: number;
|
|
505
|
+
resetAt: number;
|
|
506
|
+
};
|
|
507
|
+
type PublicWriteBudgetCharge = {
|
|
508
|
+
key: string;
|
|
509
|
+
scope: PublicWriteBudgetScope;
|
|
510
|
+
costUnits: number;
|
|
511
|
+
usedUnits: number;
|
|
512
|
+
limitUnits: number;
|
|
513
|
+
resetAt: number;
|
|
514
|
+
};
|
|
515
|
+
type PublicWriteBudgetDecision = {
|
|
516
|
+
allowed: boolean;
|
|
517
|
+
resource: AbuseResource;
|
|
518
|
+
reasons: string[];
|
|
519
|
+
charges: PublicWriteBudgetCharge[];
|
|
520
|
+
nextUsage: PublicWriteBudgetUsage[];
|
|
521
|
+
};
|
|
522
|
+
declare function evaluatePublicWriteBudget(input: PublicWriteBudgetInput, policy: PublicWriteBudgetPolicy, usage?: readonly PublicWriteBudgetUsage[]): PublicWriteBudgetDecision;
|
|
523
|
+
declare function createPublicWriteBudgetKey(input: Pick<PublicWriteBudgetInput, 'did' | 'hubId' | 'workspaceId' | 'surface'>, scope: PublicWriteBudgetScope): string | null;
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Crawl and federation query cost budget accounting.
|
|
527
|
+
*/
|
|
528
|
+
|
|
529
|
+
type QueryCostBudgetWorkType = 'crawl' | 'federation-query';
|
|
530
|
+
type QueryCostBudgetScope = 'actor' | 'hub' | 'workspace' | 'remote-peer' | 'domain' | 'route' | 'work-type' | 'hub-work-type' | 'domain-work-type' | 'remote-peer-route';
|
|
531
|
+
type QueryCostBudgetLimit = {
|
|
532
|
+
scope: QueryCostBudgetScope;
|
|
533
|
+
unitsPerWindow: number;
|
|
534
|
+
windowMs: number;
|
|
535
|
+
};
|
|
536
|
+
type QueryCostBudgetPolicy = {
|
|
537
|
+
limits: readonly QueryCostBudgetLimit[];
|
|
538
|
+
defaultCostUnits?: number;
|
|
539
|
+
};
|
|
540
|
+
type QueryCostBudgetInput = {
|
|
541
|
+
workType: QueryCostBudgetWorkType;
|
|
542
|
+
actorDID?: string;
|
|
543
|
+
hubId?: string;
|
|
544
|
+
workspaceId?: string;
|
|
545
|
+
remotePeerId?: string;
|
|
546
|
+
domain?: string;
|
|
547
|
+
route?: string;
|
|
548
|
+
costUnits?: number;
|
|
549
|
+
now?: number;
|
|
550
|
+
};
|
|
551
|
+
type QueryCostBudgetUsage = {
|
|
552
|
+
key: string;
|
|
553
|
+
scope: QueryCostBudgetScope;
|
|
554
|
+
usedUnits: number;
|
|
555
|
+
resetAt: number;
|
|
556
|
+
};
|
|
557
|
+
type QueryCostBudgetCharge = {
|
|
558
|
+
key: string;
|
|
559
|
+
scope: QueryCostBudgetScope;
|
|
560
|
+
costUnits: number;
|
|
561
|
+
usedUnits: number;
|
|
562
|
+
limitUnits: number;
|
|
563
|
+
resetAt: number;
|
|
564
|
+
};
|
|
565
|
+
type QueryCostBudgetDecision = {
|
|
566
|
+
allowed: boolean;
|
|
567
|
+
resource: AbuseResource;
|
|
568
|
+
reasons: string[];
|
|
569
|
+
charges: QueryCostBudgetCharge[];
|
|
570
|
+
nextUsage: QueryCostBudgetUsage[];
|
|
571
|
+
};
|
|
572
|
+
declare function evaluateQueryCostBudget(input: QueryCostBudgetInput, policy: QueryCostBudgetPolicy, usage?: readonly QueryCostBudgetUsage[]): QueryCostBudgetDecision;
|
|
573
|
+
declare function createQueryCostBudgetKey(input: Pick<QueryCostBudgetInput, 'actorDID' | 'hubId' | 'workspaceId' | 'remotePeerId' | 'domain' | 'route' | 'workType'>, scope: QueryCostBudgetScope): string | null;
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Deployment profiles for deterministic abuse mitigation defaults.
|
|
577
|
+
*/
|
|
578
|
+
|
|
579
|
+
type AbuseDeploymentProfileKind = 'small-self-hosted-hub' | 'public-search-hub';
|
|
580
|
+
type AbuseDeploymentProfileInput = {
|
|
581
|
+
hubId?: string;
|
|
582
|
+
windowMs?: number;
|
|
583
|
+
cloudReviewDailyMicroUsd?: number;
|
|
584
|
+
moderationReviewUnitsPerWindow?: number;
|
|
585
|
+
searchIndexUnitsPerWindow?: number;
|
|
586
|
+
};
|
|
587
|
+
type AbuseDeploymentProfile = {
|
|
588
|
+
id: string;
|
|
589
|
+
kind: AbuseDeploymentProfileKind;
|
|
590
|
+
title: string;
|
|
591
|
+
moderation: Pick<HubPolicyModerationSettings, 'mode' | 'requireSignedWrites' | 'rejectUnsignedFederation' | 'quarantineFirstContact' | 'allowLocalOverride' | 'publishLabelExplanations' | 'aiReview'>;
|
|
592
|
+
cloudReview: CloudReviewCallPolicy;
|
|
593
|
+
publicWriteBudget: PublicWriteBudgetPolicy;
|
|
594
|
+
queryCostBudget: QueryCostBudgetPolicy;
|
|
595
|
+
budgetHints: readonly HubPolicyBudgetHint[];
|
|
596
|
+
};
|
|
597
|
+
declare function createSmallSelfHostedAbuseProfile(input?: AbuseDeploymentProfileInput): AbuseDeploymentProfile;
|
|
598
|
+
declare function createPublicSearchHubAbuseProfile(input?: AbuseDeploymentProfileInput): AbuseDeploymentProfile;
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Deterministic claim extraction and citation coverage scoring.
|
|
602
|
+
*/
|
|
603
|
+
|
|
604
|
+
type CitationKind = 'markdown-link' | 'reference-link' | 'footnote-link' | 'bare-url' | 'doi';
|
|
605
|
+
type CitationReference = {
|
|
606
|
+
id: string;
|
|
607
|
+
kind: CitationKind;
|
|
608
|
+
label: string;
|
|
609
|
+
target: string;
|
|
610
|
+
domain?: string;
|
|
611
|
+
startIndex: number;
|
|
612
|
+
endIndex: number;
|
|
613
|
+
};
|
|
614
|
+
type ExtractedClaim = {
|
|
615
|
+
id: string;
|
|
616
|
+
text: string;
|
|
617
|
+
startIndex: number;
|
|
618
|
+
endIndex: number;
|
|
619
|
+
confidence: number;
|
|
620
|
+
citationRefs: readonly string[];
|
|
621
|
+
evidenceRefs: readonly string[];
|
|
622
|
+
};
|
|
623
|
+
type ClaimCitationCoverageInput = {
|
|
624
|
+
title?: string;
|
|
625
|
+
body: string;
|
|
626
|
+
published?: boolean;
|
|
627
|
+
sourceDID?: string;
|
|
628
|
+
};
|
|
629
|
+
type ClaimCitationCoverageOptions = {
|
|
630
|
+
minClaimChars?: number;
|
|
631
|
+
maxClaims?: number;
|
|
632
|
+
citationWindowChars?: number;
|
|
633
|
+
};
|
|
634
|
+
type ClaimCitationCoverageAssessment = {
|
|
635
|
+
claims: ExtractedClaim[];
|
|
636
|
+
citations: CitationReference[];
|
|
637
|
+
citationCoverage: number;
|
|
638
|
+
citedClaimCount: number;
|
|
639
|
+
unsupportedClaimCount: number;
|
|
640
|
+
claimCount: number;
|
|
641
|
+
quality: Partial<AbuseQualitySignals>;
|
|
642
|
+
evidenceRefs: string[];
|
|
643
|
+
reviewEvidenceRefs: string[];
|
|
644
|
+
treatment: 'review-evidence';
|
|
645
|
+
};
|
|
646
|
+
declare function extractCitationReferences(input: ClaimCitationCoverageInput): CitationReference[];
|
|
647
|
+
declare function extractKnowledgeClaims(input: ClaimCitationCoverageInput, options?: ClaimCitationCoverageOptions): ExtractedClaim[];
|
|
648
|
+
declare function scoreClaimCitationCoverage(input: ClaimCitationCoverageInput, options?: ClaimCitationCoverageOptions): ClaimCitationCoverageAssessment;
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Labeler trust and subscription limit helpers.
|
|
652
|
+
*/
|
|
653
|
+
|
|
654
|
+
type LabelerTrustScope = 'workspace' | 'hub';
|
|
655
|
+
type LabelerTrustLevel = 'blocked' | 'observe' | 'review' | 'trusted';
|
|
656
|
+
type LabelerTrustAction = 'accept' | 'observe' | 'review' | 'reject' | 'ignore';
|
|
657
|
+
type LabelerTrustSetting = {
|
|
658
|
+
scope: LabelerTrustScope;
|
|
659
|
+
scopeId: string;
|
|
660
|
+
labelerDID: string;
|
|
661
|
+
level: LabelerTrustLevel;
|
|
662
|
+
weight: number;
|
|
663
|
+
minConfidence: number;
|
|
664
|
+
allowedLabels?: readonly string[];
|
|
665
|
+
deniedLabels?: readonly string[];
|
|
666
|
+
maxLabelsPerSubject?: number;
|
|
667
|
+
expiresAt?: number;
|
|
668
|
+
};
|
|
669
|
+
type LabelerTrustEvaluationInput = {
|
|
670
|
+
scope: LabelerTrustScope;
|
|
671
|
+
scopeId: string;
|
|
672
|
+
labelerDID: string;
|
|
673
|
+
labelValue: string;
|
|
674
|
+
confidence: number;
|
|
675
|
+
evidenceRefs?: readonly string[];
|
|
676
|
+
labelExpiresAt?: number;
|
|
677
|
+
now?: number;
|
|
678
|
+
};
|
|
679
|
+
type ReportEscalationInput = Omit<LabelerTrustEvaluationInput, 'labelerDID' | 'evidenceRefs'> & {
|
|
680
|
+
reporterDID: string;
|
|
681
|
+
reportId: string;
|
|
682
|
+
evidenceRefs?: readonly string[];
|
|
683
|
+
};
|
|
684
|
+
type LabelerTrustDecision = {
|
|
685
|
+
accepted: boolean;
|
|
686
|
+
action: LabelerTrustAction;
|
|
687
|
+
reasons: readonly string[];
|
|
688
|
+
level: LabelerTrustLevel | 'unconfigured';
|
|
689
|
+
effectiveWeight: number;
|
|
690
|
+
minConfidence: number;
|
|
691
|
+
setting?: LabelerTrustSetting;
|
|
692
|
+
};
|
|
693
|
+
type LabelerSubscriptionStatus = 'active' | 'paused' | 'disabled';
|
|
694
|
+
type LabelerSubscription = {
|
|
695
|
+
id: string;
|
|
696
|
+
labelerDID: string;
|
|
697
|
+
workspaceId?: string;
|
|
698
|
+
hubId?: string;
|
|
699
|
+
status: LabelerSubscriptionStatus;
|
|
700
|
+
createdAt: number;
|
|
701
|
+
expiresAt?: number;
|
|
702
|
+
};
|
|
703
|
+
type LabelerSubscriptionLimitPolicy = {
|
|
704
|
+
maxWorkspaceSubscriptions?: number;
|
|
705
|
+
maxHubSubscriptions?: number;
|
|
706
|
+
maxWorkspaceSubscriptionsPerLabeler?: number;
|
|
707
|
+
maxHubSubscriptionsPerLabeler?: number;
|
|
708
|
+
};
|
|
709
|
+
type LabelerSubscriptionLimitInput = {
|
|
710
|
+
id: string;
|
|
711
|
+
labelerDID: string;
|
|
712
|
+
workspaceId?: string;
|
|
713
|
+
hubId?: string;
|
|
714
|
+
now?: number;
|
|
715
|
+
};
|
|
716
|
+
type LabelerSubscriptionLimitDecision = {
|
|
717
|
+
allowed: boolean;
|
|
718
|
+
reasons: readonly string[];
|
|
719
|
+
activeCounts: {
|
|
720
|
+
workspace: number;
|
|
721
|
+
hub: number;
|
|
722
|
+
workspaceLabeler: number;
|
|
723
|
+
hubLabeler: number;
|
|
724
|
+
};
|
|
725
|
+
nextSubscription?: LabelerSubscription;
|
|
726
|
+
};
|
|
727
|
+
type ReportEscalationDecision = {
|
|
728
|
+
canAffectVisibility: boolean;
|
|
729
|
+
trustDecision: LabelerTrustDecision;
|
|
730
|
+
trustedLabel: AbuseLabel | null;
|
|
731
|
+
evidenceRefs: readonly string[];
|
|
732
|
+
};
|
|
733
|
+
declare function evaluateLabelerTrust(input: LabelerTrustEvaluationInput, settings: readonly LabelerTrustSetting[]): LabelerTrustDecision;
|
|
734
|
+
declare function createTrustedLabelFromSetting(input: LabelerTrustEvaluationInput, settings: readonly LabelerTrustSetting[]): AbuseLabel | null;
|
|
735
|
+
declare function evaluateReportEscalation(input: ReportEscalationInput, settings: readonly LabelerTrustSetting[]): ReportEscalationDecision;
|
|
736
|
+
declare function createLabelerSubscription(input: Omit<LabelerSubscription, 'status' | 'createdAt'> & {
|
|
737
|
+
status?: LabelerSubscriptionStatus;
|
|
738
|
+
createdAt?: number;
|
|
739
|
+
}): LabelerSubscription;
|
|
740
|
+
declare function evaluateLabelerSubscriptionLimit(input: LabelerSubscriptionLimitInput, policy: LabelerSubscriptionLimitPolicy, subscriptions?: readonly LabelerSubscription[]): LabelerSubscriptionLimitDecision;
|
|
741
|
+
/**
|
|
742
|
+
* A persisted policy subscription, normalized to the fields the runtime trust
|
|
743
|
+
* setting needs. The app maps a `PolicySubscription` node onto this shape so
|
|
744
|
+
* this adapter stays decoupled from the data schema.
|
|
745
|
+
*/
|
|
746
|
+
type PolicySubscriptionTrustInput = {
|
|
747
|
+
labelerDID: string;
|
|
748
|
+
/** Persisted policy scope (user/workspace/community/hub/…). */
|
|
749
|
+
scope?: string;
|
|
750
|
+
/** Trust weight in [0, 1] (the schema's `trust`). */
|
|
751
|
+
trust: number;
|
|
752
|
+
enabled?: boolean;
|
|
753
|
+
minConfidence?: number;
|
|
754
|
+
allowedLabels?: readonly string[];
|
|
755
|
+
deniedLabels?: readonly string[];
|
|
756
|
+
maxLabelsPerSubject?: number;
|
|
757
|
+
expiresAt?: number;
|
|
758
|
+
};
|
|
759
|
+
/**
|
|
760
|
+
* Project a persisted policy subscription onto a runtime `LabelerTrustSetting`
|
|
761
|
+
* — the seam between stored subscriptions and `evaluateLabelerTrust`. Disabled
|
|
762
|
+
* or zero-trust subscriptions become `blocked` so they reject rather than
|
|
763
|
+
* silently accept.
|
|
764
|
+
*/
|
|
765
|
+
declare function subscriptionToTrustSetting(sub: PolicySubscriptionTrustInput, scopeId: string): LabelerTrustSetting;
|
|
766
|
+
/**
|
|
767
|
+
* Project many subscriptions, dropping ones that are expired at `now`. Disabled
|
|
768
|
+
* subscriptions are kept (mapped to `blocked`) so they explicitly suppress a
|
|
769
|
+
* labeler rather than falling through to `unconfigured`.
|
|
770
|
+
*/
|
|
771
|
+
declare function subscriptionsToTrustSettings(subs: readonly PolicySubscriptionTrustInput[], scopeId: string, now?: number): LabelerTrustSetting[];
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* Community note rating experiments with diversity-aware agreement.
|
|
775
|
+
*/
|
|
776
|
+
type CommunityNoteHelpfulness = 'helpful' | 'not-helpful' | 'needs-source' | 'irrelevant';
|
|
777
|
+
type CommunityNoteRatingInput = {
|
|
778
|
+
noteId?: string;
|
|
779
|
+
raterDID?: string;
|
|
780
|
+
helpfulness: CommunityNoteHelpfulness;
|
|
781
|
+
confidence: number;
|
|
782
|
+
sourceWeight?: number;
|
|
783
|
+
perspective?: string;
|
|
784
|
+
createdAt?: number;
|
|
785
|
+
};
|
|
786
|
+
type CommunityNoteAgreementStatus = 'insufficient' | 'helpful' | 'not-helpful' | 'needs-more-diversity' | 'contested';
|
|
787
|
+
type CommunityNoteAgreementOptions = {
|
|
788
|
+
minRatings?: number;
|
|
789
|
+
minHelpfulRatings?: number;
|
|
790
|
+
minPerspectiveGroups?: number;
|
|
791
|
+
minDiversityScore?: number;
|
|
792
|
+
helpfulThreshold?: number;
|
|
793
|
+
notHelpfulThreshold?: number;
|
|
794
|
+
contestedThreshold?: number;
|
|
795
|
+
};
|
|
796
|
+
type CommunityNotePerspectiveSummary = {
|
|
797
|
+
perspective: string;
|
|
798
|
+
ratingCount: number;
|
|
799
|
+
helpfulWeight: number;
|
|
800
|
+
notHelpfulWeight: number;
|
|
801
|
+
needsSourceWeight: number;
|
|
802
|
+
irrelevantWeight: number;
|
|
803
|
+
};
|
|
804
|
+
type CommunityNoteAgreementSummary = {
|
|
805
|
+
status: CommunityNoteAgreementStatus;
|
|
806
|
+
ratingCount: number;
|
|
807
|
+
effectiveWeight: number;
|
|
808
|
+
helpfulScore: number;
|
|
809
|
+
notHelpfulScore: number;
|
|
810
|
+
needsSourceScore: number;
|
|
811
|
+
irrelevantScore: number;
|
|
812
|
+
diversityScore: number;
|
|
813
|
+
agreementScore: number;
|
|
814
|
+
supportingPerspectiveCount: number;
|
|
815
|
+
perspectiveCount: number;
|
|
816
|
+
perspectives: CommunityNotePerspectiveSummary[];
|
|
817
|
+
reasons: string[];
|
|
818
|
+
};
|
|
819
|
+
declare function summarizeCommunityNoteAgreement(ratings: readonly CommunityNoteRatingInput[], options?: CommunityNoteAgreementOptions): CommunityNoteAgreementSummary;
|
|
820
|
+
declare function groupCommunityNoteRatingsByPerspective(ratings: readonly CommunityNoteRatingInput[]): Map<string, CommunityNoteRatingInput[]>;
|
|
821
|
+
declare function scoreCommunityNotePerspectiveDiversity(ratings: readonly CommunityNoteRatingInput[]): number;
|
|
822
|
+
declare function isCommunityNoteAgreementVisible(summary: Pick<CommunityNoteAgreementSummary, 'status'>): boolean;
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Staged write flow for moderation and quality labels.
|
|
826
|
+
*/
|
|
827
|
+
|
|
828
|
+
type StagedModerationSourceType = 'deterministic' | 'local-ai' | 'cloud-ai' | 'human' | 'community-note' | 'policy-list' | 'hub' | 'report' | 'crawler';
|
|
829
|
+
type StagedModerationWriteKind = 'moderation-label' | 'quality-signal';
|
|
830
|
+
type StagedModerationWriteStatus = 'staged' | 'committed' | 'rejected';
|
|
831
|
+
type StagedModerationWriteCandidate = {
|
|
832
|
+
id?: string;
|
|
833
|
+
targetId: string;
|
|
834
|
+
targetSchema?: string;
|
|
835
|
+
kind: StagedModerationWriteKind;
|
|
836
|
+
value: string;
|
|
837
|
+
score?: number;
|
|
838
|
+
confidence: number;
|
|
839
|
+
sourceType: StagedModerationSourceType;
|
|
840
|
+
sourceDID?: string;
|
|
841
|
+
sourceWeight?: number;
|
|
842
|
+
evidenceRefs?: readonly string[];
|
|
843
|
+
modelProvider?: string;
|
|
844
|
+
modelName?: string;
|
|
845
|
+
modelVersion?: string;
|
|
846
|
+
expiresAt?: number;
|
|
847
|
+
};
|
|
848
|
+
type StagedModerationWritePolicy = {
|
|
849
|
+
minStageConfidence?: number;
|
|
850
|
+
autoCommitConfidence?: number;
|
|
851
|
+
autoCommitSources?: readonly StagedModerationSourceType[];
|
|
852
|
+
requireReviewSources?: readonly StagedModerationSourceType[];
|
|
853
|
+
allowCrawlerAutoCommit?: boolean;
|
|
854
|
+
maxReviewTasks?: number;
|
|
855
|
+
maxReviewTasksBySource?: Partial<Record<StagedModerationSourceType, number>>;
|
|
856
|
+
reviewQueueByKind?: Partial<Record<StagedModerationWriteKind, AbuseReviewQueue>>;
|
|
857
|
+
defaultSourceWeight?: number;
|
|
858
|
+
stagedExpiresInMs?: number;
|
|
859
|
+
};
|
|
860
|
+
type StagedModerationWrite = StagedModerationWriteCandidate & {
|
|
861
|
+
id: string;
|
|
862
|
+
status: StagedModerationWriteStatus;
|
|
863
|
+
createdAt: number;
|
|
864
|
+
stagedAt?: number;
|
|
865
|
+
committedAt?: number;
|
|
866
|
+
committedBy?: string;
|
|
867
|
+
rejectedAt?: number;
|
|
868
|
+
rejectedBy?: string;
|
|
869
|
+
rejectionReason?: string;
|
|
870
|
+
reviewRequired: boolean;
|
|
871
|
+
reviewQueue?: AbuseReviewQueue;
|
|
872
|
+
};
|
|
873
|
+
type MaterializedModerationWrite = {
|
|
874
|
+
targetId: string;
|
|
875
|
+
targetSchema?: string;
|
|
876
|
+
kind: StagedModerationWriteKind;
|
|
877
|
+
value: string;
|
|
878
|
+
score?: number;
|
|
879
|
+
confidence: number;
|
|
880
|
+
sourceType: StagedModerationSourceType;
|
|
881
|
+
sourceDID?: string;
|
|
882
|
+
sourceWeight: number;
|
|
883
|
+
evidenceRefs: readonly string[];
|
|
884
|
+
modelProvider?: string;
|
|
885
|
+
modelName?: string;
|
|
886
|
+
modelVersion?: string;
|
|
887
|
+
expiresAt?: number;
|
|
888
|
+
};
|
|
889
|
+
type StagedModerationReviewTask = {
|
|
890
|
+
id: string;
|
|
891
|
+
stagedWriteId: string;
|
|
892
|
+
targetId: string;
|
|
893
|
+
queue: AbuseReviewQueue;
|
|
894
|
+
priority: number;
|
|
895
|
+
reasons: readonly string[];
|
|
896
|
+
};
|
|
897
|
+
type StagedModerationWritePlan = {
|
|
898
|
+
staged: StagedModerationWrite[];
|
|
899
|
+
committed: StagedModerationWrite[];
|
|
900
|
+
rejected: StagedModerationWrite[];
|
|
901
|
+
materialized: MaterializedModerationWrite[];
|
|
902
|
+
reviewTasks: StagedModerationReviewTask[];
|
|
903
|
+
};
|
|
904
|
+
type StagedModerationWriteOptions = {
|
|
905
|
+
now?: number;
|
|
906
|
+
};
|
|
907
|
+
declare function planStagedModerationWrites(candidates: readonly StagedModerationWriteCandidate[], policy?: StagedModerationWritePolicy, options?: StagedModerationWriteOptions): StagedModerationWritePlan;
|
|
908
|
+
declare function approveStagedModerationWrite(write: StagedModerationWrite, reviewerDID: string, options?: StagedModerationWriteOptions): StagedModerationWrite;
|
|
909
|
+
declare function rejectStagedModerationWrite(write: StagedModerationWrite, reviewerDID: string, reason: string, options?: StagedModerationWriteOptions): StagedModerationWrite;
|
|
910
|
+
declare function materializeStagedModerationWrite(write: StagedModerationWrite): MaterializedModerationWrite | null;
|
|
911
|
+
|
|
912
|
+
/**
|
|
913
|
+
* Appeal effects for automated moderation decisions.
|
|
914
|
+
*/
|
|
915
|
+
|
|
916
|
+
type AppealStatus = 'open' | 'accepted' | 'rejected' | 'needs-info';
|
|
917
|
+
type AppealResolutionAction = 'reverse' | 'annotate';
|
|
918
|
+
type AppealEffectAction = 'none' | 'reverse' | 'annotate';
|
|
919
|
+
type AppealEffectInput = {
|
|
920
|
+
appealId: string;
|
|
921
|
+
targetId: string;
|
|
922
|
+
appellantDID: string;
|
|
923
|
+
status: AppealStatus;
|
|
924
|
+
action?: AppealResolutionAction;
|
|
925
|
+
reviewerDID?: string;
|
|
926
|
+
decisionId?: string;
|
|
927
|
+
appealedLabelId?: string;
|
|
928
|
+
resolution?: string;
|
|
929
|
+
evidenceRefs?: readonly string[];
|
|
930
|
+
confidence?: number;
|
|
931
|
+
sourceWeight?: number;
|
|
932
|
+
expiresAt?: number;
|
|
933
|
+
};
|
|
934
|
+
type AppealAnnotation = {
|
|
935
|
+
appealId: string;
|
|
936
|
+
targetId: string;
|
|
937
|
+
status: AppealStatus;
|
|
938
|
+
action: AppealEffectAction;
|
|
939
|
+
appellantDID: string;
|
|
940
|
+
reviewerDID?: string;
|
|
941
|
+
decisionId?: string;
|
|
942
|
+
appealedLabelId?: string;
|
|
943
|
+
resolution?: string;
|
|
944
|
+
evidenceRefs: readonly string[];
|
|
945
|
+
};
|
|
946
|
+
type AppealEffect = {
|
|
947
|
+
action: AppealEffectAction;
|
|
948
|
+
annotation: AppealAnnotation;
|
|
949
|
+
labelsToApply: readonly AbuseLabel[];
|
|
950
|
+
reasons: readonly string[];
|
|
951
|
+
};
|
|
952
|
+
declare function createAppealEffect(input: AppealEffectInput): AppealEffect;
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* Signed block policy lists for local, workspace, and hub moderation state.
|
|
956
|
+
*/
|
|
957
|
+
|
|
958
|
+
type PolicyBlockScope = Extract<PolicyScope, 'user' | 'workspace' | 'community' | 'hub'>;
|
|
959
|
+
type PolicyBlockSubjectType = 'did' | 'peerId' | 'domain' | 'url' | 'contentHash' | 'nodeId';
|
|
960
|
+
type PolicyBlockAction = 'reject' | 'hide' | 'quarantine' | 'block-peer';
|
|
961
|
+
type PolicyBlockEntry = {
|
|
962
|
+
id?: string;
|
|
963
|
+
subject: string;
|
|
964
|
+
subjectType: PolicyBlockSubjectType;
|
|
965
|
+
action: PolicyBlockAction;
|
|
966
|
+
reason: string;
|
|
967
|
+
evidenceRefs?: readonly string[];
|
|
968
|
+
createdAt: number;
|
|
969
|
+
expiresAt?: number;
|
|
970
|
+
autoBlock?: boolean;
|
|
971
|
+
};
|
|
972
|
+
type UnsignedPolicyBlockList = {
|
|
973
|
+
v: 1;
|
|
974
|
+
kind: 'xnet.policy.block-list';
|
|
975
|
+
id: string;
|
|
976
|
+
title?: string;
|
|
977
|
+
scope: PolicyBlockScope;
|
|
978
|
+
issuerDID: string;
|
|
979
|
+
createdAt: number;
|
|
980
|
+
updatedAt: number;
|
|
981
|
+
entries: readonly PolicyBlockEntry[];
|
|
982
|
+
};
|
|
983
|
+
type PolicyBlockListSignature = {
|
|
984
|
+
alg: 'Ed25519';
|
|
985
|
+
value: string;
|
|
986
|
+
};
|
|
987
|
+
type SignedPolicyBlockList = UnsignedPolicyBlockList & {
|
|
988
|
+
signature: PolicyBlockListSignature;
|
|
989
|
+
};
|
|
990
|
+
type PolicyBlockListVerificationResult = {
|
|
991
|
+
valid: boolean;
|
|
992
|
+
errors: readonly string[];
|
|
993
|
+
};
|
|
994
|
+
type PolicyBlockAuditEntry = PolicyBlockEntry & {
|
|
995
|
+
active: boolean;
|
|
996
|
+
expired: boolean;
|
|
997
|
+
};
|
|
998
|
+
type PolicyBlockOverrideScope = Extract<PolicyBlockScope, 'user' | 'workspace'>;
|
|
999
|
+
type PolicyBlockOverrideEntry = {
|
|
1000
|
+
id?: string;
|
|
1001
|
+
subject: string;
|
|
1002
|
+
subjectType: PolicyBlockSubjectType;
|
|
1003
|
+
scope: PolicyBlockOverrideScope;
|
|
1004
|
+
reason: string;
|
|
1005
|
+
evidenceRefs?: readonly string[];
|
|
1006
|
+
createdAt: number;
|
|
1007
|
+
expiresAt?: number;
|
|
1008
|
+
};
|
|
1009
|
+
type ResolvedPolicyBlockEntry = PolicyBlockEntry & {
|
|
1010
|
+
listId: string;
|
|
1011
|
+
listScope: PolicyBlockScope;
|
|
1012
|
+
issuerDID: string;
|
|
1013
|
+
overridden: boolean;
|
|
1014
|
+
overrideRefs: readonly string[];
|
|
1015
|
+
};
|
|
1016
|
+
type PolicyBlockSubscriptionResolutionInput = {
|
|
1017
|
+
lists: readonly (SignedPolicyBlockList | UnsignedPolicyBlockList)[];
|
|
1018
|
+
localOverrides?: readonly PolicyBlockOverrideEntry[];
|
|
1019
|
+
now?: number;
|
|
1020
|
+
};
|
|
1021
|
+
type PolicyBlockSubscriptionResolution = {
|
|
1022
|
+
enforcedEntries: readonly ResolvedPolicyBlockEntry[];
|
|
1023
|
+
overriddenEntries: readonly ResolvedPolicyBlockEntry[];
|
|
1024
|
+
activeOverrides: readonly PolicyBlockOverrideEntry[];
|
|
1025
|
+
};
|
|
1026
|
+
declare const canonicalizePolicyBlockList: (list: UnsignedPolicyBlockList) => string;
|
|
1027
|
+
declare const policyBlockListSigningBytes: (list: UnsignedPolicyBlockList) => Uint8Array;
|
|
1028
|
+
declare const isSignedPolicyBlockList: (list: unknown) => list is SignedPolicyBlockList;
|
|
1029
|
+
declare const createPolicyBlockList: (input: Omit<UnsignedPolicyBlockList, "v" | "kind" | "createdAt" | "updatedAt"> & {
|
|
1030
|
+
createdAt?: number;
|
|
1031
|
+
updatedAt?: number;
|
|
1032
|
+
}) => UnsignedPolicyBlockList;
|
|
1033
|
+
declare const signPolicyBlockList: (list: UnsignedPolicyBlockList, signingKey: Uint8Array) => SignedPolicyBlockList;
|
|
1034
|
+
declare const unsignedPolicyBlockList: (list: SignedPolicyBlockList | UnsignedPolicyBlockList) => UnsignedPolicyBlockList;
|
|
1035
|
+
declare const verifySignedPolicyBlockList: (list: SignedPolicyBlockList) => PolicyBlockListVerificationResult;
|
|
1036
|
+
declare const policyBlockEntryIsActive: (entry: PolicyBlockEntry, now?: number) => boolean;
|
|
1037
|
+
declare const auditPolicyBlockEntries: (list: SignedPolicyBlockList | UnsignedPolicyBlockList, now?: number) => readonly PolicyBlockAuditEntry[];
|
|
1038
|
+
declare const findPolicyBlockAuditEntry: (list: SignedPolicyBlockList | UnsignedPolicyBlockList, subject: string, subjectType: PolicyBlockSubjectType, now?: number) => PolicyBlockAuditEntry | null;
|
|
1039
|
+
declare const activePolicyBlockEntries: (list: SignedPolicyBlockList | UnsignedPolicyBlockList, now?: number) => readonly PolicyBlockEntry[];
|
|
1040
|
+
declare const findPolicyBlockEntry: (list: SignedPolicyBlockList | UnsignedPolicyBlockList, subject: string, subjectType: PolicyBlockSubjectType, now?: number) => PolicyBlockEntry | null;
|
|
1041
|
+
declare const policyBlockOverrideEntryIsActive: (entry: PolicyBlockOverrideEntry, now?: number) => boolean;
|
|
1042
|
+
declare const resolveSubscribedPolicyBlockLists: (input: PolicyBlockSubscriptionResolutionInput) => PolicyBlockSubscriptionResolution;
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* @xnetjs/abuse — NSFW / sensitive-content labeling and per-viewer filtering
|
|
1046
|
+
* (exploration 0175).
|
|
1047
|
+
*
|
|
1048
|
+
* Sensitivity is a PER-VIEWER concern, not a platform-hide concern: explicit
|
|
1049
|
+
* content is not hidden from everyone by default, it is each viewer's dial.
|
|
1050
|
+
* This module is therefore deliberately separate from `decideAbuse` (which
|
|
1051
|
+
* gates platform-level abuse like spam/malware). The render gate combines the
|
|
1052
|
+
* two by taking the STRICTER of the platform decision and the viewer's
|
|
1053
|
+
* sensitivity preference — see `resolveContentVisibility`.
|
|
1054
|
+
*
|
|
1055
|
+
* Label vocabulary is aligned to the ATProto/Bluesky moderation lexicon so a
|
|
1056
|
+
* label emitted by any interoperating labeler maps onto the same dial.
|
|
1057
|
+
*/
|
|
1058
|
+
|
|
1059
|
+
declare const sensitivityLabels: readonly [{
|
|
1060
|
+
readonly id: "sexual";
|
|
1061
|
+
readonly name: "Sexually suggestive";
|
|
1062
|
+
readonly defaultVisibility: "warn";
|
|
1063
|
+
}, {
|
|
1064
|
+
readonly id: "nudity";
|
|
1065
|
+
readonly name: "Non-sexual nudity";
|
|
1066
|
+
readonly defaultVisibility: "show";
|
|
1067
|
+
}, {
|
|
1068
|
+
readonly id: "porn";
|
|
1069
|
+
readonly name: "Explicit / pornographic";
|
|
1070
|
+
readonly defaultVisibility: "hide";
|
|
1071
|
+
}, {
|
|
1072
|
+
readonly id: "graphic-media";
|
|
1073
|
+
readonly name: "Graphic / violent";
|
|
1074
|
+
readonly defaultVisibility: "warn";
|
|
1075
|
+
}];
|
|
1076
|
+
type SensitivityLabelValue = (typeof sensitivityLabels)[number]['id'];
|
|
1077
|
+
declare const SENSITIVITY_LABEL_VALUES: readonly SensitivityLabelValue[];
|
|
1078
|
+
declare function isSensitivityLabelValue(value: string): value is SensitivityLabelValue;
|
|
1079
|
+
/**
|
|
1080
|
+
* Provenance of a sensitivity signal → weight. Research (0175): the author's
|
|
1081
|
+
* own declaration is the cheapest, highest-precision signal; community reports
|
|
1082
|
+
* are gameable; an untrusted labeler counts for little until trusted.
|
|
1083
|
+
*/
|
|
1084
|
+
type SensitivitySource = 'self' | 'ml' | 'report' | 'labeler';
|
|
1085
|
+
declare const SENSITIVITY_SOURCE_WEIGHT: Readonly<Record<SensitivitySource, number>>;
|
|
1086
|
+
/** Minimum combined weighted confidence for a sensitivity value to count as present. */
|
|
1087
|
+
declare const SENSITIVITY_PRESENCE_FLOOR = 0.15;
|
|
1088
|
+
/** A per-label choice. `show` is "no filtering" for that label. */
|
|
1089
|
+
type SensitivityPreference = AbuseVisibility;
|
|
1090
|
+
type UserSensitivityPreferences = {
|
|
1091
|
+
/**
|
|
1092
|
+
* Master adult-content switch. When off (the default), any present
|
|
1093
|
+
* `sexual`/`nudity`/`porn` label is hidden regardless of per-label settings —
|
|
1094
|
+
* matching Bluesky's age-gated model.
|
|
1095
|
+
*/
|
|
1096
|
+
adultContentEnabled: boolean;
|
|
1097
|
+
/** Whether the viewer has confirmed they are an adult. Required to enable adult content. */
|
|
1098
|
+
ageConfirmed: boolean;
|
|
1099
|
+
/** Per-label visibility dial. Missing entries fall back to the vocabulary default. */
|
|
1100
|
+
labels: Partial<Record<SensitivityLabelValue, SensitivityPreference>>;
|
|
1101
|
+
/**
|
|
1102
|
+
* Dating default (exploration 0174): blur unlabeled media from a non-mutual
|
|
1103
|
+
* sender even when no sensitivity label is present.
|
|
1104
|
+
*/
|
|
1105
|
+
blurUnsolicitedMedia?: boolean;
|
|
1106
|
+
};
|
|
1107
|
+
declare const DEFAULT_SENSITIVITY_PREFERENCES: UserSensitivityPreferences;
|
|
1108
|
+
type BuildSensitivityLabelInput = {
|
|
1109
|
+
value: SensitivityLabelValue;
|
|
1110
|
+
source: SensitivitySource;
|
|
1111
|
+
confidence: number;
|
|
1112
|
+
sourceDID?: string;
|
|
1113
|
+
id?: string;
|
|
1114
|
+
expiresAt?: number;
|
|
1115
|
+
evidenceRefs?: readonly string[];
|
|
1116
|
+
};
|
|
1117
|
+
/** Build an `AbuseLabel` for a sensitivity signal with the source-appropriate weight. */
|
|
1118
|
+
declare function buildSensitivityLabel(input: BuildSensitivityLabelInput): AbuseLabel;
|
|
1119
|
+
type SensitivityAssessment = {
|
|
1120
|
+
/** Sensitivity values judged present, with their combined weighted confidence. */
|
|
1121
|
+
present: ReadonlyMap<SensitivityLabelValue, number>;
|
|
1122
|
+
/** Convenience: present values as an array. */
|
|
1123
|
+
values: readonly SensitivityLabelValue[];
|
|
1124
|
+
};
|
|
1125
|
+
/**
|
|
1126
|
+
* Combine the sensitivity labels on a piece of content into the set of values
|
|
1127
|
+
* that count as present. A value is present when the sum of
|
|
1128
|
+
* `confidence × sourceWeight` across its active labels clears the presence floor.
|
|
1129
|
+
*/
|
|
1130
|
+
declare function assessSensitivity(labels: readonly AbuseLabel[], options?: {
|
|
1131
|
+
now?: number;
|
|
1132
|
+
presenceFloor?: number;
|
|
1133
|
+
}): SensitivityAssessment;
|
|
1134
|
+
/** Return whichever visibility is stricter (hide > blur > warn > show). */
|
|
1135
|
+
declare function strictestVisibility(a: AbuseVisibility, b: AbuseVisibility): AbuseVisibility;
|
|
1136
|
+
type SensitivityVisibilityOptions = {
|
|
1137
|
+
now?: number;
|
|
1138
|
+
presenceFloor?: number;
|
|
1139
|
+
/** Dating signal: the content carries media from a non-mutual sender. */
|
|
1140
|
+
unsolicitedMedia?: boolean;
|
|
1141
|
+
};
|
|
1142
|
+
/**
|
|
1143
|
+
* Resolve how a single piece of content should appear FOR THIS VIEWER given its
|
|
1144
|
+
* sensitivity labels and the viewer's preferences. Pure; no platform-abuse
|
|
1145
|
+
* logic (combine with `decideAbuse` via `resolveContentVisibility`).
|
|
1146
|
+
*/
|
|
1147
|
+
declare function decideSensitivityVisibility(labels: readonly AbuseLabel[], preferences?: UserSensitivityPreferences, options?: SensitivityVisibilityOptions): AbuseVisibility;
|
|
1148
|
+
/** Why a sensitivity label or rule contributed to the resolved visibility. */
|
|
1149
|
+
type SensitivityReasonCause = 'adult-disabled' | 'dial' | 'unsolicited-media';
|
|
1150
|
+
type SensitivityReason = {
|
|
1151
|
+
/** The sensitivity value involved, or undefined for the unsolicited-media rule. */
|
|
1152
|
+
label?: SensitivityLabelValue;
|
|
1153
|
+
/** The visibility this reason contributed (`show` for a present-but-allowed label). */
|
|
1154
|
+
effect: AbuseVisibility;
|
|
1155
|
+
cause: SensitivityReasonCause;
|
|
1156
|
+
};
|
|
1157
|
+
type SensitivityExplanation = {
|
|
1158
|
+
/** The resolved visibility — identical to `decideSensitivityVisibility`. */
|
|
1159
|
+
visibility: AbuseVisibility;
|
|
1160
|
+
/** Per-label / per-rule breakdown of what drove the decision. */
|
|
1161
|
+
reasons: readonly SensitivityReason[];
|
|
1162
|
+
};
|
|
1163
|
+
/**
|
|
1164
|
+
* Explain *why* content resolved to its sensitivity visibility for this viewer —
|
|
1165
|
+
* the transparency primitive behind a "why was this filtered?" affordance. Walks
|
|
1166
|
+
* the same logic as `decideSensitivityVisibility`, recording each present label's
|
|
1167
|
+
* effect (and the unsolicited-media rule) so the UI can render it.
|
|
1168
|
+
*/
|
|
1169
|
+
declare function explainSensitivityVisibility(labels: readonly AbuseLabel[], preferences?: UserSensitivityPreferences, options?: SensitivityVisibilityOptions): SensitivityExplanation;
|
|
1170
|
+
/**
|
|
1171
|
+
* Express the viewer's sensitivity dial as an `AbuseDecisionOverride` so callers
|
|
1172
|
+
* can feed it through the existing `decideAbuse` pipeline. Only ever tightens
|
|
1173
|
+
* visibility (scope `'user'`), never loosens a platform decision.
|
|
1174
|
+
*/
|
|
1175
|
+
declare function sensitivityOverride(labels: readonly AbuseLabel[], preferences?: UserSensitivityPreferences, options?: SensitivityVisibilityOptions): AbuseDecisionOverride | undefined;
|
|
1176
|
+
/**
|
|
1177
|
+
* The render-gate primitive: combine a platform `decideAbuse` decision with the
|
|
1178
|
+
* viewer's sensitivity dial, returning the stricter visibility. A platform
|
|
1179
|
+
* `hide` always wins; otherwise the viewer's NSFW preference can only tighten.
|
|
1180
|
+
*/
|
|
1181
|
+
declare function resolveContentVisibility(decision: Pick<AbuseDecision, 'visibility'>, labels: readonly AbuseLabel[], preferences?: UserSensitivityPreferences, options?: SensitivityVisibilityOptions): AbuseVisibility;
|
|
1182
|
+
|
|
1183
|
+
/**
|
|
1184
|
+
* Perceptual image hashing + known-bad-hash matching (exploration 0175, phase 3).
|
|
1185
|
+
*
|
|
1186
|
+
* Operates on a decoded grayscale image (`luma` 0–255, row-major). Decoding is
|
|
1187
|
+
* the caller's job — a browser uses a `<canvas>`, a hub uses sharp/jimp — so this
|
|
1188
|
+
* module stays pure, portable, and unit-testable.
|
|
1189
|
+
*
|
|
1190
|
+
* Two distinct jobs, both needed (the research is explicit that ML classification
|
|
1191
|
+
* and hash matching are complementary):
|
|
1192
|
+
* - `perceptualHash` / `averageHash` / `differenceHash` — robust similarity
|
|
1193
|
+
* hashes for "is this the same image as one we've seen", used for dedupe and
|
|
1194
|
+
* as the comparison primitive behind known-bad matching.
|
|
1195
|
+
* - `matchKnownImageHash` — the CSAM-style matcher: compare a candidate hash to
|
|
1196
|
+
* a list of known-bad hashes (e.g. a PDQ/PhotoDNA-derived list). The matching
|
|
1197
|
+
* LOGIC lives here; sourcing the actual list is an operator/legal step.
|
|
1198
|
+
*/
|
|
1199
|
+
type GrayscaleImage = {
|
|
1200
|
+
width: number;
|
|
1201
|
+
height: number;
|
|
1202
|
+
/** Row-major luma values in [0, 255], length === width * height. */
|
|
1203
|
+
luma: readonly number[];
|
|
1204
|
+
};
|
|
1205
|
+
/** Average hash (aHash): 8×8 luma compared to the mean → 64-bit hex. */
|
|
1206
|
+
declare function averageHash(image: GrayscaleImage): string;
|
|
1207
|
+
/** Difference hash (dHash): 9×8, each pixel brighter than its right neighbour → 64-bit hex. */
|
|
1208
|
+
declare function differenceHash(image: GrayscaleImage): string;
|
|
1209
|
+
/**
|
|
1210
|
+
* DCT-based perceptual hash (pHash family): downscale to 32×32, take the 2D
|
|
1211
|
+
* DCT-II, keep the low-frequency top-left 8×8 block (excluding the DC term), and
|
|
1212
|
+
* threshold each coefficient against the block median → 64-bit hex. More robust
|
|
1213
|
+
* to scaling/compression than aHash/dHash.
|
|
1214
|
+
*/
|
|
1215
|
+
declare function perceptualHash(image: GrayscaleImage): string;
|
|
1216
|
+
/** Hamming distance (number of differing bits) between two equal-length hex hashes. */
|
|
1217
|
+
declare function hammingDistanceHex(a: string, b: string): number;
|
|
1218
|
+
/** Similarity in [0, 1] from Hamming distance over the hash bit length. */
|
|
1219
|
+
declare function imageHashSimilarity(a: string, b: string): number;
|
|
1220
|
+
type KnownImageHash = {
|
|
1221
|
+
hash: string;
|
|
1222
|
+
label: string;
|
|
1223
|
+
source?: string;
|
|
1224
|
+
};
|
|
1225
|
+
type KnownHashMatch = {
|
|
1226
|
+
label: string;
|
|
1227
|
+
source?: string;
|
|
1228
|
+
distance: number;
|
|
1229
|
+
};
|
|
1230
|
+
/**
|
|
1231
|
+
* Match a candidate hash against a list of known-bad hashes. A match within
|
|
1232
|
+
* `maxHammingBits` is the CSAM-style "known content" signal — zero ML, near-zero
|
|
1233
|
+
* false positives for the exact known item. Returns the closest match or null.
|
|
1234
|
+
*/
|
|
1235
|
+
declare function matchKnownImageHash(hash: string, known: readonly KnownImageHash[], maxHammingBits?: number): KnownHashMatch | null;
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* On-device NSFW image classifier adapter (exploration 0175, phase 1).
|
|
1239
|
+
*
|
|
1240
|
+
* The heavy model (NSFWJS / a Transformers.js ONNX classifier) is INJECTED as a
|
|
1241
|
+
* `detect` function so this package carries no model binary and stays testable.
|
|
1242
|
+
* The adapter's job is to map a detector's category scores onto the xNet
|
|
1243
|
+
* sensitivity vocabulary as `AbuseLabel`s, conforming to `LocalClassifierAdapter`.
|
|
1244
|
+
*
|
|
1245
|
+
* Privacy (0175): this runs on the author's device (pre-screen + self-label
|
|
1246
|
+
* suggestion) and on the viewer's device (private filter). It never reports the
|
|
1247
|
+
* author — its output drives labels and the viewer's own dial only.
|
|
1248
|
+
*/
|
|
1249
|
+
|
|
1250
|
+
/** A single category score from an NSFW image model (e.g. NSFWJS / Falconsai). */
|
|
1251
|
+
type NsfwImageDetection = {
|
|
1252
|
+
label: string;
|
|
1253
|
+
score: number;
|
|
1254
|
+
};
|
|
1255
|
+
type NsfwImageDetector = (input: {
|
|
1256
|
+
metadata?: Record<string, unknown>;
|
|
1257
|
+
}) => Promise<readonly NsfwImageDetection[]> | readonly NsfwImageDetection[];
|
|
1258
|
+
type NsfwImageClassifierOptions = {
|
|
1259
|
+
/** The injected model. */
|
|
1260
|
+
detect: NsfwImageDetector;
|
|
1261
|
+
id?: string;
|
|
1262
|
+
version?: string;
|
|
1263
|
+
model?: string;
|
|
1264
|
+
sourceDid?: string;
|
|
1265
|
+
/** Minimum category score to emit a label. */
|
|
1266
|
+
threshold?: number;
|
|
1267
|
+
};
|
|
1268
|
+
/**
|
|
1269
|
+
* Map an NSFW model category to the xNet sensitivity vocabulary. Covers the
|
|
1270
|
+
* common NSFWJS (`drawing/hentai/neutral/porn/sexy`) and Falconsai
|
|
1271
|
+
* (`normal/sexy/porn/hentai`) label sets plus a few generic synonyms.
|
|
1272
|
+
*/
|
|
1273
|
+
declare function mapNsfwLabelToSensitivity(label: string): SensitivityLabelValue | null;
|
|
1274
|
+
declare function createNsfwImageClassifier(options: NsfwImageClassifierOptions): LocalClassifierAdapter;
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* Before-upload image pre-screen (exploration 0177, W4).
|
|
1278
|
+
*
|
|
1279
|
+
* Turns an on-device classifier's sensitivity labels into a single upload-time
|
|
1280
|
+
* recommendation: allow silently, suggest a self-label, or warn that the image
|
|
1281
|
+
* looks explicit. Pure and model-agnostic — the heavy NSFW model is injected via
|
|
1282
|
+
* the existing `createNsfwImageClassifier` adapter, so this runs on the author's
|
|
1283
|
+
* device and never leaves it (privacy invariant from 0175).
|
|
1284
|
+
*/
|
|
1285
|
+
|
|
1286
|
+
type PrescreenRecommendation = 'allow' | 'suggest-label' | 'warn-explicit';
|
|
1287
|
+
interface ImagePrescreenResult {
|
|
1288
|
+
recommendation: PrescreenRecommendation;
|
|
1289
|
+
/** The strongest sensitivity value to self-label with, or null when clean. */
|
|
1290
|
+
suggestedLabel: SensitivityLabelValue | null;
|
|
1291
|
+
/** Confidence of the strongest sensitivity label (0 when none). */
|
|
1292
|
+
confidence: number;
|
|
1293
|
+
/** The sensitivity labels that drove the decision. */
|
|
1294
|
+
labels: readonly AbuseLabel[];
|
|
1295
|
+
}
|
|
1296
|
+
interface ImagePrescreenOptions {
|
|
1297
|
+
/** Score at/above which an explicit (`porn`) label triggers a hard warn. */
|
|
1298
|
+
explicitWarnThreshold?: number;
|
|
1299
|
+
/** Minimum score to suggest a self-label at all. */
|
|
1300
|
+
suggestThreshold?: number;
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Map classifier labels to an upload recommendation (pure). Explicit content
|
|
1304
|
+
* above the warn threshold returns `warn-explicit`; any other sensitivity above
|
|
1305
|
+
* the suggest threshold returns `suggest-label`; everything else is `allow`.
|
|
1306
|
+
*/
|
|
1307
|
+
declare function prescreenImageLabels(labels: readonly AbuseLabel[], options?: ImagePrescreenOptions): ImagePrescreenResult;
|
|
1308
|
+
/**
|
|
1309
|
+
* Run an injected on-device classifier over an image input and reduce its output
|
|
1310
|
+
* to a pre-screen recommendation. The classifier is the seam where a real ONNX
|
|
1311
|
+
* NSFW model (NSFWJS/Falconsai via Transformers.js) is plugged in.
|
|
1312
|
+
*/
|
|
1313
|
+
declare function prescreenImage(classifier: LocalClassifierAdapter, input: LocalClassifierInput, options?: ImagePrescreenOptions): Promise<ImagePrescreenResult>;
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* Privacy-preserving usage events for abuse economics and operator accounting.
|
|
1317
|
+
*/
|
|
1318
|
+
|
|
1319
|
+
declare const ABUSE_USAGE_EVENT_KINDS: readonly ["blocked", "throttled", "reviewed", "billable", "sponsored", "reciprocal"];
|
|
1320
|
+
declare const ABUSE_USAGE_SETTLEMENTS: readonly ["free", "paid", "sponsored", "reciprocal", "abuse-blocked"];
|
|
1321
|
+
type AbuseUsageEventKind = (typeof ABUSE_USAGE_EVENT_KINDS)[number];
|
|
1322
|
+
type AbuseUsageSettlement = (typeof ABUSE_USAGE_SETTLEMENTS)[number];
|
|
1323
|
+
type AbuseUsageWorkType = 'public-write' | 'remote-mutation' | 'crawl' | 'federation-query' | 'classification' | 'moderation-label' | 'appeal' | 'storage';
|
|
1324
|
+
type AbuseUsageEventInput = {
|
|
1325
|
+
kind: AbuseUsageEventKind;
|
|
1326
|
+
surface: AbuseSurface;
|
|
1327
|
+
workType: AbuseUsageWorkType;
|
|
1328
|
+
actorDID?: string;
|
|
1329
|
+
peerId?: string;
|
|
1330
|
+
remotePeerId?: string;
|
|
1331
|
+
labelerDID?: string;
|
|
1332
|
+
hubId?: string;
|
|
1333
|
+
workspaceId?: string;
|
|
1334
|
+
domain?: string;
|
|
1335
|
+
route?: string;
|
|
1336
|
+
units?: number;
|
|
1337
|
+
costMicroUsd?: number;
|
|
1338
|
+
sponsoredMicroUsd?: number;
|
|
1339
|
+
reciprocalCreditUnits?: number;
|
|
1340
|
+
settlement?: AbuseUsageSettlement;
|
|
1341
|
+
resource?: AbuseResource;
|
|
1342
|
+
reviewQueue?: AbuseReviewQueue;
|
|
1343
|
+
reasonCodes?: readonly AbuseReasonCode[];
|
|
1344
|
+
policyId?: string;
|
|
1345
|
+
tags?: readonly string[];
|
|
1346
|
+
occurredAt?: number;
|
|
1347
|
+
eventId?: string;
|
|
1348
|
+
identityHashSalt?: string;
|
|
1349
|
+
eventHashSalt?: string;
|
|
1350
|
+
};
|
|
1351
|
+
type AbuseUsageEvent = {
|
|
1352
|
+
id: string;
|
|
1353
|
+
kind: AbuseUsageEventKind;
|
|
1354
|
+
settlement: AbuseUsageSettlement;
|
|
1355
|
+
surface: AbuseSurface;
|
|
1356
|
+
workType: AbuseUsageWorkType;
|
|
1357
|
+
actorHash: string;
|
|
1358
|
+
remotePeerHash?: string;
|
|
1359
|
+
labelerHash?: string;
|
|
1360
|
+
hubId?: string;
|
|
1361
|
+
workspaceId?: string;
|
|
1362
|
+
domain?: string;
|
|
1363
|
+
route?: string;
|
|
1364
|
+
units: number;
|
|
1365
|
+
costMicroUsd: number;
|
|
1366
|
+
billableMicroUsd: number;
|
|
1367
|
+
sponsoredMicroUsd: number;
|
|
1368
|
+
reciprocalCreditUnits: number;
|
|
1369
|
+
resource?: AbuseResource;
|
|
1370
|
+
reviewQueue?: AbuseReviewQueue;
|
|
1371
|
+
reasonCodes: readonly AbuseReasonCode[];
|
|
1372
|
+
policyId?: string;
|
|
1373
|
+
tags: readonly string[];
|
|
1374
|
+
occurredAt: number;
|
|
1375
|
+
};
|
|
1376
|
+
type AbuseDecisionUsageInput = Omit<AbuseUsageEventInput, 'kind' | 'reasonCodes' | 'resource' | 'reviewQueue' | 'settlement'> & {
|
|
1377
|
+
decision: AbuseDecision;
|
|
1378
|
+
};
|
|
1379
|
+
type AbuseUsageEventSummary = {
|
|
1380
|
+
totalEvents: number;
|
|
1381
|
+
totalUnits: number;
|
|
1382
|
+
kindCounts: Record<AbuseUsageEventKind, number>;
|
|
1383
|
+
settlementCounts: Record<AbuseUsageSettlement, number>;
|
|
1384
|
+
unitsByKind: Record<AbuseUsageEventKind, number>;
|
|
1385
|
+
unitsBySettlement: Record<AbuseUsageSettlement, number>;
|
|
1386
|
+
eventsBySurface: Partial<Record<AbuseSurface, number>>;
|
|
1387
|
+
eventsByWorkType: Partial<Record<AbuseUsageWorkType, number>>;
|
|
1388
|
+
costMicroUsd: number;
|
|
1389
|
+
billableMicroUsd: number;
|
|
1390
|
+
sponsoredMicroUsd: number;
|
|
1391
|
+
reciprocalCreditUnits: number;
|
|
1392
|
+
blockedUnits: number;
|
|
1393
|
+
throttledUnits: number;
|
|
1394
|
+
reviewedUnits: number;
|
|
1395
|
+
automationSavedUnits: number;
|
|
1396
|
+
automationSavedCostMicroUsd: number;
|
|
1397
|
+
appealUnits: number;
|
|
1398
|
+
appealCostMicroUsd: number;
|
|
1399
|
+
automationSavingsRatio: number;
|
|
1400
|
+
reviewLoadRatio: number;
|
|
1401
|
+
appealLoadRatio: number;
|
|
1402
|
+
};
|
|
1403
|
+
declare function createAbuseUsageEvent(input: AbuseUsageEventInput): AbuseUsageEvent;
|
|
1404
|
+
declare function createAbuseUsageEventsFromDecision(input: AbuseDecisionUsageInput): AbuseUsageEvent[];
|
|
1405
|
+
declare function createAbuseUsageEventId(event: Omit<AbuseUsageEvent, 'id'>, salt?: string): string;
|
|
1406
|
+
declare function summarizeAbuseUsageEvents(events: readonly AbuseUsageEvent[]): AbuseUsageEventSummary;
|
|
1407
|
+
|
|
1408
|
+
export { ABUSE_USAGE_EVENT_KINDS, ABUSE_USAGE_SETTLEMENTS, type AISignalProvenance, type AISignalProvenanceInput, type AISignalProvenanceValidation, type AISignalSourceType, AbuseDecision, AbuseDecisionOverride, type AbuseDecisionUsageInput, type AbuseDeploymentProfile, type AbuseDeploymentProfileInput, type AbuseDeploymentProfileKind, AbuseFacts, AbuseLabel, AbuseQualitySignals, AbuseReasonCode, AbuseResource, AbuseReviewQueue, AbuseSurface, type AbuseUsageEvent, type AbuseUsageEventInput, type AbuseUsageEventKind, type AbuseUsageEventSummary, type AbuseUsageSettlement, type AbuseUsageWorkType, AbuseVisibility, type AppealAnnotation, type AppealEffect, type AppealEffectAction, type AppealEffectInput, type AppealResolutionAction, type AppealStatus, type BuildSensitivityLabelInput, type CitationKind, type CitationReference, type ClaimCitationCoverageAssessment, type ClaimCitationCoverageInput, type ClaimCitationCoverageOptions, type CloudClassificationOptions, type CloudClassificationResult, type CloudClassificationSkipReason, type CloudClassificationUsage, type CloudClassifierAdapter, type CloudClassifierBudgetPolicy, type CloudClassifierInput, type CloudClassifierPrivacyPolicy, type CloudClassifierProvenance, type CloudClassifierProviderResult, type CloudClassifierProviderSignal, type CloudClassifierRequest, type CloudClassifierSignal, type CloudPrivacyMode, type CloudReviewCallPolicy, type CloudReviewCallReason, type CloudReviewRouteDecision, type CloudReviewSkipReason, type CommunityNoteAgreementOptions, type CommunityNoteAgreementStatus, type CommunityNoteAgreementSummary, type CommunityNoteHelpfulness, type CommunityNotePerspectiveSummary, type CommunityNoteRatingInput, type ContentFingerprint, type ContentFingerprintInput, type ContentFingerprintOptions, DEFAULT_SENSITIVITY_PREFERENCES, DecisionExplanation, DecisionExplanationReason, type DuplicateContentAssessment, type DuplicateContentOptions, type ExtractedClaim, type GrayscaleImage, type HubModerationMode, type HubPolicyAIReviewSettings, type HubPolicyAppealChannel, type HubPolicyAppealChannelKind, type HubPolicyBudgetHint, type HubPolicyLabelSettings, type HubPolicyModerationSettings, type HubPolicyOperatorContact, type HubPolicyServiceKind, type HubPolicyServiceOfferEntry, type HubPolicyServiceOfferSignature, type HubPolicyServiceOfferVerificationResult, type HubPolicySettlementMode, type ImagePrescreenOptions, type ImagePrescreenResult, type KeywordClassifierRule, type KeywordLocalClassifierOptions, type KnownHashMatch, type KnownImageHash, type LabelerSubscription, type LabelerSubscriptionLimitDecision, type LabelerSubscriptionLimitInput, type LabelerSubscriptionLimitPolicy, type LabelerSubscriptionStatus, type LabelerTrustAction, type LabelerTrustDecision, type LabelerTrustEvaluationInput, type LabelerTrustLevel, type LabelerTrustScope, type LabelerTrustSetting, type LocalClassificationResult, type LocalClassifierAdapter, type LocalClassifierInput, type LocalClassifierOptions, type LocalClassifierProvenance, type LocalClassifierSignal, type MaterializedModerationWrite, type ModerationCascadeCloudConfig, type ModerationCascadeOptions, type ModerationCascadeResult, NormalizedAbuseFacts, type NsfwImageClassifierOptions, type NsfwImageDetection, type NsfwImageDetector, type PolicyBlockAction, type PolicyBlockAuditEntry, type PolicyBlockEntry, type PolicyBlockListSignature, type PolicyBlockListVerificationResult, type PolicyBlockOverrideEntry, type PolicyBlockOverrideScope, type PolicyBlockScope, type PolicyBlockSubjectType, type PolicyBlockSubscriptionResolution, type PolicyBlockSubscriptionResolutionInput, PolicyScope, type PolicySubscriptionTrustInput, type PrescreenRecommendation, type PublicWriteBudgetCharge, type PublicWriteBudgetDecision, type PublicWriteBudgetInput, type PublicWriteBudgetLimit, type PublicWriteBudgetPolicy, type PublicWriteBudgetScope, type PublicWriteBudgetUsage, type QueryCostBudgetCharge, type QueryCostBudgetDecision, type QueryCostBudgetInput, type QueryCostBudgetLimit, type QueryCostBudgetPolicy, type QueryCostBudgetScope, type QueryCostBudgetUsage, type QueryCostBudgetWorkType, type ReportEscalationDecision, type ReportEscalationInput, type ResolvedPolicyBlockEntry, SENSITIVITY_LABEL_VALUES, SENSITIVITY_PRESENCE_FLOOR, SENSITIVITY_SOURCE_WEIGHT, type SensitivityAssessment, type SensitivityExplanation, type SensitivityLabelValue, type SensitivityPreference, type SensitivityReason, type SensitivityReasonCause, type SensitivitySource, type SensitivityVisibilityOptions, type SignedHubPolicyServiceOffer, type SignedPolicyBlockList, type StagedModerationReviewTask, type StagedModerationSourceType, type StagedModerationWrite, type StagedModerationWriteCandidate, type StagedModerationWriteKind, type StagedModerationWriteOptions, type StagedModerationWritePlan, type StagedModerationWritePolicy, type StagedModerationWriteStatus, TRUSTED_SPAM_LABEL, type UnsignedHubPolicyServiceOffer, type UnsignedPolicyBlockList, type UserSensitivityPreferences, WARNING_SLOP_LABEL, abuseFixtures, activeHubPolicyServices, activeLabels, activePolicyBlockEntries, approveStagedModerationWrite, assessDuplicateContent, assessSensitivity, auditPolicyBlockEntries, averageHash, buildSensitivityLabel, canonicalizeContentText, canonicalizeHubPolicyServiceOffer, canonicalizePolicyBlockList, classifyWithCloudAdapter, classifyWithLocalAdapters, classifyWithModerationCascade, compareContentFingerprints, compareSimHash64, createAISignalProvenanceEvidenceRef, createAbuseUsageEvent, createAbuseUsageEventId, createAbuseUsageEventsFromDecision, createAppealEffect, createBaseFacts, createCloudClassifierAdapter, createCloudClassifierRequestBase, createContentFingerprint, createHubPolicyServiceOffer, createKeywordLocalClassifier, createLabelerSubscription, createLocalClassificationResult, createNsfwImageClassifier, createPolicyBlockList, createPublicSearchHubAbuseProfile, createPublicWriteBudgetKey, createQueryCostBudgetKey, createSmallSelfHostedAbuseProfile, createTrustedLabelFromSetting, decideAbuse, decideCloudReviewRoute, decidePublicInteraction, decideReach, decideRemoteMutation, decideSensitivityVisibility, decideTransport, differenceHash, estimateCloudClassifierCost, evaluateLabelerSubscriptionLimit, evaluateLabelerTrust, evaluatePublicWriteBudget, evaluateQueryCostBudget, evaluateReportEscalation, explainDecision, explainSensitivityVisibility, extractCitationReferences, extractKnowledgeClaims, findPolicyBlockAuditEntry, findPolicyBlockEntry, getCloudClassificationSkipReason, getReasonDetail, groupCommunityNoteRatingsByPerspective, hammingDistanceHex, hubPolicyServiceOfferSigningBytes, imageHashSimilarity, isAISignalSourceType, isCommunityNoteAgreementVisible, isRejected, isSensitivityLabelValue, isSignedHubPolicyServiceOffer, isSignedPolicyBlockList, isVisible, mapNsfwLabelToSensitivity, matchKnownImageHash, materializeStagedModerationWrite, mergeLocalClassificationResults, normalizeAbuseFacts, perceptualHash, planStagedModerationWrites, policyBlockEntryIsActive, policyBlockListSigningBytes, policyBlockOverrideEntryIsActive, prescreenImage, prescreenImageLabels, publicAppealChannels, qualityRiskScore, redactCloudClassifierText, rejectStagedModerationWrite, resolveContentVisibility, resolveSubscribedPolicyBlockLists, scoreClaimCitationCoverage, scoreCommunityNotePerspectiveDiversity, sensitivityLabels, sensitivityOverride, shouldThrottle, signHubPolicyServiceOffer, signPolicyBlockList, strictestVisibility, subscriptionToTrustSetting, subscriptionsToTrustSettings, summarizeAbuseUsageEvents, summarizeCommunityNoteAgreement, tokenizeContent, unsignedHubPolicyServiceOffer, unsignedPolicyBlockList, validateAISignalProvenance, validateHubPolicyServiceOffer, verifySignedHubPolicyServiceOffer, verifySignedPolicyBlockList, weightedLabelScore };
|