@voltro/plugin-sanctions 0.0.0-stage → 0.88.0

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.
@@ -0,0 +1,154 @@
1
+ import { Effect } from 'effect';
2
+ import { RedisStoreOptions } from '@voltro/plugin-ratelimit';
3
+ import { Schema } from 'effect';
4
+ import { Subject } from '@voltro/protocol';
5
+ import { YieldableError } from 'effect/Cause';
6
+
7
+ /** Human reports never call this slot. Other categories default to review-only. */
8
+ export declare const abuseEscalationLadder: (input: EscalationInput) => EscalationStep | null;
9
+
10
+ declare const ACTION_KINDS: readonly ["warn", "mute", "chatBan", "matchmakingBan", "rankedBan", "tradeBan", "ban", "shadowBan", "nameReset", "rollback"];
11
+
12
+ declare const CATEGORIES: readonly ["cheating", "abuse", "name", "spam", "griefing", "rmt"];
13
+
14
+ export declare const conservativeTrustScore: (input: TrustScoreInput) => number;
15
+
16
+ export declare const defaultSanctionEnforcement: ({ action, point, context }: EnforcementInput) => {
17
+ readonly denied: boolean;
18
+ readonly shadow: boolean;
19
+ };
20
+
21
+ export declare const defaultSanctionsStrategies: Readonly<{
22
+ escalationLadder: (input: EscalationInput) => EscalationStep | null;
23
+ trustScore: (input: TrustScoreInput) => number;
24
+ evidenceCollector: (_input: EvidenceCollectorInput) => Effect.Effect<ReadonlyArray<Readonly<Record<string, unknown>>>, SanctionsError>;
25
+ enforcementPoints: ({ action, point, context }: EnforcementInput) => {
26
+ readonly denied: boolean;
27
+ readonly shadow: boolean;
28
+ };
29
+ }>;
30
+
31
+ export declare interface EnforcementInput {
32
+ readonly action: Sanction;
33
+ readonly point: SanctionPoint;
34
+ readonly context: SanctionCheckContext;
35
+ }
36
+
37
+ export declare interface EscalationInput {
38
+ readonly category: SanctionCategory;
39
+ readonly count: number;
40
+ readonly confidence: number;
41
+ readonly minimumConfidence: number;
42
+ }
43
+
44
+ export declare interface EscalationStep {
45
+ readonly kind: SanctionKind;
46
+ readonly durationMs: number | null;
47
+ }
48
+
49
+ export declare interface EvidenceCollectorInput {
50
+ readonly subject: Subject;
51
+ readonly targetId: string;
52
+ readonly context: ReportContext;
53
+ }
54
+
55
+ /** The default makes no assertion that submitted context IDs are verified evidence. */
56
+ export declare const noCollectedSanctionEvidence: (_input: EvidenceCollectorInput) => Effect.Effect<ReadonlyArray<Readonly<Record<string, unknown>>>, SanctionsError>;
57
+
58
+ declare const POINTS: readonly ["chat", "matchmaking", "trade", "ranked", "login"];
59
+
60
+ declare type ReportContext = typeof ReportContextSchema.Type;
61
+
62
+ declare const ReportContextSchema: Schema.Struct<{
63
+ readonly channelId: Schema.optional<Schema.String>;
64
+ readonly messageIds: Schema.optional<Schema.$Array<Schema.String>>;
65
+ readonly roomId: Schema.optional<Schema.String>;
66
+ readonly matchId: Schema.optional<Schema.String>;
67
+ readonly replayRef: Schema.optional<Schema.String>;
68
+ }>;
69
+
70
+ export declare type ResolvedSanctionsOptions = ReturnType<typeof resolveSanctionsOptions>;
71
+
72
+ export declare const resolveSanctionsOptions: (input?: SanctionsOptions) => Readonly<{
73
+ maxActiveActions: number;
74
+ maxReportsPerCase: number;
75
+ maxEvidenceRefs: number;
76
+ maxContextMessageIds: number;
77
+ maxTextLength: number;
78
+ pageSize: number;
79
+ maxExportRows: number;
80
+ reportLimit: number;
81
+ reportWindowMs: number;
82
+ strikeDecayMs: number;
83
+ minimumSignalConfidence: number;
84
+ strategies: Readonly<{
85
+ escalationLadder: (input: EscalationInput) => EscalationStep | null;
86
+ trustScore: (input: TrustScoreInput) => number;
87
+ evidenceCollector: (_input: EvidenceCollectorInput) => Effect.Effect<ReadonlyArray<Readonly<Record<string, unknown>>>, SanctionsError>;
88
+ enforcementPoints: ({ action, point, context }: EnforcementInput) => {
89
+ readonly denied: boolean;
90
+ readonly shadow: boolean;
91
+ };
92
+ }>;
93
+ rateLimit: RedisStoreOptions | undefined;
94
+ now: () => number;
95
+ }>;
96
+
97
+ declare type Sanction = typeof SanctionSchema.Type;
98
+
99
+ declare type SanctionCategory = typeof CATEGORIES[number];
100
+
101
+ declare interface SanctionCheckContext {
102
+ readonly channelId?: string;
103
+ readonly queueId?: string;
104
+ }
105
+
106
+ declare type SanctionKind = typeof ACTION_KINDS[number];
107
+
108
+ declare type SanctionPoint = typeof POINTS[number];
109
+
110
+ declare const SanctionSchema: Schema.Struct<{
111
+ readonly id: Schema.String;
112
+ readonly kind: Schema.Literals<readonly ["warn", "mute", "chatBan", "matchmakingBan", "rankedBan", "tradeBan", "ban", "shadowBan", "nameReset", "rollback"]>;
113
+ readonly scope: Schema.Struct<{
114
+ readonly channels: Schema.$Array<Schema.String>;
115
+ readonly queues: Schema.$Array<Schema.String>;
116
+ }>;
117
+ readonly from: Schema.Number;
118
+ readonly until: Schema.NullOr<Schema.Number>;
119
+ readonly publicReason: Schema.String;
120
+ readonly appealable: Schema.Boolean;
121
+ }>;
122
+
123
+ declare class SanctionsError extends SanctionsError_base {
124
+ }
125
+
126
+ declare const SanctionsError_base: Schema.Class<SanctionsError, Schema.TaggedStruct<"SanctionsError", {
127
+ readonly code: Schema.Literals<readonly ["identity_required", "invalid_input", "forbidden", "not_found", "conflict", "rate_limited", "sanctioned", "unavailable", "export_limit"]>;
128
+ }>, YieldableError>;
129
+
130
+ export declare interface SanctionsOptions {
131
+ readonly maxActiveActions?: number;
132
+ readonly maxReportsPerCase?: number;
133
+ readonly maxEvidenceRefs?: number;
134
+ readonly maxContextMessageIds?: number;
135
+ readonly maxTextLength?: number;
136
+ readonly pageSize?: number;
137
+ readonly maxExportRows?: number;
138
+ readonly reportLimit?: number;
139
+ readonly reportWindowMs?: number;
140
+ readonly strikeDecayMs?: number;
141
+ readonly minimumSignalConfidence?: number;
142
+ readonly strategies?: Partial<typeof defaultSanctionsStrategies>;
143
+ readonly rateLimit?: RedisStoreOptions;
144
+ readonly now?: () => number;
145
+ }
146
+
147
+ export declare interface TrustScoreInput {
148
+ readonly strikes: number;
149
+ readonly verifiedAccountAgeMs: number | null;
150
+ readonly verifiedPlatform: boolean;
151
+ readonly verifiedPaymentCount: number;
152
+ }
153
+
154
+ export { }
@@ -0,0 +1,72 @@
1
+ import { sanctionsError as e } from "./errors.js";
2
+ import { Effect as t } from "effect";
3
+ // src/strategies.ts
4
+ var n = [
5
+ {
6
+ kind: "warn",
7
+ durationMs: null
8
+ },
9
+ {
10
+ kind: "mute",
11
+ durationMs: 36e5
12
+ },
13
+ {
14
+ kind: "mute",
15
+ durationMs: 864e5
16
+ },
17
+ {
18
+ kind: "chatBan",
19
+ durationMs: 6048e5
20
+ },
21
+ {
22
+ kind: "ban",
23
+ durationMs: 2592e6
24
+ },
25
+ {
26
+ kind: "ban",
27
+ durationMs: null
28
+ }
29
+ ], r = (e) => e.category === "abuse" && e.confidence >= e.minimumConfidence ? n[Math.min(n.length - 1, Math.max(0, e.count - 1))] ?? null : null, i = (e) => Math.max(0, Math.min(100, 50 - Math.min(50, e.strikes * 5) + (e.verifiedPlatform ? 10 : 0) + Math.min(10, e.verifiedPaymentCount * 2) + (e.verifiedAccountAgeMs === null ? 0 : Math.min(20, Math.floor(e.verifiedAccountAgeMs / 864e5 / 30))))), a = (e) => t.succeed([]), o = (e, t, n) => t === "chat" ? e.channels.length === 0 || n.channelId === void 0 || e.channels.includes(n.channelId) : t === "matchmaking" || t === "ranked" ? e.queues.length === 0 || n.queueId === void 0 || e.queues.includes(n.queueId) : !0, s = ({ action: e, point: t, context: n }) => ({
30
+ denied: e.kind === "ban" || o(e.scope, t, n) && (t === "chat" && (e.kind === "mute" || e.kind === "chatBan") || t === "matchmaking" && e.kind === "matchmakingBan" || t === "ranked" && (e.kind === "rankedBan" || e.kind === "matchmakingBan") || t === "trade" && e.kind === "tradeBan"),
31
+ shadow: t === "matchmaking" && e.kind === "shadowBan" && o(e.scope, t, n)
32
+ }), c = Object.freeze({
33
+ escalationLadder: r,
34
+ trustScore: i,
35
+ evidenceCollector: a,
36
+ enforcementPoints: s
37
+ }), l = (t = {}) => {
38
+ let n = {
39
+ maxActiveActions: t.maxActiveActions ?? 100,
40
+ maxReportsPerCase: t.maxReportsPerCase ?? 1e3,
41
+ maxEvidenceRefs: t.maxEvidenceRefs ?? 100,
42
+ maxContextMessageIds: t.maxContextMessageIds ?? 41,
43
+ maxTextLength: t.maxTextLength ?? 4e3,
44
+ pageSize: t.pageSize ?? 50,
45
+ maxExportRows: t.maxExportRows ?? 1e4,
46
+ reportLimit: t.reportLimit ?? 10,
47
+ reportWindowMs: t.reportWindowMs ?? 36e5,
48
+ strikeDecayMs: t.strikeDecayMs ?? 2592e6,
49
+ minimumSignalConfidence: t.minimumSignalConfidence ?? .99,
50
+ strategies: Object.freeze({
51
+ ...c,
52
+ ...t.strategies
53
+ }),
54
+ rateLimit: t.rateLimit,
55
+ now: t.now ?? Date.now
56
+ };
57
+ for (let [t, r] of [
58
+ [n.maxActiveActions, 1e4],
59
+ [n.maxReportsPerCase, 1e5],
60
+ [n.maxEvidenceRefs, 1e3],
61
+ [n.maxContextMessageIds, 1e3],
62
+ [n.maxTextLength, 2e4],
63
+ [n.pageSize, 200],
64
+ [n.maxExportRows, 1e5],
65
+ [n.reportLimit, 1e4],
66
+ [n.reportWindowMs, 864e5],
67
+ [n.strikeDecayMs, 31536e7]
68
+ ]) if (!Number.isSafeInteger(t) || t < 1 || t > r) throw e("invalid_input");
69
+ if (!Number.isFinite(n.minimumSignalConfidence) || n.minimumSignalConfidence < 0 || n.minimumSignalConfidence > 1 || typeof n.now != "function" || Object.values(n.strategies).some((e) => typeof e != "function")) throw e("invalid_input");
70
+ return Object.freeze(n);
71
+ };
72
+ export { r as abuseEscalationLadder, i as conservativeTrustScore, s as defaultSanctionEnforcement, c as defaultSanctionsStrategies, a as noCollectedSanctionEvidence, l as resolveSanctionsOptions };
@@ -0,0 +1,211 @@
1
+ import { Context } from 'effect';
2
+ import { Effect } from 'effect';
3
+ import { Layer } from 'effect';
4
+ import { Schema } from 'effect';
5
+ import { Subject } from '@voltro/protocol';
6
+ import { YieldableError } from 'effect/Cause';
7
+
8
+ declare const ACTION_KINDS: readonly ["warn", "mute", "chatBan", "matchmakingBan", "rankedBan", "tradeBan", "ban", "shadowBan", "nameReset", "rollback"];
9
+
10
+ declare const CATEGORIES: readonly ["cheating", "abuse", "name", "spam", "griefing", "rmt"];
11
+
12
+ declare const DecisionSchema: Schema.Struct<{
13
+ readonly allowed: Schema.Boolean;
14
+ readonly actionIds: Schema.$Array<Schema.String>;
15
+ readonly shadow: Schema.Boolean;
16
+ }>;
17
+
18
+ declare interface EnforcementInput {
19
+ readonly action: Sanction;
20
+ readonly point: SanctionPoint;
21
+ readonly context: SanctionCheckContext;
22
+ }
23
+
24
+ declare interface EscalationInput {
25
+ readonly category: SanctionCategory;
26
+ readonly count: number;
27
+ readonly confidence: number;
28
+ readonly minimumConfidence: number;
29
+ }
30
+
31
+ declare interface EscalationStep {
32
+ readonly kind: SanctionKind;
33
+ readonly durationMs: number | null;
34
+ }
35
+
36
+ declare interface EvidenceCollectorInput {
37
+ readonly subject: Subject;
38
+ readonly targetId: string;
39
+ readonly context: ReportContext;
40
+ }
41
+
42
+ export declare const fakeSanctionsLayer: (overrides?: Partial<SanctionsService>) => Layer.Layer<SanctionsPort, never, never>;
43
+
44
+ export declare const fakeSanctionsService: (overrides?: Partial<SanctionsService>) => SanctionsService;
45
+
46
+ declare const POINTS: readonly ["chat", "matchmaking", "trade", "ranked", "login"];
47
+
48
+ declare type ReportContext = typeof ReportContextSchema.Type;
49
+
50
+ declare const ReportContextSchema: Schema.Struct<{
51
+ readonly channelId: Schema.optional<Schema.String>;
52
+ readonly messageIds: Schema.optional<Schema.$Array<Schema.String>>;
53
+ readonly roomId: Schema.optional<Schema.String>;
54
+ readonly matchId: Schema.optional<Schema.String>;
55
+ readonly replayRef: Schema.optional<Schema.String>;
56
+ }>;
57
+
58
+ declare type Sanction = typeof SanctionSchema.Type;
59
+
60
+ declare type SanctionCategory = typeof CATEGORIES[number];
61
+
62
+ declare interface SanctionCheckContext {
63
+ readonly channelId?: string;
64
+ readonly queueId?: string;
65
+ }
66
+
67
+ declare type SanctionDecision = typeof DecisionSchema.Type;
68
+
69
+ declare type SanctionKind = typeof ACTION_KINDS[number];
70
+
71
+ declare type SanctionPoint = typeof POINTS[number];
72
+
73
+ declare const SanctionSchema: Schema.Struct<{
74
+ readonly id: Schema.String;
75
+ readonly kind: Schema.Literals<readonly ["warn", "mute", "chatBan", "matchmakingBan", "rankedBan", "tradeBan", "ban", "shadowBan", "nameReset", "rollback"]>;
76
+ readonly scope: Schema.Struct<{
77
+ readonly channels: Schema.$Array<Schema.String>;
78
+ readonly queues: Schema.$Array<Schema.String>;
79
+ }>;
80
+ readonly from: Schema.Number;
81
+ readonly until: Schema.NullOr<Schema.Number>;
82
+ readonly publicReason: Schema.String;
83
+ readonly appealable: Schema.Boolean;
84
+ }>;
85
+
86
+ export declare const sanctionsEnforcementFixture: {
87
+ kind: "slot";
88
+ defaultImplementation: ({ action, point, context }: EnforcementInput) => {
89
+ readonly denied: boolean;
90
+ readonly shadow: boolean;
91
+ };
92
+ defaultProbe: {
93
+ run: () => Effect.Effect<{
94
+ readonly denied: boolean;
95
+ readonly shadow: boolean;
96
+ }, never, never>;
97
+ expected: {
98
+ denied: boolean;
99
+ shadow: boolean;
100
+ };
101
+ };
102
+ overrideProbe: {
103
+ run: () => Effect.Effect<{
104
+ readonly denied: boolean;
105
+ readonly shadow: boolean;
106
+ }, never, never>;
107
+ expected: {
108
+ denied: boolean;
109
+ shadow: boolean;
110
+ };
111
+ };
112
+ };
113
+
114
+ declare class SanctionsError extends SanctionsError_base {
115
+ }
116
+
117
+ declare const SanctionsError_base: Schema.Class<SanctionsError, Schema.TaggedStruct<"SanctionsError", {
118
+ readonly code: Schema.Literals<readonly ["identity_required", "invalid_input", "forbidden", "not_found", "conflict", "rate_limited", "sanctioned", "unavailable", "export_limit"]>;
119
+ }>, YieldableError>;
120
+
121
+ export declare const sanctionsEscalationFixture: {
122
+ kind: "slot";
123
+ defaultImplementation: (input: EscalationInput) => EscalationStep | null;
124
+ defaultProbe: {
125
+ run: () => Effect.Effect< EscalationStep | null, never, never>;
126
+ expected: {
127
+ kind: string;
128
+ durationMs: number;
129
+ };
130
+ };
131
+ overrideProbe: {
132
+ run: () => Effect.Effect< EscalationStep | null, never, never>;
133
+ expected: null;
134
+ };
135
+ };
136
+
137
+ export declare const sanctionsEvidenceFixture: {
138
+ kind: "slot";
139
+ defaultImplementation: (_input: EvidenceCollectorInput) => Effect.Effect<ReadonlyArray<Readonly<Record<string, unknown>>>, SanctionsError>;
140
+ defaultProbe: {
141
+ run: () => Effect.Effect<readonly Readonly<Record<string, unknown>>[], SanctionsError, never>;
142
+ expected: never[];
143
+ };
144
+ overrideProbe: {
145
+ run: () => Effect.Effect<readonly Readonly<Record<string, unknown>>[], SanctionsError, never>;
146
+ expected: {
147
+ source: string;
148
+ verified: boolean;
149
+ }[];
150
+ };
151
+ };
152
+
153
+ export declare const sanctionsFakeLayer: Layer.Layer<SanctionsPort, never, never>;
154
+
155
+ /** Other systems consult this small port rather than sanction SQL or an app-local enforcement map. */
156
+ declare class SanctionsPort extends SanctionsPort_base {
157
+ }
158
+
159
+ declare const SanctionsPort_base: Context.ServiceClass<SanctionsPort, "@voltro/SanctionsPort", SanctionsService>;
160
+
161
+ export declare const sanctionsPortFixture: {
162
+ kind: "port";
163
+ tag: typeof SanctionsPort;
164
+ fakeLayer: Layer.Layer<SanctionsPort, never, never>;
165
+ probe: {
166
+ run: () => Effect.Effect<"unavailable" | "conflict" | {
167
+ readonly allowed: boolean;
168
+ readonly actionIds: readonly string[];
169
+ readonly shadow: boolean;
170
+ } | "identity_required" | "invalid_input" | "forbidden" | "not_found" | "rate_limited" | "sanctioned" | "export_limit", never, never>;
171
+ expected: string;
172
+ };
173
+ };
174
+
175
+ declare interface SanctionsService {
176
+ readonly check: (subject: Subject, point: SanctionPoint, context?: SanctionCheckContext) => Effect.Effect<SanctionDecision, SanctionsError>;
177
+ readonly active: (subject: Subject) => Effect.Effect<ReadonlyArray<Sanction>, SanctionsError>;
178
+ readonly trust: (subject: Subject) => Effect.Effect<number, SanctionsError>;
179
+ readonly recordSignal: (subject: Subject, input: TrustedSanctionSignal) => Effect.Effect<void, SanctionsError>;
180
+ }
181
+
182
+ export declare const sanctionsTrustFixture: {
183
+ kind: "slot";
184
+ defaultImplementation: (input: TrustScoreInput) => number;
185
+ defaultProbe: {
186
+ run: () => Effect.Effect<number, never, never>;
187
+ expected: number;
188
+ };
189
+ overrideProbe: {
190
+ run: () => Effect.Effect<number, never, never>;
191
+ expected: number;
192
+ };
193
+ };
194
+
195
+ declare interface TrustedSanctionSignal {
196
+ readonly tenantId: string;
197
+ readonly targetId: string;
198
+ readonly requestId: string;
199
+ readonly category: SanctionCategory;
200
+ readonly confidence: number;
201
+ readonly context?: ReportContext;
202
+ }
203
+
204
+ declare interface TrustScoreInput {
205
+ readonly strikes: number;
206
+ readonly verifiedAccountAgeMs: number | null;
207
+ readonly verifiedPlatform: boolean;
208
+ readonly verifiedPaymentCount: number;
209
+ }
210
+
211
+ export { }
@@ -0,0 +1,120 @@
1
+ import { sanctionsError as e } from "./errors.js";
2
+ import { SanctionsPort as t } from "./port.js";
3
+ import { abuseEscalationLadder as n, conservativeTrustScore as r, defaultSanctionEnforcement as i, noCollectedSanctionEvidence as a, resolveSanctionsOptions as o } from "./strategies.js";
4
+ import { Effect as s, Layer as c, Result as l } from "effect";
5
+ // src/testing.ts
6
+ var u = (t = {}) => ({
7
+ check: () => s.fail(e("unavailable")),
8
+ active: () => s.fail(e("unavailable")),
9
+ trust: () => s.fail(e("unavailable")),
10
+ recordSignal: () => s.fail(e("unavailable")),
11
+ ...t
12
+ }), d = (e = {}) => c.sync(t, () => u(e)), f = d(), p = {
13
+ kind: "port",
14
+ tag: t,
15
+ fakeLayer: f,
16
+ probe: {
17
+ run: () => s.scoped(t.pipe(s.flatMap((e) => e.check({
18
+ type: "user",
19
+ id: "one",
20
+ tenantId: "tenant"
21
+ }, "chat")), s.result, s.map((e) => l.isFailure(e) ? e.failure.code : e.success), s.provide(f))),
22
+ expected: "unavailable"
23
+ }
24
+ }, m = {
25
+ category: "abuse",
26
+ count: 2,
27
+ confidence: 1,
28
+ minimumConfidence: .99
29
+ }, h = {
30
+ kind: "slot",
31
+ defaultImplementation: n,
32
+ defaultProbe: {
33
+ run: () => s.sync(() => n(m)),
34
+ expected: {
35
+ kind: "mute",
36
+ durationMs: 36e5
37
+ }
38
+ },
39
+ overrideProbe: {
40
+ run: () => s.sync(() => o({ strategies: { escalationLadder: () => null } }).strategies.escalationLadder(m)),
41
+ expected: null
42
+ }
43
+ }, g = {
44
+ strikes: 2,
45
+ verifiedAccountAgeMs: null,
46
+ verifiedPlatform: !1,
47
+ verifiedPaymentCount: 0
48
+ }, _ = {
49
+ kind: "slot",
50
+ defaultImplementation: r,
51
+ defaultProbe: {
52
+ run: () => s.sync(() => r(g)),
53
+ expected: 40
54
+ },
55
+ overrideProbe: {
56
+ run: () => s.sync(() => o({ strategies: { trustScore: () => 7 } }).strategies.trustScore(g)),
57
+ expected: 7
58
+ }
59
+ }, v = {
60
+ subject: {
61
+ type: "user",
62
+ id: "one",
63
+ tenantId: "tenant"
64
+ },
65
+ targetId: "two",
66
+ context: { channelId: "channel" }
67
+ }, y = {
68
+ kind: "slot",
69
+ defaultImplementation: a,
70
+ defaultProbe: {
71
+ run: () => a(v),
72
+ expected: []
73
+ },
74
+ overrideProbe: {
75
+ run: () => o({ strategies: { evidenceCollector: () => s.succeed([{
76
+ source: "fixture",
77
+ verified: !0
78
+ }]) } }).strategies.evidenceCollector(v),
79
+ expected: [{
80
+ source: "fixture",
81
+ verified: !0
82
+ }]
83
+ }
84
+ }, b = {
85
+ action: {
86
+ id: "action",
87
+ kind: "chatBan",
88
+ scope: {
89
+ channels: [],
90
+ queues: []
91
+ },
92
+ from: 0,
93
+ until: null,
94
+ publicReason: "Policy",
95
+ appealable: !0
96
+ },
97
+ point: "chat",
98
+ context: {}
99
+ }, x = {
100
+ kind: "slot",
101
+ defaultImplementation: i,
102
+ defaultProbe: {
103
+ run: () => s.sync(() => i(b)),
104
+ expected: {
105
+ denied: !0,
106
+ shadow: !1
107
+ }
108
+ },
109
+ overrideProbe: {
110
+ run: () => s.sync(() => o({ strategies: { enforcementPoints: () => ({
111
+ denied: !1,
112
+ shadow: !1
113
+ }) } }).strategies.enforcementPoints(b)),
114
+ expected: {
115
+ denied: !1,
116
+ shadow: !1
117
+ }
118
+ }
119
+ };
120
+ export { d as fakeSanctionsLayer, u as fakeSanctionsService, x as sanctionsEnforcementFixture, h as sanctionsEscalationFixture, y as sanctionsEvidenceFixture, f as sanctionsFakeLayer, p as sanctionsPortFixture, _ as sanctionsTrustFixture };