proactive-gate 0.2.2 → 0.2.4

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.
Files changed (46) hide show
  1. package/README.md +126 -2
  2. package/README.tr.md +48 -0
  3. package/dist/src/checks.d.ts +43 -0
  4. package/dist/src/checks.js +62 -0
  5. package/dist/src/policy.js +1 -0
  6. package/dist/src/types.d.ts +10 -0
  7. package/package.json +5 -3
  8. package/spec/CONFORMANCE.md +83 -0
  9. package/spec/SPEC.md +140 -0
  10. package/spec/SPEC_VERSION +1 -0
  11. package/spec/fixtures/adaptive-timing/placeholder.json +58 -0
  12. package/spec/fixtures/budget/bypass-priority.json +100 -0
  13. package/spec/fixtures/budget/daily-atomic-commit.json +140 -0
  14. package/spec/fixtures/budget/near-limit.json +103 -0
  15. package/spec/fixtures/budget/race-second-commit-loses.json +93 -0
  16. package/spec/fixtures/budget/weekly-iso-week.json +134 -0
  17. package/spec/fixtures/consent/required.json +116 -0
  18. package/spec/fixtures/cooldown/three-dismissals.json +132 -0
  19. package/spec/fixtures/dedupe/already-delivered.json +87 -0
  20. package/spec/fixtures/dedupe/no-key-skips.json +49 -0
  21. package/spec/fixtures/defer/snooze-as-defer.json +138 -0
  22. package/spec/fixtures/mode/allow-list.json +139 -0
  23. package/spec/fixtures/ordering/kill-switch.json +56 -0
  24. package/spec/fixtures/ordering/short-circuit.json +235 -0
  25. package/spec/fixtures/policy/unknown-check-is-an-error.json +50 -0
  26. package/spec/fixtures/presets/cn-minor-mode.json +170 -0
  27. package/spec/fixtures/presets/kakao-brand-message.json +93 -0
  28. package/spec/fixtures/presets/kr-network-act-50.json +168 -0
  29. package/spec/fixtures/presets/telegram-bot.json +162 -0
  30. package/spec/fixtures/presets/us-tcpa.json +90 -0
  31. package/spec/fixtures/quiet-hours/apia.json +90 -0
  32. package/spec/fixtures/quiet-hours/caller-supplied-dates.json +197 -0
  33. package/spec/fixtures/quiet-hours/crosses-midnight-by-day.json +221 -0
  34. package/spec/fixtures/quiet-hours/dst-new-york.json +126 -0
  35. package/spec/fixtures/quiet-hours/istanbul.json +160 -0
  36. package/spec/fixtures/quiet-hours/wall-clock.json +94 -0
  37. package/spec/fixtures/quiet-hours/weekday-schedule.json +262 -0
  38. package/spec/fixtures/shadow/reject-continues.json +143 -0
  39. package/spec/fixtures/trust-ramp/first-week.json +154 -0
  40. package/spec/fixtures/utility/bounded-deferral-cap.json +60 -0
  41. package/spec/fixtures/utility/bounded-deferral.json +95 -0
  42. package/spec/fixtures/utility/floor.json +168 -0
  43. package/spec/schema/fixture.schema.json +58 -0
  44. package/spec/schema/policy.schema.json +23 -0
  45. package/spec/skip/python.txt +0 -0
  46. package/spec/skip/ts.txt +0 -0
