proactive-gate 0.2.3 → 0.2.5

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 (42) hide show
  1. package/README.md +95 -15
  2. package/README.tr.md +56 -17
  3. package/package.json +4 -2
  4. package/spec/CONFORMANCE.md +83 -0
  5. package/spec/SPEC.md +140 -0
  6. package/spec/SPEC_VERSION +1 -0
  7. package/spec/fixtures/adaptive-timing/placeholder.json +58 -0
  8. package/spec/fixtures/budget/bypass-priority.json +100 -0
  9. package/spec/fixtures/budget/daily-atomic-commit.json +140 -0
  10. package/spec/fixtures/budget/near-limit.json +103 -0
  11. package/spec/fixtures/budget/race-second-commit-loses.json +93 -0
  12. package/spec/fixtures/budget/weekly-iso-week.json +134 -0
  13. package/spec/fixtures/consent/required.json +116 -0
  14. package/spec/fixtures/cooldown/three-dismissals.json +132 -0
  15. package/spec/fixtures/dedupe/already-delivered.json +87 -0
  16. package/spec/fixtures/dedupe/no-key-skips.json +49 -0
  17. package/spec/fixtures/defer/snooze-as-defer.json +138 -0
  18. package/spec/fixtures/mode/allow-list.json +139 -0
  19. package/spec/fixtures/ordering/kill-switch.json +56 -0
  20. package/spec/fixtures/ordering/short-circuit.json +235 -0
  21. package/spec/fixtures/policy/unknown-check-is-an-error.json +50 -0
  22. package/spec/fixtures/presets/cn-minor-mode.json +170 -0
  23. package/spec/fixtures/presets/kakao-brand-message.json +93 -0
  24. package/spec/fixtures/presets/kr-network-act-50.json +168 -0
  25. package/spec/fixtures/presets/telegram-bot.json +162 -0
  26. package/spec/fixtures/presets/us-tcpa.json +90 -0
  27. package/spec/fixtures/quiet-hours/apia.json +90 -0
  28. package/spec/fixtures/quiet-hours/caller-supplied-dates.json +197 -0
  29. package/spec/fixtures/quiet-hours/crosses-midnight-by-day.json +221 -0
  30. package/spec/fixtures/quiet-hours/dst-new-york.json +126 -0
  31. package/spec/fixtures/quiet-hours/istanbul.json +160 -0
  32. package/spec/fixtures/quiet-hours/wall-clock.json +94 -0
  33. package/spec/fixtures/quiet-hours/weekday-schedule.json +262 -0
  34. package/spec/fixtures/shadow/reject-continues.json +143 -0
  35. package/spec/fixtures/trust-ramp/first-week.json +154 -0
  36. package/spec/fixtures/utility/bounded-deferral-cap.json +60 -0
  37. package/spec/fixtures/utility/bounded-deferral.json +95 -0
  38. package/spec/fixtures/utility/floor.json +168 -0
  39. package/spec/schema/fixture.schema.json +58 -0
  40. package/spec/schema/policy.schema.json +23 -0
  41. package/spec/skip/python.txt +0 -0
  42. package/spec/skip/ts.txt +0 -0
@@ -0,0 +1,221 @@
1
+ {
2
+ "spec_version": "1.2.0",
3
+ "since": "1.1.0",
4
+ "name": "quiet-hours/crosses-midnight-by-day",
5
+ "description": "A window belongs to the day it opens on, so Friday 18:00 to 02:00 silences Saturday morning. Saturday has no window of its own, so the carry is the only thing that can explain the silence.",
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 19:00 local rejects",
20
+ "input": {
21
+ "user": {
22
+ "id": "u1",
23
+ "consent": true,
24
+ "proactiveEnabled": true,
25
+ "mode": "normal",
26
+ "intensity": "normal",
27
+ "timezone": "Europe/Istanbul",
28
+ "quietHours": {
29
+ "default": null,
30
+ "days": {
31
+ "fri": {
32
+ "start": "18:00",
33
+ "end": "02:00"
34
+ }
35
+ }
36
+ },
37
+ "createdAt": "2026-01-01T00:00:00Z"
38
+ },
39
+ "candidate": {
40
+ "id": "c1",
41
+ "type": "reminder",
42
+ "priority": "normal",
43
+ "surfaces": [
44
+ "push",
45
+ "feed"
46
+ ]
47
+ },
48
+ "now": "2026-09-04T16:00:00Z"
49
+ },
50
+ "expect": {
51
+ "allowed": false,
52
+ "trace": [
53
+ "consent",
54
+ "quietHours"
55
+ ],
56
+ "rejectedBy": "quietHours"
57
+ }
58
+ },
59
+ {
60
+ "description": "Saturday 01:30 local rejects, carried from Friday",
61
+ "input": {
62
+ "user": {
63
+ "id": "u1",
64
+ "consent": true,
65
+ "proactiveEnabled": true,
66
+ "mode": "normal",
67
+ "intensity": "normal",
68
+ "timezone": "Europe/Istanbul",
69
+ "quietHours": {
70
+ "default": null,
71
+ "days": {
72
+ "fri": {
73
+ "start": "18:00",
74
+ "end": "02:00"
75
+ }
76
+ }
77
+ },
78
+ "createdAt": "2026-01-01T00:00:00Z"
79
+ },
80
+ "candidate": {
81
+ "id": "c1",
82
+ "type": "reminder",
83
+ "priority": "normal",
84
+ "surfaces": [
85
+ "push",
86
+ "feed"
87
+ ]
88
+ },
89
+ "now": "2026-09-04T22:30:00Z"
90
+ },
91
+ "expect": {
92
+ "allowed": false,
93
+ "trace": [
94
+ "consent",
95
+ "quietHours"
96
+ ],
97
+ "rejectedBy": "quietHours"
98
+ }
99
+ },
100
+ {
101
+ "description": "Saturday 02:30 local is past the end, passes",
102
+ "input": {
103
+ "user": {
104
+ "id": "u1",
105
+ "consent": true,
106
+ "proactiveEnabled": true,
107
+ "mode": "normal",
108
+ "intensity": "normal",
109
+ "timezone": "Europe/Istanbul",
110
+ "quietHours": {
111
+ "default": null,
112
+ "days": {
113
+ "fri": {
114
+ "start": "18:00",
115
+ "end": "02:00"
116
+ }
117
+ }
118
+ },
119
+ "createdAt": "2026-01-01T00:00:00Z"
120
+ },
121
+ "candidate": {
122
+ "id": "c1",
123
+ "type": "reminder",
124
+ "priority": "normal",
125
+ "surfaces": [
126
+ "push",
127
+ "feed"
128
+ ]
129
+ },
130
+ "now": "2026-09-04T23:30:00Z"
131
+ },
132
+ "expect": {
133
+ "allowed": true,
134
+ "trace": [
135
+ "consent",
136
+ "quietHours"
137
+ ]
138
+ }
139
+ },
140
+ {
141
+ "description": "Sunday 01:30 local passes: Saturday had no window to carry",
142
+ "input": {
143
+ "user": {
144
+ "id": "u1",
145
+ "consent": true,
146
+ "proactiveEnabled": true,
147
+ "mode": "normal",
148
+ "intensity": "normal",
149
+ "timezone": "Europe/Istanbul",
150
+ "quietHours": {
151
+ "default": null,
152
+ "days": {
153
+ "fri": {
154
+ "start": "18:00",
155
+ "end": "02:00"
156
+ }
157
+ }
158
+ },
159
+ "createdAt": "2026-01-01T00:00:00Z"
160
+ },
161
+ "candidate": {
162
+ "id": "c1",
163
+ "type": "reminder",
164
+ "priority": "normal",
165
+ "surfaces": [
166
+ "push",
167
+ "feed"
168
+ ]
169
+ },
170
+ "now": "2026-09-05T22:30:00Z"
171
+ },
172
+ "expect": {
173
+ "allowed": true,
174
+ "trace": [
175
+ "consent",
176
+ "quietHours"
177
+ ]
178
+ }
179
+ },
180
+ {
181
+ "description": "Friday 15:00 local is before the window, passes",
182
+ "input": {
183
+ "user": {
184
+ "id": "u1",
185
+ "consent": true,
186
+ "proactiveEnabled": true,
187
+ "mode": "normal",
188
+ "intensity": "normal",
189
+ "timezone": "Europe/Istanbul",
190
+ "quietHours": {
191
+ "default": null,
192
+ "days": {
193
+ "fri": {
194
+ "start": "18:00",
195
+ "end": "02:00"
196
+ }
197
+ }
198
+ },
199
+ "createdAt": "2026-01-01T00:00:00Z"
200
+ },
201
+ "candidate": {
202
+ "id": "c1",
203
+ "type": "reminder",
204
+ "priority": "normal",
205
+ "surfaces": [
206
+ "push",
207
+ "feed"
208
+ ]
209
+ },
210
+ "now": "2026-09-04T12:00:00Z"
211
+ },
212
+ "expect": {
213
+ "allowed": true,
214
+ "trace": [
215
+ "consent",
216
+ "quietHours"
217
+ ]
218
+ }
219
+ }
220
+ ]
221
+ }
@@ -0,0 +1,126 @@
1
+ {
2
+ "spec_version": "1.2.0",
3
+ "since": "1.0.0",
4
+ "name": "quiet-hours/dst-new-york",
5
+ "description": "On 2026-03-08 New York springs forward at 02:00; 06:30Z is 01:30 EST, 07:30Z is 03:30 EDT.",
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": "06:30Z is 01:30 local, inside 22:00 to 07:00",
20
+ "input": {
21
+ "user": {
22
+ "id": "u1",
23
+ "consent": true,
24
+ "proactiveEnabled": true,
25
+ "mode": "normal",
26
+ "intensity": "normal",
27
+ "timezone": "America/New_York",
28
+ "quietHours": {
29
+ "start": "22:00",
30
+ "end": "07:00"
31
+ },
32
+ "createdAt": "2026-01-01T00:00:00Z"
33
+ },
34
+ "candidate": {
35
+ "id": "c1",
36
+ "type": "reminder",
37
+ "priority": "normal",
38
+ "surfaces": [
39
+ "push",
40
+ "feed"
41
+ ]
42
+ },
43
+ "now": "2026-03-08T06:30:00Z"
44
+ },
45
+ "expect": {
46
+ "allowed": false,
47
+ "rejectedBy": "quietHours",
48
+ "trace": [
49
+ "consent",
50
+ "quietHours"
51
+ ]
52
+ }
53
+ },
54
+ {
55
+ "description": "07:30Z is 03:30 local after the jump, still inside",
56
+ "input": {
57
+ "user": {
58
+ "id": "u1",
59
+ "consent": true,
60
+ "proactiveEnabled": true,
61
+ "mode": "normal",
62
+ "intensity": "normal",
63
+ "timezone": "America/New_York",
64
+ "quietHours": {
65
+ "start": "22:00",
66
+ "end": "07:00"
67
+ },
68
+ "createdAt": "2026-01-01T00:00:00Z"
69
+ },
70
+ "candidate": {
71
+ "id": "c1",
72
+ "type": "reminder",
73
+ "priority": "normal",
74
+ "surfaces": [
75
+ "push",
76
+ "feed"
77
+ ]
78
+ },
79
+ "now": "2026-03-08T07:30:00Z"
80
+ },
81
+ "expect": {
82
+ "allowed": false,
83
+ "rejectedBy": "quietHours",
84
+ "trace": [
85
+ "consent",
86
+ "quietHours"
87
+ ]
88
+ }
89
+ },
90
+ {
91
+ "description": "11:30Z is 07:30 local, outside",
92
+ "input": {
93
+ "user": {
94
+ "id": "u1",
95
+ "consent": true,
96
+ "proactiveEnabled": true,
97
+ "mode": "normal",
98
+ "intensity": "normal",
99
+ "timezone": "America/New_York",
100
+ "quietHours": {
101
+ "start": "22:00",
102
+ "end": "07:00"
103
+ },
104
+ "createdAt": "2026-01-01T00:00:00Z"
105
+ },
106
+ "candidate": {
107
+ "id": "c1",
108
+ "type": "reminder",
109
+ "priority": "normal",
110
+ "surfaces": [
111
+ "push",
112
+ "feed"
113
+ ]
114
+ },
115
+ "now": "2026-03-08T11:30:00Z"
116
+ },
117
+ "expect": {
118
+ "allowed": true,
119
+ "trace": [
120
+ "consent",
121
+ "quietHours"
122
+ ]
123
+ }
124
+ }
125
+ ]
126
+ }
@@ -0,0 +1,160 @@
1
+ {
2
+ "spec_version": "1.2.0",
3
+ "since": "1.0.0",
4
+ "name": "quiet-hours/istanbul",
5
+ "description": "Quiet hours cross midnight in the user's zone; the priority floor bypasses them.",
6
+ "policy": {
7
+ "specVersion": "1.0.0",
8
+ "checks": [
9
+ {
10
+ "id": "consent"
11
+ },
12
+ {
13
+ "id": "quietHours",
14
+ "priorityFloor": "high"
15
+ }
16
+ ]
17
+ },
18
+ "tests": [
19
+ {
20
+ "description": "23:30 local rejects normal",
21
+ "input": {
22
+ "user": {
23
+ "id": "u1",
24
+ "consent": true,
25
+ "proactiveEnabled": true,
26
+ "mode": "normal",
27
+ "intensity": "normal",
28
+ "timezone": "Europe/Istanbul",
29
+ "quietHours": {
30
+ "start": "22:00",
31
+ "end": "08:00"
32
+ },
33
+ "createdAt": "2026-01-01T00:00:00Z"
34
+ },
35
+ "candidate": {
36
+ "id": "c1",
37
+ "type": "reminder",
38
+ "priority": "normal",
39
+ "surfaces": [
40
+ "push",
41
+ "feed"
42
+ ]
43
+ },
44
+ "now": "2026-09-04T20:30:00Z"
45
+ },
46
+ "expect": {
47
+ "allowed": false,
48
+ "rejectedBy": "quietHours",
49
+ "trace": [
50
+ "consent",
51
+ "quietHours"
52
+ ]
53
+ }
54
+ },
55
+ {
56
+ "description": "23:30 local passes high",
57
+ "input": {
58
+ "user": {
59
+ "id": "u1",
60
+ "consent": true,
61
+ "proactiveEnabled": true,
62
+ "mode": "normal",
63
+ "intensity": "normal",
64
+ "timezone": "Europe/Istanbul",
65
+ "quietHours": {
66
+ "start": "22:00",
67
+ "end": "08:00"
68
+ },
69
+ "createdAt": "2026-01-01T00:00:00Z"
70
+ },
71
+ "candidate": {
72
+ "id": "c1",
73
+ "type": "reminder",
74
+ "priority": "high",
75
+ "surfaces": [
76
+ "push",
77
+ "feed"
78
+ ]
79
+ },
80
+ "now": "2026-09-04T20:30:00Z"
81
+ },
82
+ "expect": {
83
+ "allowed": true,
84
+ "trace": [
85
+ "consent",
86
+ "quietHours"
87
+ ]
88
+ }
89
+ },
90
+ {
91
+ "description": "12:00 local passes",
92
+ "input": {
93
+ "user": {
94
+ "id": "u1",
95
+ "consent": true,
96
+ "proactiveEnabled": true,
97
+ "mode": "normal",
98
+ "intensity": "normal",
99
+ "timezone": "Europe/Istanbul",
100
+ "quietHours": {
101
+ "start": "22:00",
102
+ "end": "08:00"
103
+ },
104
+ "createdAt": "2026-01-01T00:00:00Z"
105
+ },
106
+ "candidate": {
107
+ "id": "c1",
108
+ "type": "reminder",
109
+ "priority": "normal",
110
+ "surfaces": [
111
+ "push",
112
+ "feed"
113
+ ]
114
+ },
115
+ "now": "2026-09-04T09:00:00Z"
116
+ },
117
+ "expect": {
118
+ "allowed": true,
119
+ "trace": [
120
+ "consent",
121
+ "quietHours"
122
+ ]
123
+ }
124
+ },
125
+ {
126
+ "description": "no timezone: the check skips",
127
+ "input": {
128
+ "user": {
129
+ "id": "u1",
130
+ "consent": true,
131
+ "proactiveEnabled": true,
132
+ "mode": "normal",
133
+ "intensity": "normal",
134
+ "quietHours": {
135
+ "start": "22:00",
136
+ "end": "08:00"
137
+ },
138
+ "createdAt": "2026-01-01T00:00:00Z"
139
+ },
140
+ "candidate": {
141
+ "id": "c1",
142
+ "type": "reminder",
143
+ "priority": "normal",
144
+ "surfaces": [
145
+ "push",
146
+ "feed"
147
+ ]
148
+ },
149
+ "now": "2026-09-04T20:30:00Z"
150
+ },
151
+ "expect": {
152
+ "allowed": true,
153
+ "trace": [
154
+ "consent",
155
+ "quietHours"
156
+ ]
157
+ }
158
+ }
159
+ ]
160
+ }
@@ -0,0 +1,94 @@
1
+ {
2
+ "spec_version": "1.2.0",
3
+ "since": "1.0.0",
4
+ "name": "quiet-hours/wall-clock",
5
+ "description": "now is in 2031; the outcome only holds when the implementation used the supplied instant, not the wall clock.",
6
+ "policy": {
7
+ "specVersion": "1.0.0",
8
+ "checks": [
9
+ {
10
+ "id": "consent"
11
+ },
12
+ {
13
+ "id": "quietHours"
14
+ },
15
+ {
16
+ "id": "trustRamp"
17
+ }
18
+ ]
19
+ },
20
+ "tests": [
21
+ {
22
+ "description": "2031-01-01T20:30Z is 23:30 Istanbul: rejected",
23
+ "input": {
24
+ "user": {
25
+ "id": "u1",
26
+ "consent": true,
27
+ "proactiveEnabled": true,
28
+ "mode": "normal",
29
+ "intensity": "normal",
30
+ "timezone": "Europe/Istanbul",
31
+ "quietHours": {
32
+ "start": "22:00",
33
+ "end": "08:00"
34
+ },
35
+ "createdAt": "2026-01-01T00:00:00Z"
36
+ },
37
+ "candidate": {
38
+ "id": "c1",
39
+ "type": "reminder",
40
+ "priority": "normal",
41
+ "surfaces": [
42
+ "push",
43
+ "feed"
44
+ ]
45
+ },
46
+ "now": "2031-01-01T20:30:00Z"
47
+ },
48
+ "expect": {
49
+ "allowed": false,
50
+ "rejectedBy": "quietHours",
51
+ "trace": [
52
+ "consent",
53
+ "quietHours"
54
+ ]
55
+ }
56
+ },
57
+ {
58
+ "description": "2031-01-01T09:00Z is noon: allowed and the ramp is long over",
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": "2030-12-31T00:00:00Z"
72
+ },
73
+ "candidate": {
74
+ "id": "c1",
75
+ "type": "reminder",
76
+ "priority": "normal",
77
+ "surfaces": [
78
+ "push",
79
+ "feed"
80
+ ]
81
+ },
82
+ "now": "2031-01-08T09:00:00Z"
83
+ },
84
+ "expect": {
85
+ "allowed": true,
86
+ "trace": [
87
+ "consent",
88
+ "quietHours",
89
+ "trustRamp"
90
+ ]
91
+ }
92
+ }
93
+ ]
94
+ }