@@ -0,0 +1,262 @@
1
+ {
2
+ "spec_version": "1.2.0",
3
+ "since": "1.1.0",
4
+ "name": "quiet-hours/weekday-schedule",
5
+ "description": "A Friday and Saturday weekend in Asia/Dubai (UTC+4, no daylight saving). A date beats a weekday beats the default, and null means the day has no quiet hours.",
6
+ "policy": {
7
+ "specVersion": "1.0.0",
8
+ "checks": [
9
+ {
10
+ "id": "consent"
11
+ },
12
+ {
13
+ "id": "quietHours"
14
+ }
15
+ ]
16
+ },
17
+ "tests": [
18
+ {
19
+ "description": "Friday 14:00 local is the weekend here, rejects",
20
+ "input": {
21
+ "user": {
22
+ "id": "u1",
23
+ "consent": true,
24
+ "proactiveEnabled": true,
25
+ "mode": "normal",
26
+ "intensity": "normal",
27
+ "timezone": "Asia/Dubai",
28
+ "quietHours": {
29
+ "default": {
30
+ "start": "22:00",
31
+ "end": "08:00"
32
+ },
33
+ "days": {
34
+ "fri": {
35
+ "start": "00:00",
36
+ "end": "23:59"
37
+ },
38
+ "sat": {
39
+ "start": "00:00",
40
+ "end": "23:59"
41
+ },
42
+ "sun": null
43
+ }
44
+ },
45
+ "createdAt": "2026-01-01T00:00:00Z"
46
+ },
47
+ "candidate": {
48
+ "id": "c1",
49
+ "type": "reminder",
50
+ "priority": "normal",
51
+ "surfaces": [
52
+ "push",
53
+ "feed"
54
+ ]
55
+ },
56
+ "now": "2026-09-04T10:00:00Z"
57
+ },
58
+ "expect": {
59
+ "allowed": false,
60
+ "trace": [
61
+ "consent",
62
+ "quietHours"
63
+ ],
64
+ "rejectedBy": "quietHours"
65
+ }
66
+ },
67
+ {
68
+ "description": "Saturday 14:00 local rejects",
69
+ "input": {
70
+ "user": {
71
+ "id": "u1",
72
+ "consent": true,
73
+ "proactiveEnabled": true,
74
+ "mode": "normal",
75
+ "intensity": "normal",
76
+ "timezone": "Asia/Dubai",
77
+ "quietHours": {
78
+ "default": {
79
+ "start": "22:00",
80
+ "end": "08:00"
81
+ },
82
+ "days": {
83
+ "fri": {
84
+ "start": "00:00",
85
+ "end": "23:59"
86
+ },
87
+ "sat": {
88
+ "start": "00:00",
89
+ "end": "23:59"
90
+ },
91
+ "sun": null
92
+ }
93
+ },
94
+ "createdAt": "2026-01-01T00:00:00Z"
95
+ },
96
+ "candidate": {
97
+ "id": "c1",
98
+ "type": "reminder",
99
+ "priority": "normal",
100
+ "surfaces": [
101
+ "push",
102
+ "feed"
103
+ ]
104
+ },
105
+ "now": "2026-09-05T10:00:00Z"
106
+ },
107
+ "expect": {
108
+ "allowed": false,
109
+ "trace": [
110
+ "consent",
111
+ "quietHours"
112
+ ],
113
+ "rejectedBy": "quietHours"
114
+ }
115
+ },
116
+ {
117
+ "description": "Sunday 23:00 local is a working night, sun is null so the default does not apply",
118
+ "input": {
119
+ "user": {
120
+ "id": "u1",
121
+ "consent": true,
122
+ "proactiveEnabled": true,
123
+ "mode": "normal",
124
+ "intensity": "normal",
125
+ "timezone": "Asia/Dubai",
126
+ "quietHours": {
127
+ "default": {
128
+ "start": "22:00",
129
+ "end": "08:00"
130
+ },
131
+ "days": {
132
+ "fri": {
133
+ "start": "00:00",
134
+ "end": "23:59"
135
+ },
136
+ "sat": {
137
+ "start": "00:00",
138
+ "end": "23:59"
139
+ },
140
+ "sun": null
141
+ }
142
+ },
143
+ "createdAt": "2026-01-01T00:00:00Z"
144
+ },
145
+ "candidate": {
146
+ "id": "c1",
147
+ "type": "reminder",
148
+ "priority": "normal",
149
+ "surfaces": [
150
+ "push",
151
+ "feed"
152
+ ]
153
+ },
154
+ "now": "2026-09-06T19:00:00Z"
155
+ },
156
+ "expect": {
157
+ "allowed": true,
158
+ "trace": [
159
+ "consent",
160
+ "quietHours"
161
+ ]
162
+ }
163
+ },
164
+ {
165
+ "description": "Monday 23:00 local falls back to the default and rejects",
166
+ "input": {
167
+ "user": {
168
+ "id": "u1",
169
+ "consent": true,
170
+ "proactiveEnabled": true,
171
+ "mode": "normal",
172
+ "intensity": "normal",
173
+ "timezone": "Asia/Dubai",
174
+ "quietHours": {
175
+ "default": {
176
+ "start": "22:00",
177
+ "end": "08:00"
178
+ },
179
+ "days": {
180
+ "fri": {
181
+ "start": "00:00",
182
+ "end": "23:59"
183
+ },
184
+ "sat": {
185
+ "start": "00:00",
186
+ "end": "23:59"
187
+ },
188
+ "sun": null
189
+ }
190
+ },
191
+ "createdAt": "2026-01-01T00:00:00Z"
192
+ },
193
+ "candidate": {
194
+ "id": "c1",
195
+ "type": "reminder",
196
+ "priority": "normal",
197
+ "surfaces": [
198
+ "push",
199
+ "feed"
200
+ ]
201
+ },
202
+ "now": "2026-09-07T19:00:00Z"
203
+ },
204
+ "expect": {
205
+ "allowed": false,
206
+ "trace": [
207
+ "consent",
208
+ "quietHours"
209
+ ],
210
+ "rejectedBy": "quietHours"
211
+ }
212
+ },
213
+ {
214
+ "description": "Monday 14:00 local passes",
215
+ "input": {
216
+ "user": {
217
+ "id": "u1",
218
+ "consent": true,
219
+ "proactiveEnabled": true,
220
+ "mode": "normal",
221
+ "intensity": "normal",
222
+ "timezone": "Asia/Dubai",
223
+ "quietHours": {
224
+ "default": {
225
+ "start": "22:00",
226
+ "end": "08:00"
227
+ },
228
+ "days": {
229
+ "fri": {
230
+ "start": "00:00",
231
+ "end": "23:59"
232
+ },
233
+ "sat": {
234
+ "start": "00:00",
235
+ "end": "23:59"
236
+ },
237
+ "sun": null
238
+ }
239
+ },
240
+ "createdAt": "2026-01-01T00:00:00Z"
241
+ },
242
+ "candidate": {
243
+ "id": "c1",
244
+ "type": "reminder",
245
+ "priority": "normal",
246
+ "surfaces": [
247
+ "push",
248
+ "feed"
249
+ ]
250
+ },
251
+ "now": "2026-09-07T10:00:00Z"
252
+ },
253
+ "expect": {
254
+ "allowed": true,
255
+ "trace": [
256
+ "consent",
257
+ "quietHours"
258
+ ]
259
+ }
260
+ }
261
+ ]
262
+ }
@@ -0,0 +1,143 @@
1
+ {
2
+ "spec_version": "1.2.0",
3
+ "since": "1.0.0",
4
+ "name": "shadow/reject-continues",
5
+ "description": "A shadow check records its rejection and evaluation continues.",
6
+ "policy": {
7
+ "specVersion": "1.0.0",
8
+ "checks": [
9
+ {
10
+ "id": "consent"
11
+ },
12
+ {
13
+ "id": "quietHours",
14
+ "shadow": true
15
+ },
16
+ {
17
+ "id": "dailyBudget",
18
+ "limit": 5
19
+ }
20
+ ]
21
+ },
22
+ "store_seed": {
23
+ "budget:full:2026-09-04": "5"
24
+ },
25
+ "tests": [
26
+ {
27
+ "description": "23:30 local: quiet hours would reject; the decision is allowed and lists it",
28
+ "input": {
29
+ "user": {
30
+ "id": "u1",
31
+ "consent": true,
32
+ "proactiveEnabled": true,
33
+ "mode": "normal",
34
+ "intensity": "normal",
35
+ "timezone": "Europe/Istanbul",
36
+ "quietHours": {
37
+ "start": "22:00",
38
+ "end": "08:00"
39
+ },
40
+ "createdAt": "2026-01-01T00:00:00Z"
41
+ },
42
+ "candidate": {
43
+ "id": "c1",
44
+ "type": "reminder",
45
+ "priority": "normal",
46
+ "surfaces": [
47
+ "push",
48
+ "feed"
49
+ ]
50
+ },
51
+ "now": "2026-09-04T20:30:00Z"
52
+ },
53
+ "expect": {
54
+ "allowed": true,
55
+ "trace": [
56
+ "consent",
57
+ "quietHours",
58
+ "dailyBudget"
59
+ ],
60
+ "shadowed": [
61
+ "quietHours"
62
+ ]
63
+ }
64
+ },
65
+ {
66
+ "description": "noon: nothing shadowed",
67
+ "input": {
68
+ "user": {
69
+ "id": "u1",
70
+ "consent": true,
71
+ "proactiveEnabled": true,
72
+ "mode": "normal",
73
+ "intensity": "normal",
74
+ "timezone": "Europe/Istanbul",
75
+ "quietHours": {
76
+ "start": "22:00",
77
+ "end": "08:00"
78
+ },
79
+ "createdAt": "2026-01-01T00:00:00Z"
80
+ },
81
+ "candidate": {
82
+ "id": "c1",
83
+ "type": "reminder",
84
+ "priority": "normal",
85
+ "surfaces": [
86
+ "push",
87
+ "feed"
88
+ ]
89
+ },
90
+ "now": "2026-09-04T09:00:00Z"
91
+ },
92
+ "expect": {
93
+ "allowed": true,
94
+ "trace": [
95
+ "consent",
96
+ "quietHours",
97
+ "dailyBudget"
98
+ ],
99
+ "shadowed": []
100
+ }
101
+ },
102
+ {
103
+ "description": "a real rejection later still rejects, with the shadow listed",
104
+ "input": {
105
+ "user": {
106
+ "id": "full",
107
+ "consent": true,
108
+ "proactiveEnabled": true,
109
+ "mode": "normal",
110
+ "intensity": "normal",
111
+ "timezone": "Europe/Istanbul",
112
+ "quietHours": {
113
+ "start": "22:00",
114
+ "end": "08:00"
115
+ },
116
+ "createdAt": "2026-01-01T00:00:00Z"
117
+ },
118
+ "candidate": {
119
+ "id": "c2",
120
+ "type": "reminder",
121
+ "priority": "normal",
122
+ "surfaces": [
123
+ "push",
124
+ "feed"
125
+ ]
126
+ },
127
+ "now": "2026-09-04T20:30:00Z"
128
+ },
129
+ "expect": {
130
+ "allowed": false,
131
+ "rejectedBy": "dailyBudget",
132
+ "trace": [
133
+ "consent",
134
+ "quietHours",
135
+ "dailyBudget"
136
+ ],
137
+ "shadowed": [
138
+ "quietHours"
139
+ ]
140
+ }
141
+ }
142
+ ]
143
+ }
@@ -0,0 +1,154 @@
1
+ {
2
+ "spec_version": "1.2.0",
3
+ "since": "1.0.0",
4
+ "name": "trust-ramp/first-week",
5
+ "description": "During the first days only high priority and above gets through.",
6
+ "policy": {
7
+ "specVersion": "1.0.0",
8
+ "checks": [
9
+ {
10
+ "id": "consent"
11
+ },
12
+ {
13
+ "id": "trustRamp",
14
+ "days": 7,
15
+ "minPriority": "high"
16
+ }
17
+ ]
18
+ },
19
+ "tests": [
20
+ {
21
+ "description": "day 2, normal priority rejects",
22
+ "input": {
23
+ "user": {
24
+ "id": "u1",
25
+ "consent": true,
26
+ "proactiveEnabled": true,
27
+ "mode": "normal",
28
+ "intensity": "normal",
29
+ "timezone": "Europe/Istanbul",
30
+ "quietHours": {
31
+ "start": "22:00",
32
+ "end": "08:00"
33
+ },
34
+ "createdAt": "2026-09-03T00:00:00Z"
35
+ },
36
+ "candidate": {
37
+ "id": "c1",
38
+ "type": "reminder",
39
+ "priority": "normal",
40
+ "surfaces": [
41
+ "push",
42
+ "feed"
43
+ ]
44
+ },
45
+ "now": "2026-09-04T09:00:00Z"
46
+ },
47
+ "expect": {
48
+ "allowed": false,
49
+ "rejectedBy": "trustRamp",
50
+ "trace": [
51
+ "consent",
52
+ "trustRamp"
53
+ ],
54
+ "reason_pattern": "day 2 of 7"
55
+ }
56
+ },
57
+ {
58
+ "description": "day 2, high priority passes",
59
+ "input": {
60
+ "user": {
61
+ "id": "u1",
62
+ "consent": true,
63
+ "proactiveEnabled": true,
64
+ "mode": "normal",
65
+ "intensity": "normal",
66
+ "timezone": "Europe/Istanbul",
67
+ "quietHours": {
68
+ "start": "22:00",
69
+ "end": "08:00"
70
+ },
71
+ "createdAt": "2026-09-03T00:00:00Z"
72
+ },
73
+ "candidate": {
74
+ "id": "c1",
75
+ "type": "reminder",
76
+ "priority": "high",
77
+ "surfaces": [
78
+ "push",
79
+ "feed"
80
+ ]
81
+ },
82
+ "now": "2026-09-04T09:00:00Z"
83
+ },
84
+ "expect": {
85
+ "allowed": true,
86
+ "trace": [
87
+ "consent",
88
+ "trustRamp"
89
+ ]
90
+ }
91
+ },
92
+ {
93
+ "description": "day 8 passes",
94
+ "input": {
95
+ "user": {
96
+ "id": "u1",
97
+ "consent": true,
98
+ "proactiveEnabled": true,
99
+ "mode": "normal",
100
+ "intensity": "normal",
101
+ "timezone": "Europe/Istanbul",
102
+ "quietHours": {
103
+ "start": "22:00",
104
+ "end": "08:00"
105
+ },
106
+ "createdAt": "2026-08-27T00:00:00Z"
107
+ },
108
+ "candidate": {
109
+ "id": "c1",
110
+ "type": "reminder",
111
+ "priority": "normal",
112
+ "surfaces": [
113
+ "push",
114
+ "feed"
115
+ ]
116
+ },
117
+ "now": "2026-09-04T09:00:00Z"
118
+ },
119
+ "expect": {
120
+ "allowed": true,
121
+ "trace": [
122
+ "consent",
123
+ "trustRamp"
124
+ ]
125
+ }
126
+ },
127
+ {
128
+ "description": "no createdAt: skip, not reject",
129
+ "input": {
130
+ "user": {
131
+ "id": "u3",
132
+ "consent": true
133
+ },
134
+ "candidate": {
135
+ "id": "c1",
136
+ "type": "reminder",
137
+ "priority": "normal",
138
+ "surfaces": [
139
+ "push",
140
+ "feed"
141
+ ]
142
+ },
143
+ "now": "2026-09-04T09:00:00Z"
144
+ },
145
+ "expect": {
146
+ "allowed": true,
147
+ "trace": [
148
+ "consent",
149
+ "trustRamp"
150
+ ]
151
+ }
152
+ }
153
+ ]
154
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "spec_version": "1.2.0",
3
+ "since": "1.0.0",
4
+ "name": "utility/bounded-deferral-cap",
5
+ "description": "The bound caps t*.",
6
+ "policy": {
7
+ "specVersion": "1.0.0",
8
+ "checks": [
9
+ {
10
+ "id": "consent"
11
+ },
12
+ {
13
+ "id": "boundedDeferral",
14
+ "lambda": 1,
15
+ "interruptCost": 1,
16
+ "staleness": 0.0001,
17
+ "boundSeconds": 240
18
+ }
19
+ ]
20
+ },
21
+ "tests": [
22
+ {
23
+ "description": "t* would be 5000 s; capped at 240",
24
+ "input": {
25
+ "user": {
26
+ "id": "u1",
27
+ "consent": true,
28
+ "proactiveEnabled": true,
29
+ "mode": "normal",
30
+ "intensity": "normal",
31
+ "timezone": "Europe/Istanbul",
32
+ "quietHours": {
33
+ "start": "22:00",
34
+ "end": "08:00"
35
+ },
36
+ "createdAt": "2026-01-01T00:00:00Z"
37
+ },
38
+ "candidate": {
39
+ "id": "c1",
40
+ "type": "reminder",
41
+ "priority": "normal",
42
+ "surfaces": [
43
+ "push",
44
+ "feed"
45
+ ],
46
+ "busy": true
47
+ },
48
+ "now": "2026-09-04T09:00:00Z"
49
+ },
50
+ "expect": {
51
+ "allowed": true,
52
+ "deliverAt": "2026-09-04T09:04:00.000Z",
53
+ "trace": [
54
+ "consent",
55
+ "boundedDeferral"
56
+ ]
57
+ }
58
+ }
59
+ ]
60
+ }